This is an automated email from the ASF dual-hosted git repository.

jianglongtao pushed a commit to branch fix-33341
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git

commit 2ad68571cea0715d7b071407dcd2370e3d6f217b
Author: Raigor <[email protected]>
AuthorDate: Fri Aug 16 11:46:44 2024 +0800

    Pick #32510, fix incorrect results for querying information_schema.SCHEMATA 
(#1)
    
    * Pick #32510, fix incorrect results for querying 
information_schema.SCHEMATA
    
    * Fix SelectInformationSchemataExecutorTest
---
 .../executor/AbstractDatabaseMetaDataExecutor.java | 18 ++----
 .../SelectInformationSchemataExecutor.java         | 73 +++++++++++++++-------
 .../SelectInformationSchemataExecutorTest.java     |  1 +
 3 files changed, 58 insertions(+), 34 deletions(-)

diff --git 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/admin/executor/AbstractDatabaseMetaDataExecutor.java
 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/admin/executor/AbstractDatabaseMetaDataExecutor.java
index b1884b4f2b4..33db8c08df3 100644
--- 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/admin/executor/AbstractDatabaseMetaDataExecutor.java
+++ 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/admin/executor/AbstractDatabaseMetaDataExecutor.java
@@ -70,7 +70,6 @@ public abstract class AbstractDatabaseMetaDataExecutor 
implements DatabaseAdminQ
     public final void execute(final ConnectionSession connectionSession) 
throws SQLException {
         Collection<String> databaseNames = getDatabaseNames(connectionSession);
         for (String databaseName : databaseNames) {
-            initDatabaseData(databaseName);
             processMetaData(databaseName, resultSet -> 
handleResultSet(databaseName, resultSet));
         }
         postProcess();
@@ -82,9 +81,10 @@ public abstract class AbstractDatabaseMetaDataExecutor 
implements DatabaseAdminQ
     private void handleResultSet(final String databaseName, final ResultSet 
resultSet) {
         ResultSetMetaData metaData = resultSet.getMetaData();
         while (resultSet.next()) {
-            Map<String, Object> rowMap = new LinkedHashMap<>();
-            Map<String, String> aliasMap = new LinkedHashMap<>();
-            for (int i = 1; i < metaData.getColumnCount() + 1; i++) {
+            int columnCount = metaData.getColumnCount();
+            Map<String, Object> rowMap = new LinkedHashMap<>(columnCount, 1F);
+            Map<String, String> aliasMap = new LinkedHashMap<>(columnCount, 
1F);
+            for (int i = 1; i < columnCount + 1; i++) {
                 aliasMap.put(metaData.getColumnName(i), 
metaData.getColumnLabel(i));
                 rowMap.put(metaData.getColumnLabel(i), resultSet.getString(i));
             }
@@ -100,11 +100,9 @@ public abstract class AbstractDatabaseMetaDataExecutor 
implements DatabaseAdminQ
         }
     }
     
-    protected abstract void initDatabaseData(String databaseName);
-    
     protected abstract Collection<String> getDatabaseNames(ConnectionSession 
connectionSession);
     
-    protected abstract void preProcess(String databaseName, Map<String, 
Object> rows, Map<String, String> alias);
+    protected abstract void preProcess(String databaseName, Map<String, 
Object> rows, Map<String, String> alias) throws SQLException;
     
     protected abstract void postProcess();
     
@@ -144,10 +142,6 @@ public abstract class AbstractDatabaseMetaDataExecutor 
implements DatabaseAdminQ
         
         private final List<Object> parameters;
         
-        @Override
-        protected void initDatabaseData(final String databaseName) {
-        }
-        
         @Override
         protected Collection<String> getDatabaseNames(final ConnectionSession 
connectionSession) {
             Optional<String> database = 
ProxyContext.getInstance().getAllDatabaseNames().stream().filter(each -> 
isAuthorized(each, connectionSession.getGrantee()))
@@ -175,7 +169,7 @@ public abstract class AbstractDatabaseMetaDataExecutor 
implements DatabaseAdminQ
         }
         
         @Override
-        protected void preProcess(final String databaseName, final Map<String, 
Object> rows, final Map<String, String> alias) {
+        protected void preProcess(final String databaseName, final Map<String, 
Object> rows, final Map<String, String> alias) throws SQLException {
         }
         
         @Override
diff --git 
a/proxy/backend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/information/SelectInformationSchemataExecutor.java
 
b/proxy/backend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/information/SelectInformationSchemataExecutor.java
index 2a1977247b2..22e32438fb6 100644
--- 
a/proxy/backend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/information/SelectInformationSchemataExecutor.java
+++ 
b/proxy/backend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/information/SelectInformationSchemataExecutor.java
@@ -18,6 +18,7 @@
 package 
org.apache.shardingsphere.proxy.backend.mysql.handler.admin.executor.information;
 
 import 
org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData;
+import 
org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import 
org.apache.shardingsphere.proxy.backend.handler.admin.executor.AbstractDatabaseMetaDataExecutor;
 import 
org.apache.shardingsphere.proxy.backend.handler.admin.executor.AbstractDatabaseMetaDataExecutor.DefaultDatabaseMetaDataExecutor;
@@ -27,7 +28,10 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.Projecti
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ShorthandProjectionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
 
+import java.sql.Connection;
+import java.sql.SQLException;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
@@ -84,7 +88,7 @@ public final class SelectInformationSchemataExecutor extends 
DefaultDatabaseMeta
     @Override
     protected Collection<String> getDatabaseNames(final ConnectionSession 
connectionSession) {
         Collection<String> databaseNames = 
ProxyContext.getInstance().getAllDatabaseNames().stream().filter(each -> 
isAuthorized(each, 
connectionSession.getGrantee())).collect(Collectors.toList());
-        SCHEMA_WITHOUT_DATA_SOURCE.addAll(databaseNames.stream().filter(each 
-> 
!AbstractDatabaseMetaDataExecutor.hasDataSource(each)).collect(Collectors.toSet()));
+        SCHEMA_WITHOUT_DATA_SOURCE.addAll(databaseNames.stream().filter(each 
-> !hasDataSource(each)).collect(Collectors.toSet()));
         Collection<String> result = 
databaseNames.stream().filter(AbstractDatabaseMetaDataExecutor::hasDataSource).collect(Collectors.toList());
         if (!SCHEMA_WITHOUT_DATA_SOURCE.isEmpty()) {
             fillSchemasWithoutDataSource();
@@ -92,21 +96,6 @@ public final class SelectInformationSchemataExecutor extends 
DefaultDatabaseMeta
         return result;
     }
     
-    @Override
-    protected void preProcess(final String databaseName, final Map<String, 
Object> rows, final Map<String, String> alias) {
-        ResourceMetaData resourceMetaData = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getDatabase(databaseName).getResourceMetaData();
-        Collection<String> catalogs = 
resourceMetaData.getStorageUnits().keySet()
-                .stream().map(each -> 
resourceMetaData.getStorageUnits().get(each).getCatalog()).collect(Collectors.toSet());
-        schemaNameAlias = alias.getOrDefault(SCHEMA_NAME, "");
-        String rowValue = rows.getOrDefault(schemaNameAlias, "").toString();
-        queryDatabase = !rowValue.isEmpty();
-        if (catalogs.contains(rowValue)) {
-            rows.replace(schemaNameAlias, databaseName);
-        } else {
-            rows.clear();
-        }
-    }
-    
     private void fillSchemasWithoutDataSource() {
         if (SCHEMA_WITHOUT_DATA_SOURCE.isEmpty()) {
             return;
@@ -114,21 +103,61 @@ public final class SelectInformationSchemataExecutor 
extends DefaultDatabaseMeta
         Map<String, String> defaultRowData = getTheDefaultRowData();
         SCHEMA_WITHOUT_DATA_SOURCE.forEach(each -> {
             Map<String, Object> row = new LinkedHashMap<>(defaultRowData);
-            row.replace(SCHEMA_NAME, each);
+            row.replace(schemaNameAlias, each);
             getRows().add(row);
         });
         SCHEMA_WITHOUT_DATA_SOURCE.clear();
     }
     
     private Map<String, String> getTheDefaultRowData() {
-        Map<String, String> result;
         Collection<ProjectionSegment> projections = 
sqlStatement.getProjections().getProjections();
         if 
(projections.stream().anyMatch(ShorthandProjectionSegment.class::isInstance)) {
-            result = Stream.of(CATALOG_NAME, SCHEMA_NAME, 
DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME, SQL_PATH, 
DEFAULT_ENCRYPTION).collect(Collectors.toMap(each -> each, each -> ""));
-        } else {
-            result = projections.stream().map(each -> 
((ColumnProjectionSegment) each).getColumn().getIdentifier())
-                    .map(each -> 
each.getValue().toUpperCase()).collect(Collectors.toMap(each -> each, each -> 
""));
+            return Stream.of(CATALOG_NAME, SCHEMA_NAME, 
DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME, SQL_PATH, 
DEFAULT_ENCRYPTION)
+                    .collect(Collectors.toMap(each -> each, each -> "", 
(oldValue, currentValue) -> oldValue, LinkedHashMap::new));
+        }
+        return getDefaultRowsFromProjections(projections);
+    }
+    
+    private Map<String, String> getDefaultRowsFromProjections(final 
Collection<ProjectionSegment> projections) {
+        Map<String, String> result = new LinkedHashMap<>(projections.size(), 
1F);
+        for (ProjectionSegment each : projections) {
+            if 
(!each.getClass().isAssignableFrom(ColumnProjectionSegment.class)) {
+                continue;
+            }
+            if (((ColumnProjectionSegment) each).getAlias().isPresent()) {
+                String alias = ((ColumnProjectionSegment) 
each).getAlias().get().getValue();
+                if (((ColumnProjectionSegment) 
each).getColumn().getIdentifier().getValue().equalsIgnoreCase(SCHEMA_NAME)) {
+                    schemaNameAlias = alias;
+                }
+                result.put(alias, "");
+                continue;
+            }
+            result.put(((ColumnProjectionSegment) 
each).getColumn().getIdentifier().getValue().toUpperCase(), "");
         }
         return result;
     }
+    
+    @Override
+    protected void preProcess(final String databaseName, final Map<String, 
Object> rows, final Map<String, String> alias) throws SQLException {
+        ResourceMetaData resourceMetaData = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getDatabase(databaseName).getResourceMetaData();
+        Collection<String> catalogs = getCatalogs(resourceMetaData);
+        schemaNameAlias = alias.getOrDefault(SCHEMA_NAME, "");
+        String rowValue = rows.getOrDefault(schemaNameAlias, "").toString();
+        queryDatabase = !rowValue.isEmpty();
+        if (catalogs.contains(rowValue)) {
+            rows.replace(schemaNameAlias, databaseName);
+        } else {
+            rows.clear();
+        }
+    }
+    
+    private Collection<String> getCatalogs(final ResourceMetaData 
resourceMetaData) throws SQLException {
+        Optional<StorageUnit> storageUnit = 
resourceMetaData.getStorageUnits().values().stream().findFirst();
+        if (!storageUnit.isPresent()) {
+            return Collections.emptySet();
+        }
+        try (Connection connection = 
storageUnit.get().getDataSource().getConnection()) {
+            return Collections.singleton(connection.getCatalog());
+        }
+    }
 }
diff --git 
a/proxy/backend/type/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/information/SelectInformationSchemataExecutorTest.java
 
b/proxy/backend/type/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/information/SelectInformationSchemataExecutorTest.java
index 5fe08b1e86e..85d2d214f6b 100644
--- 
a/proxy/backend/type/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/information/SelectInformationSchemataExecutorTest.java
+++ 
b/proxy/backend/type/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/executor/information/SelectInformationSchemataExecutorTest.java
@@ -186,6 +186,7 @@ class SelectInformationSchemataExecutorTest {
     private Connection mockConnection(final Map<String, String> 
expectedResultSetMap) throws SQLException {
         Connection result = mock(Connection.class, RETURNS_DEEP_STUBS);
         
when(result.getMetaData().getURL()).thenReturn("jdbc:mysql://localhost:3306/foo_ds");
+        when(result.getCatalog()).thenReturn("foo_ds");
         ResultSet resultSet = mockResultSet(expectedResultSetMap);
         
when(result.prepareStatement(any(String.class)).executeQuery()).thenReturn(resultSet);
         return result;

Reply via email to