This is an automated email from the ASF dual-hosted git repository.
tuichenchuxin 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 c8f650abead Add ENUMERABLE_LIMIT_RULE to support select limit
statement when use sql federation (#21229)
c8f650abead is described below
commit c8f650abead1a93ba68c7e927cd4d823d95c65dd
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Wed Sep 28 11:31:39 2022 +0800
Add ENUMERABLE_LIMIT_RULE to support select limit statement when use sql
federation (#21229)
Co-authored-by: shardingsphere <[email protected]>
---
.../advanced/AdvancedSQLFederationExecutor.java | 2 +-
.../metadata/expander/ShardingSphereViewExpander.java | 13 +++++++------
.../optimizer/util/SQLFederationPlannerUtil.java | 14 ++++++++------
.../sqlfederation/optimizer/SQLOptimizeEngineTest.java | 18 +++++++++++++++---
.../resources/cases/dql/dql-integration-test-cases.xml | 4 ++++
5 files changed, 35 insertions(+), 16 deletions(-)
diff --git
a/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-executor/shardingsphere-sql-federation-executor-advanced/src/main/java/org/apache/shardingsphere/sqlfederation/advanced/AdvancedSQLFederationExecutor.java
b/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-executor/shardingsphere-sql-federation-executor-advanced/src/main/java/org/apache/shardingsphere/sqlfederation/advanced/AdvancedSQLFederationExecutor.java
index af4d29fc5b7..a257f39985b 100644
---
a/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-executor/shardingsphere-sql-federation-executor-advanced/src/main/java/org/apache/shardingsphere/sqlfederation/advanced/AdvancedSQLFederationExecutor.java
+++
b/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-executor/shardingsphere-sql-federation-executor-advanced/src/main/java/org/apache/shardingsphere/sqlfederation/advanced/AdvancedSQLFederationExecutor.java
@@ -136,7 +136,7 @@ public final class AdvancedSQLFederationExecutor implements
SQLFederationExecuto
CalciteCatalogReader catalogReader =
SQLFederationPlannerUtil.createCatalogReader(schemaName, sqlFederationSchema,
JAVA_TYPE_FACTORY, connectionConfig);
SqlValidator validator =
SQLFederationPlannerUtil.createSqlValidator(catalogReader, JAVA_TYPE_FACTORY,
parserContext.getDatabaseType(), connectionConfig);
SqlToRelConverter converter =
SQLFederationPlannerUtil.createSqlToRelConverter(catalogReader, validator,
-
SQLFederationPlannerUtil.createRelOptCluster(JAVA_TYPE_FACTORY),
optimizerContext, true);
+
SQLFederationPlannerUtil.createRelOptCluster(JAVA_TYPE_FACTORY),
optimizerContext.getSqlParserRule(), parserContext.getDatabaseType(), true);
SQLOptimizeContext optimizeContext =
new SQLOptimizeEngine(converter,
SQLFederationPlannerUtil.createHepPlanner()).optimize(selectStatementContext.getSqlStatement());
Bindable<Object> executablePlan =
EnumerableInterpretable.toBindable(Collections.emptyMap(), null,
(EnumerableRel) optimizeContext.getBestPlan(), EnumerableRel.Prefer.ARRAY);
diff --git
a/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-optimizer/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/metadata/expander/ShardingSphereViewExpander.java
b/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-optimizer/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/metadata/expander/ShardingSphereViewExpander.java
index 2dd3d4874f8..d54dc22215a 100644
---
a/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-optimizer/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/metadata/expander/ShardingSphereViewExpander.java
+++
b/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-optimizer/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/metadata/expander/ShardingSphereViewExpander.java
@@ -23,10 +23,10 @@ import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql2rel.SqlToRelConverter;
-import org.apache.shardingsphere.infra.database.type.dialect.MySQLDatabaseType;
+import org.apache.shardingsphere.infra.database.type.DatabaseType;
import org.apache.shardingsphere.infra.parser.sql.SQLStatementParserEngine;
+import org.apache.shardingsphere.parser.rule.SQLParserRule;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
-import
org.apache.shardingsphere.sqlfederation.optimizer.context.OptimizerContext;
import
org.apache.shardingsphere.sqlfederation.optimizer.converter.SQLNodeConverterEngine;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -38,15 +38,16 @@ import java.util.List;
@RequiredArgsConstructor
public final class ShardingSphereViewExpander implements ViewExpander {
- private final OptimizerContext optimizerContext;
+ private final SQLParserRule sqlParserRule;
+
+ private final DatabaseType databaseType;
private final SqlToRelConverter sqlToRelConverter;
@Override
public RelRoot expandView(final RelDataType rowType, final String
queryString, final List<String> schemaPath, @Nullable final List<String>
viewPath) {
- SQLStatement sqlStatement = new SQLStatementParserEngine(new
MySQLDatabaseType().getType(),
- optimizerContext.getSqlParserRule().getSqlStatementCache(),
optimizerContext.getSqlParserRule().getParseTreeCache(),
-
optimizerContext.getSqlParserRule().isSqlCommentParseEnabled()).parse(queryString,
false);
+ SQLStatement sqlStatement = new
SQLStatementParserEngine(databaseType.getType(),
sqlParserRule.getSqlStatementCache(),
+ sqlParserRule.getParseTreeCache(),
sqlParserRule.isSqlCommentParseEnabled()).parse(queryString, false);
SqlNode sqlNode = SQLNodeConverterEngine.convert(sqlStatement);
return sqlToRelConverter.convertQuery(sqlNode, true, true);
}
diff --git
a/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-optimizer/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/util/SQLFederationPlannerUtil.java
b/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-optimizer/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/util/SQLFederationPlannerUtil.java
index 3bdafe4706f..bdb95155070 100644
---
a/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-optimizer/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/util/SQLFederationPlannerUtil.java
+++
b/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-optimizer/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/util/SQLFederationPlannerUtil.java
@@ -49,7 +49,7 @@ import org.apache.calcite.sql2rel.SqlToRelConverter;
import org.apache.calcite.sql2rel.SqlToRelConverter.Config;
import org.apache.calcite.sql2rel.StandardConvertletTable;
import org.apache.shardingsphere.infra.database.type.DatabaseType;
-import
org.apache.shardingsphere.sqlfederation.optimizer.context.OptimizerContext;
+import org.apache.shardingsphere.parser.rule.SQLParserRule;
import
org.apache.shardingsphere.sqlfederation.optimizer.metadata.expander.ShardingSphereViewExpander;
import
org.apache.shardingsphere.sqlfederation.optimizer.metadata.translatable.TranslatableFilterRule;
import
org.apache.shardingsphere.sqlfederation.optimizer.metadata.translatable.TranslatableProjectFilterRule;
@@ -110,6 +110,7 @@ public final class SQLFederationPlannerUtil {
planner.addRelTraitDef(RelCollationTraitDef.INSTANCE);
planner.addRule(EnumerableRules.ENUMERABLE_CALC_RULE);
planner.addRule(EnumerableRules.ENUMERABLE_SORT_RULE);
+ planner.addRule(EnumerableRules.ENUMERABLE_LIMIT_RULE);
planner.addRule(EnumerableRules.ENUMERABLE_JOIN_RULE);
planner.addRule(EnumerableRules.ENUMERABLE_TABLE_SCAN_RULE);
planner.addRule(EnumerableRules.ENUMERABLE_AGGREGATE_RULE);
@@ -217,14 +218,15 @@ public final class SQLFederationPlannerUtil {
* @param catalogReader catalog reader
* @param validator validator
* @param cluster cluster
- * @param optimizerContext optimizer context
+ * @param sqlParserRule sql parser rule
+ * @param databaseType database type
* @param needsViewExpand whether sql needs view expand or not
* @return sql to rel converter
*/
- public static SqlToRelConverter createSqlToRelConverter(final
CalciteCatalogReader catalogReader, final SqlValidator validator,
- final
RelOptCluster cluster, final OptimizerContext optimizerContext, final boolean
needsViewExpand) {
- ViewExpander expander = needsViewExpand ? new
ShardingSphereViewExpander(optimizerContext,
- createSqlToRelConverter(catalogReader, validator, cluster,
optimizerContext, false)) : (rowType, queryString, schemaPath, viewPath) ->
null;
+ public static SqlToRelConverter createSqlToRelConverter(final
CalciteCatalogReader catalogReader, final SqlValidator validator, final
RelOptCluster cluster,
+ final
SQLParserRule sqlParserRule, final DatabaseType databaseType, final boolean
needsViewExpand) {
+ ViewExpander expander = needsViewExpand ? new
ShardingSphereViewExpander(sqlParserRule, databaseType,
+ createSqlToRelConverter(catalogReader, validator, cluster,
sqlParserRule, databaseType, false)) : (rowType, queryString, schemaPath,
viewPath) -> null;
Config converterConfig =
SqlToRelConverter.config().withTrimUnusedFields(true);
return new SqlToRelConverter(expander, validator, catalogReader,
cluster, StandardConvertletTable.INSTANCE, converterConfig);
}
diff --git
a/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-optimizer/src/test/java/org/apache/shardingsphere/sqlfederation/optimizer/SQLOptimizeEngineTest.java
b/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-optimizer/src/test/java/org/apache/shardingsphere/sqlfederation/optimizer/SQLOptimizeEngineTest.java
index 571a34decc9..a5d9b1ae2b5 100644
---
a/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-optimizer/src/test/java/org/apache/shardingsphere/sqlfederation/optimizer/SQLOptimizeEngineTest.java
+++
b/shardingsphere-kernel/shardingsphere-sql-federation/shardingsphere-sql-federation-optimizer/src/test/java/org/apache/shardingsphere/sqlfederation/optimizer/SQLOptimizeEngineTest.java
@@ -35,7 +35,6 @@ import
org.apache.shardingsphere.infra.parser.ShardingSphereSQLParserEngine;
import org.apache.shardingsphere.parser.rule.SQLParserRule;
import
org.apache.shardingsphere.parser.rule.builder.DefaultSQLParserRuleConfigurationBuilder;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
-import
org.apache.shardingsphere.sqlfederation.optimizer.context.OptimizerContext;
import
org.apache.shardingsphere.sqlfederation.optimizer.metadata.translatable.TranslatableSchema;
import
org.apache.shardingsphere.sqlfederation.optimizer.util.SQLFederationPlannerUtil;
import org.hamcrest.MatcherAssert;
@@ -91,6 +90,8 @@ public final class SQLOptimizeEngineTest {
private static final String SELECT_UNION = "SELECT order_id, user_id FROM
t_order_federate UNION SELECT 1, user_id FROM t_user_info WHERE information =
'before'";
+ private static final String SELECT_LIMIT = "SELECT order_id, user_id FROM
t_order_federate LIMIT 1";
+
private static final String SCHEMA_NAME = "federate_jdbc";
private final SQLParserRule sqlParserRule = new SQLParserRule(new
DefaultSQLParserRuleConfigurationBuilder().build());
@@ -125,9 +126,10 @@ public final class SQLOptimizeEngineTest {
RelDataTypeFactory relDataTypeFactory = new JavaTypeFactoryImpl();
TranslatableSchema federationSchema = new
TranslatableSchema(SCHEMA_NAME, schema, null);
CalciteCatalogReader catalogReader =
SQLFederationPlannerUtil.createCatalogReader(SCHEMA_NAME, federationSchema,
relDataTypeFactory, connectionConfig);
- SqlValidator validator =
SQLFederationPlannerUtil.createSqlValidator(catalogReader, relDataTypeFactory,
new H2DatabaseType(), connectionConfig);
+ H2DatabaseType databaseType = new H2DatabaseType();
+ SqlValidator validator =
SQLFederationPlannerUtil.createSqlValidator(catalogReader, relDataTypeFactory,
databaseType, connectionConfig);
RelOptCluster cluster =
RelOptCluster.create(SQLFederationPlannerUtil.createVolcanoPlanner(), new
RexBuilder(relDataTypeFactory));
- return SQLFederationPlannerUtil.createSqlToRelConverter(catalogReader,
validator, cluster, mock(OptimizerContext.class), false);
+ return SQLFederationPlannerUtil.createSqlToRelConverter(catalogReader,
validator, cluster, mock(SQLParserRule.class), databaseType, false);
}
@Test
@@ -268,4 +270,14 @@ public final class SQLOptimizeEngineTest {
+ " TranslatableTableScan(table=[[federate_jdbc,
t_user_info]], fields=[[0]], filters=[[=(CAST($1):VARCHAR, 'before'), null]])"
+ LINE_SEPARATOR;
MatcherAssert.assertThat(actual, is(expected));
}
+
+ @Test
+ public void assertSelectLimit() {
+ ShardingSphereSQLParserEngine sqlParserEngine =
sqlParserRule.getSQLParserEngine(DatabaseTypeEngine.getTrunkDatabaseTypeName(new
H2DatabaseType()));
+ SQLStatement sqlStatement = sqlParserEngine.parse(SELECT_LIMIT, false);
+ String actual =
optimizeEngine.optimize(sqlStatement).getBestPlan().explain();
+ String expected = "EnumerableLimit(fetch=[1])" + LINE_SEPARATOR
+ + " TranslatableTableScan(table=[[federate_jdbc,
t_order_federate]], fields=[[0, 1]])" + LINE_SEPARATOR;
+ MatcherAssert.assertThat(actual, is(expected));
+ }
}
diff --git
a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-suite/src/test/resources/cases/dql/dql-integration-test-cases.xml
b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-suite/src/test/resources/cases/dql/dql-integration-test-cases.xml
index 68919251d5c..1f19ead6823 100644
---
a/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-suite/src/test/resources/cases/dql/dql-integration-test-cases.xml
+++
b/shardingsphere-test/shardingsphere-integration-test/shardingsphere-integration-test-suite/src/test/resources/cases/dql/dql-integration-test-cases.xml
@@ -530,6 +530,10 @@
<assertion parameters="1000:int, 100000:int"
expected-data-source-name="read_dataset" />
</test-case>
+ <test-case sql="SELECT o.*, i.* FROM t_order_federate o,
t_order_item_federate i WHERE o.order_id = ? AND i.item_id = ? LIMIT ?"
scenario-types="db,dbtbl_with_readwrite_splitting,dbtbl_with_readwrite_splitting_and_encrypt,sharding_and_encrypt,encrypt_and_readwrite_splitting">
+ <assertion parameters="1000:int, 100000:int, 3:int"
expected-data-source-name="read_dataset" />
+ </test-case>
+
<test-case sql="SELECT user_id, CONCAT('SUM:', total, '.') AS content FROM
(SELECT user_id, SUM(order_id_sharding) AS total FROM t_order_federate_sharding
GROUP BY user_id HAVING SUM(order_id_sharding) > ?) AS temp ORDER BY
temp.user_id" db-types="MySQL,PostgreSQL" scenario-types="tbl">
<assertion parameters="1000:int" />
</test-case>