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

jianglongtao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 043bd299fc0 [Oracle SQL] Support OE-5-214 for Oracle SQL (#27899)
043bd299fc0 is described below

commit 043bd299fc0c919550322529b44f36399a76afaa
Author: Liao Lanyu <[email protected]>
AuthorDate: Fri Aug 4 11:23:05 2023 +0800

    [Oracle SQL] Support OE-5-214 for Oracle SQL (#27899)
    
    * support select from collection table
    
    * test
---
 .../statement/type/OracleDMLStatementVisitor.java  | 25 ++++++--
 .../generic/table/CollectionTableSegment.java      | 66 ++++++++++++++++++++++
 .../asserts/segment/table/TableAssert.java         | 17 ++++++
 ...ctedTable.java => ExpectedCollectionTable.java} | 21 +++----
 .../jaxb/segment/impl/table/ExpectedTable.java     |  3 +
 .../parser/src/main/resources/case/dml/select.xml  | 19 +++++++
 .../main/resources/sql/supported/dml/select.xml    |  1 +
 7 files changed, 134 insertions(+), 18 deletions(-)

diff --git 
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
 
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
index 2f1feee1763..b052a7706d6 100644
--- 
a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
+++ 
b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/type/OracleDMLStatementVisitor.java
@@ -150,6 +150,7 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.InsertMul
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.ModelSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.WithSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.CollectionTableSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
@@ -413,8 +414,20 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
     
     @Override
     public ASTNode visitTableCollectionExpr(final TableCollectionExprContext 
ctx) {
-        OracleSelectStatement subquery = (OracleSelectStatement) 
visit(ctx.collectionExpr().selectSubquery());
-        return new 
SubquerySegment(ctx.collectionExpr().selectSubquery().start.getStartIndex(), 
ctx.collectionExpr().selectSubquery().stop.getStopIndex(), subquery);
+        if (null != ctx.collectionExpr().selectSubquery()) {
+            OracleSelectStatement subquery = (OracleSelectStatement) 
visit(ctx.collectionExpr().selectSubquery());
+            return new 
SubquerySegment(ctx.collectionExpr().selectSubquery().start.getStartIndex(), 
ctx.collectionExpr().selectSubquery().stop.getStopIndex(), subquery);
+        }
+        if (null != ctx.collectionExpr().functionCall()) {
+            return visit(ctx.collectionExpr().functionCall());
+        }
+        if (null != ctx.collectionExpr().columnName()) {
+            return visit(ctx.collectionExpr().columnName());
+        }
+        if (null != ctx.collectionExpr().expr()) {
+            return visit(ctx.collectionExpr().expr());
+        }
+        throw new UnsupportedOperationException("Unhandled table collection 
expr");
     }
     
     @Override
@@ -986,8 +999,12 @@ public final class OracleDMLStatementVisitor extends 
OracleStatementVisitor impl
             SubquerySegment subquerySegment = new 
SubquerySegment(ctx.lateralClause().selectSubquery().start.getStartIndex(), 
ctx.lateralClause().selectSubquery().stop.getStopIndex(), subquery);
             result = new SubqueryTableSegment(subquerySegment);
         } else {
-            SubquerySegment subquerySegment = (SubquerySegment) 
visit(ctx.tableCollectionExpr());
-            result = new SubqueryTableSegment(subquerySegment);
+            if (null != 
ctx.tableCollectionExpr().collectionExpr().selectSubquery()) {
+                SubquerySegment subquerySegment = (SubquerySegment) 
visit(ctx.tableCollectionExpr());
+                result = new SubqueryTableSegment(subquerySegment);
+            } else {
+                result = new CollectionTableSegment((ExpressionSegment) 
visit(ctx.tableCollectionExpr()));
+            }
         }
         return result;
     }
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/CollectionTableSegment.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/CollectionTableSegment.java
new file mode 100644
index 00000000000..88da1cfbc84
--- /dev/null
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/generic/table/CollectionTableSegment.java
@@ -0,0 +1,66 @@
+/*
+ * 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.sql.parser.sql.common.segment.generic.table;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
+
+import java.util.Optional;
+
+@RequiredArgsConstructor
+@Getter
+public final class CollectionTableSegment implements TableSegment {
+    
+    private final ExpressionSegment expressionSegment;
+    
+    @Setter
+    private AliasSegment alias;
+    
+    @Override
+    public Optional<String> getAliasName() {
+        return null == alias ? Optional.empty() : 
Optional.ofNullable(alias.getIdentifier().getValue());
+    }
+    
+    @Override
+    public Optional<IdentifierValue> getAlias() {
+        return Optional.ofNullable(alias).map(AliasSegment::getIdentifier);
+    }
+    
+    /**
+     * Get alias segment.
+     *
+     * @return alias segment
+     */
+    public Optional<AliasSegment> getAliasSegment() {
+        return Optional.ofNullable(alias);
+    }
+    
+    @Override
+    public int getStartIndex() {
+        return expressionSegment.getStartIndex();
+    }
+    
+    @Override
+    public int getStopIndex() {
+        return expressionSegment.getStopIndex();
+    }
+}
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/table/TableAssert.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/table/TableAssert.java
index 3229a525d5d..ca21f9b371c 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/table/TableAssert.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/table/TableAssert.java
@@ -21,6 +21,7 @@ import com.google.common.base.Strings;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlTableFunctionSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.CollectionTableSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
@@ -35,6 +36,7 @@ import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.own
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dml.impl.SelectStatementAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.column.ExpectedColumn;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedXmlTableFunction;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.table.ExpectedCollectionTable;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.table.ExpectedJoinTable;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.table.ExpectedSimpleTable;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.table.ExpectedSubqueryTable;
@@ -72,11 +74,26 @@ public final class TableAssert {
             assertIs(assertContext, (SubqueryTableSegment) actual, 
expected.getSubqueryTable());
         } else if (actual instanceof XmlTableSegment) {
             assertIs(assertContext, (XmlTableSegment) actual, 
expected.getXmlTable());
+        } else if (actual instanceof CollectionTableSegment) {
+            assertIs(assertContext, (CollectionTableSegment) actual, 
expected.getCollectionTable());
         } else {
             throw new UnsupportedOperationException(String.format("Unsupported 
table segment type `%s`.", actual.getClass()));
         }
     }
     
+    /**
+     * Assert actual collection table segment is correct with expected 
collection table.
+     *
+     * @param assertContext assert context
+     * @param actual actual collection table
+     * @param expected expected collection table
+     */
+    private static void assertIs(final SQLCaseAssertContext assertContext, 
final CollectionTableSegment actual, final ExpectedCollectionTable expected) {
+        if (null != expected.getExpectedExpression()) {
+            ExpressionAssert.assertExpression(assertContext, 
actual.getExpressionSegment(), expected.getExpectedExpression());
+        }
+    }
+    
     /**
      * Assert actual xml table segment is correct with expected xml table.
      *
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/table/ExpectedTable.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/table/ExpectedCollectionTable.java
similarity index 72%
copy from 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/table/ExpectedTable.java
copy to 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/table/ExpectedCollectionTable.java
index c34ef4fc687..2031eb45704 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/table/ExpectedTable.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/table/ExpectedCollectionTable.java
@@ -20,25 +20,18 @@ package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.
 import lombok.Getter;
 import lombok.Setter;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedDelimiterSQLSegment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedExpression;
 
+import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
 
-/**
- * Expected tables.
- */
 @Getter
 @Setter
-public final class ExpectedTable extends AbstractExpectedDelimiterSQLSegment {
-    
-    @XmlElement(name = "simple-table")
-    private ExpectedSimpleTable simpleTable;
-    
-    @XmlElement(name = "subquery-table")
-    private ExpectedSubqueryTable subqueryTable;
+public final class ExpectedCollectionTable extends 
AbstractExpectedDelimiterSQLSegment {
     
-    @XmlElement(name = "join-table")
-    private ExpectedJoinTable joinTable;
+    @XmlAttribute
+    private String alias;
     
-    @XmlElement(name = "xml-table")
-    private ExpectedXmlTable xmlTable;
+    @XmlElement
+    private ExpectedExpression expectedExpression;
 }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/table/ExpectedTable.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/table/ExpectedTable.java
index c34ef4fc687..e102dd9bdae 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/table/ExpectedTable.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/table/ExpectedTable.java
@@ -41,4 +41,7 @@ public final class ExpectedTable extends 
AbstractExpectedDelimiterSQLSegment {
     
     @XmlElement(name = "xml-table")
     private ExpectedXmlTable xmlTable;
+    
+    @XmlElement(name = "collection-table")
+    private ExpectedCollectionTable collectionTable;
 }
diff --git a/test/it/parser/src/main/resources/case/dml/select.xml 
b/test/it/parser/src/main/resources/case/dml/select.xml
index b60855fae9f..0d5ea310bb3 100644
--- a/test/it/parser/src/main/resources/case/dml/select.xml
+++ b/test/it/parser/src/main/resources/case/dml/select.xml
@@ -6490,4 +6490,23 @@
             <simple-table name="short_orders" alias="o" start-index="49" 
stop-index="62" literal-start-index="49" literal-stop-index="62" />
         </from>
     </select>
+
+    <select sql-case-id="select_with_collection_table">
+        <projections start-index="7" stop-index="14" literal-start-index="7" 
literal-stop-index="14">
+            <expression-projection text="VALUE(p)" start-index="7" 
stop-index="14">
+                <function function-name="value" start-index="7" 
stop-index="14" />
+            </expression-projection>
+        </projections>
+        <from>
+            <join-table join-type="COMMA">
+                <left>
+                    <simple-table name="warehouses" alias="w" start-index="21" 
stop-index="32" />
+                </left>
+                <right>
+                    <collection-table alias="p" start-index="37" 
stop-index="50">
+                    </collection-table>>
+                </right>
+            </join-table>
+        </from>
+    </select>
 </sql-parser-test-cases>
diff --git a/test/it/parser/src/main/resources/sql/supported/dml/select.xml 
b/test/it/parser/src/main/resources/sql/supported/dml/select.xml
index 27e0dfc222d..512d6e7e07d 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/select.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/select.xml
@@ -205,4 +205,5 @@
     <sql-case id="select_with_xml_functions" value="SELECT 
INSERTCHILDXML(warehouse_spec, '/Warehouse/Building', 'Owner', 
XMLType('&lt;Owner>LesserCo&lt;/Owner>')), SYS_DBURIGEN(employee_id, email), 
INSERTCHILDXMLAFTER(warehouse_spec, '/Warehouse/Building','Owner[2]', 
XMLType('&lt;Owner>ThirdOwner&lt;/Owner>')), 
INSERTCHILDXMLBEFORE(warehouse_spec, '/Warehouse/Building','Owner[2]', 
XMLType('&lt;Owner>ThirdOwner&lt;/Owner>')), 
INSERTXMLAFTER(warehouse_spec,'/Warehouse/Building/Owner[1]',  [...]
     <sql-case id="select_with_more_xml_functions" value="SELECT 
XMLCOMMENT('OrderAnalysisComp imported, reconfigured, disassembled'), 
XMLCONCAT(XMLELEMENT('First', e.first_name), XMLELEMENT('Last', e.last_name)) 
AS 'Result', XMLPATCH(XMLTYPE('xml')), XMLDIFF(XMLTYPE('xml'),XMLTYPE('xml2')), 
XMLELEMENT('Emp', XMLATTRIBUTES(e.employee_id, e.last_name)), 
XMLSEQUENCE(EXTRACT(warehouse_spec, '/Warehouse/*')) FROM DUAL" 
db-types="Oracle" />
     <sql-case id="select_with_nested_object" value="SELECT 
o.item.line_item_id, o.item.quantity FROM short_orders o;" db-types="Oracle" />
+    <sql-case id="select_with_collection_table" value="SELECT VALUE(p) FROM 
warehouses w, TABLE(XMLSEQUENCE(EXTRACT(warehouse_spec, '/Warehouse/*'))) p;" 
db-types="Oracle" />
 </sql-cases>

Reply via email to