From 6a7b150e9da9500877310827dd3600759417b1ce Mon Sep 17 00:00:00 2001 From: duanzhengqiang Date: Wed, 17 Dec 2025 16:03:27 +0800 Subject: [PATCH] Use SQLBuilderEngine to include DefaultSQLBuilder and RouteSQLBuilder --- .../infra/rewrite/SQLRewriteEntry.java | 8 +- .../rewrite/context/SQLRewriteContext.java | 4 - .../engine/GenericSQLRewriteEngine.java | 4 +- .../rewrite/engine/RouteSQLRewriteEngine.java | 6 +- .../infra/rewrite/sql/SQLBuilderEngine.java | 51 +++++++++++ .../rewrite/sql/SQLBuilderEngineTest.java | 84 +++++++++++++++++++ 6 files changed, 145 insertions(+), 12 deletions(-) create mode 100644 infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/sql/SQLBuilderEngine.java create mode 100644 infra/rewrite/core/src/test/java/org/apache/shardingsphere/infra/rewrite/sql/SQLBuilderEngineTest.java diff --git a/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/SQLRewriteEntry.java b/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/SQLRewriteEntry.java index 3a7e446c6fa7c..650a147e64d64 100644 --- a/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/SQLRewriteEntry.java +++ b/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/SQLRewriteEntry.java @@ -27,6 +27,7 @@ import org.apache.shardingsphere.infra.rewrite.engine.GenericSQLRewriteEngine; import org.apache.shardingsphere.infra.rewrite.engine.RouteSQLRewriteEngine; import org.apache.shardingsphere.infra.rewrite.engine.result.SQLRewriteResult; +import org.apache.shardingsphere.infra.rewrite.sql.token.common.generator.builder.DefaultTokenGeneratorBuilder; import org.apache.shardingsphere.infra.route.context.RouteContext; import org.apache.shardingsphere.infra.rule.ShardingSphereRule; import org.apache.shardingsphere.infra.session.query.QueryContext; @@ -76,6 +77,10 @@ public SQLRewriteResult rewrite(final QueryContext queryContext, final RouteCont private SQLRewriteContext createSQLRewriteContext(final QueryContext queryContext, final RouteContext routeContext) { HintValueContext hintValueContext = queryContext.getHintValueContext(); SQLRewriteContext result = new SQLRewriteContext(database, queryContext); + if (hintValueContext.isSkipSQLRewrite()) { + return result; + } + result.addSQLTokenGenerators(new DefaultTokenGeneratorBuilder(queryContext.getSqlStatementContext()).getSQLTokenGenerators()); decorate(result, routeContext, hintValueContext); result.generateSQLTokens(); return result; @@ -83,9 +88,6 @@ private SQLRewriteContext createSQLRewriteContext(final QueryContext queryContex @SuppressWarnings({"unchecked", "rawtypes"}) private void decorate(final SQLRewriteContext sqlRewriteContext, final RouteContext routeContext, final HintValueContext hintValueContext) { - if (hintValueContext.isSkipSQLRewrite()) { - return; - } for (Entry entry : decorators.entrySet()) { entry.getValue().decorate(entry.getKey(), props, sqlRewriteContext, routeContext); } diff --git a/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/context/SQLRewriteContext.java b/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/context/SQLRewriteContext.java index bcb8c11623558..0c6f74289d59a 100644 --- a/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/context/SQLRewriteContext.java +++ b/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/context/SQLRewriteContext.java @@ -27,7 +27,6 @@ import org.apache.shardingsphere.infra.rewrite.parameter.builder.impl.StandardParameterBuilder; import org.apache.shardingsphere.infra.rewrite.sql.token.common.generator.SQLTokenGenerator; import org.apache.shardingsphere.infra.rewrite.sql.token.common.generator.SQLTokenGenerators; -import org.apache.shardingsphere.infra.rewrite.sql.token.common.generator.builder.DefaultTokenGeneratorBuilder; import org.apache.shardingsphere.infra.rewrite.sql.token.common.pojo.SQLToken; import org.apache.shardingsphere.infra.session.connection.ConnectionContext; import org.apache.shardingsphere.infra.session.query.QueryContext; @@ -66,9 +65,6 @@ public SQLRewriteContext(final ShardingSphereDatabase database, final QueryConte sql = queryContext.getSql(); parameters = queryContext.getParameters(); connectionContext = queryContext.getConnectionContext(); - if (!queryContext.getHintValueContext().isSkipSQLRewrite()) { - addSQLTokenGenerators(new DefaultTokenGeneratorBuilder(sqlStatementContext).getSQLTokenGenerators()); - } parameterBuilder = containsGroupedParameter(sqlStatementContext) ? buildGroupedParameterBuilder(sqlStatementContext) : new StandardParameterBuilder(parameters); } diff --git a/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/engine/GenericSQLRewriteEngine.java b/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/engine/GenericSQLRewriteEngine.java index 9704e019fa2bd..31a944dad082e 100644 --- a/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/engine/GenericSQLRewriteEngine.java +++ b/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/engine/GenericSQLRewriteEngine.java @@ -25,7 +25,7 @@ import org.apache.shardingsphere.infra.rewrite.context.SQLRewriteContext; import org.apache.shardingsphere.infra.rewrite.engine.result.GenericSQLRewriteResult; import org.apache.shardingsphere.infra.rewrite.engine.result.SQLRewriteUnit; -import org.apache.shardingsphere.infra.rewrite.sql.impl.DefaultSQLBuilder; +import org.apache.shardingsphere.infra.rewrite.sql.SQLBuilderEngine; import org.apache.shardingsphere.infra.session.query.QueryContext; import org.apache.shardingsphere.sqltranslator.context.SQLTranslatorContext; import org.apache.shardingsphere.sqltranslator.rule.SQLTranslatorRule; @@ -60,7 +60,7 @@ public GenericSQLRewriteResult rewrite(final SQLRewriteContext sqlRewriteContext String sql = sqlRewriteContext.getSql(); List parameters = sqlRewriteContext.getParameterBuilder().getParameters(); Optional sqlTranslatorContext = translatorRule.translate( - new DefaultSQLBuilder(sql, sqlRewriteContext.getSqlTokens()).toSQL(), parameters, queryContext, storageType, database, globalRuleMetaData); + new SQLBuilderEngine(sql, sqlRewriteContext.getSqlTokens()).buildSQL(), parameters, queryContext, storageType, database, globalRuleMetaData); String translatedSQL = sqlTranslatorContext.isPresent() ? sqlTranslatorContext.get().getSql() : sql; List translatedParameters = sqlTranslatorContext.isPresent() ? sqlTranslatorContext.get().getParameters() : parameters; return new GenericSQLRewriteResult(new SQLRewriteUnit(translatedSQL, translatedParameters)); diff --git a/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/engine/RouteSQLRewriteEngine.java b/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/engine/RouteSQLRewriteEngine.java index 17e03cc1a5516..9edd259168f14 100644 --- a/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/engine/RouteSQLRewriteEngine.java +++ b/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/engine/RouteSQLRewriteEngine.java @@ -32,7 +32,7 @@ import org.apache.shardingsphere.infra.rewrite.parameter.builder.ParameterBuilder; import org.apache.shardingsphere.infra.rewrite.parameter.builder.impl.GroupedParameterBuilder; import org.apache.shardingsphere.infra.rewrite.parameter.builder.impl.StandardParameterBuilder; -import org.apache.shardingsphere.infra.rewrite.sql.impl.RouteSQLBuilder; +import org.apache.shardingsphere.infra.rewrite.sql.SQLBuilderEngine; import org.apache.shardingsphere.infra.route.context.RouteContext; import org.apache.shardingsphere.infra.route.context.RouteUnit; import org.apache.shardingsphere.infra.session.query.QueryContext; @@ -118,7 +118,7 @@ private SQLRewriteUnit createSQLRewriteUnit(final SQLRewriteContext sqlRewriteCo boolean containsDollarMarker = sqlRewriteContext.getSqlStatementContext() instanceof SelectStatementContext && ((SelectStatementContext) (sqlRewriteContext.getSqlStatementContext())).isContainsDollarParameterMarker(); for (RouteUnit each : routeUnits) { - sql.add(SQLUtils.trimSemicolon(new RouteSQLBuilder(sqlRewriteContext.getSql(), sqlRewriteContext.getSqlTokens(), each).toSQL())); + sql.add(SQLUtils.trimSemicolon(new SQLBuilderEngine(sqlRewriteContext.getSql(), sqlRewriteContext.getSqlTokens(), each).buildSQL())); if (containsDollarMarker && !params.isEmpty()) { continue; } @@ -132,7 +132,7 @@ private SQLRewriteUnit createSQLRewriteUnit(final SQLRewriteContext sqlRewriteCo } private String getActualSQL(final SQLRewriteContext sqlRewriteContext, final RouteUnit routeUnit) { - return new RouteSQLBuilder(sqlRewriteContext.getSql(), sqlRewriteContext.getSqlTokens(), routeUnit).toSQL(); + return new SQLBuilderEngine(sqlRewriteContext.getSql(), sqlRewriteContext.getSqlTokens(), routeUnit).buildSQL(); } private List getParameters(final SQLRewriteContext sqlRewriteContext, final RouteContext routeContext, final RouteUnit routeUnit) { diff --git a/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/sql/SQLBuilderEngine.java b/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/sql/SQLBuilderEngine.java new file mode 100644 index 0000000000000..502362c634b12 --- /dev/null +++ b/infra/rewrite/core/src/main/java/org/apache/shardingsphere/infra/rewrite/sql/SQLBuilderEngine.java @@ -0,0 +1,51 @@ +/* + * 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.rewrite.sql; + +import org.apache.shardingsphere.infra.rewrite.sql.impl.AbstractSQLBuilder; +import org.apache.shardingsphere.infra.rewrite.sql.impl.DefaultSQLBuilder; +import org.apache.shardingsphere.infra.rewrite.sql.impl.RouteSQLBuilder; +import org.apache.shardingsphere.infra.rewrite.sql.token.common.pojo.SQLToken; +import org.apache.shardingsphere.infra.route.context.RouteUnit; + +import java.util.List; + +/** + * SQL builder engine. + */ +public final class SQLBuilderEngine { + + private final AbstractSQLBuilder sqlBuilder; + + public SQLBuilderEngine(final String sql, final List sqlTokens) { + sqlBuilder = new DefaultSQLBuilder(sql, sqlTokens); + } + + public SQLBuilderEngine(final String sql, final List sqlTokens, final RouteUnit routeUnit) { + sqlBuilder = new RouteSQLBuilder(sql, sqlTokens, routeUnit); + } + + /** + * Build SQL. + * + * @return SQL string + */ + public String buildSQL() { + return sqlBuilder.toSQL(); + } +} diff --git a/infra/rewrite/core/src/test/java/org/apache/shardingsphere/infra/rewrite/sql/SQLBuilderEngineTest.java b/infra/rewrite/core/src/test/java/org/apache/shardingsphere/infra/rewrite/sql/SQLBuilderEngineTest.java new file mode 100644 index 0000000000000..18041946a7a7f --- /dev/null +++ b/infra/rewrite/core/src/test/java/org/apache/shardingsphere/infra/rewrite/sql/SQLBuilderEngineTest.java @@ -0,0 +1,84 @@ +/* + * 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.rewrite.sql; + +import org.apache.shardingsphere.infra.rewrite.sql.fixture.SQLTokenFixture; +import org.apache.shardingsphere.infra.route.context.RouteMapper; +import org.apache.shardingsphere.infra.route.context.RouteUnit; +import org.junit.jupiter.api.Test; + +import java.util.Collections; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.mock; + +class SQLBuilderEngineTest { + + @Test + void assertCreateSQLBuilderEngineWithDefaultConstructor() { + SQLBuilderEngine actual = new SQLBuilderEngine("SELECT * FROM tbl WHERE id=?", Collections.emptyList()); + assertThat(actual.buildSQL(), is("SELECT * FROM tbl WHERE id=?")); + } + + @Test + void assertCreateSQLBuilderEngineWithDefaultConstructorAndTokens() { + SQLBuilderEngine actual = new SQLBuilderEngine("SELECT * FROM tbl WHERE id=?", Collections.singletonList(new SQLTokenFixture(14, 16))); + assertThat(actual.buildSQL(), is("SELECT * FROM XXX WHERE id=?")); + } + + @Test + void assertCreateSQLBuilderEngineWithRouteUnitConstructor() { + RouteUnit routeUnit = new RouteUnit(mock(RouteMapper.class), Collections.singletonList(new RouteMapper("tbl", "tbl_0"))); + SQLBuilderEngine actual = new SQLBuilderEngine("SELECT * FROM tbl WHERE id=?", Collections.emptyList(), routeUnit); + assertThat(actual.buildSQL(), is("SELECT * FROM tbl WHERE id=?")); + } + + @Test + void assertCreateSQLBuilderEngineWithRouteUnitConstructorAndTokens() { + RouteUnit routeUnit = new RouteUnit(mock(RouteMapper.class), Collections.singletonList(new RouteMapper("tbl", "tbl_0"))); + SQLBuilderEngine actual = new SQLBuilderEngine("SELECT * FROM tbl WHERE id=?", Collections.singletonList(new SQLTokenFixture(14, 16)), routeUnit); + assertThat(actual.buildSQL(), is("SELECT * FROM XXX WHERE id=?")); + } + + @Test + void assertBuildSQLWithEmptyTokens() { + SQLBuilderEngine sqlBuilderEngine = new SQLBuilderEngine("INSERT INTO tbl (col1, col2) VALUES (?, ?)", Collections.emptyList()); + assertThat(sqlBuilderEngine.buildSQL(), is("INSERT INTO tbl (col1, col2) VALUES (?, ?)")); + } + + @Test + void assertBuildSQLWithMultipleTokens() { + SQLBuilderEngine sqlBuilderEngine = new SQLBuilderEngine("SELECT * FROM tbl WHERE col1=? AND col2=?", + java.util.Arrays.asList(new SQLTokenFixture(14, 17), new SQLTokenFixture(28, 31))); + assertThat(sqlBuilderEngine.buildSQL(), is("SELECT * FROM XXXWHERE col1XXXND col2=?")); + } + + @Test + void assertBuildSQLWithComplexSQL() { + String complexSQL = "SELECT t1.id, t2.name FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id WHERE t1.status = ? ORDER BY t2.name DESC LIMIT 10"; + SQLBuilderEngine sqlBuilderEngine = new SQLBuilderEngine(complexSQL, Collections.singletonList(new SQLTokenFixture(14, 19))); + assertThat(sqlBuilderEngine.buildSQL(), is("SELECT t1.id, XXXe FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id WHERE t1.status = ? ORDER BY t2.name DESC LIMIT 10")); + } + + @Test + void assertBuildSQLWithEmptySQLString() { + SQLBuilderEngine sqlBuilderEngine = new SQLBuilderEngine("", Collections.emptyList()); + assertThat(sqlBuilderEngine.buildSQL(), is("")); + } +}