You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by du...@apache.org on 2025/04/24 09:11:36 UTC
(shardingsphere) branch master updated: Support Oracle json_object function parsing (#35238)
This is an automated email from the ASF dual-hosted git repository.
duanzhengqiang 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 1f25074bc30 Support Oracle json_object function parsing (#35238)
1f25074bc30 is described below
commit 1f25074bc30ee581b53e7026e2903b70317cbbd3
Author: ZhangCheng <ch...@apache.org>
AuthorDate: Thu Apr 24 17:11:29 2025 +0800
Support Oracle json_object function parsing (#35238)
* Support Oracle json_object function parsing
* Support Oracle json_object function parsing
* Support Oracle json_object function parsing
---
.../src/main/antlr4/imports/oracle/BaseRule.g4 | 22 +++++++++++++++++-
.../src/main/antlr4/imports/oracle/Keyword.g4 | 4 ++++
.../main/antlr4/imports/oracle/OracleKeyword.g4 | 4 ++++
.../visitor/statement/OracleStatementVisitor.java | 16 ++++++++++++-
.../resources/case/dml/select-special-function.xml | 26 ++++++++++++++++++++++
.../sql/supported/dml/select-special-function.xml | 1 +
6 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4 b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4
index 2c59db05818..7403ba133a1 100644
--- a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4
+++ b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/BaseRule.g4
@@ -550,7 +550,27 @@ leadLagInfo
specialFunction
: castFunction | charFunction | extractFunction | formatFunction | firstOrLastValueFunction | trimFunction | featureFunction
- | setFunction | translateFunction | cursorFunction | toDateFunction | approxRank | wmConcatFunction | predictionCostFunction
+ | setFunction | translateFunction | cursorFunction | toDateFunction | approxRank | wmConcatFunction | predictionCostFunction | jsonObjectFunction
+ ;
+
+jsonObjectFunction
+ : JSON_OBJECT LP_ jsonObjectContent RP_
+ ;
+
+jsonObjectContent
+ : jsonObjectKeyValue (COMMA_ jsonObjectKeyValue)* jsonOnNullClause? jsonReturnClause?
+ ;
+
+jsonOnNullClause
+ : (NULL | ABSENT) ON NULL
+ ;
+
+jsonReturnClause
+ : RETURNING VARCHAR2 (LP_ INTEGER_ ( BYTE | CHAR)? RP_)?
+ ;
+
+jsonObjectKeyValue
+ : (KEY? expr VALUE expr) (FORMAT JSON)?
;
predictionCostFunction
diff --git a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4 b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
index fa46ae24e9a..ec2091e6892 100644
--- a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
+++ b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/Keyword.g4
@@ -1140,6 +1140,10 @@ JSONPRINT
: J S O N P R I N T
;
+JSON_OBJECT
+ : J S O N UL_ O B J E C T
+ ;
+
LINESIZE
: L I N E S I Z E
;
diff --git a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/OracleKeyword.g4 b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/OracleKeyword.g4
index 5fd42845599..f9f3d2fad5e 100644
--- a/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/OracleKeyword.g4
+++ b/parser/sql/dialect/oracle/src/main/antlr4/imports/oracle/OracleKeyword.g4
@@ -19,6 +19,10 @@ lexer grammar OracleKeyword;
import Alphabet;
+ABSENT
+ : A B S E N T
+ ;
+
BEQUEATH
: B E Q U E A T H
;
diff --git a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
index 688b79209f8..125ce772a0c 100644
--- a/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
+++ b/parser/sql/dialect/oracle/src/main/java/org/apache/shardingsphere/sql/parser/oracle/visitor/statement/OracleStatementVisitor.java
@@ -60,6 +60,8 @@ import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.IndexT
import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.IntervalDayToSecondExpressionContext;
import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.IntervalExpressionContext;
import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.IntervalYearToMonthExpressionContext;
+import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.JsonObjectFunctionContext;
+import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.JsonObjectKeyValueContext;
import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.LiteralsContext;
import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.NullValueLiteralsContext;
import org.apache.shardingsphere.sql.parser.autogen.OracleStatementParser.NumberLiteralsContext;
@@ -1051,9 +1053,21 @@ public abstract class OracleStatementVisitor extends OracleStatementBaseVisitor<
if (null != ctx.predictionCostFunction()) {
return visit(ctx.predictionCostFunction());
}
+ if (null != ctx.jsonObjectFunction()) {
+ return visit(ctx.jsonObjectFunction());
+ }
throw new IllegalStateException(
"SpecialFunctionContext must have castFunction, charFunction, extractFunction, formatFunction, firstOrLastValueFunction, "
- + "trimFunction, toDateFunction, approxCount, predictionCostFunction or featureFunction.");
+ + "trimFunction, toDateFunction, approxCount, predictionCostFunction, jsonObjectFunction or featureFunction.");
+ }
+
+ @Override
+ public ASTNode visitJsonObjectFunction(final JsonObjectFunctionContext ctx) {
+ FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.JSON_OBJECT().getText(), getOriginalText(ctx));
+ for (JsonObjectKeyValueContext each : ctx.jsonObjectContent().jsonObjectKeyValue()) {
+ result.getParameters().addAll(getExpressions(each.expr()));
+ }
+ return result;
}
@Override
diff --git a/test/it/parser/src/main/resources/case/dml/select-special-function.xml b/test/it/parser/src/main/resources/case/dml/select-special-function.xml
index b22f2d84522..dfe451a1e12 100644
--- a/test/it/parser/src/main/resources/case/dml/select-special-function.xml
+++ b/test/it/parser/src/main/resources/case/dml/select-special-function.xml
@@ -5229,4 +5229,30 @@
</expression-projection>
</projections>
</select>
+
+ <select sql-case-id="select_with_json_object_function">
+ <projections start-index="7" stop-index="67">
+ <expression-projection text="JSON_OBJECT('name' VALUE 'John', 'age' VALUE 30)" alias="json_data" start-index="7" stop-index="67">
+ <expr start-index="7" stop-index="54">
+ <function function-name="JSON_OBJECT" text="JSON_OBJECT('name' VALUE 'John', 'age' VALUE 30)" start-index="7" stop-index="54">
+ <parameter start-index="19" stop-index="24">
+ <literal-expression value="name" start-index="19" stop-index="24"/>
+ </parameter>
+ <parameter start-index="32" stop-index="37">
+ <literal-expression value="John" start-index="32" stop-index="37"/>
+ </parameter>
+ <parameter start-index="40" stop-index="44">
+ <literal-expression value="age" start-index="40" stop-index="44"/>
+ </parameter>
+ <parameter start-index="52" stop-index="53">
+ <literal-expression value="30" start-index="52" stop-index="53"/>
+ </parameter>
+ </function>
+ </expr>
+ </expression-projection>
+ </projections>
+ <from start-index="74" stop-index="77">
+ <simple-table name="DUAL" start-index="74" stop-index="77"/>
+ </from>
+ </select>
</sql-parser-test-cases>
diff --git a/test/it/parser/src/main/resources/sql/supported/dml/select-special-function.xml b/test/it/parser/src/main/resources/sql/supported/dml/select-special-function.xml
index 8e0bc506dc2..786224cf5b2 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/select-special-function.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/select-special-function.xml
@@ -302,4 +302,5 @@
<sql-case id="select_percent_rank" value="SELECT PERCENT_RANK() OVER (ORDER BY salary) FROM employees;" db-types="MySQL" />
<sql-case id="select_pi" value="SELECT PI()" db-types="MySQL" />
<sql-case id="select_regexp" value="SELECT 'a' REGEXP '^[a-d]'" db-types="MySQL" />
+ <sql-case id="select_with_json_object_function" value="SELECT JSON_OBJECT('name' VALUE 'John', 'age' VALUE 30) AS json_data FROM DUAL" db-types="Oracle" />
</sql-cases>