diff --git a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/with/WithConverter.java b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/with/WithConverter.java new file mode 100644 index 00000000000000..214e83684e2297 --- /dev/null +++ b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/with/WithConverter.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.sqlfederation.compiler.converter.segment.with; + +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlNodeList; +import org.apache.calcite.sql.SqlWithItem; +import org.apache.calcite.sql.SqlWith; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment; +import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.WithSegment; +import org.apache.shardingsphere.sqlfederation.compiler.converter.segment.expression.ExpressionConverter; +import org.apache.shardingsphere.sqlfederation.compiler.converter.statement.select.SelectStatementConverter; + +import java.util.Collection; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * With converter. + */ +public final class WithConverter { + + public Optional convert(final WithSegment segment, final SqlNode query) { + SqlIdentifier name = new SqlIdentifier(segment.getCommonTableExpressions().iterator().next().getIdentifier().getValue(), SqlParserPos.ZERO); + SqlNode selectSubquery = new SelectStatementConverter().convert(segment.getCommonTableExpressions().iterator().next().getSubquery().getSelect()); + ExpressionConverter converter = new ExpressionConverter(); + Collection collectionColumns = segment.getCommonTableExpressions().iterator().next().getColumns(); + Collection convertedColumns; + SqlNodeList columns = null; + if (!collectionColumns.isEmpty()) { + convertedColumns = collectionColumns.stream().map(converter::convert).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList()); + columns = new SqlNodeList(convertedColumns, SqlParserPos.ZERO); + } + SqlWithItem sqlWithItem = new SqlWithItem(SqlParserPos.ZERO, name, columns, selectSubquery); + SqlNodeList sqlWithItems = new SqlNodeList(SqlParserPos.ZERO); + sqlWithItems.add(sqlWithItem); + SqlWith sqlWith = new SqlWith(SqlParserPos.ZERO, sqlWithItems, query); + SqlNodeList result = new SqlNodeList(SqlParserPos.ZERO); + result.add(sqlWith); + return Optional.of(result); + } +} diff --git a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/statement/delete/DeleteStatementConverter.java b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/statement/delete/DeleteStatementConverter.java index 154bb26f6db22f..a60ed85ce220a7 100644 --- a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/statement/delete/DeleteStatementConverter.java +++ b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/statement/delete/DeleteStatementConverter.java @@ -24,12 +24,14 @@ import org.apache.calcite.sql.SqlOrderBy; import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment; +import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.WithSegment; import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.handler.dml.DeleteStatementHandler; import org.apache.shardingsphere.sqlfederation.compiler.converter.segment.from.TableConverter; import org.apache.shardingsphere.sqlfederation.compiler.converter.segment.limit.PaginationValueSQLConverter; import org.apache.shardingsphere.sqlfederation.compiler.converter.segment.orderby.OrderByConverter; import org.apache.shardingsphere.sqlfederation.compiler.converter.segment.where.WhereConverter; +import org.apache.shardingsphere.sqlfederation.compiler.converter.segment.with.WithConverter; import org.apache.shardingsphere.sqlfederation.compiler.converter.statement.SQLStatementConverter; import java.util.Optional; @@ -41,7 +43,7 @@ public final class DeleteStatementConverter implements SQLStatementConverter new OrderByConverter().convert(optional)).orElse(SqlNodeList.EMPTY); Optional limit = DeleteStatementHandler.getLimitSegment(deleteStatement); if (limit.isPresent()) { @@ -52,10 +54,15 @@ public SqlNode convert(final DeleteStatement deleteStatement) { return orderBy.isEmpty() ? sqlDelete : new SqlOrderBy(SqlParserPos.ZERO, sqlDelete, orderBy, null, null); } - private SqlDelete convertDelete(final DeleteStatement deleteStatement) { + private SqlNode convertDelete(final DeleteStatement deleteStatement) { SqlNode deleteTable = new TableConverter().convert(deleteStatement.getTable()).orElseThrow(IllegalStateException::new); SqlNode condition = deleteStatement.getWhere().flatMap(optional -> new WhereConverter().convert(optional)).orElse(null); SqlIdentifier alias = deleteStatement.getTable().getAliasName().map(optional -> new SqlIdentifier(optional, SqlParserPos.ZERO)).orElse(null); - return new SqlDelete(SqlParserPos.ZERO, deleteTable, condition, null, alias); + SqlDelete sqlDelete = new SqlDelete(SqlParserPos.ZERO, deleteTable, condition, null, alias); + Optional with = DeleteStatementHandler.getWithSegment(deleteStatement); + if (with.isPresent()) { + return new WithConverter().convert(DeleteStatementHandler.getWithSegment(deleteStatement).get(), sqlDelete).get(); + } + return sqlDelete; } } diff --git a/test/it/optimizer/src/test/java/org/apache/shardingsphere/test/it/optimizer/converter/SQLNodeConverterEngineIT.java b/test/it/optimizer/src/test/java/org/apache/shardingsphere/test/it/optimizer/converter/SQLNodeConverterEngineIT.java index fc1233355d9a99..708fb470cc2227 100644 --- a/test/it/optimizer/src/test/java/org/apache/shardingsphere/test/it/optimizer/converter/SQLNodeConverterEngineIT.java +++ b/test/it/optimizer/src/test/java/org/apache/shardingsphere/test/it/optimizer/converter/SQLNodeConverterEngineIT.java @@ -89,7 +89,7 @@ private static class TestCaseArgumentsProvider implements ArgumentsProvider { @Override public Stream provideArguments(final ExtensionContext extensionContext) { - return getTestParameters("MySQL", "PostgreSQL", "openGauss", "Oracle").stream(); + return getTestParameters("MySQL", "PostgreSQL", "openGauss", "Oracle", "SQLServer").stream(); } private Collection getTestParameters(final String... databaseTypes) { diff --git a/test/it/optimizer/src/test/resources/converter/delete.xml b/test/it/optimizer/src/test/resources/converter/delete.xml index 7145066efdb6b9..1f320631d0bedf 100644 --- a/test/it/optimizer/src/test/resources/converter/delete.xml +++ b/test/it/optimizer/src/test/resources/converter/delete.xml @@ -36,6 +36,10 @@ - - + + + + + +