You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by hu...@apache.org on 2026/07/02 05:59:13 UTC

(shardingsphere) branch master updated: Minor refacor in encrypt rewrite and QueryHeaderBuilderEngine (#38978)

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 <du...@apache.org>
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);
         }
     }