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 08:54:24 UTC

[shardingsphere] branch master updated: Update Oracle SQL XMLPI function parse (#22312)

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 affba014549 Update Oracle SQL XMLPI function parse (#22312)
affba014549 is described below

commit affba0145490b5a08aec8968d28e025df2a6b3b7
Author: Zichao <57...@users.noreply.github.com>
AuthorDate: Mon Nov 21 21:54:17 2022 +1300

    Update Oracle SQL XMLPI function parse (#22312)
    
    * Update Oracle SQL XMLPI function parse
    
    * Update Oracle SQL XMLPI function parse
---
 .../src/main/antlr4/imports/oracle/BaseRule.g4     |  5 ++
 .../src/main/antlr4/imports/oracle/Keyword.g4      |  4 ++
 .../impl/OracleDMLStatementSQLVisitor.java         | 10 ++++
 .../statement/impl/OracleStatementSQLVisitor.java  | 17 +++++-
 .../segment/dml/expr/XmlPiFunctionSegment.java     | 66 ++++++++++++++++++++++
 test/parser/src/main/resources/case/dml/select.xml |  9 +++
 .../main/resources/sql/supported/dml/select.xml    |  1 +
 7 files changed, 111 insertions(+), 1 deletion(-)

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 c5d2c454d49..56ec843dcc8 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
@@ -1620,6 +1620,7 @@ xmlFunction
     | xmlExistsFunction
     | xmlForestFunction
     | xmlParseFunction
+    | xmlPiFunction
     ;
 
 xmlAggFunction
@@ -1641,3 +1642,7 @@ xmlForestFunction
 xmlParseFunction
     : XMLPARSE LP_ (DOCUMENT | CONTENT) expr (WELLFORMED)? RP_
     ;
+
+xmlPiFunction
+    : XMLPI LP_ (EVALNAME expr | (NAME)? identifier) (COMMA_ expr)? RP_
+    ;
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 d479a305216..4d7bec212f0 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
@@ -715,3 +715,7 @@ CONTENT
 WELLFORMED
     : W E L L F O R M E D
     ;
+
+XMLPI
+    : X M L P I
+    ;
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 048743668a9..980f6c8f943 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
@@ -117,6 +117,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.Datetime
 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.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;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
@@ -747,6 +748,15 @@ public final class OracleDMLStatementSQLVisitor extends OracleStatementSQLVisito
             return new XmlExistsFunctionSegment(xmlExistsFunctionSegment.getStartIndex(), xmlExistsFunctionSegment.getStopIndex(),
                     xmlExistsFunctionSegment.getFunctionName(), xmlExistsFunctionSegment.getXQueryString(), xmlExistsFunctionSegment.getText());
         }
+        if (projection instanceof XmlPiFunctionSegment) {
+            XmlPiFunctionSegment xmlPiFunctionSegment = (XmlPiFunctionSegment) projection;
+            if (null != xmlPiFunctionSegment.getIdentifier()) {
+                return new XmlPiFunctionSegment(xmlPiFunctionSegment.getStartIndex(), xmlPiFunctionSegment.getStopIndex(), xmlPiFunctionSegment.getFunctionName(),
+                        xmlPiFunctionSegment.getIdentifier(), xmlPiFunctionSegment.getValueExpr(), xmlPiFunctionSegment.getText());
+            }
+            return new XmlPiFunctionSegment(xmlPiFunctionSegment.getStartIndex(), xmlPiFunctionSegment.getStopIndex(), xmlPiFunctionSegment.getFunctionName(),
+                    xmlPiFunctionSegment.getEvalNameValueExpr(), xmlPiFunctionSegment.getValueExpr(), xmlPiFunctionSegment.getText());
+        }
         LiteralExpressionSegment column = (LiteralExpressionSegment) projection;
         ExpressionProjectionSegment result = null == alias ? new ExpressionProjectionSegment(column.getStartIndex(), column.getStopIndex(), String.valueOf(column.getLiterals()), column)
                 : new ExpressionProjectionSegment(column.getStartIndex(), ctx.alias().stop.getStopIndex(), String.valueOf(column.getLiterals()), column);
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 51452012592..735467f7d88 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
@@ -74,6 +74,7 @@ import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlCol
 import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.XmlExistsFunctionContext;
 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.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,6 +95,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpres
 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.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;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
@@ -562,7 +564,10 @@ public abstract class OracleStatementSQLVisitor extends OracleStatementBaseVisit
         if (null != ctx.xmlForestFunction()) {
             return visit(ctx.xmlForestFunction());
         }
-        return visit(ctx.xmlParseFunction());
+        if (null != ctx.xmlParseFunction()) {
+            return visit(ctx.xmlParseFunction());
+        }
+        return visit(ctx.xmlPiFunction());
     }
     
     @Override
@@ -600,6 +605,16 @@ public abstract class OracleStatementSQLVisitor extends OracleStatementBaseVisit
         return new ExpressionProjectionSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), getOriginalText(ctx), (ExpressionSegment) visit(ctx.expr()));
     }
     
+    @Override
+    public ASTNode visitXmlPiFunction(final XmlPiFunctionContext ctx) {
+        if (null != ctx.identifier()) {
+            return new XmlPiFunctionSegment(ctx.start.getStopIndex(), ctx.stop.getStopIndex(), ctx.XMLPI().getText(),
+                    ctx.identifier().getText(), (ExpressionSegment) visit(ctx.expr(0)), getOriginalText(ctx));
+        }
+        return new XmlPiFunctionSegment(ctx.start.getStopIndex(), ctx.stop.getStopIndex(), ctx.XMLPI().getText(),
+                (ExpressionSegment) visit(ctx.expr(0)), (ExpressionSegment) visit(ctx.expr(1)), getOriginalText(ctx));
+    }
+    
     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/XmlPiFunctionSegment.java b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlPiFunctionSegment.java
new file mode 100644
index 00000000000..226c18baec8
--- /dev/null
+++ b/sql-parser/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/XmlPiFunctionSegment.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.dml.expr;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
+
+/**
+ * Xml processing instruction Function segment.
+ */
+@Getter
+@Setter
+@ToString
+public final class XmlPiFunctionSegment implements ExpressionSegment, ProjectionSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
+    
+    private final String functionName;
+    
+    private final String identifier;
+    
+    private final ExpressionSegment evalNameValueExpr;
+    
+    private final ExpressionSegment valueExpr;
+    
+    private final String text;
+    
+    public XmlPiFunctionSegment(final int startIndex, final int stopIndex, final String functionName, final String identifier, final ExpressionSegment valueExpr, final String text) {
+        this.startIndex = startIndex;
+        this.stopIndex = stopIndex;
+        this.functionName = functionName;
+        this.evalNameValueExpr = null;
+        this.identifier = identifier;
+        this.valueExpr = valueExpr;
+        this.text = text;
+    }
+    
+    public XmlPiFunctionSegment(final int startIndex, final int stopIndex, final String functionName, final ExpressionSegment evalNameValueExpr, final ExpressionSegment valueExpr, final String text) {
+        this.startIndex = startIndex;
+        this.stopIndex = stopIndex;
+        this.functionName = functionName;
+        this.identifier = null;
+        this.evalNameValueExpr = evalNameValueExpr;
+        this.valueExpr = valueExpr;
+        this.text = text;
+    }
+}
diff --git a/test/parser/src/main/resources/case/dml/select.xml b/test/parser/src/main/resources/case/dml/select.xml
index 656b49724eb..55579545a4d 100644
--- a/test/parser/src/main/resources/case/dml/select.xml
+++ b/test/parser/src/main/resources/case/dml/select.xml
@@ -4742,4 +4742,13 @@
             <simple-table name="DUAL" start-index="60" stop-index="63" />
         </from>
     </select>
+
+    <select sql-case-id="select_xmlpi_function">
+        <projections start-index="7" stop-index="89">
+            <expression-projection text="XMLPI(NAME &quot;Order analysisComp&quot;, 'imported, reconfigured, disassembled')" alias="XMLPI" start-index="11" stop-index="78" />
+        </projections>
+        <from>
+            <simple-table name="DUAL" start-index="96" stop-index="99" />
+        </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 ef3e8388c00..cb616a51153 100644
--- a/test/parser/src/main/resources/sql/supported/dml/select.xml
+++ b/test/parser/src/main/resources/sql/supported/dml/select.xml
@@ -150,4 +150,5 @@
     <sql-case id="select_xmlexists_function" value="SELECT id, XMLEXISTS('//student[@age=20]' PASSING BY VALUE xcol AS x) FROM x_table;" db-types="Oracle" />
     <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-cases>