This is an automated email from the ASF dual-hosted git repository.
chengzhang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 56117f45091 Support select with statement sql bind and add bind test
case (#34141)
56117f45091 is described below
commit 56117f45091aefdb26dec82a96c039c462d8f9bb
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Wed Dec 25 07:42:30 2024 +0800
Support select with statement sql bind and add bind test case (#34141)
* Remove TablesContext#findTableNames method and use sql bind info to
replace
* fix unit test
* optimize select statement binder
* update release note
* Support select with statement sql bind and add bind test case
* update release note
* fix build error
---
RELEASE-NOTES.md | 1 +
.../sql/EncryptSupportedSQLCheckersBuilder.java | 4 +-
.../from/type/SimpleTableSegmentBinder.java | 7 +
.../with/CommonTableExpressionSegmentBinder.java | 62 +++++++
.../engine/segment/with/WithSegmentBinder.java | 125 +++++++++++++
.../statement/dml/SelectStatementBinder.java | 4 +-
.../statement/dml/UpdateStatementBinder.java | 3 +-
.../binder/src/test/resources/cases/dml/select.xml | 206 +++++++++++++++++++++
.../binder/src/test/resources/sqls/dml/select.xml | 2 +
.../asserts/segment/orderby/OrderByItemAssert.java | 2 +
.../item/impl/ExpectedColumnOrderByItem.java | 4 +
11 files changed, 415 insertions(+), 5 deletions(-)
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 318dd2e0892..37fad67b255 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -38,6 +38,7 @@
1. SQL Binder: Support create index statement sql bind -
[#34112](https://github.com/apache/shardingsphere/pull/34112)
1. SQL Parser: Support MySQL update with statement parse -
[#34126](https://github.com/apache/shardingsphere/pull/34126)
1. SQL Binder: Remove TablesContext#findTableNames method and implement select
order by, group by bind logic -
[#34123](https://github.com/apache/shardingsphere/pull/34123)
+1. SQL Binder: Support select with statement sql bind and add bind test case -
[#34141](https://github.com/apache/shardingsphere/pull/34141)
### Bug Fixes
diff --git
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptSupportedSQLCheckersBuilder.java
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptSupportedSQLCheckersBuilder.java
index 7a661c2e926..fce03c66f10 100644
---
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptSupportedSQLCheckersBuilder.java
+++
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptSupportedSQLCheckersBuilder.java
@@ -17,10 +17,10 @@
package org.apache.shardingsphere.encrypt.checker.sql;
-import
org.apache.shardingsphere.encrypt.checker.sql.projection.EncryptInsertSelectProjectionSupportedChecker;
-import
org.apache.shardingsphere.encrypt.checker.sql.projection.EncryptSelectProjectionSupportedChecker;
import
org.apache.shardingsphere.encrypt.checker.sql.orderby.EncryptOrderByItemSupportedChecker;
import
org.apache.shardingsphere.encrypt.checker.sql.predicate.EncryptPredicateColumnSupportedChecker;
+import
org.apache.shardingsphere.encrypt.checker.sql.projection.EncryptInsertSelectProjectionSupportedChecker;
+import
org.apache.shardingsphere.encrypt.checker.sql.projection.EncryptSelectProjectionSupportedChecker;
import org.apache.shardingsphere.encrypt.constant.EncryptOrder;
import org.apache.shardingsphere.encrypt.rule.EncryptRule;
import org.apache.shardingsphere.infra.checker.SupportedSQLChecker;
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SimpleTableSegmentBinder.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SimpleTableSegmentBinder.java
index eb57d97f828..d471cb8cf01 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SimpleTableSegmentBinder.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/from/type/SimpleTableSegmentBinder.java
@@ -24,6 +24,7 @@ import lombok.NoArgsConstructor;
import
org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext;
import
org.apache.shardingsphere.infra.binder.engine.segment.from.context.type.SimpleTableSegmentBinderContext;
import
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
+import
org.apache.shardingsphere.infra.binder.engine.util.SubqueryTableBindUtils;
import
org.apache.shardingsphere.infra.database.core.metadata.database.DialectDatabaseMetaData;
import
org.apache.shardingsphere.infra.database.core.metadata.database.enums.QuoteCharacter;
import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
@@ -150,6 +151,12 @@ public final class SimpleTableSegmentBinder {
if (binderContext.getSqlStatement() instanceof CreateTableStatement) {
return new
SimpleTableSegmentBinderContext(createProjectionSegments((CreateTableStatement)
binderContext.getSqlStatement(), databaseName, schemaName, tableName));
}
+ CaseInsensitiveString caseInsensitiveTableName = new
CaseInsensitiveString(tableName.getValue());
+ if
(binderContext.getExternalTableBinderContexts().containsKey(caseInsensitiveTableName))
{
+ TableSegmentBinderContext tableSegmentBinderContext =
binderContext.getExternalTableBinderContexts().get(caseInsensitiveTableName).iterator().next();
+ return new SimpleTableSegmentBinderContext(
+
SubqueryTableBindUtils.createSubqueryProjections(tableSegmentBinderContext.getProjectionSegments(),
tableName, binderContext.getSqlStatement().getDatabaseType()));
+ }
return new SimpleTableSegmentBinderContext(Collections.emptyList());
}
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/with/CommonTableExpressionSegmentBinder.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/with/CommonTableExpressionSegmentBinder.java
new file mode 100644
index 00000000000..136c33e7fbd
--- /dev/null
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/with/CommonTableExpressionSegmentBinder.java
@@ -0,0 +1,62 @@
+/*
+ * 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.infra.binder.engine.segment.with;
+
+import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString;
+import com.google.common.collect.LinkedHashMultimap;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import
org.apache.shardingsphere.infra.binder.engine.segment.from.context.type.SimpleTableSegmentBinderContext;
+import
org.apache.shardingsphere.infra.binder.engine.segment.from.type.SubqueryTableSegmentBinder;
+import
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.complex.CommonTableExpressionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ColumnProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SubqueryTableSegment;
+
+import java.util.stream.Collectors;
+
+/**
+ * Common table expression segment binder.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class CommonTableExpressionSegmentBinder {
+
+ /**
+ * Bind common table expression segment.
+ *
+ * @param segment common table expression segment
+ * @param binderContext SQL statement binder context
+ * @param recursive recursive
+ * @return bound common table expression segment
+ */
+ public static CommonTableExpressionSegment bind(final
CommonTableExpressionSegment segment, final SQLStatementBinderContext
binderContext, final boolean recursive) {
+ if (recursive && segment.getAliasName().isPresent()) {
+ binderContext.getExternalTableBinderContexts().put(new
CaseInsensitiveString(segment.getAliasName().get()),
+ new
SimpleTableSegmentBinderContext(segment.getColumns().stream().map(ColumnProjectionSegment::new).collect(Collectors.toList())));
+ }
+ SubqueryTableSegment subqueryTableSegment = new
SubqueryTableSegment(segment.getStartIndex(), segment.getStopIndex(),
segment.getSubquery());
+ subqueryTableSegment.setAlias(segment.getAliasSegment());
+ SubqueryTableSegment boundSubquerySegment =
+ SubqueryTableSegmentBinder.bind(subqueryTableSegment,
binderContext, LinkedHashMultimap.create(),
binderContext.getExternalTableBinderContexts());
+ CommonTableExpressionSegment result = new CommonTableExpressionSegment(
+ segment.getStartIndex(), segment.getStopIndex(),
boundSubquerySegment.getAliasSegment().orElse(null),
boundSubquerySegment.getSubquery());
+ // TODO bind with columns
+ result.getColumns().addAll(segment.getColumns());
+ return result;
+ }
+}
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/with/WithSegmentBinder.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/with/WithSegmentBinder.java
new file mode 100644
index 00000000000..ca4af9da753
--- /dev/null
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/with/WithSegmentBinder.java
@@ -0,0 +1,125 @@
+/*
+ * 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.infra.binder.engine.segment.with;
+
+import com.cedarsoftware.util.CaseInsensitiveMap;
+import com.cedarsoftware.util.CaseInsensitiveMap.CaseInsensitiveString;
+import com.google.common.base.Strings;
+import com.google.common.collect.Multimap;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import
org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext;
+import
org.apache.shardingsphere.infra.binder.engine.segment.from.context.type.SimpleTableSegmentBinderContext;
+import
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.complex.CommonTableExpressionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ColumnProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ShorthandProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.WithSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.bound.ColumnSegmentBoundInfo;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.bound.TableSegmentBoundInfo;
+import
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * With segment binder.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class WithSegmentBinder {
+
+ /**
+ * Bind with segment.
+ *
+ * @param segment with segment
+ * @param binderContext SQL statement binder context
+ * @param externalTableBinderContexts external table binder contexts
+ * @return bound with segment
+ */
+ public static WithSegment bind(final WithSegment segment, final
SQLStatementBinderContext binderContext,
+ final Multimap<CaseInsensitiveString,
TableSegmentBinderContext> externalTableBinderContexts) {
+ Collection<CommonTableExpressionSegment> boundCommonTableExpressions =
new LinkedList<>();
+ for (CommonTableExpressionSegment each :
segment.getCommonTableExpressions()) {
+ CommonTableExpressionSegment boundCommonTableExpression =
CommonTableExpressionSegmentBinder.bind(each, binderContext,
segment.isRecursive());
+ boundCommonTableExpressions.add(boundCommonTableExpression);
+ if (segment.isRecursive() && each.getAliasName().isPresent()) {
+ externalTableBinderContexts.removeAll(new
CaseInsensitiveString(each.getAliasName().get()));
+ }
+ bindWithColumns(each.getColumns(), boundCommonTableExpression);
+ each.getAliasName().ifPresent(optional ->
externalTableBinderContexts.put(new CaseInsensitiveString(optional),
createWithTableBinderContext(boundCommonTableExpression)));
+ }
+ return new WithSegment(segment.getStartIndex(),
segment.getStopIndex(), boundCommonTableExpressions);
+ }
+
+ private static SimpleTableSegmentBinderContext
createWithTableBinderContext(final CommonTableExpressionSegment
commonTableExpressionSegment) {
+ return new
SimpleTableSegmentBinderContext(commonTableExpressionSegment.getSubquery().getSelect().getProjections().getProjections());
+ }
+
+ private static void bindWithColumns(final Collection<ColumnSegment>
columns, final CommonTableExpressionSegment boundCommonTableExpression) {
+ if (columns.isEmpty()) {
+ return;
+ }
+ Map<String, ColumnProjectionSegment> columnProjections =
extractWithSubqueryColumnProjections(boundCommonTableExpression);
+ columns.forEach(each -> {
+ ColumnProjectionSegment projectionSegment =
columnProjections.get(each.getIdentifier().getValue());
+ if (null != projectionSegment) {
+ each.setColumnBoundInfo(createColumnSegmentBoundInfo(each,
projectionSegment.getColumn()));
+ }
+ });
+ }
+
+ private static Map<String, ColumnProjectionSegment>
extractWithSubqueryColumnProjections(final CommonTableExpressionSegment
boundCommonTableExpression) {
+ Map<String, ColumnProjectionSegment> result = new
CaseInsensitiveMap<>();
+ Collection<ProjectionSegment> projections =
boundCommonTableExpression.getSubquery().getSelect().getProjections().getProjections();
+ projections.forEach(each -> extractWithSubqueryColumnProjections(each,
result));
+ return result;
+ }
+
+ private static void extractWithSubqueryColumnProjections(final
ProjectionSegment projectionSegment, final Map<String, ColumnProjectionSegment>
result) {
+ if (projectionSegment instanceof ColumnProjectionSegment) {
+ result.put(getColumnName((ColumnProjectionSegment)
projectionSegment), (ColumnProjectionSegment) projectionSegment);
+ }
+ if (projectionSegment instanceof ShorthandProjectionSegment) {
+ ((ShorthandProjectionSegment)
projectionSegment).getActualProjectionSegments().forEach(eachProjection -> {
+ if (eachProjection instanceof ColumnProjectionSegment) {
+ result.put(getColumnName((ColumnProjectionSegment)
eachProjection), (ColumnProjectionSegment) eachProjection);
+ }
+ });
+ }
+ }
+
+ private static String getColumnName(final ColumnProjectionSegment
columnProjection) {
+ return
columnProjection.getAliasName().orElse(columnProjection.getColumn().getIdentifier().getValue());
+ }
+
+ private static ColumnSegmentBoundInfo createColumnSegmentBoundInfo(final
ColumnSegment segment, final ColumnSegment inputColumnSegment) {
+ IdentifierValue originalDatabase = null == inputColumnSegment ? null :
inputColumnSegment.getColumnBoundInfo().getOriginalDatabase();
+ IdentifierValue originalSchema = null == inputColumnSegment ? null :
inputColumnSegment.getColumnBoundInfo().getOriginalSchema();
+ IdentifierValue segmentOriginalTable =
segment.getColumnBoundInfo().getOriginalTable();
+ IdentifierValue originalTable =
Strings.isNullOrEmpty(segmentOriginalTable.getValue())
+ ? Optional.ofNullable(inputColumnSegment).map(optional ->
optional.getColumnBoundInfo().getOriginalTable()).orElse(segmentOriginalTable)
+ : segmentOriginalTable;
+ IdentifierValue segmentOriginalColumn =
segment.getColumnBoundInfo().getOriginalColumn();
+ IdentifierValue originalColumn =
Optional.ofNullable(inputColumnSegment).map(optional ->
optional.getColumnBoundInfo().getOriginalColumn()).orElse(segmentOriginalColumn);
+ return new ColumnSegmentBoundInfo(new
TableSegmentBoundInfo(originalDatabase, originalSchema), originalTable,
originalColumn);
+ }
+}
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinder.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinder.java
index 521d949a899..3f0cf8244b2 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinder.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinder.java
@@ -32,6 +32,7 @@ import
org.apache.shardingsphere.infra.binder.engine.segment.order.OrderBySegmen
import
org.apache.shardingsphere.infra.binder.engine.segment.predicate.HavingSegmentBinder;
import
org.apache.shardingsphere.infra.binder.engine.segment.predicate.WhereSegmentBinder;
import
org.apache.shardingsphere.infra.binder.engine.segment.projection.ProjectionsSegmentBinder;
+import
org.apache.shardingsphere.infra.binder.engine.segment.with.WithSegmentBinder;
import
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinder;
import
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
import
org.apache.shardingsphere.infra.binder.engine.util.SubqueryTableBindUtils;
@@ -59,6 +60,7 @@ public final class SelectStatementBinder implements
SQLStatementBinder<SelectSta
public SelectStatement bind(final SelectStatement sqlStatement, final
SQLStatementBinderContext binderContext) {
SelectStatement result = copy(sqlStatement);
Multimap<CaseInsensitiveString, TableSegmentBinderContext>
tableBinderContexts = LinkedHashMultimap.create();
+ sqlStatement.getWithSegment().ifPresent(optional ->
result.setWithSegment(WithSegmentBinder.bind(optional, binderContext,
binderContext.getExternalTableBinderContexts())));
Optional<TableSegment> boundTableSegment =
sqlStatement.getFrom().map(optional -> TableSegmentBinder.bind(optional,
binderContext, tableBinderContexts, outerTableBinderContexts));
boundTableSegment.ifPresent(result::setFrom);
result.setProjections(ProjectionsSegmentBinder.bind(sqlStatement.getProjections(),
binderContext, boundTableSegment.orElse(null), tableBinderContexts,
outerTableBinderContexts));
@@ -71,7 +73,6 @@ public final class SelectStatementBinder implements
SQLStatementBinder<SelectSta
sqlStatement.getOrderBy().ifPresent(optional -> result.setOrderBy(
OrderBySegmentBinder.bind(optional, binderContext,
currentTableBinderContexts, tableBinderContexts, outerTableBinderContexts)));
sqlStatement.getHaving().ifPresent(optional ->
result.setHaving(HavingSegmentBinder.bind(optional, binderContext,
currentTableBinderContexts, outerTableBinderContexts)));
- // TODO support other segment bind in select statement
return result;
}
@@ -90,7 +91,6 @@ public final class SelectStatementBinder implements
SQLStatementBinder<SelectSta
sqlStatement.getWindow().ifPresent(result::setWindow);
sqlStatement.getModelSegment().ifPresent(result::setModelSegment);
sqlStatement.getSubqueryType().ifPresent(result::setSubqueryType);
- sqlStatement.getWithSegment().ifPresent(result::setWithSegment);
result.addParameterMarkerSegments(sqlStatement.getParameterMarkerSegments());
result.getCommentSegments().addAll(sqlStatement.getCommentSegments());
result.getVariableNames().addAll(sqlStatement.getVariableNames());
diff --git
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/UpdateStatementBinder.java
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/UpdateStatementBinder.java
index 1de69236fdd..ba4744cc5db 100644
---
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/UpdateStatementBinder.java
+++
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/UpdateStatementBinder.java
@@ -25,6 +25,7 @@ import
org.apache.shardingsphere.infra.binder.engine.segment.assign.AssignmentSe
import
org.apache.shardingsphere.infra.binder.engine.segment.from.TableSegmentBinder;
import
org.apache.shardingsphere.infra.binder.engine.segment.from.context.TableSegmentBinderContext;
import
org.apache.shardingsphere.infra.binder.engine.segment.predicate.WhereSegmentBinder;
+import
org.apache.shardingsphere.infra.binder.engine.segment.with.WithSegmentBinder;
import
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinder;
import
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
import
org.apache.shardingsphere.sql.parser.statement.core.statement.dml.UpdateStatement;
@@ -38,6 +39,7 @@ public final class UpdateStatementBinder implements
SQLStatementBinder<UpdateSta
public UpdateStatement bind(final UpdateStatement sqlStatement, final
SQLStatementBinderContext binderContext) {
UpdateStatement result = copy(sqlStatement);
Multimap<CaseInsensitiveString, TableSegmentBinderContext>
tableBinderContexts = LinkedHashMultimap.create();
+ sqlStatement.getWithSegment().ifPresent(optional ->
result.setWithSegment(WithSegmentBinder.bind(optional, binderContext,
binderContext.getExternalTableBinderContexts())));
result.setTable(TableSegmentBinder.bind(sqlStatement.getTable(),
binderContext, tableBinderContexts, LinkedHashMultimap.create()));
sqlStatement.getFrom().ifPresent(optional ->
result.setFrom(TableSegmentBinder.bind(optional, binderContext,
tableBinderContexts, LinkedHashMultimap.create())));
sqlStatement.getAssignmentSegment().ifPresent(optional ->
result.setSetAssignment(AssignmentSegmentBinder.bind(optional, binderContext,
tableBinderContexts, LinkedHashMultimap.create())));
@@ -50,7 +52,6 @@ public final class UpdateStatementBinder implements
SQLStatementBinder<UpdateSta
UpdateStatement result =
sqlStatement.getClass().getDeclaredConstructor().newInstance();
sqlStatement.getOrderBy().ifPresent(result::setOrderBy);
sqlStatement.getLimit().ifPresent(result::setLimit);
- sqlStatement.getWithSegment().ifPresent(result::setWithSegment);
result.addParameterMarkerSegments(sqlStatement.getParameterMarkerSegments());
result.getCommentSegments().addAll(sqlStatement.getCommentSegments());
return result;
diff --git a/test/it/binder/src/test/resources/cases/dml/select.xml
b/test/it/binder/src/test/resources/cases/dml/select.xml
index 7f03799f5f7..8caabdcb4d9 100644
--- a/test/it/binder/src/test/resources/cases/dml/select.xml
+++ b/test/it/binder/src/test/resources/cases/dml/select.xml
@@ -87,4 +87,210 @@
</simple-table>
</from>
</select>
+
+ <select sql-case-id="select_with_group_by_order_by">
+ <projections start-index="7" stop-index="30">
+ <column-projection name="order_id" start-index="7" stop-index="14">
+ <column-bound>
+ <original-database name="foo_db_1" />
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column name="order_id" start-delimiter="`"
end-delimiter="`" />
+ </column-bound>
+ </column-projection>
+ <aggregation-projection type="COUNT" expression="COUNT(1)"
start-index="17" stop-index="24" alias="count">
+ <parameter>
+ <literal-expression value="1" start-index="23"
stop-index="23" />
+ </parameter>
+ </aggregation-projection>
+ </projections>
+ <from start-index="37" stop-index="45">
+ <simple-table name="t_order" start-index="37" stop-index="45"
alias="o">
+ <table-bound>
+ <original-database name="foo_db_1" />
+ <original-schema name="foo_db_1" />
+ </table-bound>
+ </simple-table>
+ </from>
+ <group-by>
+ <column-item name="order_id" start-index="56" stop-index="63" >
+ <column-bound>
+ <original-database name="foo_db_1" />
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column name="order_id" start-delimiter="`"
end-delimiter="`" />
+ </column-bound>
+ </column-item>
+ </group-by>
+ <having start-index="65" stop-index="80">
+ <expr>
+ <binary-operation-expression start-index="72" stop-index="80">
+ <left>
+ <column name="count" start-index="72" stop-index="76"
/>
+ </left>
+ <operator>></operator>
+ <right>
+ <literal-expression start-index="80" stop-index="80"
value="1" />
+ </right>
+ </binary-operation-expression>
+ </expr>
+ </having>
+ <order-by>
+ <column-item name="order_id" start-index="91" stop-index="98">
+ <column-bound>
+ <original-database name="foo_db_1" />
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column name="order_id" start-delimiter="`"
end-delimiter="`" />
+ </column-bound>
+ </column-item>
+ </order-by>
+ </select>
+
+ <select sql-case-id="select_with_with_clause">
+ <with start-index="0" stop-index="44">
+ <common-table-expression name="t_order_tmp" start-index="5"
stop-index="44">
+ <subquery-expression start-index="5" stop-index="44">
+ <select>
+ <projections start-index="28" stop-index="28">
+ <shorthand-projection start-index="28"
stop-index="28">
+ <actual-projections>
+ <column-projection name="order_id"
start-index="0" stop-index="0" start-delimiter="`" end-delimiter="`">
+ <owner name="o" start-index="0"
stop-index="0" />
+ <column-bound>
+ <original-database name="foo_db_1"
/>
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column name="order_id"
start-delimiter="`" end-delimiter="`" />
+ </column-bound>
+ </column-projection>
+ <column-projection name="user_id"
start-index="0" stop-index="0" start-delimiter="`" end-delimiter="`">
+ <owner name="o" start-index="0"
stop-index="0" />
+ <column-bound>
+ <original-database name="foo_db_1"
/>
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column name="user_id"
start-delimiter="`" end-delimiter="`" />
+ </column-bound>
+ </column-projection>
+ <column-projection name="status"
start-index="0" stop-index="0" start-delimiter="`" end-delimiter="`">
+ <owner name="o" start-index="0"
stop-index="0" />
+ <column-bound>
+ <original-database name="foo_db_1"
/>
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column name="status"
start-delimiter="`" end-delimiter="`" />
+ </column-bound>
+ </column-projection>
+ <column-projection name="merchant_id"
start-index="0" stop-index="0" start-delimiter="`" end-delimiter="`">
+ <owner name="o" start-index="0"
stop-index="0" />
+ <column-bound>
+ <original-database name="foo_db_1"
/>
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column
name="merchant_id" start-delimiter="`" end-delimiter="`" />
+ </column-bound>
+ </column-projection>
+ <column-projection name="remark"
start-index="0" stop-index="0" start-delimiter="`" end-delimiter="`">
+ <owner name="o" start-index="0"
stop-index="0" />
+ <column-bound>
+ <original-database name="foo_db_1"
/>
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column name="remark"
start-delimiter="`" end-delimiter="`" />
+ </column-bound>
+ </column-projection>
+ <column-projection name="creation_date"
start-index="0" stop-index="0" start-delimiter="`" end-delimiter="`">
+ <owner name="o" start-index="0"
stop-index="0" />
+ <column-bound>
+ <original-database name="foo_db_1"
/>
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column
name="creation_date" start-delimiter="`" end-delimiter="`" />
+ </column-bound>
+ </column-projection>
+ </actual-projections>
+ </shorthand-projection>
+ </projections>
+ <from>
+ <simple-table name="t_order" alias="o"
start-index="35" stop-index="43">
+ <table-bound>
+ <original-database name="foo_db_1" />
+ <original-schema name="foo_db_1" />
+ </table-bound>
+ </simple-table>
+ </from>
+ </select>
+ </subquery-expression>
+ </common-table-expression>
+ </with>
+ <projections start-index="53" stop-index="53">
+ <shorthand-projection start-index="53" stop-index="53">
+ <actual-projections>
+ <column-projection name="order_id" start-index="0"
stop-index="0" start-delimiter="`" end-delimiter="`">
+ <owner name="t_order_tmp" start-index="0"
stop-index="0" />
+ <column-bound>
+ <original-database name="foo_db_1" />
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column name="order_id"
start-delimiter="`" end-delimiter="`" />
+ </column-bound>
+ </column-projection>
+ <column-projection name="user_id" start-index="0"
stop-index="0" start-delimiter="`" end-delimiter="`">
+ <owner name="t_order_tmp" start-index="0"
stop-index="0" />
+ <column-bound>
+ <original-database name="foo_db_1" />
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column name="user_id"
start-delimiter="`" end-delimiter="`" />
+ </column-bound>
+ </column-projection>
+ <column-projection name="status" start-index="0"
stop-index="0" start-delimiter="`" end-delimiter="`">
+ <owner name="t_order_tmp" start-index="0"
stop-index="0" />
+ <column-bound>
+ <original-database name="foo_db_1" />
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column name="status" start-delimiter="`"
end-delimiter="`" />
+ </column-bound>
+ </column-projection>
+ <column-projection name="merchant_id" start-index="0"
stop-index="0" start-delimiter="`" end-delimiter="`">
+ <owner name="t_order_tmp" start-index="0"
stop-index="0" />
+ <column-bound>
+ <original-database name="foo_db_1" />
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column name="merchant_id"
start-delimiter="`" end-delimiter="`" />
+ </column-bound>
+ </column-projection>
+ <column-projection name="remark" start-index="0"
stop-index="0" start-delimiter="`" end-delimiter="`">
+ <owner name="t_order_tmp" start-index="0"
stop-index="0" />
+ <column-bound>
+ <original-database name="foo_db_1" />
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column name="remark" start-delimiter="`"
end-delimiter="`" />
+ </column-bound>
+ </column-projection>
+ <column-projection name="creation_date" start-index="0"
stop-index="0" start-delimiter="`" end-delimiter="`">
+ <owner name="t_order_tmp" start-index="0"
stop-index="0" />
+ <column-bound>
+ <original-database name="foo_db_1" />
+ <original-schema name="foo_db_1" />
+ <original-table name="t_order" />
+ <original-column name="creation_date"
start-delimiter="`" end-delimiter="`" />
+ </column-bound>
+ </column-projection>
+ </actual-projections>
+ </shorthand-projection>
+ </projections>
+ <from start-index="55" stop-index="70">
+ <simple-table name="t_order_tmp" start-index="60" stop-index="70">
+ <table-bound>
+ <original-database name="foo_db_1" />
+ <original-schema name="foo_db_1" />
+ </table-bound>
+ </simple-table>
+ </from>
+ </select>
</sql-parser-test-cases>
diff --git a/test/it/binder/src/test/resources/sqls/dml/select.xml
b/test/it/binder/src/test/resources/sqls/dml/select.xml
index aa09790e7ad..cca532f1c5f 100644
--- a/test/it/binder/src/test/resources/sqls/dml/select.xml
+++ b/test/it/binder/src/test/resources/sqls/dml/select.xml
@@ -18,4 +18,6 @@
<sql-cases>
<sql-case id="select_with_shorthand_projection" value="SELECT * FROM
t_order o" db-types="MySQL"/>
+ <sql-case id="select_with_group_by_order_by" value="SELECT order_id,
COUNT(1) count FROM t_order o GROUP BY order_id HAVING count > 1 ORDER BY
order_id" db-types="MySQL"/>
+ <sql-case id="select_with_with_clause" value="WITH t_order_tmp AS (SELECT
* FROM t_order o) SELECT * FROM t_order_tmp" db-types="MySQL"/>
</sql-cases>
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/orderby/OrderByItemAssert.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/orderby/OrderByItemAssert.java
index af1be821b57..6a6df5f5aab 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/orderby/OrderByItemAssert.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/orderby/OrderByItemAssert.java
@@ -25,6 +25,7 @@ import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.ite
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.OrderByItemSegment;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.SQLSegmentAssert;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.bound.ColumnBoundAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.expression.ExpressionAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.identifier.IdentifierValueAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.owner.OwnerAssert;
@@ -106,6 +107,7 @@ public final class OrderByItemAssert {
private static void assertColumnOrderByItem(final SQLCaseAssertContext
assertContext,
final ColumnOrderByItemSegment
actual, final ExpectedColumnOrderByItem expected, final String type) {
IdentifierValueAssert.assertIs(assertContext,
actual.getColumn().getIdentifier(), expected, String.format("%s item", type));
+ ColumnBoundAssert.assertIs(assertContext,
actual.getColumn().getColumnBoundInfo(), expected.getColumnBound());
if (null == expected.getOwner()) {
assertFalse(actual.getColumn().getOwner().isPresent(),
assertContext.getText("Actual owner should not exist."));
} else {
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/orderby/item/impl/ExpectedColumnOrderByItem.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/orderby/item/impl/ExpectedColumnOrderByItem.java
index f150058e9f4..f000d2b5234 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/orderby/item/impl/ExpectedColumnOrderByItem.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/orderby/item/impl/ExpectedColumnOrderByItem.java
@@ -20,6 +20,7 @@ package
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.
import lombok.Getter;
import lombok.Setter;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.ExpectedIdentifierSQLSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.bound.ExpectedColumnBoundInfo;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.orderby.item.ExpectedOrderByItem;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.table.ExpectedOwner;
@@ -38,4 +39,7 @@ public final class ExpectedColumnOrderByItem extends
ExpectedOrderByItem impleme
@XmlElement
private ExpectedOwner owner;
+
+ @XmlElement(name = "column-bound")
+ private ExpectedColumnBoundInfo columnBound;
}