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 7be8219  Supports querying pg_tablespace, pg_namespace (#13548)
7be8219 is described below

commit 7be8219db8bf9c73110a41ba5506a252ef667579
Author: lanchengx <[email protected]>
AuthorDate: Thu Nov 11 05:33:44 2021 -0600

    Supports querying pg_tablespace, pg_namespace (#13548)
    
    * Client supports querying pg_tablespace,pg_namespace
    
    * Client supports querying pg_tablespace,pg_namespace
    
    * Client supports querying pg_tablespace,pg_namespace
    
    * Client supports querying pg_tablespace,pg_namespace
---
 .../executor/AbstractDatabaseMetadataExecutor.java |  35 ++++--
 .../postgresql/PostgreSQLAdminExecutorFactory.java |  12 ++
 .../executor/SelectDatabaseExecutor.java           |   6 +-
 .../postgresql/executor/SelectTableExecutor.java   |  81 ++++++++++++
 .../executor/SelectTableExecutorTest.java          | 137 +++++++++++++++++++++
 .../src/main/antlr4/imports/postgresql/BaseRule.g4 |   1 +
 6 files changed, 256 insertions(+), 16 deletions(-)

diff --git 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/executor/AbstractDatabaseMetadataExecutor.java
 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/executor/AbstractDatabaseMetadataExecutor.java
index 34b7ad3..312b26b 100644
--- 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/executor/AbstractDatabaseMetadataExecutor.java
+++ 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/executor/AbstractDatabaseMetadataExecutor.java
@@ -40,7 +40,8 @@ import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.sql.Types;
 import java.util.Collections;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -66,17 +67,18 @@ public abstract class AbstractDatabaseMetadataExecutor 
implements DatabaseAdminQ
     public final void execute(final BackendConnection backendConnection) 
throws SQLException {
         List<String> schemaNames = getSchemaNames();
         for (String schemaName : schemaNames) {
+            initSchemaData(schemaName);
             getSourceData(schemaName, resultSet -> handleResultSet(schemaName, 
resultSet));
         }
-        addDefaultRow(rows);
+        createPreProcessing();
         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<>();
+            Map<String, Object> rowMap = new LinkedHashMap<>();
+            Map<String, String> aliasMap = new LinkedHashMap<>();
             ResultSetMetaData metaData = resultSet.getMetaData();
             for (int i = 1; i < metaData.getColumnCount() + 1; i++) {
                 aliasMap.put(metaData.getColumnName(i), 
metaData.getColumnLabel(i));
@@ -90,6 +92,11 @@ public abstract class AbstractDatabaseMetadataExecutor 
implements DatabaseAdminQ
     }
     
     /**
+     * Initialize the schema data.
+     */
+    protected abstract void initSchemaData(String schemaName);
+    
+    /**
      * Get the schema names as a condition for SQL execution.
      *
      * @return schema names
@@ -99,9 +106,8 @@ public abstract class AbstractDatabaseMetadataExecutor 
implements DatabaseAdminQ
     /**
      * Add default row data.
      *
-     * @param rows row
      */
-    protected abstract void addDefaultRow(LinkedList<Map<String, Object>> 
rows);
+    protected abstract void createPreProcessing();
     
     /**
      * Get the source object of the row data.
@@ -123,13 +129,13 @@ public abstract class AbstractDatabaseMetadataExecutor 
implements DatabaseAdminQ
     
     private MergedResult createMergedResult() {
         List<MemoryQueryResultDataRow> resultDataRows = rows.stream()
-                .map(each -> new MemoryQueryResultDataRow(new 
LinkedList<>(each.values()))).collect(Collectors.toList());
+                .map(each -> new MemoryQueryResultDataRow(new 
LinkedList<>(each.values()))).collect(Collectors.toCollection(LinkedList::new));
         return new TransparentMergedResult(new 
RawMemoryQueryResult(queryResultMetaData, resultDataRows));
     }
     
     private RawQueryResultMetaData createQueryResultMetaData() {
-        List<RawQueryResultColumnMetaData> columns = 
rows.stream().flatMap(each -> 
each.keySet().stream()).collect(Collectors.toSet())
-                .stream().map(each -> new RawQueryResultColumnMetaData("", 
each, each, Types.VARCHAR, "VARCHAR", 20, 0)).collect(Collectors.toList());
+        List<RawQueryResultColumnMetaData> columns = 
rows.stream().flatMap(each -> 
each.keySet().stream()).collect(Collectors.toCollection(LinkedHashSet::new))
+                .stream().map(each -> new RawQueryResultColumnMetaData("", 
each, each, Types.VARCHAR, "VARCHAR", 20, 
0)).collect(Collectors.toCollection(LinkedList::new));
         return new RawQueryResultMetaData(columns);
     }
     
@@ -155,7 +161,11 @@ public abstract class AbstractDatabaseMetadataExecutor 
implements DatabaseAdminQ
         public DefaultDatabaseMetadataExecutor(final String sql) {
             this.sql = sql;
         }
-        
+    
+        @Override
+        protected void initSchemaData(final String schemaName) {
+        }
+    
         /**
          * Get the schema names as a condition for SQL execution.
          *
@@ -194,14 +204,13 @@ public abstract class AbstractDatabaseMetadataExecutor 
implements DatabaseAdminQ
         @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) {
+        protected void createPreProcessing() {
         }
     }
 }
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
index c6b6c96..7ad3603 100644
--- 
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
@@ -17,9 +17,11 @@
 
 package org.apache.shardingsphere.proxy.backend.text.admin.postgresql;
 
+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.executor.DatabaseAdminExecutorFactory;
 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.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;
@@ -35,8 +37,12 @@ import java.util.stream.Collectors;
  */
 public final class PostgreSQLAdminExecutorFactory implements 
DatabaseAdminExecutorFactory {
     
+    private static final String PG_TABLESPACE = "pg_tablespace";
+    
     private static final String PG_DATABASE = "pg_database";
     
+    private static final String PG_NAMESPACE = "pg_namespace";
+    
     @Override
     public Optional<DatabaseAdminExecutor> newInstance(final SQLStatement 
sqlStatement) {
         return Optional.empty();
@@ -49,6 +55,12 @@ public final class PostgreSQLAdminExecutorFactory implements 
DatabaseAdminExecut
             if (selectedTableNames.contains(PG_DATABASE)) {
                 return Optional.of(new 
SelectDatabaseExecutor((SelectStatement) sqlStatement, sql));
             }
+            if (selectedTableNames.contains(PG_TABLESPACE)) {
+                return Optional.of(new SelectTableExecutor(sql));
+            }
+            if (selectedTableNames.contains(PG_NAMESPACE)) {
+                return Optional.of(new DefaultDatabaseMetadataExecutor(sql));
+            }
         }
         return Optional.empty();
     }
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
index 9e1d923..eaea1ee 100644
--- 
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
@@ -35,7 +35,7 @@ import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
- * Schemata query executor, used to query the schemata table.
+ * Database metadata query executor, used to query the schemata database.
  */
 public final class SelectDatabaseExecutor extends 
DefaultDatabaseMetadataExecutor {
     
@@ -53,10 +53,10 @@ public final class SelectDatabaseExecutor extends 
DefaultDatabaseMetadataExecuto
     }
     
     @Override
-    protected void addDefaultRow(final LinkedList<Map<String, Object>> rows) {
+    protected void createPreProcessing() {
         LinkedList<String> schemaWithoutDataSource = 
ProxyContext.getInstance().getAllSchemaNames().stream()
                 .filter(each -> 
!hasDatasource(each)).collect(Collectors.toCollection(LinkedList::new));
-        schemaWithoutDataSource.forEach(each -> 
rows.addLast(getDefaultRowData(each)));
+        schemaWithoutDataSource.forEach(each -> 
getRows().addLast(getDefaultRowData(each)));
     }
     
     @Override
diff --git 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/executor/SelectTableExecutor.java
 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/executor/SelectTableExecutor.java
new file mode 100644
index 0000000..366774d
--- /dev/null
+++ 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/executor/SelectTableExecutor.java
@@ -0,0 +1,81 @@
+/*
+ * 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.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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Database metadata query executor, used to query table.
+ */
+public final class SelectTableExecutor extends DefaultDatabaseMetadataExecutor 
{
+    
+    private static final String REL_NAME = "relname";
+    
+    private static final String TABLE_NAME = "tablename";
+    
+    private String actualTableName = "";
+    
+    private List<String> tableNames;
+    
+    public SelectTableExecutor(final String sql) {
+        super(sql);
+    }
+    
+    @Override
+    protected void initSchemaData(final String schemaName) {
+        tableNames = new 
ArrayList<>(ProxyContext.getInstance().getMetaData(schemaName).getSchema().getAllTableNames());
+    }
+    
+    @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) {
+        if (actualTableName.isEmpty()) {
+            actualTableName = aliasMap.getOrDefault(REL_NAME, 
aliasMap.getOrDefault(TABLE_NAME, ""));
+        }
+    }
+    
+    @Override
+    protected void createPreProcessing() {
+        if (actualTableName.isEmpty()) {
+            return;
+        }
+        if (tableNames.size() > getRows().size()) {
+            return;
+        }
+        List<Map<String, Object>> subList = new 
LinkedList<>(getRows().subList(0, tableNames.size()));
+        for (int i = 0; i < subList.size(); i++) {
+            subList.get(i).replace(actualTableName, tableNames.get(i));
+        }
+        getRows().clear();
+        getRows().addAll(subList);
+    }
+}
diff --git 
a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/executor/SelectTableExecutorTest.java
 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/executor/SelectTableExecutorTest.java
new file mode 100644
index 0000000..3369ef6
--- /dev/null
+++ 
b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/postgresql/executor/SelectTableExecutorTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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 com.zaxxer.hikari.pool.HikariProxyResultSet;
+import 
org.apache.shardingsphere.infra.config.properties.ConfigurationProperties;
+import org.apache.shardingsphere.infra.database.type.dialect.MySQLDatabaseType;
+import org.apache.shardingsphere.infra.executor.kernel.ExecutorEngine;
+import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import 
org.apache.shardingsphere.infra.metadata.resource.CachedDatabaseMetaData;
+import org.apache.shardingsphere.infra.metadata.resource.DataSourcesMetaData;
+import 
org.apache.shardingsphere.infra.metadata.resource.ShardingSphereResource;
+import 
org.apache.shardingsphere.infra.metadata.rule.ShardingSphereRuleMetaData;
+import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
+import org.apache.shardingsphere.infra.metadata.schema.model.TableMetaData;
+import org.apache.shardingsphere.infra.optimize.context.OptimizerContext;
+import org.apache.shardingsphere.mode.manager.ContextManager;
+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.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import javax.sql.DataSource;
+import java.lang.reflect.Field;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public final class SelectTableExecutorTest {
+    
+    private static final ResultSet RESULT_SET = 
mock(HikariProxyResultSet.class);
+    
+    @Before
+    public void setUp() throws IllegalAccessException, NoSuchFieldException, 
SQLException {
+        Field contextManagerField = 
ProxyContext.getInstance().getClass().getDeclaredField("contextManager");
+        contextManagerField.setAccessible(true);
+        ContextManager contextManager = mock(ContextManager.class, 
RETURNS_DEEP_STUBS);
+        MetaDataContexts metaDataContexts = new 
MetaDataContexts(mock(MetaDataPersistService.class), new HashMap<>(), 
mock(ShardingSphereRuleMetaData.class),
+                mock(ExecutorEngine.class), new ConfigurationProperties(new 
Properties()), mock(OptimizerContext.class));
+        
when(contextManager.getMetaDataContexts()).thenReturn(metaDataContexts);
+        ProxyContext.getInstance().init(contextManager);
+    }
+    
+    private void mockResultSet(final Map<String, String> mockMap, final 
Boolean... values) throws SQLException {
+        ResultSetMetaData metaData = mock(ResultSetMetaData.class);
+        List<String> keys = new ArrayList<>(mockMap.keySet());
+        for (int i = 0; i < keys.size(); i++) {
+            when(metaData.getColumnName(i + 1)).thenReturn(keys.get(i));
+            when(metaData.getColumnLabel(i + 1)).thenReturn(keys.get(i));
+            when(RESULT_SET.getString(i + 
1)).thenReturn(mockMap.get(keys.get(i)));
+        }
+        when(RESULT_SET.next()).thenReturn(true, false);
+        when(metaData.getColumnCount()).thenReturn(mockMap.size());
+        when(RESULT_SET.getMetaData()).thenReturn(metaData);
+    }
+    
+    private ShardingSphereMetaData getMetaData() throws SQLException {
+        return new ShardingSphereMetaData("sharding_db",
+                new ShardingSphereResource(mockDatasourceMap(), 
mockDataSourcesMetaData(), mock(CachedDatabaseMetaData.class), 
mock(MySQLDatabaseType.class)),
+                mock(ShardingSphereRuleMetaData.class), new 
ShardingSphereSchema(Collections.singletonMap("t_order", 
mock(TableMetaData.class))));
+    }
+    
+    private Map<String, DataSource> mockDatasourceMap() throws SQLException {
+        DataSource dataSource = mock(DataSource.class, RETURNS_DEEP_STUBS);
+        
when(dataSource.getConnection().prepareStatement(any(String.class)).executeQuery()).thenReturn(RESULT_SET);
+        Map<String, DataSource> dataSourceMap = new HashMap<>();
+        dataSourceMap.put("ds_0", dataSource);
+        return dataSourceMap;
+    }
+    
+    private DataSourcesMetaData mockDataSourcesMetaData() {
+        DataSourcesMetaData meta = mock(DataSourcesMetaData.class, 
RETURNS_DEEP_STUBS);
+        
when(meta.getDataSourceMetaData("ds_0").getCatalog()).thenReturn("demo_ds_0");
+        return meta;
+    }
+    
+    @Test
+    public void assertSelectSchemataExecute() throws SQLException {
+        final String sql = "SELECT c.oid, n.nspname AS schemaname, c.relname 
AS tablename from pg_tablespace";
+        Map<String, String> mockResultSetMap = new LinkedHashMap<>();
+        mockResultSetMap.put("tablename", "t_order_1");
+        mockResultSetMap.put("c.oid", "0000");
+        mockResultSetMap.put("schemaname", "public");
+        mockResultSet(mockResultSetMap, true, false);
+        Map<String, ShardingSphereMetaData> metaDataMap = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaDataMap();
+        metaDataMap.put("sharding_db", getMetaData());
+        SelectTableExecutor selectSchemataExecutor = new 
SelectTableExecutor(sql);
+        selectSchemataExecutor.execute(mock(BackendConnection.class));
+        
assertThat(selectSchemataExecutor.getQueryResultMetaData().getColumnCount(), 
is(mockResultSetMap.size()));
+        int count = 0;
+        while (selectSchemataExecutor.getMergedResult().next()) {
+            count++;
+            if 
("t_order".equals(selectSchemataExecutor.getMergedResult().getValue(1, 
String.class))) {
+                
assertThat(selectSchemataExecutor.getMergedResult().getValue(2, String.class), 
is("0000"));
+                
assertThat(selectSchemataExecutor.getMergedResult().getValue(3, String.class), 
is("public"));
+            } else {
+                fail("expected : `t_order`");
+            }
+        }
+        assertThat(count, is(1));
+    }
+}
diff --git 
a/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-postgresql/src/main/antlr4/imports/postgresql/BaseRule.g4
 
b/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-postgresql/src/main/antlr4/imports/postgresql/BaseRule.g4
index 94268c9..99651b1 100644
--- 
a/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-postgresql/src/main/antlr4/imports/postgresql/BaseRule.g4
+++ 
b/shardingsphere-sql-parser/shardingsphere-sql-parser-dialect/shardingsphere-sql-parser-postgresql/src/main/antlr4/imports/postgresql/BaseRule.g4
@@ -420,6 +420,7 @@ unreservedWord
     | YES
     | ZONE
     | JSON
+    | PARAM
     ;
 
 typeFuncNameKeyword

Reply via email to