You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by ji...@apache.org on 2021/11/07 08:23:08 UTC
[shardingsphere] branch master updated: Proxy support pg_database
table of postgreSQL (#13482)
This is an automated email from the ASF dual-hosted git repository.
jianglongtao 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 1fcca09 Proxy support pg_database table of postgreSQL (#13482)
1fcca09 is described below
commit 1fcca0938f29d55df3e8be91db1a7fbf6797c4bb
Author: lanchengx <52...@users.noreply.github.com>
AuthorDate: Sun Nov 7 02:22:06 2021 -0600
Proxy support pg_database table of postgreSQL (#13482)
* Add test;
* Support `pg_database` table of `postgreSQL`
* Modify format.
---
.../information => }/FunctionWithException.java | 7 +-
.../AbstractDatabaseMetadataExecutor.java} | 80 +++++++++------
.../MySQLInformationSchemaExecutorFactory.java | 4 +-
.../SelectInformationSchemataExecutor.java | 9 +-
.../postgresql/PostgreSQLAdminExecutorFactory.java | 67 ++++++++++++
.../executor/SelectDatabaseExecutor.java | 114 +++++++++++++++++++++
...ext.admin.executor.DatabaseAdminExecutorFactory | 1 +
.../information/SelectInformationExecutorTest.java | 6 +-
.../PostgreSQLAdminExecutorFactoryTest.java | 51 +++++++++
.../executor/SelectDatabaseExecutorTest.java} | 94 ++++++++---------
10 files changed, 337 insertions(+), 96 deletions(-)
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/FunctionWithException.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/FunctionWithException.java
similarity index 82%
rename from shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/FunctionWithException.java
rename to shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/FunctionWithException.java
index fefd406..7d1a66c 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/FunctionWithException.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/FunctionWithException.java
@@ -15,20 +15,19 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.information;
+package org.apache.shardingsphere.proxy.backend.text.admin;
/**
* FunctionWithException interface.
*/
@FunctionalInterface
-public interface FunctionWithException<T, R, E extends Exception> {
+public interface FunctionWithException<T, E extends Exception> {
/**
* Apply function.
*
* @param t param
- * @return return value
* @throws E exception
*/
- R apply(T t) throws E;
+ void apply(T t) throws E;
}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/AbstractSelectInformationExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/executor/AbstractDatabaseMetadataExecutor.java
similarity index 73%
rename from shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/AbstractSelectInformationExecutor.java
rename to shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/executor/AbstractDatabaseMetadataExecutor.java
index 43b7ee0..34b7ad3 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/AbstractSelectInformationExecutor.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/executor/AbstractDatabaseMetadataExecutor.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.information;
+package org.apache.shardingsphere.proxy.backend.text.admin.executor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@@ -30,7 +30,7 @@ import org.apache.shardingsphere.infra.metadata.resource.ShardingSphereResource;
import org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection;
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
import org.apache.shardingsphere.proxy.backend.exception.DatabaseNotExistedException;
-import org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminQueryExecutor;
+import org.apache.shardingsphere.proxy.backend.text.admin.FunctionWithException;
import javax.sql.DataSource;
import java.sql.Connection;
@@ -49,9 +49,9 @@ import java.util.Optional;
import java.util.stream.Collectors;
/**
- * The abstract class of select information schema, used to define the template.
+ * The abstract class of database metadata, used to define the template.
*/
-public abstract class AbstractSelectInformationExecutor implements DatabaseAdminQueryExecutor {
+public abstract class AbstractDatabaseMetadataExecutor implements DatabaseAdminQueryExecutor {
@Getter
private QueryResultMetaData queryResultMetaData;
@@ -66,27 +66,29 @@ public abstract class AbstractSelectInformationExecutor implements DatabaseAdmin
public final void execute(final BackendConnection backendConnection) throws SQLException {
List<String> schemaNames = getSchemaNames();
for (String schemaName : schemaNames) {
- getSourceData(schemaName, resultSet -> {
- while (resultSet.next()) {
- Map<String, Object> rowMap = new HashMap<>();
- Map<String, String> aliasMap = new HashMap<>();
- ResultSetMetaData metaData = resultSet.getMetaData();
- for (int i = 1; i < metaData.getColumnCount() + 1; i++) {
- aliasMap.put(metaData.getColumnName(i), metaData.getColumnLabel(i));
- rowMap.put(metaData.getColumnLabel(i), resultSet.getString(i));
- }
- rowPostProcessing(schemaName, rowMap, aliasMap);
- if (!rowMap.isEmpty()) {
- getRows().addFirst(rowMap);
- }
- }
- return null;
- });
+ getSourceData(schemaName, resultSet -> handleResultSet(schemaName, resultSet));
}
+ addDefaultRow(rows);
queryResultMetaData = createQueryResultMetaData();
mergedResult = createMergedResult();
}
+ private void handleResultSet(final String schemaName, final ResultSet resultSet) throws SQLException {
+ while (resultSet.next()) {
+ Map<String, Object> rowMap = new HashMap<>();
+ Map<String, String> aliasMap = new HashMap<>();
+ ResultSetMetaData metaData = resultSet.getMetaData();
+ for (int i = 1; i < metaData.getColumnCount() + 1; i++) {
+ aliasMap.put(metaData.getColumnName(i), metaData.getColumnLabel(i));
+ rowMap.put(metaData.getColumnLabel(i), resultSet.getString(i));
+ }
+ rowPostProcessing(schemaName, rowMap, aliasMap);
+ if (!rowMap.isEmpty()) {
+ rows.addFirst(rowMap);
+ }
+ }
+ }
+
/**
* Get the schema names as a condition for SQL execution.
*
@@ -95,19 +97,26 @@ public abstract class AbstractSelectInformationExecutor implements DatabaseAdmin
protected abstract List<String> getSchemaNames();
/**
+ * Add default row data.
+ *
+ * @param rows row
+ */
+ protected abstract void addDefaultRow(LinkedList<Map<String, Object>> rows);
+
+ /**
* Get the source object of the row data.
*
* @param schemaName schema name
* @param callback callback for processing source data of information_schema
* @throws SQLException SQLException
*/
- protected abstract void getSourceData(String schemaName, FunctionWithException<ResultSet, Void, SQLException> callback) throws SQLException;
+ protected abstract void getSourceData(String schemaName, FunctionWithException<ResultSet, SQLException> callback) throws SQLException;
/**
* Get the source object of the row data.
- *
- * @param schemaName schema name
- * @param rowMap row
+ *
+ * @param schemaName schema name
+ * @param rowMap row
* @param aliasMap alias
*/
protected abstract void rowPostProcessing(String schemaName, Map<String, Object> rowMap, Map<String, String> aliasMap);
@@ -135,15 +144,15 @@ public abstract class AbstractSelectInformationExecutor implements DatabaseAdmin
}
/**
- * Default select information executor, execute sql directly in the database to obtain the result source data.
+ * Default database metadata executor, execute sql directly in the database to obtain the result source data.
*/
@Slf4j
- public static class DefaultSelectInformationExecutor extends AbstractSelectInformationExecutor {
+ public static class DefaultDatabaseMetadataExecutor extends AbstractDatabaseMetadataExecutor {
@Getter
private final String sql;
- public DefaultSelectInformationExecutor(final String sql) {
+ public DefaultDatabaseMetadataExecutor(final String sql) {
this.sql = sql;
}
@@ -154,7 +163,7 @@ public abstract class AbstractSelectInformationExecutor implements DatabaseAdmin
*/
@Override
protected List<String> getSchemaNames() {
- String schema = ProxyContext.getInstance().getAllSchemaNames().stream().filter(AbstractSelectInformationExecutor::hasDatasource).findFirst().orElseThrow(DatabaseNotExistedException::new);
+ String schema = ProxyContext.getInstance().getAllSchemaNames().stream().filter(AbstractDatabaseMetadataExecutor::hasDatasource).findFirst().orElseThrow(DatabaseNotExistedException::new);
return Collections.singletonList(schema);
}
@@ -165,7 +174,7 @@ public abstract class AbstractSelectInformationExecutor implements DatabaseAdmin
* @throws SQLException SQLException
*/
@Override
- protected void getSourceData(final String schemaName, final FunctionWithException<ResultSet, Void, SQLException> callback) throws SQLException {
+ protected void getSourceData(final String schemaName, final FunctionWithException<ResultSet, SQLException> callback) throws SQLException {
ShardingSphereResource resource = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData(schemaName).getResource();
Optional<Entry<String, DataSource>> dataSourceEntry = resource.getDataSources().entrySet().stream().findFirst();
log.info("Actual SQL: {} ::: {}", dataSourceEntry.orElseThrow(DatabaseNotExistedException::new).getKey(), sql);
@@ -177,13 +186,22 @@ public abstract class AbstractSelectInformationExecutor implements DatabaseAdmin
/**
* Custom processing.
- *
- * @param schemaName schema name
+ *
+ * @param schemaName schema name
* @param rowMap row
* @param aliasMap alias
*/
@Override
protected void rowPostProcessing(final String schemaName, final Map<String, Object> rowMap, final Map<String, String> aliasMap) {
}
+
+ /**
+ * Add default row data.
+ *
+ * @param rows row
+ */
+ @Override
+ protected void addDefaultRow(final LinkedList<Map<String, Object>> rows) {
+ }
}
}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLInformationSchemaExecutorFactory.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLInformationSchemaExecutorFactory.java
index b76c37a..844a82d 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLInformationSchemaExecutorFactory.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLInformationSchemaExecutorFactory.java
@@ -18,7 +18,7 @@
package org.apache.shardingsphere.proxy.backend.text.admin.mysql;
import org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminQueryExecutor;
-import org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.information.AbstractSelectInformationExecutor.DefaultSelectInformationExecutor;
+import org.apache.shardingsphere.proxy.backend.text.admin.executor.AbstractDatabaseMetadataExecutor.DefaultDatabaseMetadataExecutor;
import org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.information.SelectInformationSchemataExecutor;
import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
@@ -47,7 +47,7 @@ public final class MySQLInformationSchemaExecutorFactory {
if (SCHEMATA_TABLE.equalsIgnoreCase(tableName)) {
return new SelectInformationSchemataExecutor(sqlStatement, sql);
} else if (DEFAULT_EXECUTOR_TABLES.contains(tableName.toUpperCase())) {
- return new DefaultSelectInformationExecutor(sql);
+ return new DefaultDatabaseMetadataExecutor(sql);
}
throw new UnsupportedOperationException(String.format("unsupported table : `%s`", tableName));
}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/SelectInformationSchemataExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/SelectInformationSchemataExecutor.java
index 06f84cc..0cd2d2d 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/SelectInformationSchemataExecutor.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/SelectInformationSchemataExecutor.java
@@ -19,7 +19,8 @@ package org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.inform
import org.apache.shardingsphere.infra.metadata.resource.ShardingSphereResource;
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
-import org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.information.AbstractSelectInformationExecutor.DefaultSelectInformationExecutor;
+import org.apache.shardingsphere.proxy.backend.text.admin.executor.AbstractDatabaseMetadataExecutor;
+import org.apache.shardingsphere.proxy.backend.text.admin.executor.AbstractDatabaseMetadataExecutor.DefaultDatabaseMetadataExecutor;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ShorthandProjectionSegment;
@@ -38,7 +39,7 @@ import java.util.stream.Stream;
/**
* Schemata query executor, used to query the schemata table.
*/
-public final class SelectInformationSchemataExecutor extends DefaultSelectInformationExecutor {
+public final class SelectInformationSchemataExecutor extends DefaultDatabaseMetadataExecutor {
public static final String SCHEMA_NAME = "SCHEMA_NAME";
@@ -64,8 +65,8 @@ public final class SelectInformationSchemataExecutor extends DefaultSelectInform
@Override
protected List<String> getSchemaNames() {
Collection<String> schemaNames = ProxyContext.getInstance().getAllSchemaNames();
- SCHEMA_WITHOUT_DATA_SOURCE.addAll(schemaNames.stream().filter(each -> !AbstractSelectInformationExecutor.hasDatasource(each)).collect(Collectors.toSet()));
- List<String> result = schemaNames.stream().filter(AbstractSelectInformationExecutor::hasDatasource).collect(Collectors.toList());
+ SCHEMA_WITHOUT_DATA_SOURCE.addAll(schemaNames.stream().filter(each -> !AbstractDatabaseMetadataExecutor.hasDatasource(each)).collect(Collectors.toSet()));
+ List<String> result = schemaNames.stream().filter(AbstractDatabaseMetadataExecutor::hasDatasource).collect(Collectors.toList());
if (!SCHEMA_WITHOUT_DATA_SOURCE.isEmpty()) {
fillSchemasWithoutDatasource();
}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/PostgreSQLAdminExecutorFactory.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/PostgreSQLAdminExecutorFactory.java
new file mode 100644
index 0000000..c6b6c96
--- /dev/null
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/PostgreSQLAdminExecutorFactory.java
@@ -0,0 +1,67 @@
+/*
+ * 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.proxy.backend.text.admin.executor.DatabaseAdminExecutor;
+import org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminExecutorFactory;
+import org.apache.shardingsphere.proxy.backend.text.admin.postgresql.executor.SelectDatabaseExecutor;
+import org.apache.shardingsphere.sql.parser.sql.common.extractor.TableExtractor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * Admin executor factory for PostgreSQL.
+ */
+public final class PostgreSQLAdminExecutorFactory implements DatabaseAdminExecutorFactory {
+
+ private static final String PG_DATABASE = "pg_database";
+
+ @Override
+ public Optional<DatabaseAdminExecutor> newInstance(final SQLStatement sqlStatement) {
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional<DatabaseAdminExecutor> newInstance(final SQLStatement sqlStatement, final String sql) {
+ if (sqlStatement instanceof SelectStatement) {
+ Collection<String> selectedTableNames = getSelectedTableNames((SelectStatement) sqlStatement);
+ if (selectedTableNames.contains(PG_DATABASE)) {
+ return Optional.of(new SelectDatabaseExecutor((SelectStatement) sqlStatement, sql));
+ }
+ }
+ return Optional.empty();
+ }
+
+ private Collection<String> getSelectedTableNames(final SelectStatement sqlStatement) {
+ TableExtractor extractor = new TableExtractor();
+ extractor.extractTablesFromSelect(sqlStatement);
+ return extractor.getTableContext().stream().filter(each -> each instanceof SimpleTableSegment)
+ .map(each -> ((SimpleTableSegment) each).getTableName().getIdentifier().getValue()).collect(Collectors.toCollection(LinkedList::new));
+ }
+
+ @Override
+ public String getType() {
+ return "PostgreSQL";
+ }
+}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/executor/SelectDatabaseExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/executor/SelectDatabaseExecutor.java
new file mode 100644
index 0000000..9e1d923
--- /dev/null
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/executor/SelectDatabaseExecutor.java
@@ -0,0 +1,114 @@
+/*
+ * 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.executor;
+
+import org.apache.shardingsphere.infra.metadata.resource.ShardingSphereResource;
+import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import org.apache.shardingsphere.proxy.backend.text.admin.executor.AbstractDatabaseMetadataExecutor;
+import org.apache.shardingsphere.proxy.backend.text.admin.executor.AbstractDatabaseMetadataExecutor.DefaultDatabaseMetadataExecutor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Schemata query executor, used to query the schemata table.
+ */
+public final class SelectDatabaseExecutor extends DefaultDatabaseMetadataExecutor {
+
+ private static final String DATABASE_NAME = "databasename";
+
+ private final Set<String> columnNames = new LinkedHashSet<>();
+
+ private final SelectStatement sqlStatement;
+
+ private String databaseNameAlias = DATABASE_NAME;
+
+ public SelectDatabaseExecutor(final SelectStatement sqlStatement, final String sql) {
+ super(sql);
+ this.sqlStatement = sqlStatement;
+ }
+
+ @Override
+ protected void addDefaultRow(final LinkedList<Map<String, Object>> rows) {
+ LinkedList<String> schemaWithoutDataSource = ProxyContext.getInstance().getAllSchemaNames().stream()
+ .filter(each -> !hasDatasource(each)).collect(Collectors.toCollection(LinkedList::new));
+ schemaWithoutDataSource.forEach(each -> rows.addLast(getDefaultRowData(each)));
+ }
+
+ @Override
+ protected List<String> getSchemaNames() {
+ Collection<String> schemaNames = ProxyContext.getInstance().getAllSchemaNames();
+ return schemaNames.stream().filter(AbstractDatabaseMetadataExecutor::hasDatasource).collect(Collectors.toList());
+ }
+
+ @Override
+ protected void rowPostProcessing(final String schemaName, final Map<String, Object> rowMap, final Map<String, String> aliasMap) {
+ buildColumnNames(aliasMap);
+ ShardingSphereResource resource = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData(schemaName).getResource();
+ Set<String> catalogs = resource.getDataSources().keySet().stream().map(each -> resource.getDataSourcesMetaData().getDataSourceMetaData(each).getCatalog()).collect(Collectors.toSet());
+ databaseNameAlias = aliasMap.getOrDefault(DATABASE_NAME, "");
+ String rowValue = rowMap.getOrDefault(databaseNameAlias, "").toString();
+ if (catalogs.contains(rowValue)) {
+ rowMap.replace(databaseNameAlias, schemaName);
+ } else {
+ rowMap.clear();
+ }
+ }
+
+ private void buildColumnNames(final Map<String, String> aliasMap) {
+ aliasMap.forEach((key, value) -> {
+ if (!value.isEmpty()) {
+ columnNames.add(value);
+ } else {
+ columnNames.add(key);
+ }
+ });
+
+ }
+
+ private Map<String, Object> getDefaultRowData(final String schemaName) {
+ Map<String, Object> result;
+ if (columnNames.isEmpty()) {
+ columnNames.addAll(getDefaultColumnNames());
+ }
+ result = columnNames.stream().collect(Collectors.toMap(each -> each, each -> ""));
+ result.replace(databaseNameAlias, schemaName);
+ return result;
+ }
+
+ private Set<String> getDefaultColumnNames() {
+ Collection<ProjectionSegment> projections = sqlStatement.getProjections().getProjections();
+ if (projections.stream().anyMatch(each -> !(each instanceof ColumnProjectionSegment))) {
+ return Collections.singleton(databaseNameAlias);
+ } else {
+ return projections.stream().map(each -> {
+ ColumnProjectionSegment segment = (ColumnProjectionSegment) each;
+ return segment.getAlias().isPresent() ? segment.getAlias().get() : segment.getColumn().getIdentifier().getValue();
+ }).collect(Collectors.toCollection(LinkedHashSet::new));
+ }
+ }
+}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminExecutorFactory b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminExecutorFactory
index 3913edc..92a43c6 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminExecutorFactory
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminExecutorFactory
@@ -16,3 +16,4 @@
#
org.apache.shardingsphere.proxy.backend.text.admin.mysql.MySQLAdminExecutorFactory
+org.apache.shardingsphere.proxy.backend.text.admin.postgresql.PostgreSQLAdminExecutorFactory
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/SelectInformationExecutorTest.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/SelectInformationExecutorTest.java
index 0bf17b4..07694d7 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/SelectInformationExecutorTest.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/SelectInformationExecutorTest.java
@@ -34,7 +34,7 @@ import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
import org.apache.shardingsphere.mode.metadata.persist.MetaDataPersistService;
import org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection;
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
-import org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.information.AbstractSelectInformationExecutor.DefaultSelectInformationExecutor;
+import org.apache.shardingsphere.proxy.backend.text.admin.executor.AbstractDatabaseMetadataExecutor.DefaultDatabaseMetadataExecutor;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
import org.junit.Before;
@@ -184,7 +184,7 @@ public final class SelectInformationExecutorTest {
Map<String, ShardingSphereMetaData> metaDataMap = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaDataMap();
metaDataMap.put("demo_ds_0", getMetaData());
metaDataMap.put("test", mock(ShardingSphereMetaData.class));
- DefaultSelectInformationExecutor selectExecutor = new DefaultSelectInformationExecutor(sql);
+ DefaultDatabaseMetadataExecutor selectExecutor = new DefaultDatabaseMetadataExecutor(sql);
selectExecutor.execute(mock(BackendConnection.class));
assertThat(selectExecutor.getRows().get(0).get("sn"), is("demo_ds_0"));
assertThat(selectExecutor.getRows().get(0).get("DEFAULT_CHARACTER_SET_NAME"), is("utf8mb4"));
@@ -198,7 +198,7 @@ public final class SelectInformationExecutorTest {
mockResultSet(mockMap, false);
Map<String, ShardingSphereMetaData> metaDataMap = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaDataMap();
metaDataMap.put("sharding_db", getMetaData());
- DefaultSelectInformationExecutor defaultSelectMetaDataExecutor = new DefaultSelectInformationExecutor(sql);
+ DefaultDatabaseMetadataExecutor defaultSelectMetaDataExecutor = new DefaultDatabaseMetadataExecutor(sql);
defaultSelectMetaDataExecutor.execute(mock(BackendConnection.class));
assertThat(defaultSelectMetaDataExecutor.getQueryResultMetaData().getColumnCount(), is(mockMap.size()));
while (defaultSelectMetaDataExecutor.getMergedResult().next()) {
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/PostgreSQLAdminExecutorFactoryTest.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/PostgreSQLAdminExecutorFactoryTest.java
new file mode 100644
index 0000000..9b7f5ec
--- /dev/null
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/PostgreSQLAdminExecutorFactoryTest.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.proxy.backend.text.admin.postgresql;
+
+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.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableNameSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
+import org.junit.Test;
+
+import java.util.Optional;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+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 PostgreSQLAdminExecutorFactoryTest {
+
+ private final PostgreSQLAdminExecutorFactory postgreSQLAdminExecutorFactory = new PostgreSQLAdminExecutorFactory();
+
+ @Test
+ public void assertNewInstanceWithMySQLShowFunctionStatusStatement() {
+ SelectStatement statement = mock(SelectStatement.class);
+ SimpleTableSegment tableSegment = mock(SimpleTableSegment.class);
+ when(tableSegment.getTableName()).thenReturn(new TableNameSegment(0, 0, new IdentifierValue("pg_database")));
+ when(statement.getFrom()).thenReturn(tableSegment);
+ Optional<DatabaseAdminExecutor> executorOptional = postgreSQLAdminExecutorFactory.newInstance(statement, "");
+ assertTrue(executorOptional.isPresent());
+ assertThat(executorOptional.get(), instanceOf(SelectDatabaseExecutor.class));
+ }
+
+}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/SelectInformationExecutorTest.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/executor/SelectDatabaseExecutorTest.java
similarity index 70%
copy from shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/SelectInformationExecutorTest.java
copy to shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/executor/SelectDatabaseExecutorTest.java
index 0bf17b4..1a4d22b 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/information/SelectInformationExecutorTest.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/executor/SelectDatabaseExecutorTest.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.information;
+package org.apache.shardingsphere.proxy.backend.text.admin.postgresql.executor;
import com.zaxxer.hikari.pool.HikariProxyResultSet;
import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties;
@@ -34,7 +34,6 @@ import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
import org.apache.shardingsphere.mode.metadata.persist.MetaDataPersistService;
import org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection;
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
-import org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.information.AbstractSelectInformationExecutor.DefaultSelectInformationExecutor;
import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
import org.junit.Before;
@@ -62,7 +61,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
-public final class SelectInformationExecutorTest {
+public final class SelectDatabaseExecutorTest {
private static final ResultSet RESULT_SET = mock(HikariProxyResultSet.class);
@@ -113,25 +112,28 @@ public final class SelectInformationExecutorTest {
@Test
public void assertSelectSchemataExecute() throws SQLException {
- final String sql = "SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA";
+ final String sql = "SELECT d.oid, d.datname AS databasename, d.datacl, d.datistemplate, d.datallowconn, pg_get_userbyid(d.datdba) AS databaseowner,"
+ + " d.datcollate, d.datctype, shobj_description(d.oid, 'pg_database') AS description, d.datconnlimit, t.spcname, d.encoding, pg_encoding_to_char(d.encoding) AS encodingname "
+ + "FROM pg_database d LEFT JOIN pg_tablespace t ON d.dattablespace = t.oid;";
final SQLStatement sqlStatement = new ShardingSphereSQLParserEngine("MySQL", new ConfigurationProperties(new Properties())).parse(sql, false);
Map<String, String> mockResultSetMap = new HashMap<>();
- mockResultSetMap.put("SCHEMA_NAME", "demo_ds_0");
- mockResultSetMap.put("DEFAULT_CHARACTER_SET_NAME", "utf8mb4_0900_ai_ci");
- mockResultSetMap.put("DEFAULT_COLLATION_NAME", "utf8mb4");
+ mockResultSetMap.put("databasename", "demo_ds_0");
+ mockResultSetMap.put("databaseowner", "postgres");
+ mockResultSetMap.put("datconnlimit", "-1");
+ mockResultSetMap.put("datctype", "en_US.utf8");
mockResultSet(mockResultSetMap, true, false);
Map<String, ShardingSphereMetaData> metaDataMap = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaDataMap();
metaDataMap.put("sharding_db", getMetaData());
metaDataMap.put("test", mock(ShardingSphereMetaData.class));
- SelectInformationSchemataExecutor selectSchemataExecutor = new SelectInformationSchemataExecutor((SelectStatement) sqlStatement, sql);
+ SelectDatabaseExecutor selectSchemataExecutor = new SelectDatabaseExecutor((SelectStatement) sqlStatement, sql);
selectSchemataExecutor.execute(mock(BackendConnection.class));
assertThat(selectSchemataExecutor.getQueryResultMetaData().getColumnCount(), is(mockResultSetMap.size()));
int count = 0;
while (selectSchemataExecutor.getMergedResult().next()) {
count++;
if ("sharding_db".equals(selectSchemataExecutor.getMergedResult().getValue(1, String.class))) {
- assertThat(selectSchemataExecutor.getMergedResult().getValue(2, String.class), is("utf8mb4"));
- assertThat(selectSchemataExecutor.getMergedResult().getValue(3, String.class), is("utf8mb4_0900_ai_ci"));
+ assertThat(selectSchemataExecutor.getMergedResult().getValue(2, String.class), is("postgres"));
+ assertThat(selectSchemataExecutor.getMergedResult().getValue(3, String.class), is("-1"));
} else if ("test".equals(selectSchemataExecutor.getMergedResult().getValue(1, String.class))) {
assertThat(selectSchemataExecutor.getMergedResult().getValue(2, String.class), is(""));
assertThat(selectSchemataExecutor.getMergedResult().getValue(3, String.class), is(""));
@@ -143,66 +145,54 @@ public final class SelectInformationExecutorTest {
}
@Test
- public void assertSelectSchemataInSchemaWithoutDataSourceExecute() throws SQLException {
- final String sql = "SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME, DEFAULT_ENCRYPTION FROM information_schema.SCHEMATA";
+ public void assertSelectSchemataWithoutDataSourceExecute1() throws SQLException {
+ final String sql = "SELECT d.oid, d.datname AS databasename, d.datacl, d.datistemplate, d.datallowconn, pg_get_userbyid(d.datdba) AS databaseowner, "
+ + "d.datcollate, d.datctype, shobj_description(d.oid, 'pg_database') AS description, d.datconnlimit, t.spcname, d.encoding, pg_encoding_to_char(d.encoding) AS encodingname "
+ + "FROM pg_database d LEFT JOIN pg_tablespace t ON d.dattablespace = t.oid;";
final SQLStatement sqlStatement = new ShardingSphereSQLParserEngine("MySQL", new ConfigurationProperties(new Properties())).parse(sql, false);
Map<String, String> mockResultSetMap = new HashMap<>();
- mockResultSetMap.put("SCHEMA_NAME", "demo_ds_0");
- mockResultSetMap.put("DEFAULT_CHARACTER_SET_NAME", "utf8mb4_0900_ai_ci");
- mockResultSetMap.put("DEFAULT_COLLATION_NAME", "utf8mb4");
- mockResultSetMap.put("DEFAULT_ENCRYPTION", "NO");
+ mockResultSetMap.put("databasename", "demo_ds_0");
+ mockResultSetMap.put("databaseowner", "postgres");
+ mockResultSetMap.put("datconnlimit", "-1");
+ mockResultSetMap.put("datctype", "en_US.utf8");
mockResultSet(mockResultSetMap, false);
Map<String, ShardingSphereMetaData> metaDataMap = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaDataMap();
metaDataMap.put("sharding_db", mock(ShardingSphereMetaData.class));
- SelectInformationSchemataExecutor selectSchemataExecutor = new SelectInformationSchemataExecutor((SelectStatement) sqlStatement, sql);
+ SelectDatabaseExecutor selectSchemataExecutor = new SelectDatabaseExecutor((SelectStatement) sqlStatement, sql);
selectSchemataExecutor.execute(mock(BackendConnection.class));
- assertThat(selectSchemataExecutor.getQueryResultMetaData().getColumnCount(), is(mockResultSetMap.size()));
while (selectSchemataExecutor.getMergedResult().next()) {
assertThat(selectSchemataExecutor.getMergedResult().getValue(1, String.class), is("sharding_db"));
- assertThat(selectSchemataExecutor.getMergedResult().getValue(2, String.class), is(""));
- assertThat(selectSchemataExecutor.getMergedResult().getValue(3, String.class), is(""));
- assertThat(selectSchemataExecutor.getMergedResult().getValue(4, String.class), is(""));
}
}
@Test
- public void assertSelectSchemataInNoSchemaExecute() throws SQLException {
- final String sql = "SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME, DEFAULT_ENCRYPTION FROM information_schema.SCHEMATA";
+ public void assertSelectSchemataWithoutDataSourceExecuteAndWithColumnProjectionSegment() throws SQLException {
+ final String sql = "SELECT d.oid, d.datname AS databasename, d.datacl, d.datistemplate FROM pg_database d LEFT JOIN pg_tablespace t ON d.dattablespace = t.oid;";
final SQLStatement sqlStatement = new ShardingSphereSQLParserEngine("MySQL", new ConfigurationProperties(new Properties())).parse(sql, false);
- SelectInformationSchemataExecutor selectSchemataExecutor = new SelectInformationSchemataExecutor((SelectStatement) sqlStatement, sql);
- selectSchemataExecutor.execute(mock(BackendConnection.class));
- assertThat(selectSchemataExecutor.getQueryResultMetaData().getColumnCount(), is(0));
- }
-
- @Test
- public void assertSelectSchemaAliasExecute() throws SQLException {
- final String sql = "SELECT SCHEMA_NAME AS sn, DEFAULT_CHARACTER_SET_NAME FROM information_schema.SCHEMATA";
Map<String, String> mockResultSetMap = new HashMap<>();
- mockResultSetMap.put("sn", "demo_ds_0");
- mockResultSetMap.put("DEFAULT_CHARACTER_SET_NAME", "utf8mb4");
+ mockResultSetMap.put("databasename", "demo_ds_0");
+ mockResultSetMap.put("databaseowner", "postgres");
+ mockResultSetMap.put("datconnlimit", "-1");
+ mockResultSetMap.put("datctype", "en_US.utf8");
mockResultSet(mockResultSetMap, false);
Map<String, ShardingSphereMetaData> metaDataMap = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaDataMap();
- metaDataMap.put("demo_ds_0", getMetaData());
- metaDataMap.put("test", mock(ShardingSphereMetaData.class));
- DefaultSelectInformationExecutor selectExecutor = new DefaultSelectInformationExecutor(sql);
- selectExecutor.execute(mock(BackendConnection.class));
- assertThat(selectExecutor.getRows().get(0).get("sn"), is("demo_ds_0"));
- assertThat(selectExecutor.getRows().get(0).get("DEFAULT_CHARACTER_SET_NAME"), is("utf8mb4"));
+ metaDataMap.put("sharding_db", mock(ShardingSphereMetaData.class));
+ SelectDatabaseExecutor selectSchemataExecutor = new SelectDatabaseExecutor((SelectStatement) sqlStatement, sql);
+ selectSchemataExecutor.execute(mock(BackendConnection.class));
+ while (selectSchemataExecutor.getMergedResult().next()) {
+ assertThat(selectSchemataExecutor.getMergedResult().getValue(1, String.class), is(""));
+ assertThat(selectSchemataExecutor.getMergedResult().getValue(2, String.class), is("sharding_db"));
+ assertThat(selectSchemataExecutor.getMergedResult().getValue(3, String.class), is(""));
+ assertThat(selectSchemataExecutor.getMergedResult().getValue(4, String.class), is(""));
+ }
}
@Test
- public void assertDefaultExecute() throws SQLException {
- final String sql = "SELECT COUNT(*) AS support_ndb FROM information_schema.ENGINES WHERE Engine = 'ndbcluster'";
- Map<String, String> mockMap = new HashMap<>();
- mockMap.put("support_ndb", "0");
- mockResultSet(mockMap, false);
- Map<String, ShardingSphereMetaData> metaDataMap = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaDataMap();
- metaDataMap.put("sharding_db", getMetaData());
- DefaultSelectInformationExecutor defaultSelectMetaDataExecutor = new DefaultSelectInformationExecutor(sql);
- defaultSelectMetaDataExecutor.execute(mock(BackendConnection.class));
- assertThat(defaultSelectMetaDataExecutor.getQueryResultMetaData().getColumnCount(), is(mockMap.size()));
- while (defaultSelectMetaDataExecutor.getMergedResult().next()) {
- assertThat(defaultSelectMetaDataExecutor.getMergedResult().getValue(1, String.class), is("0"));
- }
+ public void assertSelectSchemataInNoSchemaExecute() throws SQLException {
+ final String sql = "SELECT d.oid, d.datname AS databasename, d.datacl, d.datistemplate FROM pg_database d LEFT JOIN pg_tablespace t ON d.dattablespace = t.oid;";
+ final SQLStatement sqlStatement = new ShardingSphereSQLParserEngine("MySQL", new ConfigurationProperties(new Properties())).parse(sql, false);
+ SelectDatabaseExecutor selectSchemataExecutor = new SelectDatabaseExecutor((SelectStatement) sqlStatement, sql);
+ selectSchemataExecutor.execute(mock(BackendConnection.class));
+ assertThat(selectSchemataExecutor.getQueryResultMetaData().getColumnCount(), is(0));
}
}