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 f91d64e7ea5 support json function call (#28319)
f91d64e7ea5 is described below
commit f91d64e7ea5a0fb70410326dcc7fae020988fc2f
Author: Yunbo Ni <[email protected]>
AuthorDate: Mon Sep 4 15:18:20 2023 +0800
support json function call (#28319)
* fix: function call recognize order in g4
* feat: json function call
* fix: spotless
* fix: add json function params in case
* fix: add json function params in case
* fix: spotless and check style
* fix: checkstyle
---
.../segment/expression/impl/FunctionConverter.java | 11 +++++++++-
.../segment/projection/impl/DataTypeConverter.java | 7 ++++--
.../src/main/antlr4/imports/mysql/BaseRule.g4 | 2 +-
.../visitor/statement/MySQLStatementVisitor.java | 17 +++++++++++++--
.../src/test/resources/converter/select.xml | 1 +
.../main/resources/case/dml/select-expression.xml | 25 ++++++++++++++++++++--
.../parser/src/main/resources/case/dml/select.xml | 12 ++++++++++-
7 files changed, 66 insertions(+), 9 deletions(-)
diff --git
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/expression/impl/FunctionConverter.java
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/expression/impl/FunctionConverter.java
index e687f92b011..0c509775852 100644
---
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/expression/impl/FunctionConverter.java
+++
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/expression/impl/FunctionConverter.java
@@ -21,6 +21,7 @@ import org.apache.calcite.sql.SqlBasicCall;
import org.apache.calcite.sql.SqlFunctionCategory;
import org.apache.calcite.sql.SqlIdentifier;
import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlSyntax;
import org.apache.calcite.sql.SqlUnresolvedFunction;
@@ -65,8 +66,16 @@ public class FunctionConverter implements
SQLSegmentConverter<FunctionSegment, S
private List<SqlNode> getFunctionParameters(final
Collection<ExpressionSegment> sqlSegments) {
List<SqlNode> result = new LinkedList<>();
+ ExpressionConverter expressionConverter = new ExpressionConverter();
for (ExpressionSegment each : sqlSegments) {
- new ExpressionConverter().convert(each).ifPresent(result::add);
+ if (expressionConverter.convert(each).isPresent()) {
+ SqlNode sqlNode = expressionConverter.convert(each).get();
+ if (sqlNode instanceof SqlNodeList) {
+ result.addAll(((SqlNodeList) sqlNode).getList());
+ } else {
+ result.add(expressionConverter.convert(each).get());
+ }
+ }
}
return result;
}
diff --git
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/projection/impl/DataTypeConverter.java
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/projection/impl/DataTypeConverter.java
index f2b84bd5d67..1e94cb16ebf 100644
---
a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/projection/impl/DataTypeConverter.java
+++
b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/converter/segment/projection/impl/DataTypeConverter.java
@@ -19,11 +19,13 @@ package
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.proje
import org.apache.calcite.sql.SqlDataTypeSpec;
import org.apache.calcite.sql.SqlNode;
-import org.apache.calcite.sql.SqlUserDefinedTypeNameSpec;
+import org.apache.calcite.sql.SqlBasicTypeNameSpec;
import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.type.SqlTypeName;
import
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.DataTypeSegment;
import
org.apache.shardingsphere.sqlfederation.compiler.converter.segment.SQLSegmentConverter;
+import java.util.Objects;
import java.util.Optional;
/**
@@ -36,6 +38,7 @@ public final class DataTypeConverter implements
SQLSegmentConverter<DataTypeSegm
if (null == segment) {
return Optional.empty();
}
- return Optional.of(new SqlDataTypeSpec(new
SqlUserDefinedTypeNameSpec(segment.getDataTypeName(), SqlParserPos.ZERO),
SqlParserPos.ZERO));
+ return Optional.of(new SqlDataTypeSpec(new
SqlBasicTypeNameSpec(Objects.requireNonNull(SqlTypeName.get(segment.getDataTypeName())),
segment.getDataLength().getPrecision(), SqlParserPos.ZERO),
+ SqlParserPos.ZERO));
}
}
diff --git a/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/BaseRule.g4
b/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/BaseRule.g4
index a75bac4296f..113ca78dc60 100644
--- a/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/BaseRule.g4
+++ b/parser/sql/dialect/mysql/src/main/antlr4/imports/mysql/BaseRule.g4
@@ -947,7 +947,7 @@ columnRefList
;
functionCall
- : aggregationFunction | specialFunction | regularFunction | jsonFunction |
udfFunction
+ : aggregationFunction | specialFunction | jsonFunction | regularFunction |
udfFunction
;
udfFunction
diff --git
a/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
b/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
index 7673d381e0c..9402d1e9020 100644
---
a/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
+++
b/parser/sql/dialect/mysql/src/main/java/org/apache/shardingsphere/sql/parser/mysql/visitor/statement/MySQLStatementVisitor.java
@@ -238,6 +238,7 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
+import java.util.Arrays;
/**
* Statement visitor for MySQL.
@@ -896,17 +897,21 @@ public abstract class MySQLStatementVisitor extends
MySQLStatementBaseVisitor<AS
public final ASTNode visitJsonFunction(final JsonFunctionContext ctx) {
JsonFunctionNameContext functionNameContext = ctx.jsonFunctionName();
String functionName;
+ FunctionSegment result;
if (null != functionNameContext) {
functionName = functionNameContext.getText();
+ result = new FunctionSegment(ctx.getStart().getStartIndex(),
ctx.getStop().getStopIndex(), functionName, getOriginalText(ctx));
for (ExprContext each : ctx.expr()) {
- visit(each);
+ result.getParameters().add((ExpressionSegment) visit(each));
}
} else if (null != ctx.JSON_SEPARATOR()) {
functionName = ctx.JSON_SEPARATOR().getText();
+ result = new FunctionSegment(ctx.getStart().getStartIndex(),
ctx.getStop().getStopIndex(), functionName, getOriginalText(ctx));
} else {
functionName = ctx.JSON_UNQUOTED_SEPARATOR().getText();
+ result = new FunctionSegment(ctx.getStart().getStartIndex(),
ctx.getStop().getStopIndex(), functionName, getOriginalText(ctx));
}
- return new FunctionSegment(ctx.getStart().getStartIndex(),
ctx.getStop().getStopIndex(), functionName, getOriginalText(ctx));
+ return result;
}
private ASTNode createAggregationSegment(final AggregationFunctionContext
ctx, final String aggregationType) {
@@ -1178,6 +1183,14 @@ public abstract class MySQLStatementVisitor extends
MySQLStatementBaseVisitor<AS
if (null != ctx.variable()) {
return visit(ctx.variable());
}
+ if (null != ctx.RETURNING()) {
+ ListExpression list = new
ListExpression(ctx.start.getStartIndex(), ctx.stop.getStopIndex());
+ list.getItems()
+ .addAll(Arrays.asList(new
LiteralExpressionSegment(ctx.path().start.getStartIndex(),
ctx.path().stop.getStopIndex(), ctx.path().getText()),
+ new
LiteralExpressionSegment(ctx.RETURNING().getSymbol().getStartIndex(),
ctx.RETURNING().getSymbol().getStopIndex(),
ctx.RETURNING().getSymbol().getText()),
+ (ExpressionSegment) visit(ctx.dataType())));
+ return list;
+ }
if (null != ctx.LBE_()) {
return visit(ctx.expr(0));
}
diff --git a/test/it/optimizer/src/test/resources/converter/select.xml
b/test/it/optimizer/src/test/resources/converter/select.xml
index 8bcd8cc3c15..50f904e895e 100644
--- a/test/it/optimizer/src/test/resources/converter/select.xml
+++ b/test/it/optimizer/src/test/resources/converter/select.xml
@@ -19,4 +19,5 @@
<sql-node-converter-test-cases>
<test-cases
sql-case-id="select_with_database_name_and_schema_name_in_table"
expected-sql="SELECT "order_id" FROM
"sharding_db"."public"."t_order" WHERE
"user_id" = ? AND "order_id" = ?"
db-types="PostgreSQL,openGauss" sql-case-types="PLACEHOLDER" />
<test-cases
sql-case-id="select_with_database_name_and_schema_name_in_table"
expected-sql="SELECT "order_id" FROM
"sharding_db"."public"."t_order" WHERE
"user_id" = 1 AND "order_id" = 1"
db-types="PostgreSQL,openGauss" sql-case-types="LITERAL" />
+ <test-cases sql-case-id="select_with_json_value_return_type"
expected-sql="SELECT * FROM `t_order` WHERE JSON_VALUE(`items`, '''$.name'''
'RETURNING' VARCHAR(100)) = 'jack'" db-types="MySQL" />
</sql-node-converter-test-cases>
diff --git a/test/it/parser/src/main/resources/case/dml/select-expression.xml
b/test/it/parser/src/main/resources/case/dml/select-expression.xml
index b1d9e8c7c27..2becc5b332b 100644
--- a/test/it/parser/src/main/resources/case/dml/select-expression.xml
+++ b/test/it/parser/src/main/resources/case/dml/select-expression.xml
@@ -2055,7 +2055,17 @@
</projections>
<where start-index="22" stop-index="76">
<expr>
- <function function-name="JSON_CONTAINS"
text="JSON_CONTAINS(order_msg -> '$[*].code', 'x', '$')" start-index="28"
stop-index="76" />
+ <function function-name="JSON_CONTAINS"
text="JSON_CONTAINS(order_msg -> '$[*].code', 'x', '$')" start-index="28"
stop-index="76" >
+ <parameter>
+ <function start-index="42" stop-index="65"
function-name="->" text="order_msg -> '$[*].code'" />
+ </parameter>
+ <parameter>
+ <literal-expression start-index="68" stop-index="70"
value="x" />
+ </parameter>
+ <parameter>
+ <literal-expression start-index="73" stop-index="75"
value="$" />
+ </parameter>
+ </function>
</expr>
</where>
</select>
@@ -2070,7 +2080,18 @@
</from>
<where start-index="43" stop-index="84">
<expr>
- <function function-name="json_contains"
text="json_contains(order_info, ?, '$.id')"
literal-text="json_contains(order_info, 1, '$.id')" start-index="49"
stop-index="84" />
+ <function function-name="json_contains"
text="json_contains(order_info, ?, '$.id')"
literal-text="json_contains(order_info, 1, '$.id')" start-index="49"
stop-index="84" >
+ <parameter>
+ <column start-index="63" stop-index="72"
name="order_info" />
+ </parameter>
+ <parameter>
+ <parameter-marker-expression start-index="75"
stop-index="75" parameter-index="0" />
+ <literal-expression start-index="75" stop-index="75"
value="1" />
+ </parameter>
+ <parameter>
+ <literal-expression start-index="78" stop-index="83"
value="$.id" />
+ </parameter>
+ </function>
</expr>
</where>
<limit start-index="86" stop-index="95">
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 229ed1d6134..8009fe15404 100644
--- a/test/it/parser/src/main/resources/case/dml/select.xml
+++ b/test/it/parser/src/main/resources/case/dml/select.xml
@@ -3748,7 +3748,17 @@
<column name="items" start-index="39"
stop-index="43" />
</parameter>
<parameter>
- <common-expression text="'$.name' RETURNING
VARCHAR(100)" start-index="46" stop-index="76" />
+ <list-expression start-index="46"
stop-index="76" >
+ <items>
+ <literal-expression start-index="46"
stop-index="53" value="'$.name'" />
+ </items>
+ <items>
+ <literal-expression start-index="55"
stop-index="63" value="RETURNING" />
+ </items>
+ <items>
+ <data-type value="VARCHAR"
start-index="65" stop-index="76" />
+ </items>
+ </list-expression>
</parameter>
</function>
</left>