This is an automated email from the ASF dual-hosted git repository.
terrymanu 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 f73b57cae98 Fix derived table alias columns for PostgreSQL values
subquery (#38989)
f73b57cae98 is described below
commit f73b57cae98c8c9d3aa80b70149a87c6c6caaa58
Author: Zhengcy05 <[email protected]>
AuthorDate: Sun Jul 5 05:15:26 2026 +0800
Fix derived table alias columns for PostgreSQL values subquery (#38989)
* fix: support derived table alias columns for PostgreSQL values subquery
* fix: checkstyle and CI
* fix: modify CI xml
---
.../dml/from/type/SubqueryTableSegmentBinder.java | 17 ++-
.../from/type/SubqueryTableSegmentBinderTest.java | 126 ++++++++++++++-------
.../statement/PostgreSQLStatementVisitor.java | 39 +++++--
.../statement/PostgreSQLStatementVisitorTest.java | 35 ++++++
.../core/segment/generic/AliasSegment.java | 5 +
.../src/main/resources/case/ddl/create-view.xml | 40 ++++++-
.../resources/sql/supported/ddl/create-view.xml | 3 +-
7 files changed, 211 insertions(+), 54 deletions(-)
diff --git
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/SubqueryTableSegmentBinder.java
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/SubqueryTableSegmentBinder.java
index 12feba37d8d..592345efbeb 100644
---
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/SubqueryTableSegmentBinder.java
+++
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/SubqueryTableSegmentBinder.java
@@ -84,7 +84,7 @@ public final class SubqueryTableSegmentBinder {
segment.getAliasSegment().ifPresent(result::setAlias);
Collection<ProjectionSegment> subqueryProjections =
SubqueryTableBindUtils.createSubqueryProjections(
boundSubSelect.getProjections().getProjections(),
subqueryTableName, binderContext.getSqlStatement().getDatabaseType(),
TableSourceType.TEMPORARY_TABLE);
- Collection<ColumnSegment> boundSubqueryColumns =
bindSubqueryColumns(segment.getColumns(), new ArrayList<>(subqueryProjections));
+ Collection<ColumnSegment> boundSubqueryColumns =
bindSubqueryColumns(getSubqueryColumns(segment), new
ArrayList<>(subqueryProjections));
result.getColumns().addAll(boundSubqueryColumns);
if (!boundSubqueryColumns.isEmpty()) {
subqueryProjections =
createBoundSubqueryColumnProjections(boundSubqueryColumns, subqueryTableName);
@@ -97,6 +97,21 @@ public final class SubqueryTableSegmentBinder {
return result;
}
+ private static Collection<ColumnSegment> getSubqueryColumns(final
SubqueryTableSegment segment) {
+ if (!segment.getColumns().isEmpty()) {
+ return segment.getColumns();
+ }
+ if (!segment.getAliasSegment().isPresent() ||
segment.getAliasSegment().get().getColumnAliases().isEmpty()) {
+ return Collections.emptyList();
+ }
+ Collection<ColumnSegment> result = new LinkedList<>();
+ AliasSegment aliasSegment = segment.getAliasSegment().get();
+ for (IdentifierValue each : aliasSegment.getColumnAliases()) {
+ result.add(new ColumnSegment(aliasSegment.getStartIndex(),
aliasSegment.getStopIndex(), each));
+ }
+ return result;
+ }
+
private static Multimap<CaseInsensitiveString, TableSegmentBinderContext>
createTableBinderContexts(final IdentifierValue subqueryTableName,
final TableSegmentBinderContext tableBinderContext) {
Multimap<CaseInsensitiveString, TableSegmentBinderContext> result =
LinkedHashMultimap.create();
diff --git
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/SubqueryTableSegmentBinderTest.java
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/SubqueryTableSegmentBinderTest.java
index 6928f681ffd..3cf1b58b27d 100644
---
a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/SubqueryTableSegmentBinderTest.java
+++
b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/engine/segment/dml/from/type/SubqueryTableSegmentBinderTest.java
@@ -23,10 +23,16 @@ import com.google.common.collect.Multimap;
import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
import
org.apache.shardingsphere.infra.binder.engine.segment.dml.from.context.TableSegmentBinderContext;
import
org.apache.shardingsphere.infra.binder.engine.statement.SQLStatementBinderContext;
+import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import
org.apache.shardingsphere.infra.exception.kernel.syntax.DifferenceInColumnCountOfSelectListAndColumnNameListException;
import org.apache.shardingsphere.infra.hint.HintValueContext;
import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import
org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData;
+import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereColumn;
import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
+import
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereTable;
import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import
org.apache.shardingsphere.sql.parser.statement.core.enums.TableSourceType;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
@@ -46,17 +52,18 @@ import org.junit.jupiter.api.Test;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Optional;
+import java.util.Properties;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isA;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
class SubqueryTableSegmentBinderTest {
@@ -64,12 +71,7 @@ class SubqueryTableSegmentBinderTest {
@Test
void assertBindWithSubqueryTableAlias() {
- SelectStatement selectStatement = mock(SelectStatement.class);
- when(selectStatement.getDatabaseType()).thenReturn(databaseType);
- when(selectStatement.getFrom()).thenReturn(Optional.of(new
SimpleTableSegment(new TableNameSegment(0, 0, new
IdentifierValue("t_order")))));
- ProjectionsSegment projectionsSegment = new ProjectionsSegment(0, 0);
- projectionsSegment.getProjections().add(new
ShorthandProjectionSegment(0, 0));
- when(selectStatement.getProjections()).thenReturn(projectionsSegment);
+ SelectStatement selectStatement = createSelectStatement(new
ShorthandProjectionSegment(0, 0));
SubqueryTableSegment subqueryTableSegment = new
SubqueryTableSegment(0, 0, new SubquerySegment(0, 0, selectStatement, ""));
subqueryTableSegment.setAlias(new AliasSegment(0, 0, new
IdentifierValue("temp")));
ShardingSphereMetaData metaData = createMetaData();
@@ -96,14 +98,9 @@ class SubqueryTableSegmentBinderTest {
@Test
void assertBindWithSubqueryProjectionAlias() {
- SelectStatement selectStatement = mock(SelectStatement.class);
- when(selectStatement.getDatabaseType()).thenReturn(databaseType);
- when(selectStatement.getFrom()).thenReturn(Optional.of(new
SimpleTableSegment(new TableNameSegment(0, 0, new
IdentifierValue("t_order")))));
- ProjectionsSegment projectionsSegment = new ProjectionsSegment(0, 0);
ColumnProjectionSegment columnProjectionSegment = new
ColumnProjectionSegment(new ColumnSegment(0, 0, new
IdentifierValue("order_id")));
columnProjectionSegment.setAlias(new AliasSegment(0, 0, new
IdentifierValue("order_id_alias")));
- projectionsSegment.getProjections().add(columnProjectionSegment);
- when(selectStatement.getProjections()).thenReturn(projectionsSegment);
+ SelectStatement selectStatement =
createSelectStatement(columnProjectionSegment);
SubqueryTableSegment subqueryTableSegment = new
SubqueryTableSegment(0, 0, new SubquerySegment(0, 0, selectStatement, ""));
subqueryTableSegment.setAlias(new AliasSegment(0, 0, new
IdentifierValue("temp")));
ShardingSphereMetaData metaData = createMetaData();
@@ -122,12 +119,7 @@ class SubqueryTableSegmentBinderTest {
@Test
void assertBindWithoutSubqueryTableAlias() {
- SelectStatement selectStatement = mock(SelectStatement.class);
- when(selectStatement.getDatabaseType()).thenReturn(databaseType);
- when(selectStatement.getFrom()).thenReturn(Optional.of(new
SimpleTableSegment(new TableNameSegment(0, 0, new
IdentifierValue("t_order")))));
- ProjectionsSegment projectionsSegment = new ProjectionsSegment(0, 0);
- projectionsSegment.getProjections().add(new
ShorthandProjectionSegment(0, 0));
- when(selectStatement.getProjections()).thenReturn(projectionsSegment);
+ SelectStatement selectStatement = createSelectStatement(new
ShorthandProjectionSegment(0, 0));
SubqueryTableSegment subqueryTableSegment = new
SubqueryTableSegment(0, 0, new SubquerySegment(0, 0, selectStatement, ""));
ShardingSphereMetaData metaData = createMetaData();
Multimap<CaseInsensitiveString, TableSegmentBinderContext>
tableBinderContexts = LinkedHashMultimap.create();
@@ -139,13 +131,9 @@ class SubqueryTableSegmentBinderTest {
@Test
void assertBindWithSubqueryTableColumns() {
- SelectStatement selectStatement = mock(SelectStatement.class);
- when(selectStatement.getDatabaseType()).thenReturn(databaseType);
- when(selectStatement.getFrom()).thenReturn(Optional.of(new
SimpleTableSegment(new TableNameSegment(0, 0, new
IdentifierValue("t_order")))));
- ProjectionsSegment projectionsSegment = new ProjectionsSegment(0, 0);
- projectionsSegment.getProjections().add(new
ColumnProjectionSegment(new ColumnSegment(0, 0, new
IdentifierValue("user_id"))));
- projectionsSegment.getProjections().add(new
ColumnProjectionSegment(new ColumnSegment(0, 0, new
IdentifierValue("status"))));
- when(selectStatement.getProjections()).thenReturn(projectionsSegment);
+ SelectStatement selectStatement = createSelectStatement(
+ new ColumnProjectionSegment(new ColumnSegment(0, 0, new
IdentifierValue("user_id"))),
+ new ColumnProjectionSegment(new ColumnSegment(0, 0, new
IdentifierValue("status"))));
SubqueryTableSegment subqueryTableSegment = new
SubqueryTableSegment(0, 0, new SubquerySegment(0, 0, selectStatement, ""));
subqueryTableSegment.setAlias(new AliasSegment(0, 0, new
IdentifierValue("combined")));
subqueryTableSegment.getColumns().add(new ColumnSegment(0, 0, new
IdentifierValue("id")));
@@ -187,23 +175,75 @@ class SubqueryTableSegmentBinderTest {
assertThat(actualNameProjection.getColumn().getColumnBoundInfo().getTableSourceType(),
is(TableSourceType.TEMPORARY_TABLE));
}
+ @Test
+ void assertBindWithSubqueryAliasColumns() {
+ SelectStatement selectStatement = createSelectStatement(
+ new ColumnProjectionSegment(new ColumnSegment(0, 0, new
IdentifierValue("user_id"))),
+ new ColumnProjectionSegment(new ColumnSegment(0, 0, new
IdentifierValue("status"))));
+ SubqueryTableSegment subqueryTableSegment = new
SubqueryTableSegment(0, 0, new SubquerySegment(0, 0, selectStatement, ""));
+ AliasSegment aliasSegment = new AliasSegment(0, 0, new
IdentifierValue("combined"));
+ aliasSegment.getColumnAliases().add(new IdentifierValue("id"));
+ aliasSegment.getColumnAliases().add(new IdentifierValue("name"));
+ subqueryTableSegment.setAlias(aliasSegment);
+ ShardingSphereMetaData metaData = createMetaData();
+ Multimap<CaseInsensitiveString, TableSegmentBinderContext>
tableBinderContexts = LinkedHashMultimap.create();
+ SubqueryTableSegment actual =
SubqueryTableSegmentBinder.bind(subqueryTableSegment,
+ new SQLStatementBinderContext(metaData, "foo_db", new
HintValueContext(), selectStatement),
+ tableBinderContexts, LinkedHashMultimap.create(), false);
+ assertThat(actual.getColumns().size(), is(2));
+ List<ColumnSegment> actualColumns = new
ArrayList<>(actual.getColumns());
+ assertFalse(actualColumns.get(0).getOwner().isPresent());
+ assertThat(actualColumns.get(0).getIdentifier().getValue(), is("id"));
+
assertThat(actualColumns.get(0).getColumnBoundInfo().getOriginalTable().getValue(),
is("t_order"));
+
assertThat(actualColumns.get(0).getColumnBoundInfo().getOriginalColumn().getValue(),
is("user_id"));
+ assertFalse(actualColumns.get(1).getOwner().isPresent());
+ assertThat(actualColumns.get(1).getIdentifier().getValue(),
is("name"));
+
assertThat(actualColumns.get(1).getColumnBoundInfo().getOriginalTable().getValue(),
is("t_order"));
+
assertThat(actualColumns.get(1).getColumnBoundInfo().getOriginalColumn().getValue(),
is("status"));
+
assertTrue(tableBinderContexts.containsKey(CaseInsensitiveString.of("combined")));
+ TableSegmentBinderContext tableSegmentBinderContext =
tableBinderContexts.get(CaseInsensitiveString.of("combined")).iterator().next();
+ Optional<ProjectionSegment> idProjection =
tableSegmentBinderContext.findProjectionSegmentByColumnLabel("id");
+ assertTrue(idProjection.isPresent());
+ assertThat(idProjection.get(), isA(ColumnProjectionSegment.class));
+ Optional<ProjectionSegment> nameProjection =
tableSegmentBinderContext.findProjectionSegmentByColumnLabel("name");
+ assertTrue(nameProjection.isPresent());
+ assertThat(nameProjection.get(), isA(ColumnProjectionSegment.class));
+ }
+
+ @Test
+ void assertBindWithSubqueryAliasColumnsAndDifferentColumnCount() {
+ SelectStatement selectStatement = createSelectStatement(new
ColumnProjectionSegment(new ColumnSegment(0, 0, new
IdentifierValue("user_id"))));
+ SubqueryTableSegment subqueryTableSegment = new
SubqueryTableSegment(0, 0, new SubquerySegment(0, 0, selectStatement, ""));
+ AliasSegment aliasSegment = new AliasSegment(0, 0, new
IdentifierValue("combined"));
+ aliasSegment.getColumnAliases().add(new IdentifierValue("id"));
+ aliasSegment.getColumnAliases().add(new IdentifierValue("name"));
+ subqueryTableSegment.setAlias(aliasSegment);
+ ShardingSphereMetaData metaData = createMetaData();
+
assertThrows(DifferenceInColumnCountOfSelectListAndColumnNameListException.class,
+ () -> SubqueryTableSegmentBinder.bind(subqueryTableSegment,
+ new SQLStatementBinderContext(metaData, "foo_db", new
HintValueContext(), selectStatement),
+ LinkedHashMultimap.create(),
LinkedHashMultimap.create(), false));
+ }
+
+ private SelectStatement createSelectStatement(final ProjectionSegment...
projections) {
+ ProjectionsSegment projectionsSegment = new ProjectionsSegment(0, 0);
+ projectionsSegment.getProjections().addAll(Arrays.asList(projections));
+ return
SelectStatement.builder().databaseType(databaseType).projections(projectionsSegment)
+ .from(new SimpleTableSegment(new TableNameSegment(0, 0, new
IdentifierValue("t_order")))).build();
+ }
+
private ShardingSphereMetaData createMetaData() {
- ShardingSphereSchema schema = mock(ShardingSphereSchema.class,
RETURNS_DEEP_STUBS);
- IdentifierValue fooDatabase = new IdentifierValue("foo_db");
- IdentifierValue tOrder = new IdentifierValue("t_order");
- when(schema.getTable(tOrder).getAllColumns()).thenReturn(Arrays.asList(
+ Collection<ShardingSphereColumn> columns = Arrays.asList(
new ShardingSphereColumn("order_id", Types.INTEGER, true,
false, false, true, false, false),
new ShardingSphereColumn("user_id", Types.INTEGER, false,
false, false, true, false, false),
- new ShardingSphereColumn("status", Types.INTEGER, false,
false, false, true, false, false)));
- ShardingSphereMetaData result = mock(ShardingSphereMetaData.class,
RETURNS_DEEP_STUBS);
-
when(result.getDatabase("foo_db").getSchema("foo_db")).thenReturn(schema);
-
when(result.getDatabase(fooDatabase).getSchema(fooDatabase)).thenReturn(schema);
- when(result.containsDatabase(fooDatabase)).thenReturn(true);
-
when(result.getDatabase("foo_db").getDefaultSchemaName()).thenReturn("foo_db");
-
when(result.getDatabase(fooDatabase).getDefaultSchemaName()).thenReturn("foo_db");
-
when(result.getDatabase("foo_db").containsSchema("foo_db")).thenReturn(true);
-
when(result.getDatabase(fooDatabase).containsSchema(fooDatabase)).thenReturn(true);
-
when(result.getDatabase(fooDatabase).getSchema(fooDatabase).containsTable(tOrder)).thenReturn(true);
- return result;
+ new ShardingSphereColumn("status", Types.INTEGER, false,
false, false, true, false, false));
+ ShardingSphereTable table = new ShardingSphereTable("t_order",
columns, Collections.emptyList(), Collections.emptyList());
+ ShardingSphereSchema schema = new ShardingSphereSchema("foo_db",
databaseType, Collections.singletonList(table), Collections.emptyList());
+ ConfigurationProperties props = new ConfigurationProperties(new
Properties());
+ ResourceMetaData globalResourceMetaData = new
ResourceMetaData(Collections.emptyMap(), Collections.emptyMap());
+ RuleMetaData globalRuleMetaData = new
RuleMetaData(Collections.emptyList());
+ ShardingSphereDatabase database = new ShardingSphereDatabase("foo_db",
databaseType,
+ new ResourceMetaData(Collections.emptyMap(),
Collections.emptyMap()), new RuleMetaData(Collections.emptyList()),
Collections.singletonList(schema), props);
+ return new ShardingSphereMetaData(Collections.singletonList(database),
globalResourceMetaData, globalRuleMetaData, props);
}
}
diff --git
a/parser/sql/engine/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
b/parser/sql/engine/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
index 8ec7348f9e1..9eb2f88e9d8 100644
---
a/parser/sql/engine/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
+++
b/parser/sql/engine/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
@@ -1075,14 +1075,16 @@ public abstract class PostgreSQLStatementVisitor
extends PostgreSQLStatementPars
@Override
public ASTNode visitSimpleSelect(final SimpleSelectContext ctx) {
SelectStatement.SelectStatementBuilder selectStatementBuilder =
SelectStatement.builder().databaseType(databaseType);
- if (null == ctx.targetList()) {
- selectStatementBuilder.projections(new ProjectionsSegment(-1, -1));
- } else {
+ if (null != ctx.targetList()) {
ProjectionsSegment projects = (ProjectionsSegment)
visit(ctx.targetList());
if (null != ctx.distinctClause()) {
projects.setDistinctRow(true);
}
selectStatementBuilder.projections(projects);
+ } else if (null != ctx.valuesClause()) {
+
selectStatementBuilder.projections(createValuesProjections(ctx.valuesClause()));
+ } else {
+ selectStatementBuilder.projections(new ProjectionsSegment(-1, -1));
}
if (null != ctx.intoClause()) {
selectStatementBuilder.into((TableSegment)
visit(ctx.intoClause()));
@@ -1105,6 +1107,18 @@ public abstract class PostgreSQLStatementVisitor extends
PostgreSQLStatementPars
return selectStatementBuilder.build();
}
+ private ProjectionsSegment createValuesProjections(final
ValuesClauseContext ctx) {
+ ProjectionsSegment result = new
ProjectionsSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex());
+ Collection<InsertValuesSegment> values =
createInsertValuesSegments(ctx);
+ if (values.isEmpty()) {
+ return result;
+ }
+ for (ExpressionSegment each : values.iterator().next().getValues()) {
+ result.getProjections().add(new
ExpressionProjectionSegment(each.getStartIndex(), each.getStopIndex(),
each.getText(), each));
+ }
+ return result;
+ }
+
@Override
public ASTNode visitIntoClause(final IntoClauseContext ctx) {
return visit(ctx.optTempTableName().qualifiedName());
@@ -1422,13 +1436,22 @@ public abstract class PostgreSQLStatementVisitor
extends PostgreSQLStatementPars
@Override
public ASTNode visitAliasClause(final AliasClauseContext ctx) {
- StringBuilder aliasName = new StringBuilder(ctx.colId().getText());
+ AliasSegment result = new
AliasSegment(ctx.colId().start.getStartIndex(), ctx.stop.getStopIndex(), new
IdentifierValue(ctx.colId().getText()));
+ if (null != ctx.nameList()) {
+
result.getColumnAliases().addAll(generateAliasColumns(ctx.nameList()));
+ }
+ return result;
+ }
+
+ private Collection<IdentifierValue> generateAliasColumns(final
NameListContext ctx) {
+ Collection<IdentifierValue> result = new LinkedList<>();
if (null != ctx.nameList()) {
- aliasName.append(ctx.LP_().getText());
- aliasName.append(ctx.nameList().getText());
- aliasName.append(ctx.RP_().getText());
+ result.addAll(generateAliasColumns(ctx.nameList()));
}
- return new AliasSegment(ctx.colId().start.getStartIndex(),
ctx.stop.getStopIndex(), new IdentifierValue(aliasName.toString()));
+ if (null != ctx.name()) {
+ result.add(new IdentifierValue(ctx.name().getText()));
+ }
+ return result;
}
private OwnerSegment createTableOwner(final IndirectionContext ctx) {
diff --git
a/parser/sql/engine/dialect/postgresql/src/test/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitorTest.java
b/parser/sql/engine/dialect/postgresql/src/test/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitorTest.java
index 2a42131aba9..681d4528a57 100644
---
a/parser/sql/engine/dialect/postgresql/src/test/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitorTest.java
+++
b/parser/sql/engine/dialect/postgresql/src/test/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitorTest.java
@@ -24,15 +24,20 @@ import
org.apache.shardingsphere.sql.parser.engine.core.ParseASTNode;
import
org.apache.shardingsphere.sql.parser.statement.core.extractor.TableExtractor;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.NotExpression;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.AggregationProjectionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ExpressionProjectionSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.WindowItemSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SubqueryTableSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
+import
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.UpdateStatement;
+import
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
import org.junit.jupiter.api.Test;
import java.util.Collection;
import java.util.stream.Collectors;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isA;
@@ -55,6 +60,36 @@ class PostgreSQLStatementVisitorTest {
assertThat(rewriteTableNames, hasItems("t17", "t23", "t22"));
}
+ @Test
+ void assertVisitSelectWithValuesDerivedTableColumnAliases() {
+ SelectStatement statement = (SelectStatement) new
SQLStatementVisitorEngine("PostgreSQL").visit(
+ new SQLParserEngine("PostgreSQL", new CacheOption(128,
1024L)).parse("SELECT * FROM (VALUES ('k1', 'v1', 1)) AS t(pk, col_a,
col_a_type)", false));
+ assertTrue(statement.getFrom().isPresent());
+ assertThat(statement.getFrom().get(), isA(SubqueryTableSegment.class));
+ SubqueryTableSegment subqueryTableSegment = (SubqueryTableSegment)
statement.getFrom().get();
+ assertTrue(subqueryTableSegment.getAliasSegment().isPresent());
+
assertThat(subqueryTableSegment.getAliasSegment().get().getIdentifier().getValue(),
is("t"));
+ Collection<String> actualColumnAliases =
subqueryTableSegment.getAliasSegment().get().getColumnAliases().stream().map(IdentifierValue::getValue).collect(Collectors.toList());
+ assertThat(actualColumnAliases, contains("pk", "col_a", "col_a_type"));
+ Collection<ProjectionSegment> actualProjections =
subqueryTableSegment.getSubquery().getSelect().getProjections().getProjections();
+ assertThat(actualProjections.size(), is(3));
+ actualProjections.forEach(each -> assertThat(each,
isA(ExpressionProjectionSegment.class)));
+ }
+
+ @Test
+ void assertVisitUpdateWithValuesDerivedTableColumnAliases() {
+ UpdateStatement statement = (UpdateStatement) new
SQLStatementVisitorEngine("PostgreSQL").visit(new SQLParserEngine("PostgreSQL",
new CacheOption(128, 1024L))
+ .parse("UPDATE t_order SET status = t.status FROM (VALUES (1,
'PAID')) AS t(order_id, status) WHERE t_order.order_id = t.order_id", false));
+ assertTrue(statement.getFrom().isPresent());
+ assertThat(statement.getFrom().get(), isA(SubqueryTableSegment.class));
+ SubqueryTableSegment subqueryTableSegment = (SubqueryTableSegment)
statement.getFrom().get();
+ assertTrue(subqueryTableSegment.getAliasSegment().isPresent());
+
assertThat(subqueryTableSegment.getAliasSegment().get().getIdentifier().getValue(),
is("t"));
+ Collection<String> actualColumnAliases =
subqueryTableSegment.getAliasSegment().get().getColumnAliases().stream().map(IdentifierValue::getValue).collect(Collectors.toList());
+ assertThat(actualColumnAliases, contains("order_id", "status"));
+
assertThat(subqueryTableSegment.getSubquery().getSelect().getProjections().getProjections().size(),
is(2));
+ }
+
@Test
void assertVisitWindowAggregationProjection() {
String sql = "select pg_catalog.max(ref_0.c36) over (partition by
ref_0.c39 order by ref_0.vkey desc) as c_5 from t24 as ref_0";
diff --git
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/generic/AliasSegment.java
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/generic/AliasSegment.java
index ed6db791145..7605fca53da 100644
---
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/generic/AliasSegment.java
+++
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/generic/AliasSegment.java
@@ -22,6 +22,9 @@ import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.sql.parser.statement.core.segment.SQLSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
+import java.util.Collection;
+import java.util.LinkedList;
+
/**
* Alias segment.
*/
@@ -34,4 +37,6 @@ public final class AliasSegment implements SQLSegment {
private final int stopIndex;
private final IdentifierValue identifier;
+
+ private final Collection<IdentifierValue> columnAliases = new
LinkedList<>();
}
diff --git a/test/it/parser/src/main/resources/case/ddl/create-view.xml
b/test/it/parser/src/main/resources/case/ddl/create-view.xml
index ab2cb958bd3..9a9409d1492 100644
--- a/test/it/parser/src/main/resources/case/ddl/create-view.xml
+++ b/test/it/parser/src/main/resources/case/ddl/create-view.xml
@@ -156,7 +156,45 @@
<owner name="public" start-index="22" stop-index="27" />
</view>
<select>
- <!-- FIXME support VALUES (1) projection parse -->
+ <projections start-index="47" stop-index="56">
+ <expression-projection text="1" start-index="55"
stop-index="55" />
+ </projections>
+ <combine combine-type="UNION_ALL" start-index="47"
stop-index="107">
+ <left>
+ <projections start-index="47" stop-index="56">
+ <expression-projection text="1" start-index="55"
stop-index="55" />
+ </projections>
+ </left>
+ <right>
+ <projections start-index="75" stop-index="77">
+ <expression-projection text="n+1" start-index="75"
stop-index="77" />
+ </projections>
+ <from>
+ <simple-table name="nums_1_100" start-index="84"
stop-index="93" />
+ </from>
+ <where start-index="95" stop-index="107">
+ <expr>
+ <binary-operation-expression start-index="101"
stop-index="107">
+ <left>
+ <column name="n" start-index="101"
stop-index="101" />
+ </left>
+ <right>
+ <literal-expression value="100"
start-index="105" stop-index="107" />
+ </right>
+ <operator>=</operator>
+ </binary-operation-expression>
+ </expr>
+ </where>
+ </right>
+ </combine>
+ </select>
+ </create-view>
+
+ <create-view sql-case-id="create_view_with_recursive_opengauss"
view-definition="VALUES (1) UNION ALL SELECT n+1 FROM nums_1_100 WHERE n = 100">
+ <view name="nums_1_100" start-index="22" stop-index="38">
+ <owner name="public" start-index="22" stop-index="27" />
+ </view>
+ <select>
<projections start-index="-1" stop-index="-1" />
<combine combine-type="UNION_ALL" start-index="47"
stop-index="107">
<left>
diff --git
a/test/it/parser/src/main/resources/sql/supported/ddl/create-view.xml
b/test/it/parser/src/main/resources/sql/supported/ddl/create-view.xml
index bd54900366e..5d741687521 100644
--- a/test/it/parser/src/main/resources/sql/supported/ddl/create-view.xml
+++ b/test/it/parser/src/main/resources/sql/supported/ddl/create-view.xml
@@ -24,7 +24,8 @@
<sql-case id="create_view_with_owner_doris" value="CREATE VIEW
report.v_sales AS SELECT order_id, user_id FROM t_order" db-types="Doris" />
<sql-case id="create_view_with_columns_doris" value="CREATE VIEW
example_view (c1, c2) AS SELECT k1, k2 FROM example_table" db-types="Doris" />
<sql-case id="create_view_with_check_option" value="CREATE VIEW
universal_comedies AS SELECT * FROM comedies WHERE classification = 'U' WITH
LOCAL CHECK OPTION" db-types="PostgreSQL,openGauss" />
- <sql-case id="create_view_with_recursive" value="CREATE RECURSIVE VIEW
public.nums_1_100 (n) AS VALUES (1) UNION ALL SELECT n+1 FROM nums_1_100 WHERE
n = 100" db-types="PostgreSQL,openGauss" />
+ <sql-case id="create_view_with_recursive" value="CREATE RECURSIVE VIEW
public.nums_1_100 (n) AS VALUES (1) UNION ALL SELECT n+1 FROM nums_1_100 WHERE
n = 100" db-types="PostgreSQL" />
+ <sql-case id="create_view_with_recursive_opengauss" value="CREATE
RECURSIVE VIEW public.nums_1_100 (n) AS VALUES (1) UNION ALL SELECT n+1 FROM
nums_1_100 WHERE n = 100" db-types="openGauss" />
<sql-case id="create_view_with_option" value="CREATE OR REPLACE TEMP view
order_view (order_id,user_id) WITH (security_barrier=TRUE) AS SELECT * FROM
t_order" db-types="PostgreSQL,openGauss" />
<sql-case id="create_or_replace_view_with_select" value="create or replace
view named_moons as select p.name planet, p.class, m.name moon, m.radius from
planets p, moons m where p.name = m.planet_name(+) and m.name(+) not like
'S/%'" db-types="Oracle" />
<sql-case id="create_view_as_simple_select1" value="CREATE VIEW
laurel.employee AS SELECT * FROM laurel.emp" db-types="Oracle" />