This is an automated email from the ASF dual-hosted git repository.
iamhucong 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 fff1310070b Minor refacor in encrypt rewrite and
QueryHeaderBuilderEngine (#38978)
fff1310070b is described below
commit fff1310070b6bb2f995917b63e6228dc65f96fc8
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Thu Jul 2 13:59:08 2026 +0800
Minor refacor in encrypt rewrite and QueryHeaderBuilderEngine (#38978)
---
.../rewrite/token/EncryptTokenGenerateBuilder.java | 2 +-
.../insert/EncryptInsertValuesTokenGenerator.java | 25 ++++++++++-
.../select/EncryptGroupByItemTokenGenerator.java | 52 +++++++++++-----------
.../EncryptInsertValuesTokenGeneratorTest.java | 6 ++-
.../connector/StandardDatabaseProxyConnector.java | 10 ++---
.../header/query/QueryHeaderBuilderEngine.java | 35 +++++++++++----
.../header/query/QueryHeaderBuilderEngineTest.java | 52 +++++++++++++++++++---
.../prepare/MySQLProjectionMetadataResolver.java | 4 +-
.../impl/ShardingSphereProxyEmbeddedContainer.java | 3 +-
.../storage/type/DockerStorageContainer.java | 2 +-
.../storage/type/NativeStorageContainer.java | 42 +++++++++++++----
.../test/e2e/sql/it/sql/dql/BaseDQLE2EIT.java | 17 ++++---
12 files changed, 185 insertions(+), 65 deletions(-)
diff --git
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/EncryptTokenGenerateBuilder.java
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/EncryptTokenGenerateBuilder.java
index f06a46f786a..ef5eb45481e 100644
---
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/EncryptTokenGenerateBuilder.java
+++
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/EncryptTokenGenerateBuilder.java
@@ -72,7 +72,7 @@ public final class EncryptTokenGenerateBuilder implements
SQLTokenGeneratorBuild
addSQLTokenGenerator(result, new
EncryptInsertPredicateColumnTokenGenerator(rule));
addSQLTokenGenerator(result, new
EncryptPredicateValueTokenGenerator(rule, database, encryptConditions));
addSQLTokenGenerator(result, new
EncryptInsertPredicateValueTokenGenerator(rule, database, encryptConditions));
- addSQLTokenGenerator(result, new
EncryptInsertValuesTokenGenerator(rule, database));
+ addSQLTokenGenerator(result, new
EncryptInsertValuesTokenGenerator(rule, database, sqlRewriteContext));
addSQLTokenGenerator(result, new
EncryptInsertDefaultColumnsTokenGenerator(rule));
addSQLTokenGenerator(result, new
EncryptInsertCipherNameTokenGenerator(rule));
addSQLTokenGenerator(result, new
EncryptInsertDerivedColumnsTokenGenerator(rule));
diff --git
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/insert/EncryptInsertValuesTokenGenerator.java
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/insert/EncryptInsertValuesTokenGenerator.java
index c69c0521bd3..ae14e6a125c 100644
---
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/insert/EncryptInsertValuesTokenGenerator.java
+++
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/insert/EncryptInsertValuesTokenGenerator.java
@@ -34,6 +34,7 @@ import
org.apache.shardingsphere.infra.binder.context.segment.insert.values.Inse
import
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
import
org.apache.shardingsphere.infra.binder.context.statement.type.dml.InsertStatementContext;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.infra.rewrite.context.SQLRewriteContext;
import
org.apache.shardingsphere.infra.rewrite.sql.token.common.generator.OptionalSQLTokenGenerator;
import
org.apache.shardingsphere.infra.rewrite.sql.token.common.generator.aware.PreviousSQLTokensAware;
import
org.apache.shardingsphere.infra.rewrite.sql.token.common.pojo.Attachable;
@@ -73,6 +74,8 @@ public final class EncryptInsertValuesTokenGenerator
implements OptionalSQLToken
private final ShardingSphereDatabase database;
+ private final SQLRewriteContext sqlRewriteContext;
+
private List<SQLToken> previousSQLTokens;
@Override
@@ -199,6 +202,13 @@ public final class EncryptInsertValuesTokenGenerator
implements OptionalSQLToken
return Optional.empty();
}
+ private Optional<String> getOriginalSQLExpressionText(final
ExpressionSegment valueExpression) {
+ if (null == sqlRewriteContext || valueExpression.getStartIndex() < 0
|| valueExpression.getStopIndex() >= sqlRewriteContext.getSql().length()) {
+ return Optional.empty();
+ }
+ return
Optional.of(sqlRewriteContext.getSql().substring(valueExpression.getStartIndex(),
valueExpression.getStopIndex() + 1));
+ }
+
private Optional<EncryptInsertColumnToken> addAssistedQueryColumn(final
String schemaName, final String tableName, final EncryptColumn encryptColumn,
final
ExpressionSegment valueExpression, final int columnIndex, final Object
originalValue,
final
int parameterIndexCount) {
@@ -248,13 +258,24 @@ public final class EncryptInsertValuesTokenGenerator
implements OptionalSQLToken
}
private Optional<String> getTemporalLiteralValue(final ExpressionSegment
valueExpression) {
- if (null == valueExpression.getText()) {
+ return
getTemporalLiteralExpressionText(valueExpression).flatMap(this::getTemporalLiteralValue);
+ }
+
+ private Optional<String> getTemporalLiteralValue(final String
expressionText) {
+ if (null == expressionText) {
return Optional.empty();
}
- Matcher matcher =
TEMPORAL_LITERAL_PATTERN.matcher(valueExpression.getText());
+ Matcher matcher = TEMPORAL_LITERAL_PATTERN.matcher(expressionText);
return matcher.matches() ? Optional.of(matcher.group(1)) :
Optional.empty();
}
+ private Optional<String> getTemporalLiteralExpressionText(final
ExpressionSegment valueExpression) {
+ if (getTemporalLiteralValue(valueExpression.getText()).isPresent()) {
+ return Optional.of(valueExpression.getText());
+ }
+ return getOriginalSQLExpressionText(valueExpression).filter(optional
-> getTemporalLiteralValue(optional).isPresent());
+ }
+
private int getParameterIndexCount(final Collection<ExpressionSegment>
expressionSegments) {
int result = 0;
for (ExpressionSegment each : expressionSegments) {
diff --git
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/select/EncryptGroupByItemTokenGenerator.java
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/select/EncryptGroupByItemTokenGenerator.java
index 463c020eadc..04d9de9a354 100644
---
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/select/EncryptGroupByItemTokenGenerator.java
+++
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/select/EncryptGroupByItemTokenGenerator.java
@@ -22,6 +22,7 @@ import lombok.Setter;
import
org.apache.shardingsphere.database.connector.core.metadata.database.enums.QuoteCharacter;
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
import
org.apache.shardingsphere.database.connector.core.type.DatabaseTypeRegistry;
+import org.apache.shardingsphere.encrypt.enums.EncryptDerivedColumnSuffix;
import org.apache.shardingsphere.encrypt.rule.EncryptRule;
import org.apache.shardingsphere.encrypt.rule.column.EncryptColumn;
import org.apache.shardingsphere.encrypt.rule.table.EncryptTable;
@@ -74,19 +75,25 @@ public final class EncryptGroupByItemTokenGenerator
implements CollectionSQLToke
@Override
public Collection<SQLToken> generateSQLTokens(final SelectStatementContext
sqlStatementContext) {
+ return generateGroupBySQLTokens(sqlStatementContext);
+ }
+
+ private Collection<SQLToken> generateGroupBySQLTokens(final
SelectStatementContext selectStatementContext) {
Collection<SQLToken> result = new LinkedList<>();
- for (GroupByContext each : getGroupByItems(sqlStatementContext)) {
- for (OrderByItem item : each.getItems()) {
- if (item.getSegment() instanceof ColumnOrderByItemSegment) {
- ColumnSegment columnSegment = ((ColumnOrderByItemSegment)
item.getSegment()).getColumn();
- generateSQLToken(columnSegment,
sqlStatementContext).ifPresent(result::add);
- }
+ GroupByContext groupByContext =
selectStatementContext.getGroupByContext();
+ for (OrderByItem item : groupByContext.getItems()) {
+ if (item.getSegment() instanceof ColumnOrderByItemSegment) {
+ ColumnSegment columnSegment = ((ColumnOrderByItemSegment)
item.getSegment()).getColumn();
+ generateSQLToken(columnSegment,
selectStatementContext).ifPresent(result::add);
}
}
+ for (SelectStatementContext each :
selectStatementContext.getSubqueryContexts().values()) {
+ result.addAll(generateGroupBySQLTokens(each));
+ }
return result;
}
- private Optional<SubstitutableColumnNameToken> generateSQLToken(final
ColumnSegment columnSegment, final SelectStatementContext
selectStatementContext) {
+ private Optional<SQLToken> generateSQLToken(final ColumnSegment
columnSegment, final SelectStatementContext selectStatementContext) {
DatabaseType databaseType =
selectStatementContext.getSqlStatement().getDatabaseType();
Optional<EncryptTable> encryptTable =
rule.findEncryptTable(columnSegment.getColumnBoundInfo().getOriginalTable().getValue());
String columnName =
columnSegment.getColumnBoundInfo().getOriginalColumn().getValue();
@@ -96,29 +103,24 @@ public final class EncryptGroupByItemTokenGenerator
implements CollectionSQLToke
EncryptColumn encryptColumn =
encryptTable.get().getEncryptColumn(columnName);
int startIndex = columnSegment.getOwner().isPresent() ?
columnSegment.getOwner().get().getStopIndex() + 2 :
columnSegment.getStartIndex();
int stopIndex = columnSegment.getStopIndex();
- QuoteCharacter quoteCharacter = getQuoteCharacter(columnSegment,
databaseType);
+ // SPEX CHANGED: BEGIN
return Optional.of(encryptColumn.getAssistedQuery()
- .map(optional -> new SubstitutableColumnNameToken(startIndex,
stopIndex, createColumnProjections(optional.getName(), quoteCharacter,
databaseType),
+ .map(optional -> new SubstitutableColumnNameToken(startIndex,
stopIndex,
+ createColumnProjections(optional.getName(),
columnSegment, databaseType, EncryptDerivedColumnSuffix.ASSISTED_QUERY),
databaseType))
.orElseGet(() -> new SubstitutableColumnNameToken(startIndex,
stopIndex,
-
createColumnProjections(encryptColumn.getCipher().getName(), quoteCharacter,
databaseType), databaseType)));
- }
-
- private Collection<GroupByContext> getGroupByItems(final
SelectStatementContext sqlStatementContext) {
- Collection<GroupByContext> result = new LinkedList<>();
- result.add(sqlStatementContext.getGroupByContext());
- for (SelectStatementContext each :
sqlStatementContext.getSubqueryContexts().values()) {
- result.addAll(getGroupByItems(each));
- }
- return result;
- }
-
- private QuoteCharacter getQuoteCharacter(final ColumnSegment
columnSegment, final DatabaseType databaseType) {
- return TableSourceType.PHYSICAL_TABLE ==
columnSegment.getColumnBoundInfo().getTableSourceType() ? new
DatabaseTypeRegistry(databaseType).getDialectDatabaseMetaData().getQuoteCharacter()
- : columnSegment.getIdentifier().getQuoteCharacter();
+
createColumnProjections(encryptColumn.getCipher().getName(), columnSegment,
databaseType, EncryptDerivedColumnSuffix.CIPHER), databaseType)));
+ // SPEX CHANGED: END
}
- private Collection<Projection> createColumnProjections(final String
columnName, final QuoteCharacter quoteCharacter, final DatabaseType
databaseType) {
+ private Collection<Projection> createColumnProjections(final String
actualColumnName, final ColumnSegment columnSegment, final DatabaseType
databaseType,
+ final
EncryptDerivedColumnSuffix derivedColumnSuffix) {
+ String columnName = TableSourceType.TEMPORARY_TABLE ==
columnSegment.getColumnBoundInfo().getTableSourceType()
+ ?
derivedColumnSuffix.getDerivedColumnName(columnSegment.getIdentifier().getValue(),
databaseType)
+ : actualColumnName;
+ QuoteCharacter quoteCharacter = TableSourceType.TEMPORARY_TABLE ==
columnSegment.getColumnBoundInfo().getTableSourceType()
+ ? columnSegment.getIdentifier().getQuoteCharacter()
+ : new
DatabaseTypeRegistry(databaseType).getDialectDatabaseMetaData().getQuoteCharacter();
return Collections.singleton(new ColumnProjection(null, new
IdentifierValue(columnName, quoteCharacter), null, databaseType));
}
}
diff --git
a/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/insert/EncryptInsertValuesTokenGeneratorTest.java
b/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/insert/EncryptInsertValuesTokenGeneratorTest.java
index 15b1b17bef0..d5337330e54 100644
---
a/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/insert/EncryptInsertValuesTokenGeneratorTest.java
+++
b/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/insert/EncryptInsertValuesTokenGeneratorTest.java
@@ -25,6 +25,7 @@ import
org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import
org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData;
import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
+import org.apache.shardingsphere.infra.rewrite.context.SQLRewriteContext;
import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.InsertValuesSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
@@ -49,6 +50,7 @@ import static org.hamcrest.Matchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
class EncryptInsertValuesTokenGeneratorTest {
@@ -58,8 +60,10 @@ class EncryptInsertValuesTokenGeneratorTest {
@BeforeEach
void setup() {
+ SQLRewriteContext sqlRewriteContext = mock(SQLRewriteContext.class);
+ when(sqlRewriteContext.getSql()).thenReturn("");
generator = new
EncryptInsertValuesTokenGenerator(EncryptGeneratorFixtureBuilder.createEncryptRule(),
- new ShardingSphereDatabase("foo_db", mock(), mock(), mock(),
Collections.emptyList(), new ConfigurationProperties(new Properties())));
+ new ShardingSphereDatabase("foo_db", mock(), mock(), mock(),
Collections.emptyList(), new ConfigurationProperties(new Properties())),
sqlRewriteContext);
}
@Test
diff --git
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/StandardDatabaseProxyConnector.java
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/StandardDatabaseProxyConnector.java
index 3076ab1fded..183643fa41d 100644
---
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/StandardDatabaseProxyConnector.java
+++
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/StandardDatabaseProxyConnector.java
@@ -300,9 +300,10 @@ public final class StandardDatabaseProxyConnector
implements DatabaseProxyConnec
int columnCount = getColumnCount(sqlStatementContext,
queryResultSample);
List<QueryHeader> result = new ArrayList<>(columnCount);
QueryHeaderBuilderEngine queryHeaderBuilderEngine = new
QueryHeaderBuilderEngine(database.getProtocolType());
+ Collection<ShardingSphereDatabase> databases =
queryContext.getMetaData().getAllDatabases();
ShardingSphereResultSetMetaData resultSetMetaData = new
ShardingSphereResultSetMetaData(queryResultSample.getMetaData().getResultSetMetaData(),
database, sqlStatementContext);
for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
- result.add(createQueryHeader(queryHeaderBuilderEngine,
sqlStatementContext, resultSetMetaData, database, columnIndex));
+ result.add(createQueryHeader(queryHeaderBuilderEngine,
sqlStatementContext, resultSetMetaData, database, databases, columnIndex));
}
return result;
}
@@ -314,10 +315,9 @@ public final class StandardDatabaseProxyConnector
implements DatabaseProxyConnec
}
private QueryHeader createQueryHeader(final QueryHeaderBuilderEngine
queryHeaderBuilderEngine, final SQLStatementContext sqlStatementContext,
- final
ShardingSphereResultSetMetaData resultSetMetaData, final ShardingSphereDatabase
database, final int columnIndex) throws SQLException {
- return containsDerivedProjections
- ? queryHeaderBuilderEngine.build(((SelectStatementContext)
sqlStatementContext).getProjectionsContext(), resultSetMetaData, database,
columnIndex)
- : queryHeaderBuilderEngine.build(resultSetMetaData, database,
columnIndex);
+ final
ShardingSphereResultSetMetaData resultSetMetaData, final ShardingSphereDatabase
database,
+ final
Collection<ShardingSphereDatabase> databases, final int columnIndex) throws
SQLException {
+ return queryHeaderBuilderEngine.build(sqlStatementContext,
resultSetMetaData, database, databases, columnIndex);
}
private MergedResult mergeQuery(final List<QueryResult> queryResults)
throws SQLException {
diff --git
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/response/header/query/QueryHeaderBuilderEngine.java
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/response/header/query/QueryHeaderBuilderEngine.java
index d43c26169b1..dd1ec10889e 100644
---
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/response/header/query/QueryHeaderBuilderEngine.java
+++
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/response/header/query/QueryHeaderBuilderEngine.java
@@ -21,12 +21,14 @@ import
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoa
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
import
org.apache.shardingsphere.driver.jdbc.core.resultset.ShardingSphereResultSetMetaData;
import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
-import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.ProjectionsContext;
+import
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+import
org.apache.shardingsphere.infra.binder.context.statement.type.dml.SelectStatementContext;
import org.apache.shardingsphere.infra.exception.ShardingSpherePreconditions;
import
org.apache.shardingsphere.infra.exception.kernel.syntax.ColumnIndexOutOfRangeException;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import java.sql.SQLException;
+import java.util.Collection;
/**
* Query header builder engine.
@@ -57,17 +59,34 @@ public final class QueryHeaderBuilderEngine {
/**
* Build query header builder.
*
- * @param projectionsContext projections context
+ * @param sqlStatementContext SQL statement context
* @param resultSetMetaData result set meta data
- * @param database database
+ * @param database current database
+ * @param databases available databases
* @param columnIndex column index
* @return query header
* @throws SQLException SQL exception
*/
- public QueryHeader build(final ProjectionsContext projectionsContext,
final ShardingSphereResultSetMetaData resultSetMetaData, final
ShardingSphereDatabase database,
- final int columnIndex) throws SQLException {
- ShardingSpherePreconditions.checkState(columnIndex <=
projectionsContext.getExpandProjections().size(), () -> new
ColumnIndexOutOfRangeException(columnIndex));
- Projection projection =
projectionsContext.getExpandProjections().get(columnIndex - 1);
- return queryHeaderBuilder.build(resultSetMetaData, database,
projection.getColumnName(), projection.getColumnLabel(), columnIndex);
+ public QueryHeader build(final SQLStatementContext sqlStatementContext,
final ShardingSphereResultSetMetaData resultSetMetaData, final
ShardingSphereDatabase database,
+ final Collection<ShardingSphereDatabase>
databases, final int columnIndex) throws SQLException {
+ Projection projection = findProjection(sqlStatementContext,
columnIndex);
+ return null == projection
+ ? build(resultSetMetaData, database, columnIndex)
+ : queryHeaderBuilder.build(resultSetMetaData, database,
projection.getColumnName(), projection.getColumnLabel(), columnIndex);
+ }
+
+ private Projection findProjection(final SQLStatementContext
sqlStatementContext, final int columnIndex) {
+ if (!(sqlStatementContext instanceof SelectStatementContext) ||
!((SelectStatementContext) sqlStatementContext).containsDerivedProjections()) {
+ return null;
+ }
+ checkColumnIndex(sqlStatementContext, columnIndex);
+ return ((SelectStatementContext)
sqlStatementContext).getProjectionsContext().getExpandProjections().get(columnIndex
- 1);
+ }
+
+ private void checkColumnIndex(final SQLStatementContext
sqlStatementContext, final int columnIndex) {
+ if (sqlStatementContext instanceof SelectStatementContext &&
((SelectStatementContext) sqlStatementContext).containsDerivedProjections()) {
+ ShardingSpherePreconditions.checkState(columnIndex <=
((SelectStatementContext)
sqlStatementContext).getProjectionsContext().getExpandProjections().size(),
+ () -> new ColumnIndexOutOfRangeException(columnIndex));
+ }
}
}
diff --git
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/response/header/query/QueryHeaderBuilderEngineTest.java
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/response/header/query/QueryHeaderBuilderEngineTest.java
index bf99744d57d..58b13bbf844 100644
---
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/response/header/query/QueryHeaderBuilderEngineTest.java
+++
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/response/header/query/QueryHeaderBuilderEngineTest.java
@@ -22,6 +22,8 @@ import
org.apache.shardingsphere.database.connector.core.type.DatabaseType;
import
org.apache.shardingsphere.driver.jdbc.core.resultset.ShardingSphereResultSetMetaData;
import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
import
org.apache.shardingsphere.infra.binder.context.segment.select.projection.ProjectionsContext;
+import
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+import
org.apache.shardingsphere.infra.binder.context.statement.type.dml.SelectStatementContext;
import
org.apache.shardingsphere.infra.exception.kernel.syntax.ColumnIndexOutOfRangeException;
import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
@@ -31,8 +33,8 @@ import org.mockito.MockedStatic;
import java.sql.SQLException;
import java.util.Collections;
-import static org.hamcrest.Matchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
@@ -59,12 +61,15 @@ class QueryHeaderBuilderEngineTest {
}
@Test
- void assertBuildWithProjections() throws SQLException {
+ void assertBuildWithDerivedProjections() throws SQLException {
Projection projection = mock(Projection.class);
when(projection.getColumnName()).thenReturn("c1");
when(projection.getColumnLabel()).thenReturn("l1");
when(projection.getExpression()).thenReturn("c1");
ProjectionsContext projectionsContext = new ProjectionsContext(0, 0,
false, Collections.singleton(projection));
+ SelectStatementContext sqlStatementContext =
mock(SelectStatementContext.class);
+
when(sqlStatementContext.containsDerivedProjections()).thenReturn(true);
+
when(sqlStatementContext.getProjectionsContext()).thenReturn(projectionsContext);
ShardingSphereResultSetMetaData resultSetMetaData =
mock(ShardingSphereResultSetMetaData.class);
ShardingSphereDatabase database = mock(ShardingSphereDatabase.class);
QueryHeader expectedQueryHeader = mock(QueryHeader.class);
@@ -72,22 +77,59 @@ class QueryHeaderBuilderEngineTest {
QueryHeaderBuilder queryHeaderBuilder =
mock(QueryHeaderBuilder.class);
when(queryHeaderBuilder.build(resultSetMetaData, database, "c1",
"l1", 1)).thenReturn(expectedQueryHeader);
spiLoader.when(() ->
DatabaseTypedSPILoader.getService(QueryHeaderBuilder.class,
databaseType)).thenReturn(queryHeaderBuilder);
- QueryHeader actualQueryHeader = new
QueryHeaderBuilderEngine(databaseType).build(projectionsContext,
resultSetMetaData, database, 1);
+ QueryHeader actualQueryHeader = new
QueryHeaderBuilderEngine(databaseType).build(sqlStatementContext,
resultSetMetaData, database, Collections.singleton(database), 1);
+ assertThat(actualQueryHeader, is(expectedQueryHeader));
+ }
+ }
+
+ @Test
+ void assertBuildWithDerivedProjectionsColumnIndexOutOfRange() {
+ Projection projection = mock(Projection.class);
+ when(projection.getColumnLabel()).thenReturn("label");
+ when(projection.getColumnName()).thenReturn("column");
+ when(projection.getExpression()).thenReturn("column");
+ ProjectionsContext projectionsContext = new ProjectionsContext(0, 0,
false, Collections.singleton(projection));
+ SelectStatementContext sqlStatementContext =
mock(SelectStatementContext.class);
+
when(sqlStatementContext.containsDerivedProjections()).thenReturn(true);
+
when(sqlStatementContext.getProjectionsContext()).thenReturn(projectionsContext);
+ try (MockedStatic<DatabaseTypedSPILoader> spiLoader =
mockStatic(DatabaseTypedSPILoader.class)) {
+ spiLoader.when(() ->
DatabaseTypedSPILoader.getService(QueryHeaderBuilder.class,
databaseType)).thenReturn(mock(QueryHeaderBuilder.class));
+ assertThrows(ColumnIndexOutOfRangeException.class,
+ () -> new
QueryHeaderBuilderEngine(databaseType).build(sqlStatementContext,
mock(ShardingSphereResultSetMetaData.class), mock(),
Collections.singleton(mock()), 2));
+ }
+ }
+
+ @Test
+ void assertBuildWithSQLStatementContext() throws SQLException {
+ SQLStatementContext sqlStatementContext =
mock(SQLStatementContext.class);
+ ShardingSphereResultSetMetaData resultSetMetaData =
mock(ShardingSphereResultSetMetaData.class);
+ when(resultSetMetaData.getColumnName(1)).thenReturn("col_name");
+ when(resultSetMetaData.getColumnLabel(1)).thenReturn("col_label");
+ ShardingSphereDatabase database = mock(ShardingSphereDatabase.class);
+ QueryHeader expectedQueryHeader = mock(QueryHeader.class);
+ try (MockedStatic<DatabaseTypedSPILoader> spiLoader =
mockStatic(DatabaseTypedSPILoader.class)) {
+ QueryHeaderBuilder queryHeaderBuilder =
mock(QueryHeaderBuilder.class);
+ when(queryHeaderBuilder.build(resultSetMetaData, database,
"col_name", "col_label", 1)).thenReturn(expectedQueryHeader);
+ spiLoader.when(() ->
DatabaseTypedSPILoader.getService(QueryHeaderBuilder.class,
databaseType)).thenReturn(queryHeaderBuilder);
+ QueryHeader actualQueryHeader = new
QueryHeaderBuilderEngine(databaseType).build(sqlStatementContext,
resultSetMetaData, database, Collections.singleton(database), 1);
assertThat(actualQueryHeader, is(expectedQueryHeader));
}
}
@Test
- void assertBuildWithProjectionsColumnIndexOutOfRange() {
+ void assertBuildWithSQLStatementContextColumnIndexOutOfRange() {
Projection projection = mock(Projection.class);
when(projection.getColumnLabel()).thenReturn("label");
when(projection.getColumnName()).thenReturn("column");
when(projection.getExpression()).thenReturn("column");
ProjectionsContext projectionsContext = new ProjectionsContext(0, 0,
false, Collections.singleton(projection));
+ SelectStatementContext sqlStatementContext =
mock(SelectStatementContext.class);
+
when(sqlStatementContext.containsDerivedProjections()).thenReturn(true);
+
when(sqlStatementContext.getProjectionsContext()).thenReturn(projectionsContext);
try (MockedStatic<DatabaseTypedSPILoader> spiLoader =
mockStatic(DatabaseTypedSPILoader.class)) {
spiLoader.when(() ->
DatabaseTypedSPILoader.getService(QueryHeaderBuilder.class,
databaseType)).thenReturn(mock(QueryHeaderBuilder.class));
assertThrows(ColumnIndexOutOfRangeException.class,
- () -> new
QueryHeaderBuilderEngine(databaseType).build(projectionsContext,
mock(ShardingSphereResultSetMetaData.class), mock(), 2));
+ () -> new
QueryHeaderBuilderEngine(databaseType).build(sqlStatementContext,
mock(ShardingSphereResultSetMetaData.class), mock(),
Collections.singleton(mock()), 2));
}
}
}
diff --git
a/proxy/frontend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/prepare/MySQLProjectionMetadataResolver.java
b/proxy/frontend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/prepare/MySQLProjectionMetadataResolver.java
index 9c6e417c078..ebd0a75fc32 100644
---
a/proxy/frontend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/prepare/MySQLProjectionMetadataResolver.java
+++
b/proxy/frontend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/binary/prepare/MySQLProjectionMetadataResolver.java
@@ -40,6 +40,7 @@ import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
/**
@@ -77,7 +78,8 @@ public final class MySQLProjectionMetadataResolver {
QueryHeaderBuilderEngine queryHeaderBuilderEngine = new
QueryHeaderBuilderEngine(database.getProtocolType());
Collection<MySQLPacket> result = new
ArrayList<>(selectStatementContext.getProjectionsContext().getExpandProjections().size());
for (int columnIndex = 1; columnIndex <=
selectStatementContext.getProjectionsContext().getExpandProjections().size();
columnIndex++) {
- QueryHeader queryHeader =
queryHeaderBuilderEngine.build(selectStatementContext.getProjectionsContext(),
resultSetMetaData, database, columnIndex);
+ QueryHeader queryHeader =
+ queryHeaderBuilderEngine.build(selectStatementContext,
resultSetMetaData, database, Collections.singleton(database), columnIndex);
result.add(createMySQLColumnDefinition41Packet(queryHeader,
characterSet));
}
return result;
diff --git
a/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/container/adapter/impl/ShardingSphereProxyEmbeddedContainer.java
b/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/container/adapter/impl/ShardingSphereProxyEmbeddedContainer.java
index a9c9bc6ed31..8e95cc4685d 100644
---
a/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/container/adapter/impl/ShardingSphereProxyEmbeddedContainer.java
+++
b/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/container/adapter/impl/ShardingSphereProxyEmbeddedContainer.java
@@ -127,7 +127,8 @@ public final class ShardingSphereProxyEmbeddedContainer
implements EmbeddedE2ECo
@SneakyThrows({SQLException.class, IOException.class,
InterruptedException.class})
private void startProxy() {
- YamlProxyConfiguration yamlConfig =
ProxyConfigurationLoader.load(getTempConfigurationDirectory().toString());
+ Path tempConfigurationDirectory = getTempConfigurationDirectory();
+ YamlProxyConfiguration yamlConfig =
ProxyConfigurationLoader.load(tempConfigurationDirectory.toString());
new BootstrapInitializer().init(yamlConfig, proxyPort);
ProxySSLContext.init();
proxy = new ShardingSphereProxy();
diff --git
a/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/container/storage/type/DockerStorageContainer.java
b/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/container/storage/type/DockerStorageContainer.java
index f812e679e83..f4a104b205f 100644
---
a/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/container/storage/type/DockerStorageContainer.java
+++
b/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/container/storage/type/DockerStorageContainer.java
@@ -165,7 +165,7 @@ public final class DockerStorageContainer extends
DockerE2EContainer implements
}
private Map<String, DataSource> createAccessDataSources(final
Collection<String> databaseNames) {
- return
databaseNames.stream().distinct().collect(Collectors.toMap(Function.identity(),
this::createAccessDataSource));
+ return
databaseNames.stream().distinct().collect(Collectors.toMap(Function.identity(),
this::createAccessDataSource, (previous, current) -> previous,
LinkedHashMap::new));
}
/**
diff --git
a/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/container/storage/type/NativeStorageContainer.java
b/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/container/storage/type/NativeStorageContainer.java
index 7cdc7831c5a..9b4653e4aaf 100644
---
a/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/container/storage/type/NativeStorageContainer.java
+++
b/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/container/storage/type/NativeStorageContainer.java
@@ -21,7 +21,6 @@ import lombok.Getter;
import lombok.Setter;
import
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
-import
org.apache.shardingsphere.test.e2e.env.container.constants.StorageContainerConstants;
import
org.apache.shardingsphere.test.e2e.env.container.storage.StorageContainer;
import
org.apache.shardingsphere.test.e2e.env.container.storage.mount.MountSQLResourceGenerator;
import
org.apache.shardingsphere.test.e2e.env.container.storage.option.StorageContainerOption;
@@ -37,6 +36,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -47,6 +47,8 @@ public final class NativeStorageContainer implements
StorageContainer {
private static final Collection<String> INITIALIZED_DATABASES = new
HashSet<>();
+ private static final String SQL_RESOURCE_SUFFIX = ".sql";
+
private final NativeDatabaseEnvironment env;
@Getter
@@ -89,14 +91,40 @@ public final class NativeStorageContainer implements
StorageContainer {
}
private void initDatabase(final String initDatabaseCacheKey) {
- DataSource dataSource =
StorageContainerUtils.generateDataSource(option.getConnectOption().getURL(env.getHost(),
env.getPort(databaseType)),
- env.getUser(), env.getPassword(), 2);
- new MountSQLResourceGenerator(option.getType(),
option.getCreateOption()).generate(0, scenario).keySet().forEach(each ->
SQLScriptUtils.execute(dataSource, each));
+ DataSource dataSource = createInitDataSource();
+ Map<String, String> mountedResources = generateMountedResources();
+ executeSQLScripts(dataSource, mountedResources.keySet());
INITIALIZED_DATABASES.add(initDatabaseCacheKey);
}
+ private Map<String, String> generateMountedResources() {
+ return new MountSQLResourceGenerator(option.getType(),
option.getCreateOption()).generate(getDefaultMajorVersion(), scenario);
+ }
+
+ private int getDefaultMajorVersion() {
+ List<Integer> supportedMajorVersions =
option.getCreateOption().getSupportedMajorVersions();
+ return supportedMajorVersions.isEmpty() ? 0 :
supportedMajorVersions.get(0);
+ }
+
+ private void executeSQLScripts(final DataSource dataSource, final
Collection<String> mountedResources) {
+ for (String each : mountedResources) {
+ if (each.endsWith(SQL_RESOURCE_SUFFIX)) {
+ SQLScriptUtils.execute(dataSource, each);
+ }
+ }
+ }
+
+ private DataSource createInitDataSource() {
+ return
StorageContainerUtils.generateDataSource(option.getConnectOption().getURL(env.getHost(),
env.getPort(databaseType)),
+ getInitUser(), env.getPassword(), 2);
+ }
+
+ private String getInitUser() {
+ return env.getUser();
+ }
+
private String getInitDatabaseCacheKey() {
- return String.join(":", String.valueOf(scenario),
databaseType.getType(), env.getHost(),
String.valueOf(env.getPort(databaseType)));
+ return String.join(":", String.valueOf(scenario),
databaseType.getType(), env.getHost(),
String.valueOf(env.getPort(databaseType)),
String.valueOf(getDefaultMajorVersion()));
}
private Map<String, DataSource> createDataSourceMap(final Type type) {
@@ -104,7 +132,7 @@ public final class NativeStorageContainer implements
StorageContainer {
}
private Map<String, DataSource> getDataSourceMap(final Collection<String>
databaseNames) {
- Map<String, DataSource> result = new HashMap<>(databaseNames.size(),
1F);
+ Map<String, DataSource> result = new
LinkedHashMap<>(databaseNames.size(), 1F);
for (String each : databaseNames) {
DataSource dataSource =
StorageContainerUtils.generateDataSource(option.getConnectOption().getURL(env.getHost(),
env.getPort(databaseType), each),
env.getUser(), env.getPassword(), 2);
@@ -137,8 +165,6 @@ public final class NativeStorageContainer implements
StorageContainer {
for (String each : getNetworkAliases()) {
result.put(each + ":" + getExposedPort(), env.getHost() + ":" +
env.getPort(databaseType));
}
- result.put(StorageContainerConstants.OPERATION_USER, env.getUser());
- result.put(StorageContainerConstants.OPERATION_PASSWORD,
env.getPassword());
return result;
}
}
diff --git
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/sql/it/sql/dql/BaseDQLE2EIT.java
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/sql/it/sql/dql/BaseDQLE2EIT.java
index 3c2e7e7ace6..6177de21254 100644
---
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/sql/it/sql/dql/BaseDQLE2EIT.java
+++
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/sql/it/sql/dql/BaseDQLE2EIT.java
@@ -108,11 +108,15 @@ public abstract class BaseDQLE2EIT implements SQLE2EIT {
}
private DataSource getExpectedDataSource(final AssertionTestParameter
testParam, final SQLE2EITContext context) {
- if (null != context.getAssertion().getExpectedDataSourceName() && 1 !=
getEnvironmentEngine().getExpectedDataSourceMap().size()) {
- return
getEnvironmentEngine().getExpectedDataSourceMap().get(context.getAssertion().getExpectedDataSourceName());
+ Map<String, DataSource> expectedDataSourceMap =
getEnvironmentEngine().getExpectedDataSourceMap();
+ if (null != context.getAssertion().getExpectedDataSourceName() && 1 !=
expectedDataSourceMap.size()) {
+ return
expectedDataSourceMap.get(context.getAssertion().getExpectedDataSourceName());
}
- DataSource result =
getEnvironmentEngine().getExpectedDataSourceMap().get(testParam.getScenario());
- return null == result ?
getFirstExpectedDataSource(getEnvironmentEngine().getExpectedDataSourceMap().values())
: result;
+ DataSource result = expectedDataSourceMap.get(testParam.getScenario());
+ if (null == result) {
+ result = expectedDataSourceMap.get(testParam.getScenario());
+ }
+ return null == result ?
getFirstExpectedDataSource(expectedDataSourceMap.values()) : result;
}
private void fillDataOnlyOnce(final AssertionTestParameter testParam)
throws IOException, JAXBException {
@@ -127,9 +131,8 @@ public abstract class BaseDQLE2EIT implements SQLE2EIT {
new DataSetEnvironmentManager(
new ScenarioDataPath(testParam.getScenario(),
Type.ACTUAL).getDataSetFile(), getEnvironmentEngine().getActualDataSourceMap(),
testParam.getDatabaseType()).fillData(Collections.emptyList());
- new DataSetEnvironmentManager(
- new ScenarioDataPath(testParam.getScenario(),
Type.EXPECTED).getDataSetFile(),
getEnvironmentEngine().getExpectedDataSourceMap(),
-
testParam.getDatabaseType()).fillData(Collections.emptyList());
+ new DataSetEnvironmentManager(new
ScenarioDataPath(testParam.getScenario(), Type.EXPECTED).getDataSetFile(),
+ getEnvironmentEngine().getExpectedDataSourceMap(),
testParam.getDatabaseType()).fillData(Collections.emptyList());
FILLED_SUITES.add(cacheKey);
}
}