This is an automated email from the ASF dual-hosted git repository.
terrymanu 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 c5102c6814e Simplify binder predicates and statement copying (#40337)
c5102c6814e is described below
commit c5102c6814e8ebc069ee9eb0a85f51f3e6dfb851
Author: Liang Zhang <[email protected]>
AuthorDate: Thu Oct 22 19:12:27 2026 +0800
Simplify binder predicates and statement copying (#40337)
---
.../select/pagination/PaginationContext.java | 3 +-
.../type/dml/SelectStatementBaseContext.java | 26 +++++---
.../dml/expression/type/ColumnSegmentBinder.java | 2 +-
.../dml/projection/ProjectionsSegmentBinder.java | 6 +-
.../statement/dml/InsertStatementBinder.java | 28 +++-----
.../statement/dml/SelectStatementBinder.java | 22 ++-----
.../type/dml/SelectStatementContextTest.java | 77 ++++++++++++++++++++++
.../statement/dml/InsertStatementBinderTest.java | 24 +++++++
.../statement/dml/SelectStatementBinderTest.java | 60 +++++++++++++++++
9 files changed, 202 insertions(+), 46 deletions(-)
diff --git
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/PaginationContext.java
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/PaginationContext.java
index bc5b9820365..1e228625caf 100644
---
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/PaginationContext.java
+++
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/PaginationContext.java
@@ -72,8 +72,7 @@ public final class PaginationContext {
return ((ExpressionRowNumberValueSegment)
paginationValueSegment).getValue(params);
}
if (paginationValueSegment instanceof
ExpressionPaginationValueSegment) {
- Long result =
getValueFromExpression(((ExpressionPaginationValueSegment)
paginationValueSegment).getExpression(), params);
- return result;
+ return getValueFromExpression(((ExpressionPaginationValueSegment)
paginationValueSegment).getExpression(), params);
}
return ((NumberLiteralPaginationValueSegment)
paginationValueSegment).getValue();
}
diff --git
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementBaseContext.java
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementBaseContext.java
index d6909a17635..1807f55eb30 100644
---
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementBaseContext.java
+++
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementBaseContext.java
@@ -408,11 +408,17 @@ public final class SelectStatementBaseContext implements
SQLStatementContext {
ColumnSegmentBoundInfo orderByBoundInfo =
orderByColumn.getColumnBoundInfo();
ColumnSegmentBoundInfo groupByOtherUsingBoundInfo =
groupByColumn.getOtherUsingColumnBoundInfo();
ColumnSegmentBoundInfo orderByOtherUsingBoundInfo =
orderByColumn.getOtherUsingColumnBoundInfo();
- return
groupByColumn.getQualifiedName().equals(orderByColumn.getQualifiedName()) &&
null != groupByBoundInfo && null != orderByBoundInfo
- && isSameColumnBoundInfo(groupByBoundInfo, orderByBoundInfo)
- && (null == groupByOtherUsingBoundInfo ? null ==
orderByOtherUsingBoundInfo
- : null != orderByOtherUsingBoundInfo &&
isSameColumnBoundInfo(groupByOtherUsingBoundInfo, orderByOtherUsingBoundInfo))
- && !isAmbiguousProjectionReference(groupByColumn);
+ if
(!groupByColumn.getQualifiedName().equals(orderByColumn.getQualifiedName()) ||
null == groupByBoundInfo || null == orderByBoundInfo
+ || !isSameColumnBoundInfo(groupByBoundInfo, orderByBoundInfo))
{
+ return false;
+ }
+ if (null == groupByOtherUsingBoundInfo && null !=
orderByOtherUsingBoundInfo) {
+ return false;
+ }
+ if (null != groupByOtherUsingBoundInfo && (null ==
orderByOtherUsingBoundInfo ||
!isSameColumnBoundInfo(groupByOtherUsingBoundInfo,
orderByOtherUsingBoundInfo))) {
+ return false;
+ }
+ return !isAmbiguousProjectionReference(groupByColumn);
}
private boolean isAmbiguousProjectionReference(final ColumnSegment column)
{
@@ -436,9 +442,13 @@ public final class SelectStatementBaseContext implements
SQLStatementContext {
}
private boolean isSameColumnBoundInfo(final ColumnSegmentBoundInfo left,
final ColumnSegmentBoundInfo right) {
- return null != left && null != right && left.getTableSourceType() ==
right.getTableSourceType()
- && Objects.equals(left.getOriginalDatabase(),
right.getOriginalDatabase()) && Objects.equals(left.getOriginalSchema(),
right.getOriginalSchema())
- && Objects.equals(left.getOriginalTable(),
right.getOriginalTable()) && Objects.equals(left.getOriginalColumn(),
right.getOriginalColumn());
+ if (null == left || null == right || left.getTableSourceType() !=
right.getTableSourceType()) {
+ return false;
+ }
+ if (!Objects.equals(left.getOriginalDatabase(),
right.getOriginalDatabase()) || !Objects.equals(left.getOriginalSchema(),
right.getOriginalSchema())) {
+ return false;
+ }
+ return Objects.equals(left.getOriginalTable(),
right.getOriginalTable()) && Objects.equals(left.getOriginalColumn(),
right.getOriginalColumn());
}
/**
diff --git
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ColumnSegmentBinder.java
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ColumnSegmentBinder.java
index 63d4c5235f6..baf0dce1f5c 100644
---
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ColumnSegmentBinder.java
+++
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/expression/type/ColumnSegmentBinder.java
@@ -100,7 +100,6 @@ public final class ColumnSegmentBinder {
return segment;
}
ColumnSegment columnSegment = createNestedObjectColumnSegment(segment,
parentSegmentType, binderContext, tableBinderContexts,
outerTableBinderContexts).orElse(segment);
- ColumnSegment result = copy(columnSegment);
Collection<TableSegmentBinderContext> tableSegmentBinderContexts =
getTableSegmentBinderContexts(columnSegment,
parentSegmentType, binderContext, tableBinderContexts,
outerTableBinderContexts);
ColumnSegmentInfo columnSegmentInfo =
getColumnSegmentInfo(columnSegment, parentSegmentType,
tableSegmentBinderContexts, outerTableBinderContexts, binderContext);
@@ -110,6 +109,7 @@ public final class ColumnSegmentBinder {
}
ShardingSpherePreconditions.checkState(inputColumnSegment.isPresent()
|| isSkipColumnBind(tableSegmentBinderContexts,
outerTableBinderContexts.values()),
() -> new ColumnNotFoundException(segment.getExpression(),
SEGMENT_TYPE_MESSAGES.getOrDefault(parentSegmentType,
UNKNOWN_SEGMENT_TYPE_MESSAGE)));
+ ColumnSegment result = copy(columnSegment);
inputColumnSegment.ifPresent(optional ->
result.setVariable(optional.isVariable()));
columnSegment.getOwner().ifPresent(optional ->
result.setOwner(bindOwnerTableContext(optional,
inputColumnSegment.orElse(null))));
result.setColumnBoundInfo(createColumnSegmentBoundInfo(columnSegment,
inputColumnSegment.orElse(null), columnSegmentInfo.getTableSourceType()));
diff --git
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/projection/ProjectionsSegmentBinder.java
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/projection/ProjectionsSegmentBinder.java
index a60385cdb54..a8ad7a12ad6 100644
---
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/projection/ProjectionsSegmentBinder.java
+++
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/projection/ProjectionsSegmentBinder.java
@@ -176,8 +176,10 @@ public final class ProjectionsSegmentBinder {
}
ColumnSegment columnSegment = ((ColumnProjectionSegment)
projectionSegment).getColumn();
String columnName = columnSegment.getIdentifier().getValue();
- return !columnSegment.getOwner().isPresent() && (null ==
columnSegment.getNestedObjectAttributes() ||
columnSegment.getNestedObjectAttributes().isEmpty())
- && (isTableAliasOrName(boundTableSegment, columnName) ||
tableBinderContexts.containsKey(CaseInsensitiveString.of(columnName)));
+ if (columnSegment.getOwner().isPresent() || null !=
columnSegment.getNestedObjectAttributes() &&
!columnSegment.getNestedObjectAttributes().isEmpty()) {
+ return false;
+ }
+ return isTableAliasOrName(boundTableSegment, columnName) ||
tableBinderContexts.containsKey(CaseInsensitiveString.of(columnName));
}
private static boolean isSupportWholeRowProjection(final
SQLStatementBinderContext binderContext) {
diff --git
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/InsertStatementBinder.java
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/InsertStatementBinder.java
index ec71a3d1771..5ac19877f55 100644
---
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/InsertStatementBinder.java
+++
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/InsertStatementBinder.java
@@ -69,7 +69,16 @@ public final class InsertStatementBinder implements
SQLStatementBinder<InsertSta
SubquerySegment boundInsertSelect =
sqlStatement.getInsertSelect().map(optional ->
SubquerySegmentBinder.bind(optional, binderContext,
tableBinderContexts)).orElse(null);
OnDuplicateKeyColumnsSegment boundOnDuplicateKeyColumns =
sqlStatement.getOnDuplicateKeyColumns()
.map(optional -> AssignmentSegmentBinder.bind(optional,
binderContext, tableBinderContexts, outerTableBinderContexts)).orElse(null);
- InsertStatement result = copy(sqlStatement, boundWith, boundTable,
boundInsertColumns, boundSetAssignment, boundInsertSelect,
boundOnDuplicateKeyColumns, boundValues);
+ InsertStatement result =
InsertStatement.builder().databaseType(sqlStatement.getDatabaseType()).table(boundTable).insertColumns(boundInsertColumns)
+
.insertSelect(boundInsertSelect).setAssignment(boundSetAssignment).onDuplicateKeyColumns(boundOnDuplicateKeyColumns)
+
.valueReference(sqlStatement.getValueReference().orElse(null)).returning(sqlStatement.getReturning().orElse(null))
+ .errorLogging(sqlStatement.getErrorLogging().orElse(null))
+
.output(sqlStatement.getOutput().orElse(null)).with(boundWith).multiTableInsertType(sqlStatement.getMultiTableInsertType().orElse(null))
+
.multiTableInsertInto(sqlStatement.getMultiTableInsertInto().orElse(null)).multiTableConditionalInto(sqlStatement.getMultiTableConditionalInto().orElse(null))
+
.where(sqlStatement.getWhere().orElse(null)).exec(sqlStatement.getExec().orElse(null)).withTableHint(sqlStatement.getWithTableHint().orElse(null))
+
.rowSetFunction(sqlStatement.getRowSetFunction().orElse(null)).ignore(sqlStatement.isIgnore()).replace(sqlStatement.isReplace())
+ .overwrite(sqlStatement.isOverwrite()).values(new
LinkedList<>(boundValues)).build();
+ SQLStatementCopyUtils.copyAttributes(sqlStatement, result);
if (!sqlStatement.getInsertColumns().isPresent() ||
sqlStatement.getInsertColumns().get().getColumns().isEmpty()) {
tableBinderContexts.values().forEach(each ->
result.getDerivedInsertColumns().addAll(getVisibleColumns(each.getProjectionSegments())));
}
@@ -90,23 +99,6 @@ public final class InsertStatementBinder implements
SQLStatementBinder<InsertSta
return result;
}
- private InsertStatement copy(final InsertStatement sqlStatement, final
WithSegment boundWith, final SimpleTableSegment boundTable,
- final InsertColumnsSegment
boundInsertColumns, final SetAssignmentSegment boundSetAssignment, final
SubquerySegment boundInsertSelect,
- final OnDuplicateKeyColumnsSegment
boundOnDuplicateKeyColumns,
- final Collection<InsertValuesSegment>
boundValues) {
- InsertStatement result =
InsertStatement.builder().databaseType(sqlStatement.getDatabaseType()).table(boundTable).insertColumns(boundInsertColumns)
-
.insertSelect(boundInsertSelect).setAssignment(boundSetAssignment).onDuplicateKeyColumns(boundOnDuplicateKeyColumns)
-
.valueReference(sqlStatement.getValueReference().orElse(null)).returning(sqlStatement.getReturning().orElse(null))
- .errorLogging(sqlStatement.getErrorLogging().orElse(null))
-
.output(sqlStatement.getOutput().orElse(null)).with(boundWith).multiTableInsertType(sqlStatement.getMultiTableInsertType().orElse(null))
-
.multiTableInsertInto(sqlStatement.getMultiTableInsertInto().orElse(null)).multiTableConditionalInto(sqlStatement.getMultiTableConditionalInto().orElse(null))
-
.where(sqlStatement.getWhere().orElse(null)).exec(sqlStatement.getExec().orElse(null)).withTableHint(sqlStatement.getWithTableHint().orElse(null))
-
.rowSetFunction(sqlStatement.getRowSetFunction().orElse(null)).ignore(sqlStatement.isIgnore()).replace(sqlStatement.isReplace())
- .overwrite(sqlStatement.isOverwrite()).values(new
LinkedList<>(boundValues)).build();
- SQLStatementCopyUtils.copyAttributes(sqlStatement, result);
- return result;
- }
-
private Collection<ColumnSegment> getVisibleColumns(final
Collection<ProjectionSegment> projectionSegments) {
return projectionSegments.stream().filter(each -> each instanceof
ColumnProjectionSegment
&& each.isVisible()).map(each -> ((ColumnProjectionSegment)
each).getColumn()).collect(Collectors.toList());
diff --git
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinder.java
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinder.java
index 2db9faa44be..748c09aa52c 100644
---
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinder.java
+++
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinder.java
@@ -99,8 +99,13 @@ public final class SelectStatementBinder implements
SQLStatementBinder<SelectSta
sqlStatement.getHaving().map(optional ->
HavingSegmentBinder.bind(optional, binderContext, currentTableBinderContexts,
tableBinderContexts, outerTableBinderContexts)).orElse(null);
WindowSegment boundWindow = sqlStatement.getWindow().map(optional ->
bindWindowSegment(optional, binderContext, tableBinderContexts,
outerTableBinderContexts)).orElse(null);
Collection<FunctionSegment> boundTransformSegments =
bindTransformSegments(sqlStatement, binderContext, tableBinderContexts,
outerTableBinderContexts);
- return copy(sqlStatement, boundWith, boundFrom.orElse(null),
boundProjections, boundWhere,
- boundHierarchicalQuery, boundCombine, boundLock, boundGroupBy,
boundOrderBy, boundHaving, boundModel, boundWindow, boundTransformSegments);
+ SelectStatement result =
SelectStatement.builder().databaseType(sqlStatement.getDatabaseType()).with(boundWith).from(boundFrom.orElse(null)).projections(boundProjections)
+
.where(boundWhere).hierarchicalQuery(boundHierarchicalQuery).combine(boundCombine).lock(boundLock).groupBy(boundGroupBy).orderBy(boundOrderBy).having(boundHaving)
+
.limit(sqlStatement.getLimit().orElse(null)).window(boundWindow).model(boundModel)
+
.subqueryType(sqlStatement.getSubqueryType().orElse(null)).build();
+ result.getTransformSegments().addAll(boundTransformSegments);
+ SQLStatementCopyUtils.copyAttributes(sqlStatement, result);
+ return result;
}
private ModelSegment bindModelSegment(final ModelSegment segment, final
SQLStatementBinderContext binderContext,
@@ -185,19 +190,6 @@ public final class SelectStatementBinder implements
SQLStatementBinder<SelectSta
return result;
}
- private SelectStatement copy(final SelectStatement sqlStatement, final
WithSegment boundWith, final TableSegment boundFrom, final ProjectionsSegment
boundProjections,
- final WhereSegment boundWhere, final
HierarchicalQuerySegment boundHierarchicalQuery, final CombineSegment
boundCombine,
- final LockSegment boundLock, final
GroupBySegment boundGroupBy, final OrderBySegment boundOrderBy, final
HavingSegment boundHaving,
- final ModelSegment boundModel, final
WindowSegment boundWindow, final Collection<FunctionSegment>
boundTransformSegments) {
- SelectStatement result =
SelectStatement.builder().databaseType(sqlStatement.getDatabaseType()).with(boundWith).from(boundFrom).projections(boundProjections)
-
.where(boundWhere).hierarchicalQuery(boundHierarchicalQuery).combine(boundCombine).lock(boundLock).groupBy(boundGroupBy).orderBy(boundOrderBy).having(boundHaving)
-
.limit(sqlStatement.getLimit().orElse(null)).window(boundWindow).model(boundModel)
-
.subqueryType(sqlStatement.getSubqueryType().orElse(null)).build();
- result.getTransformSegments().addAll(boundTransformSegments);
- SQLStatementCopyUtils.copyAttributes(sqlStatement, result);
- return result;
- }
-
private Collection<FunctionSegment> bindTransformSegments(final
SelectStatement sqlStatement, final SQLStatementBinderContext binderContext,
final
Multimap<CaseInsensitiveString, TableSegmentBinderContext> tableBinderContexts,
final
Multimap<CaseInsensitiveString, TableSegmentBinderContext>
outerTableBinderContexts) {
diff --git
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementContextTest.java
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementContextTest.java
index 02e9c029f36..c1a90873df4 100644
---
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementContextTest.java
+++
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementContextTest.java
@@ -33,6 +33,7 @@ import
org.apache.shardingsphere.sql.parser.statement.core.enums.CombineType;
import
org.apache.shardingsphere.sql.parser.statement.core.enums.OrderDirection;
import
org.apache.shardingsphere.sql.parser.statement.core.enums.ParameterMarkerType;
import org.apache.shardingsphere.sql.parser.statement.core.enums.SubqueryType;
+import
org.apache.shardingsphere.sql.parser.statement.core.enums.TableSourceType;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.combine.CombineSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BinaryOperationExpression;
@@ -70,12 +71,16 @@ import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table
import
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
import
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.Optional;
import java.util.Properties;
+import java.util.stream.Stream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@@ -193,6 +198,78 @@ class SelectStatementContextTest {
assertTrue(selectStatementContext.isSameGroupByAndOrderByItems());
}
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("getDifferentColumnBoundInfos")
+ void
assertIsNotSameGroupByAndOrderByItemsWithDifferentColumnBoundInfo(final String
scenario, final ColumnSegmentBoundInfo groupByBoundInfo, final
ColumnSegmentBoundInfo orderByBoundInfo) {
+ ColumnSegment groupByColumn = new ColumnSegment(0, 0, new
IdentifierValue("id"));
+ groupByColumn.setColumnBoundInfo(groupByBoundInfo);
+ ColumnSegment orderByColumn = new ColumnSegment(0, 0, new
IdentifierValue("id"));
+ orderByColumn.setColumnBoundInfo(orderByBoundInfo);
+ SelectStatementContext selectStatementContext =
createColumnOrderByContext(groupByColumn, orderByColumn);
+ assertFalse(selectStatementContext.isSameGroupByAndOrderByItems(),
scenario);
+ }
+
+ private SelectStatementContext createColumnOrderByContext(final
ColumnSegment groupByColumn, final ColumnSegment orderByColumn) {
+ SelectStatement selectStatement =
SelectStatement.builder().databaseType(databaseType).projections(new
ProjectionsSegment(0, 0))
+ .groupBy(new GroupBySegment(0, 0,
Collections.singletonList(new ColumnOrderByItemSegment(groupByColumn,
OrderDirection.ASC, NullsOrderType.LAST))))
+ .orderBy(new OrderBySegment(0, 0,
Collections.singletonList(new ColumnOrderByItemSegment(orderByColumn,
OrderDirection.DESC, NullsOrderType.LAST)))).build();
+ return createSelectStatementContext(selectStatement);
+ }
+
+ private static Stream<Arguments> getDifferentColumnBoundInfos() {
+ ColumnSegmentBoundInfo boundInfo =
createColumnBoundInfo(TableSourceType.PHYSICAL_TABLE, "foo_db", "foo_schema",
"foo_table", "foo_column");
+ return Stream.of(
+ Arguments.of("source", boundInfo,
createColumnBoundInfo(TableSourceType.TEMPORARY_TABLE, "foo_db", "foo_schema",
"foo_table", "foo_column")),
+ Arguments.of("database", boundInfo,
createColumnBoundInfo(TableSourceType.PHYSICAL_TABLE, "bar_db", "foo_schema",
"foo_table", "foo_column")),
+ Arguments.of("schema", boundInfo,
createColumnBoundInfo(TableSourceType.PHYSICAL_TABLE, "foo_db", "bar_schema",
"foo_table", "foo_column")),
+ Arguments.of("table", boundInfo,
createColumnBoundInfo(TableSourceType.PHYSICAL_TABLE, "foo_db", "foo_schema",
"bar_table", "foo_column")),
+ Arguments.of("column", boundInfo,
createColumnBoundInfo(TableSourceType.PHYSICAL_TABLE, "foo_db", "foo_schema",
"foo_table", "bar_column")),
+ Arguments.of("quoted database", boundInfo,
createColumnBoundInfo(TableSourceType.PHYSICAL_TABLE, "\"foo_db\"",
"foo_schema", "foo_table", "foo_column")),
+ Arguments.of("quoted schema", boundInfo,
createColumnBoundInfo(TableSourceType.PHYSICAL_TABLE, "foo_db",
"\"foo_schema\"", "foo_table", "foo_column")),
+ Arguments.of("quoted table", boundInfo,
createColumnBoundInfo(TableSourceType.PHYSICAL_TABLE, "foo_db", "foo_schema",
"\"foo_table\"", "foo_column")),
+ Arguments.of("quoted column", boundInfo,
createColumnBoundInfo(TableSourceType.PHYSICAL_TABLE, "foo_db", "foo_schema",
"foo_table", "\"foo_column\"")),
+ Arguments.of("missing group by binding", null, boundInfo),
+ Arguments.of("missing order by binding", boundInfo, null),
+ Arguments.of("missing both bindings", null, null));
+ }
+
+ private static ColumnSegmentBoundInfo createColumnBoundInfo(final
TableSourceType sourceType, final String databaseName, final String schemaName,
final String tableName, final String columnName) {
+ return new ColumnSegmentBoundInfo(new TableSegmentBoundInfo(new
IdentifierValue(databaseName), new IdentifierValue(schemaName)),
+ new IdentifierValue(tableName), new
IdentifierValue(columnName), sourceType);
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("getDifferentOtherUsingColumnBoundInfos")
+ void
assertIsNotSameGroupByAndOrderByItemsWithDifferentOtherUsingColumnBoundInfo(final
String scenario,
+
final ColumnSegmentBoundInfo groupByBoundInfo, final
ColumnSegmentBoundInfo orderByBoundInfo) {
+ ColumnSegment groupByColumn = new ColumnSegment(0, 0, new
IdentifierValue("id"));
+ groupByColumn.setOtherUsingColumnBoundInfo(groupByBoundInfo);
+ ColumnSegment orderByColumn = new ColumnSegment(0, 0, new
IdentifierValue("id"));
+ orderByColumn.setOtherUsingColumnBoundInfo(orderByBoundInfo);
+ SelectStatementContext selectStatementContext =
createColumnOrderByContext(groupByColumn, orderByColumn);
+ assertFalse(selectStatementContext.isSameGroupByAndOrderByItems(),
scenario);
+ }
+
+ private static Stream<Arguments> getDifferentOtherUsingColumnBoundInfos() {
+ ColumnSegmentBoundInfo boundInfo = new ColumnSegmentBoundInfo(new
IdentifierValue("foo_column"));
+ return Stream.of(
+ Arguments.of("only group by has other using binding",
boundInfo, null),
+ Arguments.of("only order by has other using binding", null,
boundInfo),
+ Arguments.of("different other using column", boundInfo, new
ColumnSegmentBoundInfo(new IdentifierValue("bar_column"))));
+ }
+
+ @Test
+ void assertIsSameGroupByAndOrderByItemsWithSameOtherUsingColumnBoundInfo()
{
+ ColumnSegment groupByColumn = new ColumnSegment(0, 0, new
IdentifierValue("id"));
+
groupByColumn.setColumnBoundInfo(createColumnBoundInfo(TableSourceType.PHYSICAL_TABLE,
"\"foo_db\"", "\"foo_schema\"", "\"foo_table\"", "\"foo_column\""));
+ groupByColumn.setOtherUsingColumnBoundInfo(new
ColumnSegmentBoundInfo(new IdentifierValue("foo_column")));
+ ColumnSegment orderByColumn = new ColumnSegment(0, 0, new
IdentifierValue("id"));
+
orderByColumn.setColumnBoundInfo(createColumnBoundInfo(TableSourceType.PHYSICAL_TABLE,
"\"foo_db\"", "\"foo_schema\"", "\"foo_table\"", "\"foo_column\""));
+ orderByColumn.setOtherUsingColumnBoundInfo(new
ColumnSegmentBoundInfo(new IdentifierValue("foo_column")));
+ SelectStatementContext selectStatementContext =
createColumnOrderByContext(groupByColumn, orderByColumn);
+ assertTrue(selectStatementContext.isSameGroupByAndOrderByItems());
+ }
+
@Test
void assertIsSameGroupByAndOrderByItemsWithGeneratedOrderBy() {
SelectStatement selectStatement =
SelectStatement.builder().databaseType(databaseType).projections(new
ProjectionsSegment(0, 0))
diff --git
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/InsertStatementBinderTest.java
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/InsertStatementBinderTest.java
index e7d6bb3504d..8e2e9d6a2d0 100644
---
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/InsertStatementBinderTest.java
+++
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/InsertStatementBinderTest.java
@@ -32,12 +32,14 @@ import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.In
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.OnDuplicateKeyColumnsSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BinaryOperationExpression;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.LiteralExpressionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubqueryExpressionSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment;
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.ProjectionsSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.WhereSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.CommentSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.OwnerSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableNameSegment;
@@ -53,6 +55,7 @@ import java.util.Collections;
import java.util.Iterator;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isA;
import static org.hamcrest.Matchers.not;
@@ -108,6 +111,27 @@ class InsertStatementBinderTest {
assertThat(statusColumnSegment.getColumnBoundInfo().getOriginalColumn().getValue(),
is("status"));
}
+ @Test
+ void assertBindWithStatementAttributes() {
+ ParameterMarkerExpressionSegment parameterMarker = new
ParameterMarkerExpressionSegment(0, 0, 0);
+ InsertStatement insertStatement =
InsertStatement.builder().databaseType(databaseType)
+ .table(new SimpleTableSegment(new TableNameSegment(0, 0, new
IdentifierValue("t_order"))))
+ .insertColumns(new InsertColumnsSegment(0, 0,
Arrays.asList(new ColumnSegment(0, 0, new IdentifierValue("order_id")),
+ new ColumnSegment(0, 0, new
IdentifierValue("user_id")), new ColumnSegment(0, 0, new
IdentifierValue("status")))))
+ .values(Collections.singletonList(new InsertValuesSegment(0, 0,
+ Arrays.asList(parameterMarker, new ColumnSegment(0, 0,
new IdentifierValue("foo_variable")), new LiteralExpressionSegment(0, 0,
"OK")))))
+ .build();
+ CommentSegment comment = new CommentSegment("/* foo_comment */", 0,
16);
+
insertStatement.addParameterMarkers(Collections.singletonList(parameterMarker));
+ insertStatement.getVariableNames().add("foo_variable");
+ insertStatement.getComments().add(comment);
+ InsertStatement actual = new
InsertStatementBinder().bind(insertStatement, new
SQLStatementBinderContext(createMetaData(), "foo_db", new HintValueContext(),
insertStatement));
+ assertThat(actual.getParameterMarkers(), contains(parameterMarker));
+ assertThat(actual.getParameterCount(), is(1));
+ assertThat(actual.getVariableNames(), contains("foo_variable"));
+ assertThat(actual.getComments(), contains(comment));
+ }
+
@Test
void assertBindInsertSelectWithColumns() {
ProjectionsSegment projections = new ProjectionsSegment(0, 0);
diff --git
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinderTest.java
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinderTest.java
index fcdc716e627..581054f2c01 100644
---
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinderTest.java
+++
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinderTest.java
@@ -23,6 +23,7 @@ import
org.apache.shardingsphere.database.connector.core.metadata.database.metad
import
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
import
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
+import
org.apache.shardingsphere.infra.exception.kernel.metadata.ColumnNotFoundException;
import org.apache.shardingsphere.infra.hint.HintValueContext;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereColumn;
@@ -40,6 +41,7 @@ import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.Func
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ListExpression;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.complex.CommonTableExpressionSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.LiteralExpressionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubqueryExpressionSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.AggregationProjectionSegment;
@@ -54,6 +56,7 @@ import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.ite
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.HierarchicalQuerySegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.WhereSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.AliasSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.CommentSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.OwnerSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.WindowItemSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.WindowSegment;
@@ -65,6 +68,8 @@ import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table
import
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
import
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
import org.mockito.MockedStatic;
import java.sql.Types;
@@ -75,9 +80,11 @@ import java.util.LinkedList;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isA;
import static org.hamcrest.Matchers.not;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
@@ -130,6 +137,25 @@ class SelectStatementBinderTest {
.getColumnBoundInfo().getOriginalTable().getValue(),
is("t_order"));
}
+ @Test
+ void assertBindWithStatementAttributes() {
+ ParameterMarkerExpressionSegment parameterMarker = new
ParameterMarkerExpressionSegment(0, 0, 0);
+ ProjectionsSegment projections = new ProjectionsSegment(0, 0);
+ projections.getProjections().add(new ColumnProjectionSegment(new
ColumnSegment(0, 0, new IdentifierValue("foo_variable"))));
+ BinaryOperationExpression predicate = new BinaryOperationExpression(0,
0, new ColumnSegment(0, 0, new IdentifierValue("order_id")), parameterMarker,
"=", "order_id = ?");
+ SelectStatement selectStatement =
SelectStatement.builder().databaseType(databaseType).projections(projections)
+ .from(new SimpleTableSegment(new TableNameSegment(0, 0, new
IdentifierValue("t_order")))).where(new WhereSegment(0, 0, predicate)).build();
+ CommentSegment comment = new CommentSegment("/* foo_comment */", 0,
16);
+
selectStatement.addParameterMarkers(Collections.singletonList(parameterMarker));
+ selectStatement.getVariableNames().add("foo_variable");
+ selectStatement.getComments().add(comment);
+ SelectStatement actual = new
SelectStatementBinder().bind(selectStatement, new
SQLStatementBinderContext(mockMetaData(), "foo_db", new HintValueContext(),
selectStatement));
+ assertThat(actual.getParameterMarkers(), contains(parameterMarker));
+ assertThat(actual.getParameterCount(), is(1));
+ assertThat(actual.getVariableNames(), contains("foo_variable"));
+ assertThat(actual.getComments(), contains(comment));
+ }
+
@Test
void assertBindWholeRowProjection() {
DatabaseType protocolType = mock(DatabaseType.class);
@@ -151,6 +177,40 @@ class SelectStatementBinderTest {
}
}
+ @ParameterizedTest(name = "{0}: qualified={1}, nested={2}")
+ @CsvSource({"PostgreSQL, true, false", "PostgreSQL, false, true",
"FIXTURE, false, false"})
+ void assertBindWholeRowProjectionExclusions(final String databaseTypeName,
final boolean qualified, final boolean nested) {
+ ColumnSegment column = new ColumnSegment(0, 0, new
IdentifierValue("o"));
+ if (qualified) {
+ column.setOwner(new OwnerSegment(0, 0, new IdentifierValue("o")));
+ }
+ if (nested) {
+ column.setNestedObjectAttributes(Collections.singletonList(new
IdentifierValue("foo_attribute")));
+ }
+ ProjectionsSegment projections = new ProjectionsSegment(0, 0);
+ projections.getProjections().add(new ColumnProjectionSegment(column));
+ SimpleTableSegment table = createAliasedSimpleTableSegment("t_order",
"o");
+ table.setOwner(new OwnerSegment(0, 0, new IdentifierValue("foo_db")));
+ SelectStatement selectStatement =
SelectStatement.builder().databaseType(TypedSPILoader.getService(DatabaseType.class,
databaseTypeName)).projections(projections).from(table).build();
+ SQLStatementBinderContext binderContext = new
SQLStatementBinderContext(mockMetaData(), "foo_db", new HintValueContext(),
selectStatement);
+ assertThrows(ColumnNotFoundException.class, () -> new
SelectStatementBinder().bind(selectStatement, binderContext));
+ }
+
+ @Test
+ void assertBindWholeRowProjectionWithSameNameColumn() {
+ ProjectionsSegment projections = new ProjectionsSegment(0, 0);
+ projections.getProjections().add(new ColumnProjectionSegment(new
ColumnSegment(0, 0, new IdentifierValue("order_id"))));
+ SimpleTableSegment table = createAliasedSimpleTableSegment("t_order",
"order_id");
+ table.setOwner(new OwnerSegment(0, 0, new IdentifierValue("foo_db")));
+ SelectStatement selectStatement =
SelectStatement.builder().databaseType(TypedSPILoader.getService(DatabaseType.class,
"PostgreSQL")).projections(projections).from(table).build();
+ SelectStatement actual = new
SelectStatementBinder().bind(selectStatement, new
SQLStatementBinderContext(mockMetaData(), "foo_db", new HintValueContext(),
selectStatement));
+ ProjectionSegment actualProjection =
actual.getProjections().getProjections().iterator().next();
+ assertThat(actualProjection, isA(ColumnProjectionSegment.class));
+ ColumnSegment actualColumn = ((ColumnProjectionSegment)
actualProjection).getColumn();
+
assertThat(actualColumn.getColumnBoundInfo().getOriginalTable().getValue(),
is("t_order"));
+
assertThat(actualColumn.getColumnBoundInfo().getOriginalColumn().getValue(),
is("order_id"));
+ }
+
@Test
void assertBindHierarchicalQuery() {
ProjectionsSegment projections = new ProjectionsSegment(0, 0);