You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by du...@apache.org on 2022/07/28 05:33:04 UTC

[shardingsphere] branch master updated: Replace stream with loop in PostgreSQLAdminExecutorCreator (#19629)

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 4427ff99f30 Replace stream with loop in PostgreSQLAdminExecutorCreator (#19629)
4427ff99f30 is described below

commit 4427ff99f30487c35964358a2b2601371cbcf621
Author: 吴伟杰 <wu...@apache.org>
AuthorDate: Thu Jul 28 13:32:56 2022 +0800

    Replace stream with loop in PostgreSQLAdminExecutorCreator (#19629)
    
    * Replace stream with loop in PostgreSQLAdminExecutorCreator
    
    * Add PostgreSQLAdminExecutorCreatorTest
---
 .../postgresql/PostgreSQLAdminExecutorCreator.java |  34 ++++--
 .../PostgreSQLAdminExecutorCreatorTest.java        | 132 +++++++++++++++++++++
 2 files changed, 154 insertions(+), 12 deletions(-)

diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/PostgreSQLAdminExecutorCreator.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/PostgreSQLAdminExecutorCreator.java
index 099bbf998a3..dd6d9eb937f 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/PostgreSQLAdminExecutorCreator.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/PostgreSQLAdminExecutorCreator.java
@@ -31,10 +31,11 @@ import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dal.SetStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Optional;
-import java.util.stream.Collectors;
 
 /**
  * Database admin executor creator for PostgreSQL.
@@ -69,8 +70,10 @@ public final class PostgreSQLAdminExecutorCreator implements DatabaseAdminExecut
             if (isQueryPgTable(selectedTableNames)) {
                 return Optional.of(new SelectTableExecutor(sql));
             }
-            if (selectedTableNames.stream().anyMatch(each -> each.startsWith(PG_PREFIX))) {
-                return Optional.of(new DefaultDatabaseMetadataExecutor(sql));
+            for (String each : selectedTableNames) {
+                if (each.startsWith(PG_PREFIX)) {
+                    return Optional.of(new DefaultDatabaseMetadataExecutor(sql));
+                }
             }
         }
         return sqlStatement instanceof SetStatement ? Optional.of(new PostgreSQLSetVariableAdminExecutor((SetStatement) sqlStatement)) : Optional.empty();
@@ -78,20 +81,27 @@ public final class PostgreSQLAdminExecutorCreator implements DatabaseAdminExecut
     
     private boolean isQueryPgTable(final Collection<String> selectedTableNames) {
         boolean isComplexQueryTable = selectedTableNames.contains(PG_CLASS) && selectedTableNames.contains(PG_TRIGGER) && selectedTableNames.contains(PG_INHERITS);
-        return selectedTableNames.contains(PG_TABLESPACE) || isComplexQueryTable;
+        return isComplexQueryTable || selectedTableNames.contains(PG_TABLESPACE);
     }
     
     private Collection<String> getSelectedTableNames(final SelectStatement sqlStatement) {
         TableExtractor extractor = new TableExtractor();
         extractor.extractTablesFromSelect(sqlStatement);
-        List<TableSegment> subQueryTableSegment = extractor.getTableContext().stream().filter(each -> each instanceof SubqueryTableSegment).map(each -> {
-            TableExtractor subExtractor = new TableExtractor();
-            subExtractor.extractTablesFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect());
-            return subExtractor.getTableContext();
-        }).flatMap(Collection::stream).collect(Collectors.toList());
-        extractor.getTableContext().addAll(subQueryTableSegment);
-        return extractor.getTableContext().stream().filter(each -> each instanceof SimpleTableSegment)
-                .map(each -> ((SimpleTableSegment) each).getTableName().getIdentifier().getValue()).collect(Collectors.toList());
+        List<TableSegment> extracted = new LinkedList<>(extractor.getTableContext());
+        for (TableSegment each : extractor.getTableContext()) {
+            if (each instanceof SubqueryTableSegment) {
+                TableExtractor subExtractor = new TableExtractor();
+                subExtractor.extractTablesFromSelect(((SubqueryTableSegment) each).getSubquery().getSelect());
+                extracted.addAll(subExtractor.getTableContext());
+            }
+        }
+        List<String> result = new ArrayList<>(extracted.size());
+        for (TableSegment each : extracted) {
+            if (each instanceof SimpleTableSegment) {
+                result.add(((SimpleTableSegment) each).getTableName().getIdentifier().getValue());
+            }
+        }
+        return result;
     }
     
     @Override
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/PostgreSQLAdminExecutorCreatorTest.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/PostgreSQLAdminExecutorCreatorTest.java
new file mode 100644
index 00000000000..e0ed83e0350
--- /dev/null
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/PostgreSQLAdminExecutorCreatorTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.proxy.backend.text.admin.postgresql;
+
+import org.apache.shardingsphere.infra.binder.statement.CommonSQLStatementContext;
+import org.apache.shardingsphere.infra.binder.statement.dml.DeleteStatementContext;
+import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
+import org.apache.shardingsphere.parser.config.SQLParserRuleConfiguration;
+import org.apache.shardingsphere.parser.rule.SQLParserRule;
+import org.apache.shardingsphere.proxy.backend.text.admin.executor.AbstractDatabaseMetadataExecutor.DefaultDatabaseMetadataExecutor;
+import org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminExecutor;
+import org.apache.shardingsphere.proxy.backend.text.admin.postgresql.executor.SelectDatabaseExecutor;
+import org.apache.shardingsphere.proxy.backend.text.admin.postgresql.executor.SelectTableExecutor;
+import org.apache.shardingsphere.sql.parser.api.CacheOption;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.dal.PostgreSQLSetStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.dml.PostgreSQLDeleteStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.dml.PostgreSQLSelectStatement;
+import org.junit.Test;
+
+import java.util.Optional;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public final class PostgreSQLAdminExecutorCreatorTest {
+    
+    private static final String PSQL_SELECT_DATABASES = "SELECT d.datname as \"Name\",\n"
+            + "       pg_catalog.pg_get_userbyid(d.datdba) as \"Owner\",\n"
+            + "       pg_catalog.pg_encoding_to_char(d.encoding) as \"Encoding\",\n"
+            + "       d.datcollate as \"Collate\",\n"
+            + "       d.datctype as \"Ctype\",\n"
+            + "       pg_catalog.array_to_string(d.datacl, E'\\n') AS \"Access privileges\"\n"
+            + "FROM pg_catalog.pg_database d\n"
+            + "ORDER BY 1";
+    
+    private static final String PSQL_SELECT_TABLESPACES = "SELECT spcname AS \"Name\",\n"
+            + "  pg_catalog.pg_get_userbyid(spcowner) AS \"Owner\",\n"
+            + "  pg_catalog.pg_tablespace_location(oid) AS \"Location\"\n"
+            + "FROM pg_catalog.pg_tablespace\n"
+            + "ORDER BY 1";
+    
+    private static final String SELECT_PG_CATALOG_WITH_SUBQUERY = "select * from (select * from pg_catalog.pg_namespace) t;";
+    
+    @Test
+    public void assertCreateWithSQLStatementContextOnly() {
+        assertThat(new PostgreSQLAdminExecutorCreator().create(null), is(Optional.empty()));
+    }
+    
+    @Test
+    public void assertCreateWithSelectDatabase() {
+        SQLStatement sqlStatement = parseSQL(PSQL_SELECT_DATABASES);
+        SelectStatementContext selectStatementContext = mock(SelectStatementContext.class);
+        when(selectStatementContext.getSqlStatement()).thenReturn((SelectStatement) sqlStatement);
+        Optional<DatabaseAdminExecutor> actual = new PostgreSQLAdminExecutorCreator().create(selectStatementContext, PSQL_SELECT_DATABASES, "");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), instanceOf(SelectDatabaseExecutor.class));
+    }
+    
+    @Test
+    public void assertCreateWithSelectTablespace() {
+        SQLStatement sqlStatement = parseSQL(PSQL_SELECT_TABLESPACES);
+        SelectStatementContext selectStatementContext = mock(SelectStatementContext.class);
+        when(selectStatementContext.getSqlStatement()).thenReturn((SelectStatement) sqlStatement);
+        Optional<DatabaseAdminExecutor> actual = new PostgreSQLAdminExecutorCreator().create(selectStatementContext, PSQL_SELECT_TABLESPACES, "");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), instanceOf(SelectTableExecutor.class));
+    }
+    
+    @Test
+    public void assertCreateWithSelectPgCatalogWithSubquery() {
+        SQLStatement sqlStatement = parseSQL(SELECT_PG_CATALOG_WITH_SUBQUERY);
+        SelectStatementContext selectStatementContext = mock(SelectStatementContext.class);
+        when(selectStatementContext.getSqlStatement()).thenReturn((SelectStatement) sqlStatement);
+        Optional<DatabaseAdminExecutor> actual = new PostgreSQLAdminExecutorCreator().create(selectStatementContext, SELECT_PG_CATALOG_WITH_SUBQUERY, "");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), instanceOf(DefaultDatabaseMetadataExecutor.class));
+    }
+    
+    private static SQLStatement parseSQL(final String sql) {
+        CacheOption cacheOption = new CacheOption(0, 0);
+        SQLParserRule sqlParserRule = new SQLParserRule(new SQLParserRuleConfiguration(false, cacheOption, cacheOption));
+        return sqlParserRule.getSQLParserEngine("PostgreSQL").parse(sql, false);
+    }
+    
+    @Test
+    public void assertCreateWithSelectNonPgCatalog() {
+        SelectStatementContext selectStatementContext = mock(SelectStatementContext.class);
+        when(selectStatementContext.getSqlStatement()).thenReturn(new PostgreSQLSelectStatement());
+        assertThat(new PostgreSQLAdminExecutorCreator().create(selectStatementContext, "select 1", ""), is(Optional.empty()));
+    }
+    
+    @Test
+    public void assertCreateWithSetStatement() {
+        PostgreSQLSetStatement setStatement = new PostgreSQLSetStatement();
+        CommonSQLStatementContext<PostgreSQLSetStatement> sqlStatementContext = new CommonSQLStatementContext<>(setStatement);
+        Optional<DatabaseAdminExecutor> actual = new PostgreSQLAdminExecutorCreator().create(sqlStatementContext, "SET client_encoding = utf8", "");
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), instanceOf(PostgreSQLSetVariableAdminExecutor.class));
+    }
+    
+    @Test
+    public void assertCreateWithDMLStatement() {
+        DeleteStatementContext sqlStatementContext = new DeleteStatementContext(new PostgreSQLDeleteStatement());
+        assertThat(new PostgreSQLAdminExecutorCreator().create(sqlStatementContext, "delete from t where id = 1", ""), is(Optional.empty()));
+    }
+    
+    @Test
+    public void assertGetType() {
+        assertThat(new PostgreSQLAdminExecutorCreator().getType(), is("PostgreSQL"));
+    }
+}