From 07cc083f2c26df10b5f388517b8a894a212a1465 Mon Sep 17 00:00:00 2001 From: yydeng626 Date: Fri, 19 Jan 2024 04:16:15 -0600 Subject: [PATCH] Support parsing SQL Server SELECT JSON_OBJECT('name':'value', sql #29160 (#29740) * Support parsing SQL Server SELECT JSON_OBJECT('name':'value', sql #29160 * fix jsonNullClauseExpression text value --- .../main/antlr4/imports/sqlserver/BaseRule.g4 | 22 +- .../main/antlr4/imports/sqlserver/Keyword.g4 | 56 ++--- .../statement/SQLServerStatementVisitor.java | 64 ++++++ .../segment/dml/expr/KeyValueSegment.java | 42 ++++ .../sqlserver/json/JsonNullClauseSegment.java | 36 ++++ .../segment/expression/ExpressionAssert.java | 55 ++++- .../segment/impl/expr/ExpectedExpression.java | 7 + .../impl/expr/ExpectedKeyValueSegment.java | 38 ++++ .../json/ExpectedJsonNullClauseSegment.java | 36 ++++ .../case/dml/select-special-function.xml | 202 ++++++++++++++++++ .../supported/dml/select-special-function.xml | 5 + 11 files changed, 529 insertions(+), 34 deletions(-) create mode 100644 parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/KeyValueSegment.java create mode 100644 parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/segment/sqlserver/json/JsonNullClauseSegment.java create mode 100644 test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedKeyValueSegment.java create mode 100644 test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/json/ExpectedJsonNullClauseSegment.java diff --git a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/BaseRule.g4 b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/BaseRule.g4 index b441a5224804c..d0290de3dcc9a 100644 --- a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/BaseRule.g4 +++ b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/BaseRule.g4 @@ -311,7 +311,27 @@ distinct ; specialFunction - : castFunction | charFunction | convertFunction | openJsonFunction | openRowSetFunction + : castFunction | charFunction | convertFunction | openJsonFunction | jsonFunction | openRowSetFunction + ; + +jsonFunction + : jsonObjectFunction | jsonArrayFunction + ; + +jsonObjectFunction + : JSON_OBJECT LP_ (jsonKeyValue (COMMA_ jsonKeyValue)* jsonNullClause?)? RP_ + ; + +jsonArrayFunction + : JSON_ARRAY LP_ expr (COMMA_ expr)* jsonNullClause? RP_ + ; + +jsonKeyValue + : expr COLON_ expr + ; + +jsonNullClause + : NULL ON NULL | ABSENT ON NULL ; castFunction diff --git a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/Keyword.g4 b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/Keyword.g4 index 10b9150f39559..f28dc17c8d85e 100644 --- a/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/Keyword.g4 +++ b/parser/sql/dialect/sqlserver/src/main/antlr4/imports/sqlserver/Keyword.g4 @@ -728,50 +728,54 @@ NOLOCK : N O L O C K ; -NOLOCK -: N O L O C K -; - NOWAIT -: N O W A I T -; + : N O W A I T + ; PAGLOCK -: P A G L O C K -; + : P A G L O C K + ; READCOMMITTED -: R E A D C O M M I T T E D -; + : R E A D C O M M I T T E D + ; READCOMMITTEDLOCK -: R E A D C O M M I T T E D L O C K -; + : R E A D C O M M I T T E D L O C K + ; READPAST -: R E A D P A S T -; + : R E A D P A S T + ; REPEATABLEREAD -: R E P E A T A B L E R E A D -; + : R E P E A T A B L E R E A D + ; ROWLOCK -: R O W L O C K -; + : R O W L O C K + ; TABLOCK -: T A B L O C K -; + : T A B L O C K + ; TABLOCKX -: T A B L O C K X -; + : T A B L O C K X + ; UPDLOCK -: U P D L O C K -; + : U P D L O C K + ; XLOCK -: X L O C K -; + : X L O C K + ; + +JSON_OBJECT + : J S O N UL_ O B J E C T + ; + +JSON_ARRAY + : J S O N UL_ A R R A Y + ; diff --git a/parser/sql/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/SQLServerStatementVisitor.java b/parser/sql/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/SQLServerStatementVisitor.java index e9d148371759d..e160f2896db3a 100644 --- a/parser/sql/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/SQLServerStatementVisitor.java +++ b/parser/sql/dialect/sqlserver/src/main/java/org/apache/shardingsphere/sql/parser/sqlserver/visitor/statement/SQLServerStatementVisitor.java @@ -63,6 +63,11 @@ import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.IndexNameContext; import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.InsertContext; import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.InsertDefaultValueContext; +import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.JsonArrayFunctionContext; +import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.JsonFunctionContext; +import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.JsonKeyValueContext; +import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.JsonNullClauseContext; +import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.JsonObjectFunctionContext; import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.WithTableHintContext; import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.InsertSelectClauseContext; import org.apache.shardingsphere.sql.parser.autogen.SQLServerStatementParser.InsertValuesClauseContext; @@ -138,6 +143,7 @@ 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.InExpression; +import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.KeyValueSegment; 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.complex.CommonExpressionSegment; @@ -197,6 +203,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.value.literal.impl.StringLiteralValue; import org.apache.shardingsphere.sql.parser.sql.common.value.parametermarker.ParameterMarkerValue; import org.apache.shardingsphere.sql.parser.sql.dialect.segment.sqlserver.exec.ExecSegment; +import org.apache.shardingsphere.sql.parser.sql.dialect.segment.sqlserver.json.JsonNullClauseSegment; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.ddl.SQLServerCreateTableStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.ddl.SQLServerUpdateStatisticsStatement; import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.dml.SQLServerDeleteStatement; @@ -665,9 +672,66 @@ public final ASTNode visitSpecialFunction(final SpecialFunctionContext ctx) { if (null != ctx.openRowSetFunction()) { return visit(ctx.openRowSetFunction()); } + if (null != ctx.jsonFunction()) { + return visit(ctx.jsonFunction()); + } return new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.getChild(0).getChild(0).getText(), getOriginalText(ctx)); } + @Override + public final ASTNode visitJsonFunction(final JsonFunctionContext ctx) { + if (null != ctx.jsonArrayFunction()) { + return visit(ctx.jsonArrayFunction()); + } + if (null != ctx.jsonObjectFunction()) { + return visit(ctx.jsonObjectFunction()); + } + return new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.getText(), getOriginalText(ctx)); + } + + @Override + public final ASTNode visitJsonArrayFunction(final JsonArrayFunctionContext ctx) { + FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.JSON_ARRAY().getText(), getOriginalText(ctx)); + if (null != ctx.expr()) { + for (ExprContext each : ctx.expr()) { + result.getParameters().add((ExpressionSegment) visit(each)); + } + } + if (null != ctx.jsonNullClause()) { + result.getParameters().add(new LiteralExpressionSegment(ctx.jsonNullClause().start.getStartIndex(), ctx.jsonNullClause().stop.getStopIndex(), ctx.jsonNullClause().getText())); + } + return result; + } + + @Override + public final ASTNode visitJsonObjectFunction(final JsonObjectFunctionContext ctx) { + FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.JSON_OBJECT().getText(), getOriginalText(ctx)); + if (null != ctx.jsonKeyValue()) { + for (JsonKeyValueContext each : ctx.jsonKeyValue()) { + result.getParameters().add((ExpressionSegment) visit(each)); + } + } + if (null != ctx.jsonNullClause()) { + result.getParameters().add((ExpressionSegment) visit(ctx.jsonNullClause())); + } + return result; + } + + @Override + public final ASTNode visitJsonNullClause(final JsonNullClauseContext ctx) { + return new JsonNullClauseSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), getOriginalText(ctx)); + } + + @Override + public final ASTNode visitJsonKeyValue(final JsonKeyValueContext ctx) { + KeyValueSegment result = new KeyValueSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), ctx.getText()); + if (null != ctx.expr()) { + result.setKey((ExpressionSegment) visit(ctx.expr(0))); + result.setValue((ExpressionSegment) visit(ctx.expr(1))); + } + return result; + } + @Override public final ASTNode visitCastFunction(final CastFunctionContext ctx) { calculateParameterCount(Collections.singleton(ctx.expr())); diff --git a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/KeyValueSegment.java b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/KeyValueSegment.java new file mode 100644 index 0000000000000..8e49b035f5a17 --- /dev/null +++ b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/expr/KeyValueSegment.java @@ -0,0 +1,42 @@ +/* + * 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.RequiredArgsConstructor; +import lombok.Setter; + +/** + * Key value segment. + **/ +@RequiredArgsConstructor +@Getter +public final class KeyValueSegment implements ExpressionSegment { + + private final int startIndex; + + private final int stopIndex; + + @Setter + private ExpressionSegment key; + + @Setter + private ExpressionSegment value; + + private final String text; +} diff --git a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/segment/sqlserver/json/JsonNullClauseSegment.java b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/segment/sqlserver/json/JsonNullClauseSegment.java new file mode 100644 index 0000000000000..a22304fba13d1 --- /dev/null +++ b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/dialect/segment/sqlserver/json/JsonNullClauseSegment.java @@ -0,0 +1,36 @@ +/* + * 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.dialect.segment.sqlserver.json; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment; + +/** + * Json null clause segment. + **/ +@RequiredArgsConstructor +@Getter +public final class JsonNullClauseSegment implements ExpressionSegment { + + private final int startIndex; + + private final int stopIndex; + + private final String text; +} diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java index 44873376b178b..13060c0c952be 100644 --- a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/expression/ExpressionAssert.java @@ -30,6 +30,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExtractArgExpression; import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment; import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression; +import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.KeyValueSegment; import org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.interval.IntervalDayToSecondExpression; import org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.interval.IntervalYearToMonthExpression; import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression; @@ -52,6 +53,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.IntervalExpressionProjection; import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.DataTypeSegment; import org.apache.shardingsphere.sql.parser.sql.dialect.segment.oracle.xml.XmlQueryAndExistsFunctionSegment; +import org.apache.shardingsphere.sql.parser.sql.dialect.segment.sqlserver.json.JsonNullClauseSegment; import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext; import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.SQLSegmentAssert; import org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.column.ColumnAssert; @@ -72,6 +74,7 @@ import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedIntervalDayToSecondExpression; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedIntervalExpression; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedIntervalYearToMonthExpression; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedKeyValueSegment; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedListExpression; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedMatchExpression; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.ExpectedMultisetExpression; @@ -86,6 +89,7 @@ import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.simple.ExpectedParameterMarkerExpression; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.simple.ExpectedSubquery; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.function.ExpectedFunction; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.json.ExpectedJsonNullClauseSegment; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.xmlquery.ExpectedXmlQueryAndExistsFunctionSegment; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.sql.type.SQLCaseType; @@ -100,7 +104,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; /** - * Expression assert. + * Expression assert. */ @NoArgsConstructor(access = AccessLevel.PRIVATE) public final class ExpressionAssert { @@ -217,7 +221,7 @@ public static void assertExistsSubqueryExpression(final SQLCaseAssertContext ass /** * Assert binary operation expression. - * + * * @param assertContext assert context * @param actual actual binary operation expression * @param expected expected binary operation expression @@ -238,7 +242,7 @@ public static void assertBinaryOperationExpression(final SQLCaseAssertContext as /** * Assert in operation expression. - * + * * @param assertContext assert context * @param actual actual in operation expression * @param expected expected in operation expression @@ -259,7 +263,7 @@ public static void assertInExpression(final SQLCaseAssertContext assertContext, /** * Assert not operation expression. - * + * * @param assertContext assert context * @param actual actual not operation expression * @param expected expected not operation expression @@ -277,7 +281,7 @@ public static void assertNotExpression(final SQLCaseAssertContext assertContext, /** * Assert list operation expression. - * + * * @param assertContext assert context * @param actual actual list operation expression * @param expected expected list operation expression @@ -301,7 +305,7 @@ public static void assertListExpression(final SQLCaseAssertContext assertContext /** * Assert between operation expression. - * + * * @param assertContext assert context * @param actual actual between operation expression * @param expected expected between operation expression @@ -548,7 +552,7 @@ private static void assertRowExpression(final SQLCaseAssertContext assertContext /** * Assert unary operation expression. - * + * * @param assertContext assert context * @param actual actual unary operation expression * @param expected expected unary operation expression @@ -584,6 +588,39 @@ private static void assertXmlQueryAndExistsFunctionSegment(final SQLCaseAssertCo } } + /** + * Assert key value segment. + * + * @param assertContext assert context + * @param actual actual key value segment + * @param expected expected key value segment + */ + private static void assertKeyValueSegment(final SQLCaseAssertContext assertContext, final KeyValueSegment actual, final ExpectedKeyValueSegment expected) { + if (null == expected) { + assertNull(actual, assertContext.getText("Actual key value should not exist.")); + } else { + assertNotNull(actual, assertContext.getText("Actual key value should exist.")); + assertExpression(assertContext, actual.getKey(), expected.getKey()); + assertExpression(assertContext, actual.getValue(), expected.getValue()); + } + } + + /** + * Assert json null clause segment. + * + * @param assertContext assert context + * @param actual actual json null clause segment + * @param expected expected json null clause segment + */ + private static void assertJsonNullClauseSegment(final SQLCaseAssertContext assertContext, final JsonNullClauseSegment actual, final ExpectedJsonNullClauseSegment expected) { + if (null == expected) { + assertNull(actual, assertContext.getText("Actual json null clause should not exist.")); + } else { + assertNotNull(actual, assertContext.getText("Actual json null clause should exist.")); + assertThat(assertContext.getText("Json null clause assertion error."), actual.getText(), is(expected.getText())); + } + } + /** * Assert expression by actual expression segment class type. * @@ -655,6 +692,10 @@ public static void assertExpression(final SQLCaseAssertContext assertContext, assertUnaryOperationExpression(assertContext, (UnaryOperationExpression) actual, expected.getUnaryOperationExpression()); } else if (actual instanceof XmlQueryAndExistsFunctionSegment) { assertXmlQueryAndExistsFunctionSegment(assertContext, (XmlQueryAndExistsFunctionSegment) actual, expected.getExpectedXmlQueryAndExistsFunctionSegment()); + } else if (actual instanceof KeyValueSegment) { + assertKeyValueSegment(assertContext, (KeyValueSegment) actual, expected.getKeyValueSegment()); + } else if (actual instanceof JsonNullClauseSegment) { + assertJsonNullClauseSegment(assertContext, (JsonNullClauseSegment) actual, expected.getJsonNullClauseSegment()); } else { throw new UnsupportedOperationException(String.format("Unsupported expression: %s", actual.getClass().getName())); } diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java index d8e3ed2eb2f33..d6dc7cc284626 100644 --- a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedExpression.java @@ -27,6 +27,7 @@ import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.simple.ExpectedSubquery; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.function.ExpectedFunction; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.generic.ExpectedDataType; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.json.ExpectedJsonNullClauseSegment; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.projection.impl.aggregation.ExpectedAggregationProjection; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.projection.impl.expression.ExpectedExpressionProjection; import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.xmlquery.ExpectedXmlQueryAndExistsFunctionSegment; @@ -123,4 +124,10 @@ public final class ExpectedExpression extends AbstractExpectedSQLSegment { @XmlElement(name = "xmlquery-projection") private ExpectedXmlQueryAndExistsFunctionSegment expectedXmlQueryAndExistsFunctionSegment; + + @XmlElement(name = "key-value") + private ExpectedKeyValueSegment keyValueSegment; + + @XmlElement(name = "json-null-clause-expression") + private ExpectedJsonNullClauseSegment jsonNullClauseSegment; } diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedKeyValueSegment.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedKeyValueSegment.java new file mode 100644 index 0000000000000..ac7afa2d09805 --- /dev/null +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/expr/ExpectedKeyValueSegment.java @@ -0,0 +1,38 @@ +/* + * 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.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr; + +import lombok.Getter; +import lombok.Setter; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment; + +import javax.xml.bind.annotation.XmlElement; + +/** + * Expected key value segment. + */ +@Getter +@Setter +public class ExpectedKeyValueSegment extends AbstractExpectedSQLSegment implements ExpectedExpressionSegment { + + @XmlElement + private ExpectedExpression key; + + @XmlElement + private ExpectedExpression value; +} diff --git a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/json/ExpectedJsonNullClauseSegment.java b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/json/ExpectedJsonNullClauseSegment.java new file mode 100644 index 0000000000000..d13d6d50d86a1 --- /dev/null +++ b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/json/ExpectedJsonNullClauseSegment.java @@ -0,0 +1,36 @@ +/* + * 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.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.json; + +import lombok.Getter; +import lombok.Setter; +import org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.expr.simple.ExpectedBaseSimpleExpression; + +import javax.xml.bind.annotation.XmlAttribute; + +/** + * Expected json null clause segment. + */ +@Getter +@Setter +public class ExpectedJsonNullClauseSegment extends ExpectedBaseSimpleExpression { + + @XmlAttribute + private String text; + +} 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 617ad7675689c..e6a797c6312c4 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 @@ -715,4 +715,206 @@ + + + + + + + + + + + + + + + + + + + + + + + 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 d5493b6bd2c9c..7abcf363d6568 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 @@ -49,4 +49,9 @@ + + + + +