You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by ji...@apache.org on 2022/11/21 14:03:23 UTC

[shardingsphere] branch master updated: Update Oracle SQL XMLQUERY function parse (#22319)

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 947c8c484b6 Update Oracle SQL XMLQUERY function parse (#22319)
947c8c484b6 is described below

commit 947c8c484b6eb6227891bc0500a52ce39f211584
Author: Zichao <57...@users.noreply.github.com>
AuthorDate: Tue Nov 22 03:03:06 2022 +1300

    Update Oracle SQL XMLQUERY function parse (#22319)
---
 .../src/main/antlr4/imports/oracle/BaseRule.g4     | 11 ++++++++++-
 .../src/main/antlr4/imports/oracle/Keyword.g4      |  4 ++++
 .../impl/OracleDMLStatementSQLVisitor.java         |  8 ++++----
 .../statement/impl/OracleStatementSQLVisitor.java  | 23 +++++++++++++++++-----
 ....java => XmlQueryAndExistsFunctionSegment.java} |  4 ++--
 test/parser/src/main/resources/case/dml/select.xml |  9 +++++++++
 .../main/resources/sql/supported/dml/select.xml    |  1 +
 7 files changed, 48 insertions(+), 12 deletions(-)

diff --git a/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4 b/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4
index 56ec843dcc8..8231e3bfcae 100644
--- a/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4
+++ b/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4
@@ -1621,6 +1621,7 @@ xmlFunction
     | xmlForestFunction
     | xmlParseFunction
     | xmlPiFunction
+    | xmlQueryFunction
     ;
 
 xmlAggFunction
@@ -1632,7 +1633,7 @@ xmlColattvalFunction
     ;
 
 xmlExistsFunction
-    : XMLEXISTS LP_ STRING_ (PASSING (BY VALUE)? expr (AS alias)? (COMMA_ expr (AS alias)?)*)? RP_
+    : XMLEXISTS LP_ STRING_ xmlPassingClause? RP_
     ;
 
 xmlForestFunction
@@ -1646,3 +1647,11 @@ xmlParseFunction
 xmlPiFunction
     : XMLPI LP_ (EVALNAME expr | (NAME)? identifier) (COMMA_ expr)? RP_
     ;
+
+xmlQueryFunction
+    : XMLQUERY LP_ STRING_ xmlPassingClause? RETURNING CONTENT (NULL ON EMPTY)? RP_
+    ;
+
+xmlPassingClause
+    : PASSING (BY VALUE)? expr (AS alias)? (COMMA_ expr (AS alias)?)*
+    ;
diff --git a/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4 b/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
index 4d7bec212f0..67e019be8a9 100644
--- a/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
+++ b/sql-parser/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
@@ -719,3 +719,7 @@ WELLFORMED
 XMLPI
     : X M L P I
     ;
+
+XMLQUERY
+    : X M L Q U E R Y
+    ;
diff --git a/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleDMLStatementSQLVisitor.java b/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleDMLStatementSQLVisitor.java
index 980f6c8f943..2932d3df5c9 100644
--- a/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleDMLStatementSQLVisitor.java
+++ b/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleDMLStatementSQLVisitor.java
@@ -116,7 +116,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOp
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.DatetimeExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlExistsFunctionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlQueryAndExistsFunctionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlPiFunctionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonTableExpressionSegment;
@@ -743,9 +743,9 @@ public final class OracleDMLStatementSQLVisitor extends OracleStatementSQLVisito
             }
             return new DatetimeProjectionSegment(datetimeExpression.getStartIndex(), datetimeExpression.getStopIndex(), datetimeExpression.getLeft(), datetimeExpression.getText());
         }
-        if (projection instanceof XmlExistsFunctionSegment) {
-            XmlExistsFunctionSegment xmlExistsFunctionSegment = (XmlExistsFunctionSegment) projection;
-            return new XmlExistsFunctionSegment(xmlExistsFunctionSegment.getStartIndex(), xmlExistsFunctionSegment.getStopIndex(),
+        if (projection instanceof XmlQueryAndExistsFunctionSegment) {
+            XmlQueryAndExistsFunctionSegment xmlExistsFunctionSegment = (XmlQueryAndExistsFunctionSegment) projection;
+            return new XmlQueryAndExistsFunctionSegment(xmlExistsFunctionSegment.getStartIndex(), xmlExistsFunctionSegment.getStopIndex(),
                     xmlExistsFunctionSegment.getFunctionName(), xmlExistsFunctionSegment.getXQueryString(), xmlExistsFunctionSegment.getText());
         }
         if (projection instanceof XmlPiFunctionSegment) {
diff --git a/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleStatementSQLVisitor.java b/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleStatementSQLVisitor.java
index 735467f7d88..f19b4b76839 100644
--- a/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleStatementSQLVisitor.java
+++ b/sql-parser/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/impl/OracleStatementSQLVisitor.java
@@ -75,6 +75,7 @@ import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlExi
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlForestFunctionContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlParseFunctionContext;
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlPiFunctionContext;
+import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlQueryFunctionContext;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.AggregationType;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.NullsOrderType;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.OrderDirection;
@@ -94,7 +95,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.Function
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.NotExpression;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlExistsFunctionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlQueryAndExistsFunctionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.XmlPiFunctionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
@@ -567,7 +568,10 @@ public abstract class OracleStatementSQLVisitor extends OracleStatementBaseVisit
         if (null != ctx.xmlParseFunction()) {
             return visit(ctx.xmlParseFunction());
         }
-        return visit(ctx.xmlPiFunction());
+        if (null != ctx.xmlPiFunction()) {
+            return visit(ctx.xmlPiFunction());
+        }
+        return visit(ctx.xmlQueryFunction());
     }
     
     @Override
@@ -585,9 +589,9 @@ public abstract class OracleStatementSQLVisitor extends OracleStatementBaseVisit
     
     @Override
     public ASTNode visitXmlExistsFunction(final XmlExistsFunctionContext ctx) {
-        XmlExistsFunctionSegment result =
-                new XmlExistsFunctionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.XMLEXISTS().getText(), ctx.STRING_().getText(), getOriginalText(ctx));
-        Collection<ExpressionSegment> expressionSegments = ctx.expr().stream().map(each -> (ExpressionSegment) visit(each)).collect(Collectors.toList());
+        XmlQueryAndExistsFunctionSegment result =
+                new XmlQueryAndExistsFunctionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.XMLEXISTS().getText(), ctx.STRING_().getText(), getOriginalText(ctx));
+        Collection<ExpressionSegment> expressionSegments = ctx.xmlPassingClause().expr().stream().map(each -> (ExpressionSegment) visit(each)).collect(Collectors.toList());
         result.getParameters().addAll(expressionSegments);
         return result;
     }
@@ -615,6 +619,15 @@ public abstract class OracleStatementSQLVisitor extends OracleStatementBaseVisit
                 (ExpressionSegment) visit(ctx.expr(0)), (ExpressionSegment) visit(ctx.expr(1)), getOriginalText(ctx));
     }
     
+    @Override
+    public ASTNode visitXmlQueryFunction(final XmlQueryFunctionContext ctx) {
+        XmlQueryAndExistsFunctionSegment result =
+                new XmlQueryAndExistsFunctionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.XMLQUERY().getText(), ctx.STRING_().getText(), getOriginalText(ctx));
+        Collection<ExpressionSegment> expressionSegments = ctx.xmlPassingClause().expr().stream().map(each -> (ExpressionSegment) visit(each)).collect(Collectors.toList());
+        result.getParameters().addAll(expressionSegments);
+        return result;
+    }
+    
     private Collection<ExpressionSegment> getExpressions(final AggregationFunctionContext ctx) {
         return null == ctx.expr() ? Collections.emptyList() : ctx.expr().stream().map(each -> (ExpressionSegment) visit(each)).collect(Collectors.toList());
     }
diff --git a/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlExistsFunctionSegment.java b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlQueryAndExistsFunctionSegment.java
similarity index 91%
rename from sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlExistsFunctionSegment.java
rename to sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlQueryAndExistsFunctionSegment.java
index db2afa4ed86..8aa168ab30b 100644
--- a/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlExistsFunctionSegment.java
+++ b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlQueryAndExistsFunctionSegment.java
@@ -27,12 +27,12 @@ import java.util.Collection;
 import java.util.LinkedList;
 
 /**
- * Xml Exists Function segment.
+ * Xml Query and Exists Function segment.
  */
 @RequiredArgsConstructor
 @Getter
 @ToString
-public final class XmlExistsFunctionSegment implements ComplexExpressionSegment, ProjectionSegment {
+public final class XmlQueryAndExistsFunctionSegment implements ComplexExpressionSegment, ProjectionSegment {
     
     private final int startIndex;
     
diff --git a/test/parser/src/main/resources/case/dml/select.xml b/test/parser/src/main/resources/case/dml/select.xml
index 55579545a4d..866b9ff3c10 100644
--- a/test/parser/src/main/resources/case/dml/select.xml
+++ b/test/parser/src/main/resources/case/dml/select.xml
@@ -4751,4 +4751,13 @@
             <simple-table name="DUAL" start-index="96" stop-index="99" />
         </from>
     </select>
+
+    <select sql-case-id="select_xmlquery_function">
+        <projections start-index="7" stop-index="95">
+            <expression-projection text="XMLQUERY('//student[@age=20]' PASSING BY VALUE xcol AS x RETURNING CONTENT NULL ON EMPTY)" start-index="7" stop-index="95" />
+        </projections>
+        <from>
+            <simple-table name="x_table" start-index="102" stop-index="108" />
+        </from>
+    </select>
 </sql-parser-test-cases>
diff --git a/test/parser/src/main/resources/sql/supported/dml/select.xml b/test/parser/src/main/resources/sql/supported/dml/select.xml
index cb616a51153..4eb82922b8f 100644
--- a/test/parser/src/main/resources/sql/supported/dml/select.xml
+++ b/test/parser/src/main/resources/sql/supported/dml/select.xml
@@ -151,4 +151,5 @@
     <sql-case id="select_xmlforest_function" value="SELECT XMLFOREST(e.employee_id AS EVALNAME 'ID', e.last_name AS name, e.salary) FROM employees e WHERE employee_id = 204;" db-types="Oracle" />
     <sql-case id="select_xmlparse_function" value="SELECT XMLPARSE(DOCUMENT 'DEPTXML' WELLFORMED) AS dept FROM DUAL;" db-types="Oracle" />
     <sql-case id="select_xmlpi_function" value="SELECT XMLPI(NAME &quot;Order analysisComp&quot;, 'imported, reconfigured, disassembled') AS 'XMLPI' FROM DUAL;" db-types="Oracle" />
+    <sql-case id="select_xmlquery_function" value="SELECT XMLQUERY('//student[@age=20]' PASSING BY VALUE xcol AS x RETURNING CONTENT NULL ON EMPTY) FROM x_table;" db-types="Oracle" />
 </sql-cases>