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

FlyingZC 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 c7975f3f001 Support PostgreSQL whole-row projection binding (#39276)
c7975f3f001 is described below

commit c7975f3f001beb39d3a45a316728d2053a56aa3a
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Thu Jul 30 18:49:06 2026 +0800

    Support PostgreSQL whole-row projection binding (#39276)
---
 RELEASE-NOTES.md                                   |  1 +
 .../database/metadata/DialectDatabaseMetaData.java | 11 +++++
 .../metadata/option/sql/DefaultSQLOption.java      | 24 +++++++++++
 .../metadata/option/sql/DialectSQLOption.java      | 33 +++++++++++++++
 .../metadata/DialectDatabaseMetaDataTest.java      |  9 +++++
 .../database/OpenGaussDatabaseMetaData.java        |  7 ++++
 .../database/OpenGaussDatabaseMetaDataTest.java    |  7 ++++
 .../database/PostgreSQLDatabaseMetaData.java       |  7 ++++
 .../database/option/PostgreSQLSQLOption.java       | 31 ++++++++++++++
 .../database/PostgreSQLDatabaseMetaDataTest.java   |  7 ++++
 .../dml/projection/ProjectionsSegmentBinder.java   | 47 ++++++++++++++++++++++
 .../statement/dml/SelectStatementBinderTest.java   | 28 +++++++++++++
 12 files changed, 212 insertions(+)

diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index e4d3f243035..d48b21b7238 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -77,6 +77,7 @@
 1. SQL Parser: Support function table alias column parsing for PostgreSQL and 
openGauss - [#39268](https://github.com/apache/shardingsphere/pull/39268)
 1. SQL Binder: Support select order by index bind metadata - 
[#38386](https://github.com/apache/shardingsphere/pull/38386)
 1. SQL Binder: Support SQL bind when with temp table name is same with 
physical table - [#38411](https://github.com/apache/shardingsphere/pull/38411)
+1. SQL Binder: Support PostgreSQL whole-row projection binding - 
[#39276](https://github.com/apache/shardingsphere/pull/39276)
 1. Metadata: Support Oracle dictionary views by adding SYS default system 
schema and YAML definitions - 
[#38388](https://github.com/apache/shardingsphere/pull/38388)
 1. Metadata: Support parsing query properties from Oracle JDBC URLs - 
[#38901](https://github.com/apache/shardingsphere/pull/38901)
 1. JDBC: Support setMaxRows and getMaxRows method in jdbc when not execute SQL 
- [#38337](https://github.com/apache/shardingsphere/pull/38337)
diff --git 
a/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/database/metadata/DialectDatabaseMetaData.java
 
b/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/database/metadata/DialectDatabaseMetaData.java
index 2e7d51234d0..c9c170da25b 100644
--- 
a/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/database/metadata/DialectDatabaseMetaData.java
+++ 
b/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/database/metadata/DialectDatabaseMetaData.java
@@ -35,6 +35,8 @@ import 
org.apache.shardingsphere.database.connector.core.metadata.database.metad
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.schema.DialectSchemaOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.schema.DialectSchemaSemantics;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.sequence.DialectSequenceOption;
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.sql.DefaultSQLOption;
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.sql.DialectSQLOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.sqlbatch.DialectSQLBatchOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.table.DialectDriverQuerySystemCatalogOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.transaction.DDLCommitPolicy;
@@ -191,6 +193,15 @@ public interface DialectDatabaseMetaData extends 
DatabaseTypedSPI {
         return new DialectSQLBatchOption(true);
     }
     
+    /**
+     * Get SQL option.
+     *
+     * @return SQL option
+     */
+    default DialectSQLOption getSQLOption() {
+        return new DefaultSQLOption();
+    }
+    
     /**
      * Get protocol version option.
      *
diff --git 
a/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/database/metadata/option/sql/DefaultSQLOption.java
 
b/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/database/metadata/option/sql/DefaultSQLOption.java
new file mode 100644
index 00000000000..9d3277a65ae
--- /dev/null
+++ 
b/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/database/metadata/option/sql/DefaultSQLOption.java
@@ -0,0 +1,24 @@
+/*
+ * 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.database.connector.core.metadata.database.metadata.option.sql;
+
+/**
+ * Default SQL option.
+ */
+public final class DefaultSQLOption implements DialectSQLOption {
+}
diff --git 
a/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/database/metadata/option/sql/DialectSQLOption.java
 
b/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/database/metadata/option/sql/DialectSQLOption.java
new file mode 100644
index 00000000000..56d6169ffee
--- /dev/null
+++ 
b/database/connector/core/src/main/java/org/apache/shardingsphere/database/connector/core/metadata/database/metadata/option/sql/DialectSQLOption.java
@@ -0,0 +1,33 @@
+/*
+ * 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.database.connector.core.metadata.database.metadata.option.sql;
+
+/**
+ * Dialect SQL option.
+ */
+public interface DialectSQLOption {
+    
+    /**
+     * Judge whether whole-row projection is supported.
+     *
+     * @return whether whole-row projection is supported
+     */
+    default boolean isSupportWholeRowProjection() {
+        return false;
+    }
+}
diff --git 
a/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/metadata/database/metadata/DialectDatabaseMetaDataTest.java
 
b/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/metadata/database/metadata/DialectDatabaseMetaDataTest.java
index 284e79f5078..356aa57e09b 100644
--- 
a/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/metadata/database/metadata/DialectDatabaseMetaDataTest.java
+++ 
b/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/metadata/database/metadata/DialectDatabaseMetaDataTest.java
@@ -24,6 +24,8 @@ import 
org.apache.shardingsphere.database.connector.core.metadata.database.metad
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.pagination.DialectPaginationOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.schema.DialectSchemaOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.schema.DialectSchemaSemantics;
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.sql.DefaultSQLOption;
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.sql.DialectSQLOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.transaction.DDLCommitPolicy;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.transaction.DialectTransactionOption;
 import org.junit.jupiter.api.Test;
@@ -122,6 +124,13 @@ class DialectDatabaseMetaDataTest {
         
assertTrue(dialectDatabaseMetaData.getSQLBatchOption().isSupportSQLBatch());
     }
     
+    @Test
+    void assertGetSQLOption() {
+        DialectSQLOption actual = dialectDatabaseMetaData.getSQLOption();
+        assertThat(actual, isA(DefaultSQLOption.class));
+        assertFalse(actual.isSupportWholeRowProjection());
+    }
+    
     @Test
     void assertGetProtocolVersionOption() {
         
assertThat(dialectDatabaseMetaData.getProtocolVersionOption().getDefaultVersion(),
 is(""));
diff --git 
a/database/connector/dialect/opengauss/src/main/java/org/apache/shardingsphere/database/connector/opengauss/metadata/database/OpenGaussDatabaseMetaData.java
 
b/database/connector/dialect/opengauss/src/main/java/org/apache/shardingsphere/database/connector/opengauss/metadata/database/OpenGaussDatabaseMetaData.java
index 4c029a5550d..87c18171c1f 100644
--- 
a/database/connector/dialect/opengauss/src/main/java/org/apache/shardingsphere/database/connector/opengauss/metadata/database/OpenGaussDatabaseMetaData.java
+++ 
b/database/connector/dialect/opengauss/src/main/java/org/apache/shardingsphere/database/connector/opengauss/metadata/database/OpenGaussDatabaseMetaData.java
@@ -26,6 +26,7 @@ import 
org.apache.shardingsphere.database.connector.core.metadata.database.metad
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.index.DialectIndexOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.schema.DialectSchemaOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.sequence.DialectSequenceOption;
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.sql.DialectSQLOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.table.DialectDriverQuerySystemCatalogOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.transaction.DDLCommitPolicy;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.transaction.DialectTransactionOption;
@@ -34,6 +35,7 @@ import 
org.apache.shardingsphere.database.connector.opengauss.metadata.database.
 import 
org.apache.shardingsphere.database.connector.opengauss.metadata.database.option.OpenGaussDriverQuerySystemCatalogOption;
 import 
org.apache.shardingsphere.database.connector.opengauss.metadata.database.option.OpenGaussSchemaOption;
 import 
org.apache.shardingsphere.database.connector.postgresql.metadata.database.option.PostgreSQLFunctionOption;
+import 
org.apache.shardingsphere.database.connector.postgresql.metadata.database.option.PostgreSQLSQLOption;
 
 import java.util.Collections;
 import java.util.Optional;
@@ -96,6 +98,11 @@ public final class OpenGaussDatabaseMetaData implements 
DialectDatabaseMetaData
                 Collections.singleton("org.opengauss.xa.PGXADataSource"));
     }
     
+    @Override
+    public DialectSQLOption getSQLOption() {
+        return new PostgreSQLSQLOption();
+    }
+    
     @Override
     public DialectProtocolVersionOption getProtocolVersionOption() {
         return new DialectProtocolVersionOption("9.2.4");
diff --git 
a/database/connector/dialect/opengauss/src/test/java/org/apache/shardingsphere/database/connector/opengauss/metadata/database/OpenGaussDatabaseMetaDataTest.java
 
b/database/connector/dialect/opengauss/src/test/java/org/apache/shardingsphere/database/connector/opengauss/metadata/database/OpenGaussDatabaseMetaDataTest.java
index 497a11b103f..96ffefb3f1a 100644
--- 
a/database/connector/dialect/opengauss/src/test/java/org/apache/shardingsphere/database/connector/opengauss/metadata/database/OpenGaussDatabaseMetaDataTest.java
+++ 
b/database/connector/dialect/opengauss/src/test/java/org/apache/shardingsphere/database/connector/opengauss/metadata/database/OpenGaussDatabaseMetaDataTest.java
@@ -33,6 +33,7 @@ import 
org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import 
org.apache.shardingsphere.database.connector.opengauss.metadata.database.option.OpenGaussDataTypeOption;
 import 
org.apache.shardingsphere.database.connector.opengauss.metadata.database.option.OpenGaussSchemaOption;
 import 
org.apache.shardingsphere.database.connector.postgresql.metadata.database.option.PostgreSQLFunctionOption;
+import 
org.apache.shardingsphere.database.connector.postgresql.metadata.database.option.PostgreSQLSQLOption;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.junit.jupiter.api.Test;
 
@@ -120,6 +121,12 @@ class OpenGaussDatabaseMetaDataTest {
         
assertTrue(actual.getXaDriverClassNames().contains("org.opengauss.xa.PGXADataSource"));
     }
     
+    @Test
+    void assertGetSQLOption() {
+        assertThat(dialectDatabaseMetaData.getSQLOption(), 
isA(PostgreSQLSQLOption.class));
+        
assertTrue(dialectDatabaseMetaData.getSQLOption().isSupportWholeRowProjection());
+    }
+    
     @Test
     void assertGetProtocolVersionOption() {
         
assertThat(dialectDatabaseMetaData.getProtocolVersionOption().getDefaultVersion(),
 is("9.2.4"));
diff --git 
a/database/connector/dialect/postgresql/src/main/java/org/apache/shardingsphere/database/connector/postgresql/metadata/database/PostgreSQLDatabaseMetaData.java
 
b/database/connector/dialect/postgresql/src/main/java/org/apache/shardingsphere/database/connector/postgresql/metadata/database/PostgreSQLDatabaseMetaData.java
index c8c596fc5bc..a68438ade4d 100644
--- 
a/database/connector/dialect/postgresql/src/main/java/org/apache/shardingsphere/database/connector/postgresql/metadata/database/PostgreSQLDatabaseMetaData.java
+++ 
b/database/connector/dialect/postgresql/src/main/java/org/apache/shardingsphere/database/connector/postgresql/metadata/database/PostgreSQLDatabaseMetaData.java
@@ -26,11 +26,13 @@ import 
org.apache.shardingsphere.database.connector.core.metadata.database.metad
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.index.DialectIndexOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.schema.DialectSchemaOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.sequence.DialectSequenceOption;
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.sql.DialectSQLOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.transaction.DDLCommitPolicy;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.transaction.DialectTransactionOption;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.version.DialectProtocolVersionOption;
 import 
org.apache.shardingsphere.database.connector.postgresql.metadata.database.option.PostgreSQLDataTypeOption;
 import 
org.apache.shardingsphere.database.connector.postgresql.metadata.database.option.PostgreSQLFunctionOption;
+import 
org.apache.shardingsphere.database.connector.postgresql.metadata.database.option.PostgreSQLSQLOption;
 import 
org.apache.shardingsphere.database.connector.postgresql.metadata.database.option.PostgreSQLSchemaOption;
 
 import java.util.Collections;
@@ -89,6 +91,11 @@ public final class PostgreSQLDatabaseMetaData implements 
DialectDatabaseMetaData
                 Collections.singleton("org.postgresql.xa.PGXADataSource"));
     }
     
+    @Override
+    public DialectSQLOption getSQLOption() {
+        return new PostgreSQLSQLOption();
+    }
+    
     @Override
     public DialectProtocolVersionOption getProtocolVersionOption() {
         return new DialectProtocolVersionOption("12.3");
diff --git 
a/database/connector/dialect/postgresql/src/main/java/org/apache/shardingsphere/database/connector/postgresql/metadata/database/option/PostgreSQLSQLOption.java
 
b/database/connector/dialect/postgresql/src/main/java/org/apache/shardingsphere/database/connector/postgresql/metadata/database/option/PostgreSQLSQLOption.java
new file mode 100644
index 00000000000..42b445c77c6
--- /dev/null
+++ 
b/database/connector/dialect/postgresql/src/main/java/org/apache/shardingsphere/database/connector/postgresql/metadata/database/option/PostgreSQLSQLOption.java
@@ -0,0 +1,31 @@
+/*
+ * 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.database.connector.postgresql.metadata.database.option;
+
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.sql.DialectSQLOption;
+
+/**
+ * SQL option of PostgreSQL.
+ */
+public final class PostgreSQLSQLOption implements DialectSQLOption {
+    
+    @Override
+    public boolean isSupportWholeRowProjection() {
+        return true;
+    }
+}
diff --git 
a/database/connector/dialect/postgresql/src/test/java/org/apache/shardingsphere/database/connector/postgresql/metadata/database/PostgreSQLDatabaseMetaDataTest.java
 
b/database/connector/dialect/postgresql/src/test/java/org/apache/shardingsphere/database/connector/postgresql/metadata/database/PostgreSQLDatabaseMetaDataTest.java
index fe939359c13..95b7f3a459f 100644
--- 
a/database/connector/dialect/postgresql/src/test/java/org/apache/shardingsphere/database/connector/postgresql/metadata/database/PostgreSQLDatabaseMetaDataTest.java
+++ 
b/database/connector/dialect/postgresql/src/test/java/org/apache/shardingsphere/database/connector/postgresql/metadata/database/PostgreSQLDatabaseMetaDataTest.java
@@ -30,6 +30,7 @@ import 
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoa
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import 
org.apache.shardingsphere.database.connector.postgresql.metadata.database.option.PostgreSQLDataTypeOption;
 import 
org.apache.shardingsphere.database.connector.postgresql.metadata.database.option.PostgreSQLFunctionOption;
+import 
org.apache.shardingsphere.database.connector.postgresql.metadata.database.option.PostgreSQLSQLOption;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.junit.jupiter.api.Test;
 
@@ -105,6 +106,12 @@ class PostgreSQLDatabaseMetaDataTest {
         
assertTrue(actual.getXaDriverClassNames().contains("org.postgresql.xa.PGXADataSource"));
     }
     
+    @Test
+    void assertGetSQLOption() {
+        assertThat(dialectDatabaseMetaData.getSQLOption(), 
isA(PostgreSQLSQLOption.class));
+        
assertTrue(dialectDatabaseMetaData.getSQLOption().isSupportWholeRowProjection());
+    }
+    
     @Test
     void assertGetProtocolVersionOption() {
         
assertThat(dialectDatabaseMetaData.getProtocolVersionOption().getDefaultVersion(),
 is("12.3"));
diff --git 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/projection/ProjectionsSegmentBinder.java
 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/projection/ProjectionsSegmentBinder.java
index 7de9e257766..f560fea0c70 100644
--- 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/projection/ProjectionsSegmentBinder.java
+++ 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/projection/ProjectionsSegmentBinder.java
@@ -22,6 +22,7 @@ import com.google.common.collect.LinkedHashMultimap;
 import com.google.common.collect.Multimap;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
+import 
org.apache.shardingsphere.database.connector.core.type.DatabaseTypeRegistry;
 import org.apache.shardingsphere.infra.binder.engine.segment.SegmentType;
 import 
org.apache.shardingsphere.infra.binder.engine.segment.dml.expression.ExpressionSegmentBinder;
 import 
org.apache.shardingsphere.infra.binder.engine.segment.dml.expression.type.AggregationDistinctProjectionSegmentBinder;
@@ -35,6 +36,7 @@ import 
org.apache.shardingsphere.infra.binder.engine.segment.util.SubqueryTableB
 import 
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
 import 
org.apache.shardingsphere.infra.exception.kernel.metadata.ColumnNotFoundException;
 import 
org.apache.shardingsphere.sql.parser.statement.core.enums.TableSourceType;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.AggregationDistinctProjectionSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.AggregationProjectionSegment;
@@ -46,6 +48,8 @@ import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.Shor
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.SubqueryProjectionSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.xml.XmlElementFunctionSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.xml.XmlSerializeFunctionSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.JoinTableSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
 
@@ -87,6 +91,9 @@ public final class ProjectionsSegmentBinder {
         try {
             return bind(projectionSegment, binderContext, boundTableSegment, 
tableBinderContexts, outerTableBinderContexts);
         } catch (final ColumnNotFoundException ignored) {
+            if (isWholeRowProjection(projectionSegment, binderContext, 
boundTableSegment, tableBinderContexts)) {
+                return createWholeRowProjection((ColumnProjectionSegment) 
projectionSegment);
+            }
             return bind(projectionSegment, binderContext, boundTableSegment, 
currentTableBinderContexts, outerTableBinderContexts);
         }
     }
@@ -146,6 +153,46 @@ public final class ProjectionsSegmentBinder {
         return result;
     }
     
+    private static boolean isWholeRowProjection(final ProjectionSegment 
projectionSegment, final SQLStatementBinderContext binderContext,
+                                                final TableSegment 
boundTableSegment,
+                                                final 
Multimap<CaseInsensitiveString, TableSegmentBinderContext> tableBinderContexts) 
{
+        if (!(projectionSegment instanceof ColumnProjectionSegment) || 
!isSupportWholeRowProjection(binderContext)) {
+            return false;
+        }
+        ColumnSegment columnSegment = ((ColumnProjectionSegment) 
projectionSegment).getColumn();
+        String columnName = columnSegment.getIdentifier().getValue();
+        return !columnSegment.getOwner().isPresent() && (null == 
columnSegment.getNestedObjectAttributes() || 
columnSegment.getNestedObjectAttributes().isEmpty())
+                && (isTableAliasOrName(boundTableSegment, columnName) || 
tableBinderContexts.containsKey(CaseInsensitiveString.of(columnName)));
+    }
+    
+    private static boolean isSupportWholeRowProjection(final 
SQLStatementBinderContext binderContext) {
+        return new 
DatabaseTypeRegistry(binderContext.getSqlStatement().getDatabaseType()).getDialectDatabaseMetaData().getSQLOption().isSupportWholeRowProjection();
+    }
+    
+    private static ExpressionProjectionSegment createWholeRowProjection(final 
ColumnProjectionSegment projectionSegment) {
+        ColumnSegment columnSegment = projectionSegment.getColumn();
+        ExpressionProjectionSegment result = new 
ExpressionProjectionSegment(columnSegment.getStartIndex(), 
columnSegment.getStopIndex(), columnSegment.getExpression());
+        projectionSegment.getAliasSegment().ifPresent(result::setAlias);
+        return result;
+    }
+    
+    private static boolean isTableAliasOrName(final TableSegment tableSegment, 
final String identifier) {
+        if (null == tableSegment) {
+            return false;
+        }
+        if (tableSegment.getAliasName().isPresent()) {
+            return 
tableSegment.getAliasName().get().equalsIgnoreCase(identifier);
+        }
+        if (tableSegment instanceof SimpleTableSegment) {
+            return ((SimpleTableSegment) 
tableSegment).getTableName().getIdentifier().getValue().equalsIgnoreCase(identifier);
+        }
+        if (tableSegment instanceof JoinTableSegment) {
+            JoinTableSegment joinTableSegment = (JoinTableSegment) 
tableSegment;
+            return isTableAliasOrName(joinTableSegment.getLeft(), identifier) 
|| isTableAliasOrName(joinTableSegment.getRight(), identifier);
+        }
+        return false;
+    }
+    
     private static Multimap<CaseInsensitiveString, TableSegmentBinderContext> 
createCurrentTableBinderContexts(final SQLStatementBinderContext binderContext,
                                                                                
                                final Collection<ProjectionSegment> 
projections) {
         Multimap<CaseInsensitiveString, TableSegmentBinderContext> result = 
LinkedHashMultimap.create();
diff --git 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinderTest.java
 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinderTest.java
index 98f6c9c411c..ba8046c52bb 100644
--- 
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinderTest.java
+++ 
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/statement/dml/SelectStatementBinderTest.java
@@ -17,6 +17,10 @@
 
 package org.apache.shardingsphere.infra.binder.engine.statement.dml;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.QuoteCharacter;
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.DialectDatabaseMetaData;
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.sql.DialectSQLOption;
+import 
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import 
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
 import org.apache.shardingsphere.infra.hint.HintValueContext;
@@ -59,6 +63,7 @@ import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
 import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
 
 import java.sql.Types;
 import java.util.ArrayList;
@@ -72,8 +77,10 @@ import static org.hamcrest.Matchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.isA;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
 import static org.mockito.Mockito.when;
 
 class SelectStatementBinderTest {
@@ -121,6 +128,27 @@ class SelectStatementBinderTest {
                 .getColumnBoundInfo().getOriginalTable().getValue(), 
is("t_order"));
     }
     
+    @Test
+    void assertBindWholeRowProjection() {
+        DatabaseType protocolType = mock(DatabaseType.class);
+        DialectDatabaseMetaData dialectDatabaseMetaData = 
mock(DialectDatabaseMetaData.class, CALLS_REAL_METHODS);
+        DialectSQLOption sqlOption = mock(DialectSQLOption.class);
+        when(sqlOption.isSupportWholeRowProjection()).thenReturn(true);
+        when(dialectDatabaseMetaData.getSQLOption()).thenReturn(sqlOption);
+        
when(dialectDatabaseMetaData.getQuoteCharacter()).thenReturn(QuoteCharacter.NONE);
+        ProjectionsSegment projections = new ProjectionsSegment(0, 0);
+        projections.getProjections().add(new ColumnProjectionSegment(new 
ColumnSegment(0, 0, new IdentifierValue("o"))));
+        SelectStatement selectStatement = 
SelectStatement.builder().databaseType(protocolType).projections(projections).from(createAliasedSimpleTableSegment("t_order",
 "o")).build();
+        try (MockedStatic<DatabaseTypedSPILoader> databaseTypedSPILoader = 
mockStatic(DatabaseTypedSPILoader.class)) {
+            databaseTypedSPILoader.when(() -> 
DatabaseTypedSPILoader.getService(DialectDatabaseMetaData.class, 
protocolType)).thenReturn(dialectDatabaseMetaData);
+            SelectStatement actual = new 
SelectStatementBinder().bind(selectStatement,
+                    new SQLStatementBinderContext(mockMetaData(), "foo_db", 
new HintValueContext(), selectStatement));
+            ProjectionSegment actualProjection = 
actual.getProjections().getProjections().iterator().next();
+            assertThat(actualProjection, 
isA(ExpressionProjectionSegment.class));
+            assertThat(((ExpressionProjectionSegment) 
actualProjection).getText(), is("o"));
+        }
+    }
+    
     @Test
     void assertBindHierarchicalQuery() {
         ProjectionsSegment projections = new ProjectionsSegment(0, 0);

Reply via email to