This is an automated email from the ASF dual-hosted git repository.
zhangliang 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 d92e1d42a09 Add more test cases on ColumnExtractorTest (#37507)
d92e1d42a09 is described below
commit d92e1d42a09b630be056618fe5c2b8da9a018e92
Author: Liang Zhang <[email protected]>
AuthorDate: Thu Dec 25 16:08:26 2025 +0800
Add more test cases on ColumnExtractorTest (#37507)
* Add more test cases on ColumnExtractorTest
* Add more test cases on ColumnExtractorTest
* Add more test cases on ColumnExtractorTest
---
.../core/extractor/ColumnExtractorTest.java | 285 ++++++++++++++++++---
1 file changed, 251 insertions(+), 34 deletions(-)
diff --git
a/parser/sql/statement/core/src/test/java/org/apache/shardingsphere/sql/parser/statement/core/extractor/ColumnExtractorTest.java
b/parser/sql/statement/core/src/test/java/org/apache/shardingsphere/sql/parser/statement/core/extractor/ColumnExtractorTest.java
index 9d7afecb901..0fd212836d2 100644
---
a/parser/sql/statement/core/src/test/java/org/apache/shardingsphere/sql/parser/statement/core/extractor/ColumnExtractorTest.java
+++
b/parser/sql/statement/core/src/test/java/org/apache/shardingsphere/sql/parser/statement/core/extractor/ColumnExtractorTest.java
@@ -17,68 +17,285 @@
package org.apache.shardingsphere.sql.parser.statement.core.extractor;
+import
org.apache.shardingsphere.database.connector.core.metadata.database.enums.NullsOrderType;
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import
org.apache.shardingsphere.sql.parser.statement.core.enums.AggregationType;
+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.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.BetweenExpression;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BinaryOperationExpression;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.FunctionSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.InExpression;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.RowExpression;
+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.subquery.SubquerySegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.AggregationProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ColumnProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.DatetimeProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ExpressionProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.IntervalExpressionProjection;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionsSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.SubqueryProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.join.OuterJoinExpression;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.GroupBySegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.OrderBySegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.ColumnOrderByItemSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.ExpressionOrderByItemSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.OrderByItemSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.HavingSegment;
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.table.CollectionTableSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.JoinTableSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SubqueryTableSegment;
+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.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.ArgumentsProvider;
-import org.junit.jupiter.params.provider.ArgumentsSource;
-import org.junit.jupiter.params.support.ParameterDeclarations;
+import org.junit.jupiter.params.provider.MethodSource;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.mock;
class ColumnExtractorTest {
- private static final ColumnSegment COLUMN_SEGMENT = new ColumnSegment(35,
42, new IdentifierValue("order_item_id"));
-
@Test
void assertExtractColumnSegments() {
- Collection<ColumnSegment> columnSegments =
ColumnExtractor.extractColumnSegments(createWhereSegments());
- assertThat(columnSegments.size(), is(2));
- Iterator<ColumnSegment> iterator = columnSegments.iterator();
- ColumnSegment firstColumn = iterator.next();
- assertThat(firstColumn.getIdentifier().getValue(), is("name"));
- ColumnSegment secondColumn = iterator.next();
- assertThat(secondColumn.getIdentifier().getValue(), is("pwd"));
+
assertThat(toColumnNames(ColumnExtractor.extractColumnSegments(createWhereSegments())),
is(Arrays.asList("foo_name", "bar_pwd")));
+ }
+
+ @ParameterizedTest(name = "SelectStatement: {0}")
+ @MethodSource("provideSelectStatements")
+ void assertExtractFromSelectStatement(final String name, final
SelectStatement selectStatement, final boolean containsSubQuery,
+ final List<String>
expectedColumnNames) {
+ Collection<ColumnSegment> columnSegments = new LinkedList<>();
+ ColumnExtractor.extractFromSelectStatement(columnSegments,
selectStatement, containsSubQuery);
+ assertThat(toColumnNames(columnSegments), is(expectedColumnNames));
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("provideExpressions")
+ void assertExtract(final String name, final ExpressionSegment expression,
final List<String> expectedColumnNames) {
+ assertThat(toColumnNames(ColumnExtractor.extract(expression)),
is(expectedColumnNames));
}
- private Collection<WhereSegment> createWhereSegments() {
+ private static Stream<Arguments> provideSelectStatements() {
+ return Stream.of(
+ Arguments.of("FullSegments",
createSelectStatementForExtraction(), true, Arrays.asList(
+ "foo_projection_column",
+ "foo_projection_agg_param",
+ "foo_datetime_left",
+ "foo_datetime_right",
+ "foo_expression_projection",
+ "foo_interval_left",
+ "foo_interval_right",
+ "foo_interval_minus",
+ "foo_subquery_projection_column",
+ "foo_collection_expr",
+ "foo_cte_subquery_column",
+ "foo_inner_join_left",
+ "bar_inner_join_right",
+ "foo_subquery_table_column",
+ "foo_join_left",
+ "bar_join_right",
+ "foo_using_column",
+ "bar_derived_using_column",
+ "foo_where_left",
+ "bar_where_right",
+ "foo_group_by_column",
+ "foo_group_by_expr_column",
+ "foo_having_left",
+ "bar_having_right",
+ "foo_order_by_column",
+ "bar_order_by_expr_column",
+ "foo_combine_left_column",
+ "bar_combine_right_column")),
+ Arguments.of("SkipSubqueryFlagFalse",
createSelectStatementSkippingSubquery(), false, Collections.emptyList()),
+ Arguments.of("NoOptionalSegments",
createSelectStatementWithoutOptionalSegments(), true, Collections.emptyList()));
+ }
+
+ private static Stream<Arguments> provideExpressions() {
+ return Stream.of(
+ Arguments.of("BinaryOperationColumns",
createBinaryOperation("foo_left_col", "bar_right_col"),
Arrays.asList("foo_left_col", "bar_right_col")),
+ Arguments.of("BinaryOperationOuterJoin",
createBinaryOperationWithOuterJoin(), Arrays.asList("foo_outer_left",
"bar_outer_right")),
+ Arguments.of("InExpressionWithColumnLeft",
createInExpression(createColumnSegment("foo_in_left"),
+ createBinaryOperation("foo_in_right_left",
"bar_in_right_right")), Arrays.asList("foo_in_left", "foo_in_right_left",
"bar_in_right_right")),
+ Arguments.of("InExpressionWithRowLeft",
createInExpression(createRowExpression(),
+ createBinaryOperation("foo_row_right_left",
"bar_row_right_right")), Arrays.asList("foo_row_item", "foo_row_right_left",
"bar_row_right_right")),
+ Arguments.of("InExpressionWithFunctionLeft",
+
createInExpression(createFunctionWithSingleColumnParameter("foo_function_left_column"),
createBinaryOperation("foo_function_right_left", "bar_function_right_right")),
+ Arrays.asList("foo_function_left_column",
"foo_function_right_left", "bar_function_right_right")),
+ Arguments.of("BetweenExpressionWithColumns",
createBetweenExpressionWithColumns(), Arrays.asList("foo_between_left",
"foo_between_between", "foo_between_and")),
+ Arguments.of("BetweenExpressionWithNonColumnOperands",
createBetweenExpressionWithMixedOperands(),
+ Arrays.asList("foo_between_function_column",
"foo_between_binary_left", "bar_between_binary_right")),
+ Arguments.of("AggregationProjectionWithFunctionParameters",
createAggregationProjectionExpression(),
+ Arrays.asList("foo_agg_direct", "foo_agg_func_direct",
"foo_agg_func_binary_left", "bar_agg_func_binary_right")),
+ Arguments.of("FunctionSegmentWithNestedBinary",
createFunctionWithColumnAndBinaryParameter(),
+ Arrays.asList("foo_function_direct",
"foo_function_binary_left", "bar_function_binary_right")));
+ }
+
+ private static Collection<WhereSegment> createWhereSegments() {
BinaryOperationExpression leftExpression = new
BinaryOperationExpression(10, 24,
- new ColumnSegment(10, 13, new IdentifierValue("name")), new
LiteralExpressionSegment(18, 22, "LiLei"), "=", "name = 'LiLei'");
+ new ColumnSegment(10, 13, new IdentifierValue("foo_name")),
new LiteralExpressionSegment(18, 22, "LiLei"), "=", "foo_name = 'LiLei'");
BinaryOperationExpression rightExpression = new
BinaryOperationExpression(30, 44,
- new ColumnSegment(30, 32, new IdentifierValue("pwd")), new
LiteralExpressionSegment(40, 45, "123456"), "=", "pwd = '123456'");
- return Collections.singleton(new WhereSegment(0, 0, new
BinaryOperationExpression(0, 0, leftExpression, rightExpression, "AND", "name =
'LiLei' AND pwd = '123456'")));
+ new ColumnSegment(30, 32, new IdentifierValue("bar_pwd")), new
LiteralExpressionSegment(40, 45, "123456"), "=", "bar_pwd = '123456'");
+ return Collections.singleton(new WhereSegment(0, 0, new
BinaryOperationExpression(0, 0, leftExpression, rightExpression, "AND",
"foo_name = 'LiLei' AND bar_pwd = '123456'")));
}
- @ParameterizedTest(name = "{0}")
- @ArgumentsSource(TestCaseArgumentsProvider.class)
- void assertExtract(final ExpressionSegment expression) {
- Collection<ColumnSegment> columnSegments =
ColumnExtractor.extract(expression);
- assertThat(columnSegments.size(), is(1));
- assertThat(columnSegments.iterator().next(), is(COLUMN_SEGMENT));
- }
-
- private static final class TestCaseArgumentsProvider implements
ArgumentsProvider {
-
- @Override
- public Stream<? extends Arguments> provideArguments(final
ParameterDeclarations parameters, final ExtensionContext context) {
- return Stream.of(Arguments.of(new BinaryOperationExpression(0, 0,
COLUMN_SEGMENT, null, null, null)),
- Arguments.of(new InExpression(0, 0, COLUMN_SEGMENT, null,
false)),
- Arguments.of(new BetweenExpression(0, 0, COLUMN_SEGMENT,
null, null, false)));
- }
+ private static SelectStatement createSelectStatementForExtraction() {
+ ProjectionsSegment projections = new ProjectionsSegment(0, 0);
+ projections.getProjections().add(new
ColumnProjectionSegment(createColumnSegment("foo_projection_column")));
+ AggregationProjectionSegment aggregationProjectionSegment = new
AggregationProjectionSegment(0, 0, AggregationType.COUNT,
"COUNT(foo_projection_agg_param)");
+
aggregationProjectionSegment.getParameters().add(createColumnSegment("foo_projection_agg_param"));
+ projections.getProjections().add(aggregationProjectionSegment);
+ projections.getProjections().add(new DatetimeProjectionSegment(0, 0,
createColumnSegment("foo_datetime_left"),
createColumnSegment("foo_datetime_right"), "date_add"));
+ projections.getProjections().add(new ExpressionProjectionSegment(0, 0,
"foo_expression_projection", createColumnSegment("foo_expression_projection")));
+ projections.getProjections().add(new IntervalExpressionProjection(0,
0, createColumnSegment("foo_interval_left"),
+ createColumnSegment("foo_interval_minus"),
createColumnSegment("foo_interval_right"), "interval expr"));
+ projections.getProjections().add(new SubqueryProjectionSegment(new
SubquerySegment(0, 0,
createSelectStatementWithProjection("foo_subquery_projection_column"), ""),
"subquery"));
+ SelectStatement result = new SelectStatement(mock(DatabaseType.class));
+ result.setProjections(projections);
+ result.setFrom(createJoinTableForExtraction());
+ result.setWhere(new WhereSegment(0, 0,
createBinaryOperation("foo_where_left", "bar_where_right")));
+ result.setGroupBy(createGroupBySegment());
+ result.setHaving(new HavingSegment(0, 0,
createBinaryOperation("foo_having_left", "bar_having_right")));
+ result.setOrderBy(createOrderBySegment());
+ result.setCombine(createCombineSegment());
+ return result;
+ }
+
+ private static SelectStatement
createSelectStatementWithoutOptionalSegments() {
+ SelectStatement result = new SelectStatement(mock(DatabaseType.class));
+ result.setProjections(new ProjectionsSegment(0, 0));
+ return result;
+ }
+
+ private static SelectStatement createSelectStatementSkippingSubquery() {
+ ProjectionsSegment projectionsSegment = new ProjectionsSegment(0, 0);
+ projectionsSegment.getProjections().add(new
SubqueryProjectionSegment(new SubquerySegment(0, 0,
createSelectStatementWithProjection("foo_skip_projection"), ""), "sub"));
+ SelectStatement result = new SelectStatement(mock(DatabaseType.class));
+ result.setProjections(projectionsSegment);
+ result.setFrom(new SubqueryTableSegment(0, 0, new SubquerySegment(0,
0, createSelectStatementWithProjection("bar_skip_from"), "")));
+ return result;
+ }
+
+ private static GroupBySegment createGroupBySegment() {
+ Collection<OrderByItemSegment> groupByItems = new LinkedList<>();
+ groupByItems.add(new
ColumnOrderByItemSegment(createColumnSegment("foo_group_by_column"),
OrderDirection.ASC, NullsOrderType.FIRST));
+ groupByItems.add(new ExpressionOrderByItemSegment(0, 0,
"group_by_expr", OrderDirection.ASC, NullsOrderType.FIRST,
createColumnSegment("foo_group_by_expr_column")));
+ return new GroupBySegment(0, 0, groupByItems);
+ }
+
+ private static OrderBySegment createOrderBySegment() {
+ Collection<OrderByItemSegment> orderByItems = new LinkedList<>();
+ orderByItems.add(new
ColumnOrderByItemSegment(createColumnSegment("foo_order_by_column"),
OrderDirection.DESC, NullsOrderType.LAST));
+ orderByItems.add(new ExpressionOrderByItemSegment(0, 0,
"order_by_expr", OrderDirection.DESC, NullsOrderType.LAST,
createColumnSegment("bar_order_by_expr_column")));
+ return new OrderBySegment(0, 0, orderByItems);
+ }
+
+ private static CombineSegment createCombineSegment() {
+ SubquerySegment left = new SubquerySegment(0, 0,
createSelectStatementWithProjection("foo_combine_left_column"), "");
+ SubquerySegment right = new SubquerySegment(0, 0,
createSelectStatementWithProjection("bar_combine_right_column"), "");
+ return new CombineSegment(0, 0, left, CombineType.UNION, right);
+ }
+
+ private static JoinTableSegment createJoinTableForExtraction() {
+ JoinTableSegment innerJoin = new JoinTableSegment();
+ innerJoin.setLeft(new
CollectionTableSegment(createColumnSegment("foo_collection_expr")));
+ CommonTableExpressionSegment commonTableExpressionSegment = new
CommonTableExpressionSegment(0, 0, new AliasSegment(0, 0, new
IdentifierValue("cte_alias")),
+ new SubquerySegment(0, 0,
createSelectStatementWithProjection("foo_cte_subquery_column"), ""));
+ innerJoin.setRight(commonTableExpressionSegment);
+ innerJoin.setCondition(createBinaryOperation("foo_inner_join_left",
"bar_inner_join_right"));
+ JoinTableSegment result = new JoinTableSegment();
+ result.setLeft(innerJoin);
+ result.setRight(new SubqueryTableSegment(0, 0, new SubquerySegment(0,
0, createSelectStatementWithProjection("foo_subquery_table_column"), "")));
+ result.setCondition(createBinaryOperation("foo_join_left",
"bar_join_right"));
+
result.setUsing(Collections.singletonList(createColumnSegment("foo_using_column")));
+
result.setDerivedUsing(Collections.singletonList(createColumnSegment("bar_derived_using_column")));
+ return result;
+ }
+
+ private static SelectStatement createSelectStatementWithProjection(final
String columnName) {
+ SelectStatement result = new SelectStatement(mock(DatabaseType.class));
+ ProjectionsSegment projections = new ProjectionsSegment(0, 0);
+ projections.getProjections().add(new
ColumnProjectionSegment(createColumnSegment(columnName)));
+ result.setProjections(projections);
+ return result;
+ }
+
+ private static BinaryOperationExpression createBinaryOperation(final
String leftColumnName, final String rightColumnName) {
+ return new BinaryOperationExpression(0, 0,
createColumnSegment(leftColumnName), createColumnSegment(rightColumnName), "=",
leftColumnName + " = " + rightColumnName);
+ }
+
+ private static BinaryOperationExpression
createBinaryOperationWithOuterJoin() {
+ OuterJoinExpression left = new OuterJoinExpression(0, 0,
createColumnSegment("foo_outer_left"), "=", "foo_outer_left");
+ OuterJoinExpression right = new OuterJoinExpression(0, 0,
createColumnSegment("bar_outer_right"), "=", "bar_outer_right");
+ return new BinaryOperationExpression(0, 0, left, right, "=", "outer
join");
+ }
+
+ private static InExpression createInExpression(final ExpressionSegment
left, final ExpressionSegment right) {
+ return new InExpression(0, 0, left, right, false);
+ }
+
+ private static RowExpression createRowExpression() {
+ RowExpression result = new RowExpression(0, 0, "(row)");
+ result.getItems().add(createColumnSegment("foo_row_item"));
+ result.getItems().add(new LiteralExpressionSegment(0, 0, 1));
+ return result;
+ }
+
+ private static BetweenExpression createBetweenExpressionWithColumns() {
+ return new BetweenExpression(0, 0,
createColumnSegment("foo_between_left"),
createColumnSegment("foo_between_between"),
createColumnSegment("foo_between_and"), false);
+ }
+
+ private static BetweenExpression
createBetweenExpressionWithMixedOperands() {
+ return new BetweenExpression(0, 0,
+ new LiteralExpressionSegment(0, 0, 1),
createFunctionWithSingleColumnParameter("foo_between_function_column"),
+ createBinaryOperation("foo_between_binary_left",
"bar_between_binary_right"), false);
+ }
+
+ private static AggregationProjectionSegment
createAggregationProjectionExpression() {
+ AggregationProjectionSegment result = new
AggregationProjectionSegment(0, 0, AggregationType.SUM, "SUM(expr)");
+ result.getParameters().add(createColumnSegment("foo_agg_direct"));
+ FunctionSegment functionSegment = new FunctionSegment(0, 0, "MAX",
"max");
+
functionSegment.getParameters().add(createColumnSegment("foo_agg_func_direct"));
+
functionSegment.getParameters().add(createBinaryOperation("foo_agg_func_binary_left",
"bar_agg_func_binary_right"));
+ result.getParameters().add(functionSegment);
+ return result;
+ }
+
+ private static FunctionSegment
createFunctionWithSingleColumnParameter(final String columnName) {
+ FunctionSegment result = new FunctionSegment(0, 0, "FUNC", "func");
+ result.getParameters().add(createColumnSegment(columnName));
+ return result;
+ }
+
+ private static FunctionSegment
createFunctionWithColumnAndBinaryParameter() {
+ FunctionSegment result = new FunctionSegment(0, 0, "FUNC", "func");
+ result.getParameters().add(createColumnSegment("foo_function_direct"));
+
result.getParameters().add(createBinaryOperation("foo_function_binary_left",
"bar_function_binary_right"));
+ return result;
+ }
+
+ private static ColumnSegment createColumnSegment(final String columnName) {
+ return new ColumnSegment(0, 0, new IdentifierValue(columnName));
+ }
+
+ private static List<String> toColumnNames(final Collection<ColumnSegment>
columnSegments) {
+ return columnSegments.stream().map(each ->
each.getIdentifier().getValue()).collect(Collectors.toList());
}
}