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

duanzhengqiang 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 26fdf020748 Optimize database admin executor creator (#34608)
26fdf020748 is described below

commit 26fdf0207481d21bcecd43a74b85a46ff4619834
Author: jiangML <1060319...@qq.com>
AuthorDate: Sun Feb 9 11:44:16 2025 +0800

    Optimize database admin executor creator (#34608)
    
    * Optimize database admin executor creator
    
    * Fix test error
    
    * Optimize OpenGaussAdminExecutorCreator
    
    * Fix e2e test error
---
 .../opengauss/OpenGaussStatisticsCollector.java    | 51 ++++++++++++
 ...cs.collector.DialectDatabaseStatisticsCollector |  1 +
 .../MySQLInformationSchemaExecutorFactory.java     | 16 +++-
 .../admin/OpenGaussAdminExecutorCreator.java       | 94 ++++++++++++++++++----
 .../admin/OpenGaussAdminExecutorCreatorTest.java   | 41 ++++++++--
 .../admin/OpenGaussAdminExecutorFactoryTest.java   | 49 +++++++----
 .../admin/PostgreSQLAdminExecutorCreator.java      | 84 ++++++++++++++++---
 7 files changed, 287 insertions(+), 49 deletions(-)

diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/statistics/collector/opengauss/OpenGaussStatisticsCollector.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/statistics/collector/opengauss/OpenGaussStatisticsCollector.java
new file mode 100644
index 00000000000..461c6bdebc7
--- /dev/null
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/metadata/statistics/collector/opengauss/OpenGaussStatisticsCollector.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 
org.apache.shardingsphere.infra.metadata.statistics.collector.opengauss;
+
+import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import 
org.apache.shardingsphere.infra.metadata.statistics.collector.DialectDatabaseStatisticsCollector;
+import 
org.apache.shardingsphere.infra.metadata.statistics.collector.postgresql.PostgreSQLStatisticsCollector;
+
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * Statistics collector for openGauss.
+ */
+public final class OpenGaussStatisticsCollector implements 
DialectDatabaseStatisticsCollector {
+    
+    private final PostgreSQLStatisticsCollector delegated = new 
PostgreSQLStatisticsCollector();
+    
+    @Override
+    public Map<String, Collection<String>> getStatisticsSchemaTables() {
+        return delegated.getStatisticsSchemaTables();
+    }
+    
+    @Override
+    public Optional<Collection<Map<String, Object>>> 
collectRowColumnValues(final String databaseName, final String schemaName, 
final String tableName,
+                                                                            
final ShardingSphereMetaData metaData) throws SQLException {
+        return delegated.collectRowColumnValues(databaseName, schemaName, 
tableName, metaData);
+    }
+    
+    @Override
+    public String getDatabaseType() {
+        return "openGauss";
+    }
+}
diff --git 
a/infra/common/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.metadata.statistics.collector.DialectDatabaseStatisticsCollector
 
b/infra/common/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.metadata.statistics.collector.DialectDatabaseStatisticsCollector
index c1ee220d54d..41ca193f35a 100644
--- 
a/infra/common/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.metadata.statistics.collector.DialectDatabaseStatisticsCollector
+++ 
b/infra/common/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.metadata.statistics.collector.DialectDatabaseStatisticsCollector
@@ -17,3 +17,4 @@
 
 
org.apache.shardingsphere.infra.metadata.statistics.collector.shardingsphere.ShardingSphereStatisticsCollector
 
org.apache.shardingsphere.infra.metadata.statistics.collector.postgresql.PostgreSQLStatisticsCollector
+org.apache.shardingsphere.infra.metadata.statistics.collector.opengauss.OpenGaussStatisticsCollector
diff --git 
a/proxy/backend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLInformationSchemaExecutorFactory.java
 
b/proxy/backend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLInformationSchemaExecutorFactory.java
index c13ddef2562..0157d62bf18 100644
--- 
a/proxy/backend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLInformationSchemaExecutorFactory.java
+++ 
b/proxy/backend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLInformationSchemaExecutorFactory.java
@@ -26,7 +26,11 @@ import 
org.apache.shardingsphere.proxy.backend.mysql.handler.admin.executor.info
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.dml.SelectStatement;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Optional;
 
 /**
@@ -50,12 +54,22 @@ public final class MySQLInformationSchemaExecutorFactory {
             return Optional.empty();
         }
         String tableName = ((SimpleTableSegment) 
sqlStatement.getFrom().get()).getTableName().getIdentifier().getValue();
+        Map<String, Collection<String>> selectedSchemaTables = 
Collections.singletonMap("information_schema", 
Collections.singletonList(tableName));
         if (SCHEMATA_TABLE.equalsIgnoreCase(tableName)) {
             return Optional.of(new 
SelectInformationSchemataExecutor(sqlStatement, sql, parameters));
         }
-        if (SystemSchemaManager.isSystemTable("mysql", "information_schema", 
tableName)) {
+        if (isSelectSystemTable(selectedSchemaTables)) {
             return Optional.of(new DefaultDatabaseMetaDataExecutor(sql, 
parameters));
         }
         return Optional.empty();
     }
+    
+    private static boolean isSelectSystemTable(final Map<String, 
Collection<String>> selectedSchemaTableNames) {
+        for (Entry<String, Collection<String>> each : 
selectedSchemaTableNames.entrySet()) {
+            if (!SystemSchemaManager.isSystemTable("mysql", each.getKey(), 
each.getValue())) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
diff --git 
a/proxy/backend/type/opengauss/src/main/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorCreator.java
 
b/proxy/backend/type/opengauss/src/main/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorCreator.java
index 6e91bdac1e4..45db5398953 100644
--- 
a/proxy/backend/type/opengauss/src/main/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorCreator.java
+++ 
b/proxy/backend/type/opengauss/src/main/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorCreator.java
@@ -17,23 +17,34 @@
 
 package org.apache.shardingsphere.proxy.backend.opengauss.handler.admin;
 
+import com.cedarsoftware.util.CaseInsensitiveMap;
 import com.cedarsoftware.util.CaseInsensitiveSet;
+import com.google.common.base.Strings;
 import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
 import org.apache.shardingsphere.infra.binder.context.type.TableAvailable;
+import 
org.apache.shardingsphere.infra.database.core.spi.DatabaseTypedSPILoader;
+import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.manager.SystemSchemaManager;
+import 
org.apache.shardingsphere.infra.metadata.statistics.collector.DialectDatabaseStatisticsCollector;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import 
org.apache.shardingsphere.proxy.backend.handler.admin.executor.AbstractDatabaseMetaDataExecutor.DefaultDatabaseMetaDataExecutor;
 import 
org.apache.shardingsphere.proxy.backend.handler.admin.executor.DatabaseAdminExecutor;
 import 
org.apache.shardingsphere.proxy.backend.handler.admin.executor.DatabaseAdminExecutorCreator;
 import 
org.apache.shardingsphere.proxy.backend.postgresql.handler.admin.PostgreSQLAdminExecutorCreator;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ExpressionProjectionSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableNameSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.dal.ShowStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.dml.SelectStatement;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Optional;
 
 /**
@@ -43,7 +54,7 @@ public final class OpenGaussAdminExecutorCreator implements 
DatabaseAdminExecuto
     
     private static final Collection<String> SYSTEM_CATALOG_QUERY_EXPRESSIONS = 
new CaseInsensitiveSet<>();
     
-    private static final Collection<String> SYSTEM_CATALOG_TABLES = new 
CaseInsensitiveSet<>();
+    private static final Map<String, Collection<String>> SCHEMA_TABLES = new 
CaseInsensitiveMap<>();
     
     static {
         SYSTEM_CATALOG_QUERY_EXPRESSIONS.add("VERSION()");
@@ -56,11 +67,8 @@ public final class OpenGaussAdminExecutorCreator implements 
DatabaseAdminExecuto
         SYSTEM_CATALOG_QUERY_EXPRESSIONS.add("pg_catalog.intervaltonum()");
         
SYSTEM_CATALOG_QUERY_EXPRESSIONS.add("pg_catalog.intervaltonum(pg_catalog.gs_password_deadline())");
         
SYSTEM_CATALOG_QUERY_EXPRESSIONS.add("pg_catalog.gs_password_notifytime()");
-        SYSTEM_CATALOG_TABLES.add("pg_class");
-        SYSTEM_CATALOG_TABLES.add("pg_namespace");
-        SYSTEM_CATALOG_TABLES.add("pg_database");
-        SYSTEM_CATALOG_TABLES.add("pg_tables");
-        SYSTEM_CATALOG_TABLES.add("pg_roles");
+        SCHEMA_TABLES.put("pg_catalog", new 
CaseInsensitiveSet<>(Arrays.asList("pg_class", "pg_namespace", "pg_database", 
"pg_tables", "pg_roles")));
+        SCHEMA_TABLES.put("shardingsphere", new 
CaseInsensitiveSet<>(Arrays.asList("cluster_information", 
"sharding_table_statistics")));
     }
     
     private final PostgreSQLAdminExecutorCreator delegated = new 
PostgreSQLAdminExecutorCreator();
@@ -76,18 +84,68 @@ public final class OpenGaussAdminExecutorCreator implements 
DatabaseAdminExecuto
     
     @Override
     public Optional<DatabaseAdminExecutor> create(final SQLStatementContext 
sqlStatementContext, final String sql, final String databaseName, final 
List<Object> parameters) {
-        if (isSQLFederationSystemCatalogQuery(sqlStatementContext) || 
isSQLFederationSystemCatalogQueryExpressions(sqlStatementContext)) {
+        Map<String, Collection<String>> selectedSchemaTables = 
sqlStatementContext instanceof TableAvailable ? 
getSelectedSchemaTables(sqlStatementContext) : Collections.emptyMap();
+        if (isSQLFederationSystemCatalogQuery(selectedSchemaTables) || 
isSQLFederationSystemCatalogQueryExpressions(sqlStatementContext)) {
             return Optional.of(new 
OpenGaussSystemCatalogAdminQueryExecutor(sqlStatementContext, sql, 
databaseName, parameters));
         }
-        if (isPassThroughSystemCatalogQuery(sqlStatementContext)) {
+        if (isPassThroughSystemCatalogQuery(selectedSchemaTables)) {
             return Optional.of(new DefaultDatabaseMetaDataExecutor(sql, 
parameters));
         }
         return delegated.create(sqlStatementContext, sql, databaseName, 
parameters);
     }
     
-    private boolean isSQLFederationSystemCatalogQuery(final 
SQLStatementContext sqlStatementContext) {
-        Collection<String> tableNames = sqlStatementContext instanceof 
TableAvailable ? ((TableAvailable) 
sqlStatementContext).getTablesContext().getTableNames() : 
Collections.emptyList();
-        return !tableNames.isEmpty() && 
SYSTEM_CATALOG_TABLES.containsAll(tableNames);
+    private Map<String, Collection<String>> getSelectedSchemaTables(final 
SQLStatementContext sqlStatementContext) {
+        Map<String, Collection<String>> result = new CaseInsensitiveMap<>();
+        for (SimpleTableSegment each : ((TableAvailable) 
sqlStatementContext).getTablesContext().getSimpleTables()) {
+            TableNameSegment tableNameSegment = each.getTableName();
+            String schemaName = 
tableNameSegment.getTableBoundInfo().map(optional -> 
optional.getOriginalSchema().getValue()).orElse(null);
+            schemaName = Strings.isNullOrEmpty(schemaName) ? 
each.getOwner().map(optional -> 
optional.getIdentifier().getValue()).orElse(null) : schemaName;
+            if (!Strings.isNullOrEmpty(schemaName)) {
+                Collection<String> tables = result.getOrDefault(schemaName, 
new CaseInsensitiveSet<>());
+                tables.add(tableNameSegment.getIdentifier().getValue());
+                result.put(schemaName, tables);
+            }
+        }
+        return result;
+    }
+    
+    private boolean isSQLFederationSystemCatalogQuery(final Map<String, 
Collection<String>> selectedSchemaTables) {
+        if (isSelectedStatisticsSystemTable(selectedSchemaTables)) {
+            return true;
+        }
+        if (selectedSchemaTables.isEmpty()) {
+            return false;
+        }
+        for (Entry<String, Collection<String>> each : 
selectedSchemaTables.entrySet()) {
+            if (!SCHEMA_TABLES.containsKey(each.getKey())) {
+                return false;
+            }
+            if 
(!SCHEMA_TABLES.get(each.getKey()).containsAll(each.getValue())) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    private boolean isSelectedStatisticsSystemTable(final Map<String, 
Collection<String>> selectedSchemaTables) {
+        if (selectedSchemaTables.isEmpty()) {
+            return false;
+        }
+        DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "openGauss");
+        Optional<DialectDatabaseStatisticsCollector> 
dialectStatisticsCollector = 
DatabaseTypedSPILoader.findService(DialectDatabaseStatisticsCollector.class, 
databaseType);
+        if (!dialectStatisticsCollector.isPresent()) {
+            return false;
+        }
+        Map<String, Collection<String>> statisticalSchemaTables = 
dialectStatisticsCollector.get().getStatisticsSchemaTables();
+        for (Entry<String, Collection<String>> each : 
selectedSchemaTables.entrySet()) {
+            if (!statisticalSchemaTables.containsKey(each.getKey())) {
+                return false;
+            }
+            if 
(!statisticalSchemaTables.get(each.getKey()).containsAll(each.getValue())) {
+                return false;
+            }
+        }
+        return true;
     }
     
     private boolean isSQLFederationSystemCatalogQueryExpressions(final 
SQLStatementContext sqlStatementContext) {
@@ -100,10 +158,16 @@ public final class OpenGaussAdminExecutorCreator 
implements DatabaseAdminExecuto
                 && 
SYSTEM_CATALOG_QUERY_EXPRESSIONS.contains(((ExpressionProjectionSegment) 
projections.iterator().next()).getText());
     }
     
-    private boolean isPassThroughSystemCatalogQuery(final SQLStatementContext 
sqlStatementContext) {
-        Collection<String> tableNames = sqlStatementContext instanceof 
TableAvailable ? ((TableAvailable) 
sqlStatementContext).getTablesContext().getTableNames() : 
Collections.emptyList();
-        return !tableNames.isEmpty() && 
(SystemSchemaManager.isSystemTable("opengauss", "information_schema", 
tableNames)
-                || SystemSchemaManager.isSystemTable("opengauss", 
"pg_catalog", tableNames));
+    private boolean isPassThroughSystemCatalogQuery(final Map<String, 
Collection<String>> selectedSchemaTables) {
+        if (selectedSchemaTables.isEmpty()) {
+            return false;
+        }
+        for (Entry<String, Collection<String>> each : 
selectedSchemaTables.entrySet()) {
+            if (!SystemSchemaManager.isSystemTable("opengauss", each.getKey(), 
each.getValue())) {
+                return false;
+            }
+        }
+        return true;
     }
     
     @Override
diff --git 
a/proxy/backend/type/opengauss/src/test/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorCreatorTest.java
 
b/proxy/backend/type/opengauss/src/test/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorCreatorTest.java
index a2989580f54..2b67d868c02 100644
--- 
a/proxy/backend/type/opengauss/src/test/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorCreatorTest.java
+++ 
b/proxy/backend/type/opengauss/src/test/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorCreatorTest.java
@@ -20,9 +20,18 @@ package 
org.apache.shardingsphere.proxy.backend.opengauss.handler.admin;
 import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
 import 
org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatementContext;
 import org.apache.shardingsphere.infra.binder.context.type.TableAvailable;
+import 
org.apache.shardingsphere.infra.database.core.spi.DatabaseTypedSPILoader;
+import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
+import 
org.apache.shardingsphere.infra.metadata.statistics.collector.DialectDatabaseStatisticsCollector;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import 
org.apache.shardingsphere.proxy.backend.handler.admin.executor.DatabaseAdminExecutor;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ExpressionProjectionSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.bound.TableSegmentBoundInfo;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.test.mock.AutoMockExtension;
+import org.apache.shardingsphere.test.mock.StaticMockSettings;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
 
 import java.util.Collections;
 import java.util.Optional;
@@ -36,12 +45,14 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.withSettings;
 
+@ExtendWith(AutoMockExtension.class)
+@StaticMockSettings(DatabaseTypedSPILoader.class)
 class OpenGaussAdminExecutorCreatorTest {
     
     @Test
     void assertCreateExecutorForSelectDatabase() {
-        SelectStatementContext selectStatementContext = 
mock(SelectStatementContext.class, RETURNS_DEEP_STUBS);
-        
when(selectStatementContext.getTablesContext().getTableNames()).thenReturn(Collections.singletonList("pg_database"));
+        setUp("pg_database");
+        SelectStatementContext selectStatementContext = 
mockSelectStatementContext("pg_database");
         Optional<DatabaseAdminExecutor> actual = new 
OpenGaussAdminExecutorCreator()
                 .create(selectStatementContext, "select datname, 
datcompatibility from pg_database where datname = 'sharding_db'", "postgres", 
Collections.emptyList());
         assertTrue(actual.isPresent());
@@ -50,8 +61,8 @@ class OpenGaussAdminExecutorCreatorTest {
     
     @Test
     void assertCreateExecutorForSelectTables() {
-        SelectStatementContext selectStatementContext = 
mock(SelectStatementContext.class, RETURNS_DEEP_STUBS);
-        
when(selectStatementContext.getTablesContext().getTableNames()).thenReturn(Collections.singletonList("pg_tables"));
+        setUp("pg_tables");
+        SelectStatementContext selectStatementContext = 
mockSelectStatementContext("pg_tables");
         Optional<DatabaseAdminExecutor> actual = new 
OpenGaussAdminExecutorCreator()
                 .create(selectStatementContext, "select schemaname, tablename 
from pg_tables where schemaname = 'sharding_db'", "postgres", 
Collections.emptyList());
         assertTrue(actual.isPresent());
@@ -60,8 +71,8 @@ class OpenGaussAdminExecutorCreatorTest {
     
     @Test
     void assertCreateExecutorForSelectRoles() {
-        SelectStatementContext selectStatementContext = 
mock(SelectStatementContext.class, RETURNS_DEEP_STUBS);
-        
when(selectStatementContext.getTablesContext().getTableNames()).thenReturn(Collections.singletonList("pg_roles"));
+        setUp("pg_roles");
+        SelectStatementContext selectStatementContext = 
mockSelectStatementContext("pg_roles");
         Optional<DatabaseAdminExecutor> actual = new 
OpenGaussAdminExecutorCreator()
                 .create(selectStatementContext, "select rolname from 
pg_roles", "postgres", Collections.emptyList());
         assertTrue(actual.isPresent());
@@ -85,4 +96,22 @@ class OpenGaussAdminExecutorCreatorTest {
         assertThat(creator.create(sqlStatementContext), is(Optional.empty()));
         assertThat(creator.create(sqlStatementContext, "", "", 
Collections.emptyList()), is(Optional.empty()));
     }
+    
+    private void setUp(final String tableName) {
+        DialectDatabaseStatisticsCollector statisticsCollector = 
mock(DialectDatabaseStatisticsCollector.class);
+        
when(statisticsCollector.getStatisticsSchemaTables()).thenReturn(Collections.singletonMap("pg_catalog",
 Collections.singletonList(tableName)));
+        
when(DatabaseTypedSPILoader.findService(DialectDatabaseStatisticsCollector.class,
 TypedSPILoader.getService(DatabaseType.class, 
"openGauss"))).thenReturn(Optional.of(statisticsCollector));
+    }
+    
+    private SelectStatementContext mockSelectStatementContext(final String 
tableName) {
+        SimpleTableSegment simpleTableSegment = mock(SimpleTableSegment.class, 
RETURNS_DEEP_STUBS);
+        
when(simpleTableSegment.getTableName().getIdentifier().getValue()).thenReturn(tableName);
+        TableSegmentBoundInfo tableSegmentBoundInfo = 
mock(TableSegmentBoundInfo.class, RETURNS_DEEP_STUBS);
+        
when(tableSegmentBoundInfo.getOriginalSchema().getValue()).thenReturn("pg_catalog");
+        
when(simpleTableSegment.getTableName().getTableBoundInfo()).thenReturn(Optional.of(tableSegmentBoundInfo));
+        SelectStatementContext result = mock(SelectStatementContext.class, 
RETURNS_DEEP_STUBS);
+        
when(result.getTablesContext().getSimpleTables()).thenReturn(Collections.singletonList(simpleTableSegment));
+        
when(result.getTablesContext().getTableNames()).thenReturn(Collections.singletonList(tableName));
+        return result;
+    }
 }
diff --git 
a/proxy/backend/type/opengauss/src/test/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorFactoryTest.java
 
b/proxy/backend/type/opengauss/src/test/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorFactoryTest.java
index 2d7f9536c04..da250b123aa 100644
--- 
a/proxy/backend/type/opengauss/src/test/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorFactoryTest.java
+++ 
b/proxy/backend/type/opengauss/src/test/java/org/apache/shardingsphere/proxy/backend/opengauss/handler/admin/OpenGaussAdminExecutorFactoryTest.java
@@ -19,16 +19,22 @@ package 
org.apache.shardingsphere.proxy.backend.opengauss.handler.admin;
 
 import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
 import 
org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatementContext;
+import 
org.apache.shardingsphere.infra.database.core.spi.DatabaseTypedSPILoader;
+import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
+import 
org.apache.shardingsphere.infra.metadata.statistics.collector.DialectDatabaseStatisticsCollector;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import 
org.apache.shardingsphere.proxy.backend.handler.admin.executor.DatabaseAdminExecutor;
 import 
org.apache.shardingsphere.proxy.backend.postgresql.handler.admin.PostgreSQLAdminExecutorCreator;
-import 
org.apache.shardingsphere.sql.parser.statement.core.statement.dml.SelectStatement;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.bound.TableSegmentBoundInfo;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.opengauss.dal.OpenGaussShowStatement;
+import org.apache.shardingsphere.test.mock.AutoMockExtension;
+import org.apache.shardingsphere.test.mock.StaticMockSettings;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Mock;
 import org.mockito.internal.configuration.plugins.Plugins;
-import org.mockito.junit.jupiter.MockitoExtension;
 
 import java.util.Collections;
 import java.util.Optional;
@@ -41,7 +47,8 @@ import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
-@ExtendWith(MockitoExtension.class)
+@ExtendWith(AutoMockExtension.class)
+@StaticMockSettings(DatabaseTypedSPILoader.class)
 class OpenGaussAdminExecutorFactoryTest {
     
     @Mock
@@ -63,18 +70,6 @@ class OpenGaussAdminExecutorFactoryTest {
         assertTrue(actual.isPresent());
     }
     
-    @Test
-    void assertNewInstanceWithSelectDatabase() {
-        SelectStatementContext sqlStatementContext = 
mock(SelectStatementContext.class, RETURNS_DEEP_STUBS);
-        SelectStatement statement = mock(SelectStatement.class, 
RETURNS_DEEP_STUBS);
-        when(sqlStatementContext.getSqlStatement()).thenReturn(statement);
-        
when(sqlStatementContext.getTablesContext().getTableNames()).thenReturn(Collections.singletonList("pg_database"));
-        String sql = "select datcompatibility from pg_database where datname = 
'sharding_db'";
-        Optional<DatabaseAdminExecutor> actual = 
openGaussAdminExecutorFactory.create(sqlStatementContext, sql, "", 
Collections.emptyList());
-        assertTrue(actual.isPresent());
-        assertThat(actual.get(), 
instanceOf(OpenGaussSystemCatalogAdminQueryExecutor.class));
-    }
-    
     @Test
     void assertNewInstanceWithOtherSQL() {
         SelectStatementContext sqlStatementContext = 
mock(SelectStatementContext.class, RETURNS_DEEP_STUBS);
@@ -85,4 +80,28 @@ class OpenGaussAdminExecutorFactoryTest {
         assertTrue(actual.isPresent());
         assertThat(actual.get(), is(expected));
     }
+    
+    @Test
+    void assertNewInstanceWithSelectDatabase() {
+        DialectDatabaseStatisticsCollector statisticsCollector = 
mock(DialectDatabaseStatisticsCollector.class);
+        
when(statisticsCollector.getStatisticsSchemaTables()).thenReturn(Collections.singletonMap("pg_catalog",
 Collections.singletonList("pg_database")));
+        
when(DatabaseTypedSPILoader.findService(DialectDatabaseStatisticsCollector.class,
 TypedSPILoader.getService(DatabaseType.class, 
"openGauss"))).thenReturn(Optional.of(statisticsCollector));
+        SelectStatementContext sqlStatementContext = 
mockSelectStatementContext();
+        String sql = "select datcompatibility from pg_database where datname = 
'sharding_db'";
+        Optional<DatabaseAdminExecutor> actual = 
openGaussAdminExecutorFactory.create(sqlStatementContext, sql, "", 
Collections.emptyList());
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), 
instanceOf(OpenGaussSystemCatalogAdminQueryExecutor.class));
+    }
+    
+    private SelectStatementContext mockSelectStatementContext() {
+        SimpleTableSegment simpleTableSegment = mock(SimpleTableSegment.class, 
RETURNS_DEEP_STUBS);
+        
when(simpleTableSegment.getTableName().getIdentifier().getValue()).thenReturn("pg_database");
+        TableSegmentBoundInfo tableSegmentBoundInfo = 
mock(TableSegmentBoundInfo.class, RETURNS_DEEP_STUBS);
+        
when(tableSegmentBoundInfo.getOriginalSchema().getValue()).thenReturn("pg_catalog");
+        
when(simpleTableSegment.getTableName().getTableBoundInfo()).thenReturn(Optional.of(tableSegmentBoundInfo));
+        SelectStatementContext result = mock(SelectStatementContext.class, 
RETURNS_DEEP_STUBS);
+        
when(result.getTablesContext().getSimpleTables()).thenReturn(Collections.singletonList(simpleTableSegment));
+        
when(result.getTablesContext().getTableNames()).thenReturn(Collections.singletonList("pg_database"));
+        return result;
+    }
 }
diff --git 
a/proxy/backend/type/postgresql/src/main/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLAdminExecutorCreator.java
 
b/proxy/backend/type/postgresql/src/main/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLAdminExecutorCreator.java
index 866fd0a8182..124fe3d4728 100644
--- 
a/proxy/backend/type/postgresql/src/main/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLAdminExecutorCreator.java
+++ 
b/proxy/backend/type/postgresql/src/main/java/org/apache/shardingsphere/proxy/backend/postgresql/handler/admin/PostgreSQLAdminExecutorCreator.java
@@ -17,8 +17,14 @@
 
 package org.apache.shardingsphere.proxy.backend.postgresql.handler.admin;
 
+import com.cedarsoftware.util.CaseInsensitiveMap;
+import com.cedarsoftware.util.CaseInsensitiveSet;
 import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+import 
org.apache.shardingsphere.infra.database.core.spi.DatabaseTypedSPILoader;
+import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.manager.SystemSchemaManager;
+import 
org.apache.shardingsphere.infra.metadata.statistics.collector.DialectDatabaseStatisticsCollector;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import 
org.apache.shardingsphere.proxy.backend.handler.admin.executor.AbstractDatabaseMetaDataExecutor.DefaultDatabaseMetaDataExecutor;
 import 
org.apache.shardingsphere.proxy.backend.handler.admin.executor.DatabaseAdminExecutor;
 import 
org.apache.shardingsphere.proxy.backend.handler.admin.executor.DatabaseAdminExecutorCreator;
@@ -26,6 +32,7 @@ import 
org.apache.shardingsphere.proxy.backend.postgresql.handler.admin.executor
 import 
org.apache.shardingsphere.proxy.backend.postgresql.handler.admin.executor.PostgreSQLSetVariableAdminExecutor;
 import 
org.apache.shardingsphere.proxy.backend.postgresql.handler.admin.executor.PostgreSQLShowVariableExecutor;
 import 
org.apache.shardingsphere.sql.parser.statement.core.extractor.TableExtractor;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.OwnerSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SubqueryTableSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableSegment;
@@ -35,11 +42,12 @@ import 
org.apache.shardingsphere.sql.parser.statement.core.statement.dal.SetStat
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.dal.ShowStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.dml.SelectStatement;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Optional;
 
 /**
@@ -47,11 +55,11 @@ import java.util.Optional;
  */
 public final class PostgreSQLAdminExecutorCreator implements 
DatabaseAdminExecutorCreator {
     
-    private static final String PG_CLASS = "pg_class";
+    private static final Map<String, Collection<String>> SCHEMA_TABLES = new 
CaseInsensitiveMap<>();
     
-    private static final String PG_NAMESPACE = "pg_namespace";
-    
-    private static final Collection<String> KERNEL_SUPPORTED_TABLES = 
Arrays.asList(PG_NAMESPACE, PG_CLASS);
+    static {
+        SCHEMA_TABLES.put("shardingsphere", new 
CaseInsensitiveSet<>(Arrays.asList("cluster_information", 
"sharding_table_statistics")));
+    }
     
     @Override
     public Optional<DatabaseAdminExecutor> create(final SQLStatementContext 
sqlStatementContext) {
@@ -66,12 +74,11 @@ public final class PostgreSQLAdminExecutorCreator 
implements DatabaseAdminExecut
     public Optional<DatabaseAdminExecutor> create(final SQLStatementContext 
sqlStatementContext, final String sql, final String databaseName, final 
List<Object> parameters) {
         SQLStatement sqlStatement = sqlStatementContext.getSqlStatement();
         if (sqlStatement instanceof SelectStatement) {
-            Collection<String> selectedTableNames = 
getSelectedTableNames((SelectStatement) sqlStatement);
-            if (!selectedTableNames.isEmpty() && 
KERNEL_SUPPORTED_TABLES.containsAll(selectedTableNames)) {
+            Map<String, Collection<String>> selectedSchemaTables = 
getSelectedSchemaTables((SelectStatement) sqlStatement);
+            if (isSelectedStatisticsSystemTable(selectedSchemaTables) || 
isSelectedShardingSphereSystemTable(selectedSchemaTables)) {
                 return Optional.empty();
             }
-            if (!selectedTableNames.isEmpty() && 
(SystemSchemaManager.isSystemTable("postgresql", "information_schema", 
selectedTableNames)
-                    || SystemSchemaManager.isSystemTable("postgresql", 
"pg_catalog", selectedTableNames))) {
+            if (isSelectSystemTable(selectedSchemaTables)) {
                 return Optional.of(new DefaultDatabaseMetaDataExecutor(sql, 
parameters));
             }
         }
@@ -84,7 +91,7 @@ public final class PostgreSQLAdminExecutorCreator implements 
DatabaseAdminExecut
         return Optional.empty();
     }
     
-    private Collection<String> getSelectedTableNames(final SelectStatement 
sqlStatement) {
+    private Map<String, Collection<String>> getSelectedSchemaTables(final 
SelectStatement sqlStatement) {
         TableExtractor extractor = new TableExtractor();
         extractor.extractTablesFromSelect(sqlStatement);
         List<TableSegment> extracted = new 
LinkedList<>(extractor.getTableContext());
@@ -95,15 +102,68 @@ public final class PostgreSQLAdminExecutorCreator 
implements DatabaseAdminExecut
                 extracted.addAll(subExtractor.getTableContext());
             }
         }
-        List<String> result = new ArrayList<>(extracted.size());
+        Map<String, Collection<String>> result = new CaseInsensitiveMap<>();
         for (TableSegment each : extracted) {
             if (each instanceof SimpleTableSegment) {
-                result.add(((SimpleTableSegment) 
each).getTableName().getIdentifier().getValue());
+                Optional<OwnerSegment> ownerSegment = ((SimpleTableSegment) 
each).getOwner();
+                if (ownerSegment.isPresent()) {
+                    Collection<String> tables = 
result.getOrDefault(ownerSegment.get().getIdentifier().getValue(), new 
CaseInsensitiveSet<>());
+                    tables.add(((SimpleTableSegment) 
each).getTableName().getIdentifier().getValue());
+                    result.put(ownerSegment.get().getIdentifier().getValue(), 
tables);
+                }
             }
         }
         return result;
     }
     
+    private boolean isSelectedStatisticsSystemTable(final Map<String, 
Collection<String>> selectedSchemaTables) {
+        if (selectedSchemaTables.isEmpty()) {
+            return false;
+        }
+        DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "PostgreSQL");
+        Optional<DialectDatabaseStatisticsCollector> 
dialectStatisticsCollector = 
DatabaseTypedSPILoader.findService(DialectDatabaseStatisticsCollector.class, 
databaseType);
+        if (!dialectStatisticsCollector.isPresent()) {
+            return false;
+        }
+        Map<String, Collection<String>> statisticalSchemaTables = 
dialectStatisticsCollector.get().getStatisticsSchemaTables();
+        for (Entry<String, Collection<String>> each : 
selectedSchemaTables.entrySet()) {
+            if (!statisticalSchemaTables.containsKey(each.getKey())) {
+                return false;
+            }
+            if 
(!statisticalSchemaTables.get(each.getKey()).containsAll(each.getValue())) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    private boolean isSelectedShardingSphereSystemTable(final Map<String, 
Collection<String>> selectedSchemaTables) {
+        if (selectedSchemaTables.isEmpty()) {
+            return false;
+        }
+        for (Entry<String, Collection<String>> each : 
selectedSchemaTables.entrySet()) {
+            if (!SCHEMA_TABLES.containsKey(each.getKey())) {
+                return false;
+            }
+            if 
(!SCHEMA_TABLES.get(each.getKey()).containsAll(each.getValue())) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    private boolean isSelectSystemTable(final Map<String, Collection<String>> 
selectedSchemaTables) {
+        if (selectedSchemaTables.isEmpty()) {
+            return false;
+        }
+        for (Entry<String, Collection<String>> each : 
selectedSchemaTables.entrySet()) {
+            if (!SystemSchemaManager.isSystemTable("postgresql", 
each.getKey(), each.getValue())) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
     @Override
     public String getDatabaseType() {
         return "PostgreSQL";


Reply via email to