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);