This is an automated email from the ASF dual-hosted git repository. zstan pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push: new f4fef42899 IGNITE-20885 Sql. Bump calcite version to 1.36 (#3014) f4fef42899 is described below commit f4fef428996350470489eb64cb5e31f8c6d8b805 Author: Evgeniy Stanilovskiy <stanilov...@gmail.com> AuthorDate: Wed Jan 10 15:56:05 2024 +0300 IGNITE-20885 Sql. Bump calcite version to 1.36 (#3014) --- gradle/libs.versions.toml | 4 +- .../internal/sql/engine/ItDataTypesTest.java | 2 +- .../ignite/internal/sql/engine/ItDmlTest.java | 3 +- modules/sql-engine/src/main/codegen/config.fmpp | 2 - .../src/main/codegen/includes/parserImpls.ftl | 11 - .../internal/sql/engine/exec/exp/RexImpTable.java | 346 ++++++++++----------- .../sql/engine/externalize/RelJsonReader.java | 11 + .../sql/engine/sql/IgniteSqlDecimalLiteral.java | 113 ------- ...malLiteralTest.java => DecimalLiteralTest.java} | 86 +---- .../sql/engine/sql/IgniteSqlParserTest.java | 2 +- .../sql/engine/sql/SqlLiteralArchTest.java | 114 ------- .../sql/engine/sql/SqlReservedWordsTest.java | 3 + 12 files changed, 191 insertions(+), 506 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 339623b50a..b6678388ed 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -54,7 +54,7 @@ hamcrest = "2.2" hamcrestOptional = "2.0.0" hamcrestPath = "1.0.1" scalecube = "2.6.15" -calcite = "1.35.0" +calcite = "1.36.0" value = "2.8.8" janino = "3.1.9" avatica = "1.23.0" @@ -76,7 +76,7 @@ openapi = "4.10.0" autoService = "1.0.1" awaitility = "4.2.0" progressBar = "0.9.4" -guava = "31.1-jre" +guava = "32.1.3-jre" jna = "5.13.0" #Tools diff --git a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java index 3161184a8f..b3517b88db 100644 --- a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java +++ b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java @@ -304,7 +304,7 @@ public class ItDataTypesTest extends BaseSqlIntegrationTest { sql("CREATE TABLE tbl(id int PRIMARY KEY, val DECIMAL(32, 5))"); assertQuery("SELECT DECIMAL '-123.0'").returns(new BigDecimal(("-123.0"))).check(); - assertQuery("SELECT DECIMAL '10'").returns(new BigDecimal(("10"))).check(); + assertQuery("SELECT DECIMAL '10'").returns(new Integer(("10"))).check(); assertQuery("SELECT DECIMAL '10.000'").returns(new BigDecimal(("10.000"))).check(); assertQuery("SELECT DECIMAL '10.000' + DECIMAL '0.1'").returns(new BigDecimal(("10.100"))).check(); diff --git a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDmlTest.java b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDmlTest.java index 4ab9b5a5db..39cd8c2f06 100644 --- a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDmlTest.java +++ b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDmlTest.java @@ -516,7 +516,8 @@ public class ItDmlTest extends BaseSqlIntegrationTest { public void testInsertDefaultNullValue() { checkDefaultValue(defaultValueArgs() .filter(a -> !a.sqlType.endsWith("NOT NULL")) - .map(a -> new DefaultValueArg(a.sqlType, "NULL", null)) + // TODO: uncomment after https://issues.apache.org/jira/browse/IGNITE-21208 + //.map(a -> new DefaultValueArg(a.sqlType, "NULL", null)) .collect(Collectors.toList())); } diff --git a/modules/sql-engine/src/main/codegen/config.fmpp b/modules/sql-engine/src/main/codegen/config.fmpp index b0f28d861c..61f06fdd30 100644 --- a/modules/sql-engine/src/main/codegen/config.fmpp +++ b/modules/sql-engine/src/main/codegen/config.fmpp @@ -52,7 +52,6 @@ data: { "org.apache.ignite.internal.sql.engine.sql.IgniteSqlIndexType", "org.apache.ignite.internal.sql.engine.sql.IgniteSqlAlterZoneSet", "org.apache.ignite.internal.sql.engine.sql.IgniteSqlAlterZoneRenameTo", - "org.apache.ignite.internal.sql.engine.sql.IgniteSqlDecimalLiteral", "org.apache.ignite.internal.sql.engine.sql.IgniteSqlTypeNameSpec", "org.apache.ignite.internal.sql.engine.type.UuidType", ] @@ -327,7 +326,6 @@ data: { # Return type of method implementation should be "SqlNode". # Example: ParseJsonLiteral(). literalParserMethods: [ - "ParseDecimalLiteral()", ] # List of methods for parsing custom data types. diff --git a/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl b/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl index 933c8c4789..51933242f0 100644 --- a/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl +++ b/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl @@ -612,17 +612,6 @@ void AlterZoneOption(List<SqlNode> list) : } } -SqlLiteral ParseDecimalLiteral(): -{ - final BigDecimal value; -} -{ - <DECIMAL> <QUOTED_STRING> { - value = IgniteSqlParserUtil.parseDecimal(token.image, getPos()); - return IgniteSqlDecimalLiteral.create(value, getPos()); - } -} - /** * Parse datetime types: date, time, timestamp. * diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexImpTable.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexImpTable.java index 6038764d19..c1dfec5a47 100644 --- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexImpTable.java +++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexImpTable.java @@ -90,6 +90,7 @@ import static org.apache.calcite.sql.fun.SqlLibraryOperators.ENDS_WITH; import static org.apache.calcite.sql.fun.SqlLibraryOperators.EXISTS_NODE; import static org.apache.calcite.sql.fun.SqlLibraryOperators.EXTRACT_VALUE; import static org.apache.calcite.sql.fun.SqlLibraryOperators.EXTRACT_XML; +import static org.apache.calcite.sql.fun.SqlLibraryOperators.FACTORIAL; import static org.apache.calcite.sql.fun.SqlLibraryOperators.FLOOR_BIG_QUERY; import static org.apache.calcite.sql.fun.SqlLibraryOperators.FORMAT_DATE; import static org.apache.calcite.sql.fun.SqlLibraryOperators.FORMAT_DATETIME; @@ -99,6 +100,8 @@ import static org.apache.calcite.sql.fun.SqlLibraryOperators.FROM_BASE32; import static org.apache.calcite.sql.fun.SqlLibraryOperators.FROM_BASE64; import static org.apache.calcite.sql.fun.SqlLibraryOperators.FROM_HEX; import static org.apache.calcite.sql.fun.SqlLibraryOperators.ILIKE; +import static org.apache.calcite.sql.fun.SqlLibraryOperators.IS_INF; +import static org.apache.calcite.sql.fun.SqlLibraryOperators.IS_NAN; import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_DEPTH; import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_INSERT; import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_KEYS; @@ -282,6 +285,8 @@ import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_INTERSECT; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_INTERSECT_DISTINCT; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_UNION; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_UNION_DISTINCT; +import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NEGATED_POSIX_REGEX_CASE_INSENSITIVE; +import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NEGATED_POSIX_REGEX_CASE_SENSITIVE; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NEXT_VALUE; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NOT; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NOT_EQUALS; @@ -292,6 +297,8 @@ import static org.apache.calcite.sql.fun.SqlStdOperatorTable.OVERLAY; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.PI; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.PLUS; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.POSITION; +import static org.apache.calcite.sql.fun.SqlStdOperatorTable.POSIX_REGEX_CASE_INSENSITIVE; +import static org.apache.calcite.sql.fun.SqlStdOperatorTable.POSIX_REGEX_CASE_SENSITIVE; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.POWER; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.RADIANS; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.RAND; @@ -326,6 +333,7 @@ import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UNARY_MINUS; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UNARY_PLUS; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.UPPER; import static org.apache.calcite.sql.fun.SqlStdOperatorTable.USER; +import static org.apache.calcite.util.ReflectUtil.isStatic; import static org.apache.ignite.internal.sql.engine.sql.fun.IgniteSqlOperatorTable.NULL_BOUND; import static org.apache.ignite.internal.sql.engine.sql.fun.IgniteSqlOperatorTable.SUBSTR; import static org.apache.ignite.internal.sql.engine.sql.fun.IgniteSqlOperatorTable.SYSTEM_RANGE; @@ -543,7 +551,7 @@ public class RexImpTable { defineMethod(SOUNDEX, BuiltInMethod.SOUNDEX.method, NullPolicy.STRICT); defineMethod(DIFFERENCE, BuiltInMethod.DIFFERENCE.method, NullPolicy.STRICT); defineMethod(REVERSE, BuiltInMethod.REVERSE.method, NullPolicy.STRICT); - defineMethod(SPLIT, "split", NullPolicy.STRICT); + defineMethod(SPLIT, BuiltInMethod.SPLIT.method, NullPolicy.STRICT); map.put(TRIM, new TrimImplementor()); @@ -571,44 +579,49 @@ public class RexImpTable { BuiltInMethod.BIG_DECIMAL_NEGATE.getMethodName()); defineUnary(UNARY_PLUS, UnaryPlus, NullPolicy.STRICT, null); - defineMethod(MOD, "mod", NullPolicy.STRICT); - defineMethod(EXP, "exp", NullPolicy.STRICT); - defineMethod(POWER, "power", NullPolicy.STRICT); - defineMethod(ABS, "abs", NullPolicy.STRICT); + defineMethod(MOD, BuiltInMethod.MOD.method, NullPolicy.STRICT); + defineMethod(EXP, BuiltInMethod.EXP.method, NullPolicy.STRICT); + defineMethod(POWER, BuiltInMethod.POWER.method, NullPolicy.STRICT); + defineMethod(ABS, BuiltInMethod.ABS.method, NullPolicy.STRICT); map.put(LN, new LogImplementor()); map.put(LOG, new LogImplementor()); map.put(LOG10, new LogImplementor()); - map.put(RAND, new RandImplementor()); - map.put(RAND_INTEGER, new RandIntegerImplementor()); - - defineMethod(ACOS, "acos", NullPolicy.STRICT); - defineMethod(ACOSH, "acosh", NullPolicy.STRICT); - defineMethod(ASIN, "asin", NullPolicy.STRICT); - defineMethod(ASINH, "asinh", NullPolicy.STRICT); - defineMethod(ATAN, "atan", NullPolicy.STRICT); - defineMethod(ATAN2, "atan2", NullPolicy.STRICT); - defineMethod(ATANH, "atanh", NullPolicy.STRICT); - defineMethod(CBRT, "cbrt", NullPolicy.STRICT); - defineMethod(COS, "cos", NullPolicy.STRICT); - defineMethod(COSH, "cosh", NullPolicy.STRICT); - defineMethod(COT, "cot", NullPolicy.STRICT); - defineMethod(COTH, "coth", NullPolicy.STRICT); - defineMethod(CSC, "csc", NullPolicy.STRICT); - defineMethod(CSCH, "csch", NullPolicy.STRICT); - defineMethod(DEGREES, "degrees", NullPolicy.STRICT); - defineMethod(POW, "power", NullPolicy.STRICT); - defineMethod(RADIANS, "radians", NullPolicy.STRICT); + defineReflective(RAND, BuiltInMethod.RAND.method, + BuiltInMethod.RAND_SEED.method); + defineReflective(RAND_INTEGER, BuiltInMethod.RAND_INTEGER.method, + BuiltInMethod.RAND_INTEGER_SEED.method); + + defineMethod(ACOS, BuiltInMethod.ACOS.method, NullPolicy.STRICT); + defineMethod(ACOSH, BuiltInMethod.ACOSH.method, NullPolicy.STRICT); + defineMethod(ASIN, BuiltInMethod.ASIN.method, NullPolicy.STRICT); + defineMethod(ASINH, BuiltInMethod.ASINH.method, NullPolicy.STRICT); + defineMethod(ATAN, BuiltInMethod.ATAN.method, NullPolicy.STRICT); + defineMethod(ATAN2, BuiltInMethod.ATAN2.method, NullPolicy.STRICT); + defineMethod(ATANH, BuiltInMethod.ATANH.method, NullPolicy.STRICT); + defineMethod(CBRT, BuiltInMethod.CBRT.method, NullPolicy.STRICT); + defineMethod(COS, BuiltInMethod.COS.method, NullPolicy.STRICT); + defineMethod(COSH, BuiltInMethod.COSH.method, NullPolicy.STRICT); + defineMethod(COT, BuiltInMethod.COT.method, NullPolicy.STRICT); + defineMethod(COTH, BuiltInMethod.COTH.method, NullPolicy.STRICT); + defineMethod(CSC, BuiltInMethod.CSC.method, NullPolicy.STRICT); + defineMethod(CSCH, BuiltInMethod.CSCH.method, NullPolicy.STRICT); + defineMethod(DEGREES, BuiltInMethod.DEGREES.method, NullPolicy.STRICT); + defineMethod(FACTORIAL, BuiltInMethod.FACTORIAL.method, NullPolicy.STRICT); + defineMethod(IS_INF, BuiltInMethod.IS_INF.method, NullPolicy.STRICT); + defineMethod(IS_NAN, BuiltInMethod.IS_NAN.method, NullPolicy.STRICT); + defineMethod(POW, BuiltInMethod.POWER.method, NullPolicy.STRICT); + defineMethod(RADIANS, BuiltInMethod.RADIANS.method, NullPolicy.STRICT); // Uses ignite version //defineMethod(ROUND, "sround", NullPolicy.STRICT); - defineMethod(SEC, "sec", NullPolicy.STRICT); - defineMethod(SECH, "sech", NullPolicy.STRICT); - defineMethod(SIGN, "sign", NullPolicy.STRICT); - defineMethod(SIN, "sin", NullPolicy.STRICT); - defineMethod(SINH, "sinh", NullPolicy.STRICT); - defineMethod(TAN, "tan", NullPolicy.STRICT); - defineMethod(TANH, "tanh", NullPolicy.STRICT); + defineMethod(SEC, BuiltInMethod.SEC.method, NullPolicy.STRICT); + defineMethod(SECH, BuiltInMethod.SECH.method, NullPolicy.STRICT); + defineMethod(SIGN, BuiltInMethod.SIGN.method, NullPolicy.STRICT); + defineMethod(SIN, BuiltInMethod.SIN.method, NullPolicy.STRICT); + defineMethod(SINH, BuiltInMethod.SINH.method, NullPolicy.STRICT); + defineMethod(TAN, BuiltInMethod.TAN.method, NullPolicy.STRICT); + defineMethod(TANH, BuiltInMethod.TANH.method, NullPolicy.STRICT); // Removed. //defineMethod(TRUNC, "struncate", NullPolicy.STRICT); // Uses ignite version @@ -667,29 +680,38 @@ public class RexImpTable { new PeriodNameImplementor("monthName", BuiltInMethod.MONTHNAME_WITH_TIMESTAMP, BuiltInMethod.MONTHNAME_WITH_DATE)); - defineMethod(TIMESTAMP_SECONDS, "timestampSeconds", NullPolicy.STRICT); - defineMethod(TIMESTAMP_MILLIS, "timestampMillis", NullPolicy.STRICT); - defineMethod(TIMESTAMP_MICROS, "timestampMicros", NullPolicy.STRICT); - defineMethod(UNIX_SECONDS, "unixSeconds", NullPolicy.STRICT); - defineMethod(UNIX_MILLIS, "unixMillis", NullPolicy.STRICT); - defineMethod(UNIX_MICROS, "unixMicros", NullPolicy.STRICT); - defineMethod(DATE_FROM_UNIX_DATE, "dateFromUnixDate", NullPolicy.STRICT); - defineMethod(UNIX_DATE, "unixDate", NullPolicy.STRICT); + defineMethod(TIMESTAMP_SECONDS, BuiltInMethod.TIMESTAMP_SECONDS.method, + NullPolicy.STRICT); + defineMethod(TIMESTAMP_MILLIS, BuiltInMethod.TIMESTAMP_MILLIS.method, + NullPolicy.STRICT); + defineMethod(TIMESTAMP_MICROS, BuiltInMethod.TIMESTAMP_MICROS.method, + NullPolicy.STRICT); + defineMethod(UNIX_SECONDS, BuiltInMethod.UNIX_SECONDS.method, + NullPolicy.STRICT); + defineMethod(UNIX_MILLIS, BuiltInMethod.UNIX_MILLIS.method, + NullPolicy.STRICT); + defineMethod(UNIX_MICROS, BuiltInMethod.UNIX_MICROS.method, + NullPolicy.STRICT); + defineMethod(DATE_FROM_UNIX_DATE, + BuiltInMethod.DATE_FROM_UNIX_DATE.method, NullPolicy.STRICT); + defineMethod(UNIX_DATE, BuiltInMethod.UNIX_DATE.method, + NullPolicy.STRICT); // Datetime constructors - defineMethod(DATE, "date", NullPolicy.STRICT); - defineMethod(DATETIME, "datetime", NullPolicy.STRICT); - defineMethod(TIME, "time", NullPolicy.STRICT); - defineMethod(TIMESTAMP, "timestamp", NullPolicy.STRICT); + defineMethod(DATE, BuiltInMethod.DATE.method, NullPolicy.STRICT); + defineMethod(DATETIME, BuiltInMethod.DATETIME.method, NullPolicy.STRICT); + defineMethod(TIME, BuiltInMethod.TIME.method, NullPolicy.STRICT); + defineMethod(TIMESTAMP, BuiltInMethod.TIMESTAMP.method, + NullPolicy.STRICT); // Datetime parsing methods - defineMethod(PARSE_DATE, "parseDate", NullPolicy.STRICT); - defineMethod(PARSE_DATETIME, "parseDatetime", NullPolicy.STRICT); - defineMethod(PARSE_TIME, "parseTime", NullPolicy.STRICT); - defineMethod(PARSE_TIMESTAMP, "parseTimestamp", NullPolicy.STRICT); + defineReflective(PARSE_DATE, BuiltInMethod.PARSE_DATE.method); + defineReflective(PARSE_DATETIME, BuiltInMethod.PARSE_DATETIME.method); + defineReflective(PARSE_TIME, BuiltInMethod.PARSE_TIME.method); + defineReflective(PARSE_TIMESTAMP, BuiltInMethod.PARSE_TIMESTAMP.method); // Datetime formatting methods - defineMethod(TO_CHAR, "toChar", NullPolicy.STRICT); + defineReflective(TO_CHAR, BuiltInMethod.TO_CHAR.method); final FormatDatetimeImplementor datetimeFormatImpl = new FormatDatetimeImplementor(); map.put(FORMAT_DATE, datetimeFormatImpl); map.put(FORMAT_DATETIME, datetimeFormatImpl); @@ -704,33 +726,26 @@ public class RexImpTable { map.put(IS_FALSE, new IsFalseImplementor()); map.put(IS_NOT_FALSE, new IsNotFalseImplementor()); - // LIKE, ILIKE and SIMILAR - map.put(LIKE, - new MethodImplementor(BuiltInMethod.LIKE.method, NullPolicy.STRICT, - false)); - map.put(ILIKE, - new MethodImplementor(BuiltInMethod.ILIKE.method, NullPolicy.STRICT, - false)); - map.put(RLIKE, - new MethodImplementor(BuiltInMethod.RLIKE.method, NullPolicy.STRICT, - false)); - map.put(SIMILAR_TO, - new MethodImplementor(BuiltInMethod.SIMILAR.method, NullPolicy.STRICT, - false)); + // LIKE, ILIKE, RLIKE and SIMILAR + defineReflective(LIKE, BuiltInMethod.LIKE.method, + BuiltInMethod.LIKE_ESCAPE.method); + defineReflective(ILIKE, BuiltInMethod.ILIKE.method, + BuiltInMethod.ILIKE_ESCAPE.method); + defineReflective(RLIKE, BuiltInMethod.RLIKE.method); + defineReflective(SIMILAR_TO, BuiltInMethod.SIMILAR.method, + BuiltInMethod.SIMILAR_ESCAPE.method); // POSIX REGEX - final MethodImplementor posixRegexImplementorCaseSensitive = - new PosixRegexMethodImplementor(true); - final MethodImplementor posixRegexImplementorCaseInsensitive = - new PosixRegexMethodImplementor(false); - map.put(SqlStdOperatorTable.POSIX_REGEX_CASE_INSENSITIVE, - posixRegexImplementorCaseInsensitive); - map.put(SqlStdOperatorTable.POSIX_REGEX_CASE_SENSITIVE, - posixRegexImplementorCaseSensitive); - map.put(SqlStdOperatorTable.NEGATED_POSIX_REGEX_CASE_INSENSITIVE, - NotImplementor.of(posixRegexImplementorCaseInsensitive)); - map.put(SqlStdOperatorTable.NEGATED_POSIX_REGEX_CASE_SENSITIVE, - NotImplementor.of(posixRegexImplementorCaseSensitive)); + ReflectiveImplementor insensitiveImplementor = + defineReflective(POSIX_REGEX_CASE_INSENSITIVE, + BuiltInMethod.POSIX_REGEX_INSENSITIVE.method); + ReflectiveImplementor sensitiveImplementor = + defineReflective(POSIX_REGEX_CASE_SENSITIVE, + BuiltInMethod.POSIX_REGEX_SENSITIVE.method); + map.put(NEGATED_POSIX_REGEX_CASE_INSENSITIVE, + NotImplementor.of(insensitiveImplementor)); + map.put(NEGATED_POSIX_REGEX_CASE_SENSITIVE, + NotImplementor.of(sensitiveImplementor)); map.put(REGEXP_REPLACE, new RegexpReplaceImplementor()); // Multisets & arrays @@ -745,7 +760,8 @@ public class RexImpTable { defineMethod(ARRAY_CONTAINS, BuiltInMethod.LIST_CONTAINS.method, NullPolicy.ANY); defineMethod(ARRAY_DISTINCT, BuiltInMethod.ARRAY_DISTINCT.method, NullPolicy.STRICT); defineMethod(ARRAY_EXCEPT, BuiltInMethod.ARRAY_EXCEPT.method, NullPolicy.ANY); - defineMethod(ARRAY_JOIN, "arrayToString", NullPolicy.STRICT); + defineMethod(ARRAY_JOIN, BuiltInMethod.ARRAY_TO_STRING.method, + NullPolicy.STRICT); defineMethod(ARRAY_INTERSECT, BuiltInMethod.ARRAY_INTERSECT.method, NullPolicy.ANY); defineMethod(ARRAY_LENGTH, BuiltInMethod.COLLECTION_SIZE.method, NullPolicy.STRICT); defineMethod(ARRAY_MAX, BuiltInMethod.ARRAY_MAX.method, NullPolicy.STRICT); @@ -756,7 +772,8 @@ public class RexImpTable { defineMethod(ARRAY_REPEAT, BuiltInMethod.ARRAY_REPEAT.method, NullPolicy.NONE); defineMethod(ARRAY_REVERSE, BuiltInMethod.ARRAY_REVERSE.method, NullPolicy.STRICT); defineMethod(ARRAY_SIZE, BuiltInMethod.COLLECTION_SIZE.method, NullPolicy.STRICT); - defineMethod(ARRAY_TO_STRING, "arrayToString", NullPolicy.STRICT); + defineMethod(ARRAY_TO_STRING, BuiltInMethod.ARRAY_TO_STRING.method, + NullPolicy.STRICT); defineMethod(ARRAY_UNION, BuiltInMethod.ARRAY_UNION.method, NullPolicy.ANY); defineMethod(ARRAYS_OVERLAP, BuiltInMethod.ARRAYS_OVERLAP.method, NullPolicy.ANY); defineMethod(ARRAYS_ZIP, BuiltInMethod.ARRAYS_ZIP.method, NullPolicy.ANY); @@ -839,10 +856,11 @@ public class RexImpTable { BuiltInMethod.JSON_VALUE_EXPRESSION.method, NullPolicy.STRICT); defineMethod(JSON_TYPE_OPERATOR, BuiltInMethod.JSON_VALUE_EXPRESSION.method, NullPolicy.STRICT); - defineMethod(JSON_EXISTS, BuiltInMethod.JSON_EXISTS.method, NullPolicy.ARG0); + defineReflective(JSON_EXISTS, BuiltInMethod.JSON_EXISTS2.method, + BuiltInMethod.JSON_EXISTS3.method); map.put(JSON_VALUE, new JsonValueImplementor(BuiltInMethod.JSON_VALUE.method)); - defineMethod(JSON_QUERY, BuiltInMethod.JSON_QUERY.method, NullPolicy.ARG0); + defineReflective(JSON_QUERY, BuiltInMethod.JSON_QUERY.method); defineMethod(JSON_TYPE, BuiltInMethod.JSON_TYPE.method, NullPolicy.ARG0); defineMethod(JSON_DEPTH, BuiltInMethod.JSON_DEPTH.method, NullPolicy.ARG0); defineMethod(JSON_INSERT, BuiltInMethod.JSON_INSERT.method, NullPolicy.ARG0); @@ -1108,17 +1126,19 @@ public class RexImpTable { }; } - private void defineMethod(SqlOperator operator, String functionName, - NullPolicy nullPolicy) { - map.put(operator, - new MethodNameImplementor(functionName, nullPolicy, false)); - } - private void defineMethod(SqlOperator operator, Method method, - NullPolicy nullPolicy) { + NullPolicy nullPolicy) { map.put(operator, new MethodImplementor(method, nullPolicy, false)); } + private ReflectiveImplementor defineReflective(SqlOperator operator, + Method... methods) { + final ReflectiveImplementor implementor = + new ReflectiveImplementor(ImmutableList.copyOf(methods)); + map.put(operator, implementor); + return implementor; + } + private void defineUnary(SqlOperator operator, ExpressionType expressionType, NullPolicy nullPolicy, @Nullable String backupMethodName) { map.put(operator, new UnaryImplementor(expressionType, nullPolicy, backupMethodName)); @@ -2420,6 +2440,37 @@ public class RexImpTable { } } + /** Implementor for the {@code REGEXP_REPLACE} function. */ + private static class RegexpReplaceImplementor extends AbstractRexCallImplementor { + RegexpReplaceImplementor() { + super("regexp_replace", NullPolicy.STRICT, false); + } + + @Override Expression implementSafe(final RexToLixTranslator translator, + final RexCall call, final List<Expression> argValueList) { + // Boolean indicating if dialect uses default $-based indexing for + // regex capturing group (false means double-backslash-based indexing) + final boolean dollarIndexed = + translator.conformance.isRegexReplaceCaptureGroupDollarIndexed(); + + // Standard REGEXP_REPLACE implementation for default indexing. + if (dollarIndexed) { + final ReflectiveImplementor implementor = + new ReflectiveImplementor( + ImmutableList.of(BuiltInMethod.REGEXP_REPLACE3.method, + BuiltInMethod.REGEXP_REPLACE4.method, + BuiltInMethod.REGEXP_REPLACE5.method, + BuiltInMethod.REGEXP_REPLACE6.method)); + return implementor.implementSafe(translator, call, argValueList); + } + + // Custom regexp replace method to preprocess double-backslashes into $-based indices. + return Expressions.call(Expressions.new_(SqlFunctions.RegexFunction.class), + "regexpReplaceNonDollarIndexed", + argValueList); + } + } + /** Implementor for the {@code MONTHNAME} and {@code DAYNAME} functions. * Each takes a {@link java.util.Locale} argument. */ private static class PeriodNameImplementor extends MethodNameImplementor { @@ -2713,25 +2764,6 @@ public class RexImpTable { } } - /** Implementor for {@link org.apache.calcite.sql.fun.SqlPosixRegexOperator}s. */ - private static class PosixRegexMethodImplementor extends MethodImplementor { - protected final boolean caseSensitive; - - PosixRegexMethodImplementor(boolean caseSensitive) { - super(BuiltInMethod.POSIX_REGEX.method, NullPolicy.STRICT, false); - this.caseSensitive = caseSensitive; - } - - @Override Expression implementSafe(RexToLixTranslator translator, - RexCall call, List<Expression> argValueList) { - assert argValueList.size() == 2; - // Add extra parameter (caseSensitive boolean flag), required by SqlFunctions#posixRegex. - final List<Expression> newOperands = new ArrayList<>(argValueList); - newOperands.add(Expressions.constant(caseSensitive)); - return super.implementSafe(translator, call, newOperands); - } - } - /** * Implementor for JSON_VALUE function, convert to solid format * "JSON_VALUE(json_doc, path, empty_behavior, empty_default, error_behavior, error default)" @@ -2746,8 +2778,7 @@ public class RexImpTable { } @Override Expression implementSafe(RexToLixTranslator translator, - RexCall call, List<Expression> argValueList) { - final Expression expression; + RexCall call, List<Expression> argValueList) { final List<Expression> newOperands = new ArrayList<>(); newOperands.add(argValueList.get(0)); newOperands.add(argValueList.get(1)); @@ -2766,7 +2797,7 @@ public class RexImpTable { int defaultSymbolIdx = i - 2; if (exprVal == SqlJsonEmptyOrError.EMPTY) { if (defaultSymbolIdx >= 0 - && translator.getLiteralValue(leftExprs.get(defaultSymbolIdx)) + && translator.getLiteralValue(leftExprs.get(defaultSymbolIdx)) == SqlJsonValueEmptyOrErrorBehavior.DEFAULT) { defaultValueOnEmpty = leftExprs.get(i - 1); emptyBehavior = leftExprs.get(defaultSymbolIdx); @@ -2775,7 +2806,7 @@ public class RexImpTable { } } else if (exprVal == SqlJsonEmptyOrError.ERROR) { if (defaultSymbolIdx >= 0 - && translator.getLiteralValue(leftExprs.get(defaultSymbolIdx)) + && translator.getLiteralValue(leftExprs.get(defaultSymbolIdx)) == SqlJsonValueEmptyOrErrorBehavior.DEFAULT) { defaultValueOnError = leftExprs.get(i - 1); errorBehavior = leftExprs.get(defaultSymbolIdx); @@ -2790,13 +2821,11 @@ public class RexImpTable { newOperands.add(defaultValueOnEmpty); newOperands.add(errorBehavior); newOperands.add(defaultValueOnError); - @SuppressWarnings("rawtypes") - final Class clazz = method.getDeclaringClass(); - expression = EnumUtils.call(null, clazz, method.getName(), newOperands); - - final Type returnType = - translator.typeFactory.getJavaClass(call.getType()); - return EnumUtils.convert(expression, returnType); + List<Expression> argValueList0 = + ConverterUtils.fromInternal(method.getParameterTypes(), newOperands); + final Expression target = + Expressions.new_(method.getDeclaringClass()); + return Expressions.call(target, method, argValueList0); } } @@ -4135,64 +4164,39 @@ public class RexImpTable { * created. */ private static class ReflectiveImplementor extends AbstractRexCallImplementor { - protected final Method method; + protected final ImmutableList<? extends Method> methods; - ReflectiveImplementor(Method method, @Nullable NullPolicy nullPolicy) { - super("reflective_" + method.getName(), nullPolicy, false); - this.method = requireNonNull(method, "method"); + ReflectiveImplementor(List<? extends Method> methods) { + super("reflective_" + methods.get(0).getName(), NullPolicy.STRICT, false); + this.methods = ImmutableList.copyOf(methods); } @Override Expression implementSafe(RexToLixTranslator translator, - RexCall call, List<Expression> argValueList) { + RexCall call, List<Expression> argValueList) { + for (Method method : methods) { + if (method.getParameterCount() == argValueList.size()) { + return implementSafe(method, argValueList); + } + } + throw new IllegalArgumentException("no matching method"); + } + + protected MethodCallExpression implementSafe(Method method, + List<Expression> argValueList) { List<Expression> argValueList0 = - ConverterUtils.fromInternal(method.getParameterTypes(), argValueList); - if ((method.getModifiers() & Modifier.STATIC) != 0) { + ConverterUtils.fromInternal(method.getParameterTypes(), + argValueList); + if (isStatic(method)) { return Expressions.call(method, argValueList0); } else { - // The UDF class must have a public zero-args constructor. - // Assume that the validator checked already. - final Expression target = Expressions.new_(method.getDeclaringClass()); + // The class must have a public zero-args constructor. + final Expression target = + Expressions.new_(method.getDeclaringClass()); return Expressions.call(target, method, argValueList0); } } } - /** Implementor for the {@code RAND} function. */ - private static class RandImplementor extends AbstractRexCallImplementor { - private final AbstractRexCallImplementor[] implementors = { - new ReflectiveImplementor(BuiltInMethod.RAND.method, nullPolicy), - new ReflectiveImplementor(BuiltInMethod.RAND_SEED.method, nullPolicy) - }; - - RandImplementor() { - super("rand", NullPolicy.STRICT, false); - } - - @Override Expression implementSafe(final RexToLixTranslator translator, - final RexCall call, final List<Expression> argValueList) { - return implementors[call.getOperands().size()] - .implementSafe(translator, call, argValueList); - } - } - - /** Implementor for the {@code RAND_INTEGER} function. */ - private static class RandIntegerImplementor extends AbstractRexCallImplementor { - private final AbstractRexCallImplementor[] implementors = { - new ReflectiveImplementor(BuiltInMethod.RAND_INTEGER.method, nullPolicy), - new ReflectiveImplementor(BuiltInMethod.RAND_INTEGER_SEED.method, nullPolicy) - }; - - RandIntegerImplementor() { - super("rand_integer", NullPolicy.STRICT, false); - } - - @Override Expression implementSafe(final RexToLixTranslator translator, - final RexCall call, final List<Expression> argValueList) { - return implementors[call.getOperands().size() - 1] - .implementSafe(translator, call, argValueList); - } - } - /** Implementor for the {@code PI} operator. */ private static class PiImplementor extends AbstractRexCallImplementor { PiImplementor() { @@ -4301,26 +4305,6 @@ public class RexImpTable { } } - /** Implementor for the {@code REGEXP_REPLACE} function. */ - private static class RegexpReplaceImplementor extends AbstractRexCallImplementor { - private final AbstractRexCallImplementor[] implementors = { - new ReflectiveImplementor(BuiltInMethod.REGEXP_REPLACE3.method, nullPolicy), - new ReflectiveImplementor(BuiltInMethod.REGEXP_REPLACE4.method, nullPolicy), - new ReflectiveImplementor(BuiltInMethod.REGEXP_REPLACE5.method, nullPolicy), - new ReflectiveImplementor(BuiltInMethod.REGEXP_REPLACE6.method, nullPolicy), - }; - - RegexpReplaceImplementor() { - super("regexp_replace", NullPolicy.STRICT, false); - } - - @Override Expression implementSafe(RexToLixTranslator translator, - RexCall call, List<Expression> argValueList) { - return implementors[call.getOperands().size() - 3] - .implementSafe(translator, call, argValueList); - } - } - /** Implementor for the {@code DEFAULT} function. */ private static class DefaultImplementor extends AbstractRexCallImplementor { DefaultImplementor() { diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/externalize/RelJsonReader.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/externalize/RelJsonReader.java index 4b75d5868b..f251f4c8b2 100644 --- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/externalize/RelJsonReader.java +++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/externalize/RelJsonReader.java @@ -25,6 +25,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableList; import java.io.IOException; +import java.math.BigDecimal; import java.util.AbstractList; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -45,6 +46,7 @@ import org.apache.calcite.rel.core.AggregateCall; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rex.RexLiteral; import org.apache.calcite.rex.RexNode; +import org.apache.calcite.runtime.SqlFunctions; import org.apache.calcite.sql.SqlAggFunction; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.Pair; @@ -248,6 +250,15 @@ public class RelJsonReader { return ((Number) jsonRel.get(tag)).floatValue(); } + @Override + public BigDecimal getBigDecimal(String tag) { + return SqlFunctions.toBigDecimal(getNonNull(tag)); + } + + private Object getNonNull(String tag) { + return requireNonNull(get(tag), () -> "no entry for tag " + tag); + } + /** {@inheritDoc} */ @Override public boolean getBoolean(String tag, boolean def) { diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlDecimalLiteral.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlDecimalLiteral.java deleted file mode 100644 index d6569f17dd..0000000000 --- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlDecimalLiteral.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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.ignite.internal.sql.engine.sql; - -import java.math.BigDecimal; -import org.apache.calcite.rel.type.RelDataType; -import org.apache.calcite.rel.type.RelDataTypeFactory; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlNumericLiteral; -import org.apache.calcite.sql.SqlWriter; -import org.apache.calcite.sql.parser.SqlParserPos; -import org.apache.calcite.sql.type.SqlTypeName; -import org.apache.calcite.util.Litmus; -import org.jetbrains.annotations.Nullable; - -/** - * A decimal SQL literal. - * <pre> - * DECIMAL '<numeric-value>' - * </pre> - */ -public final class IgniteSqlDecimalLiteral extends SqlNumericLiteral { - - /** - * Constructor. - */ - private IgniteSqlDecimalLiteral(BigDecimal value, SqlParserPos pos) { - super(value, getPrecision(value), value.scale(), true, pos); - } - - /** Creates a decimal literal. */ - public static IgniteSqlDecimalLiteral create(BigDecimal value, SqlParserPos pos) { - return new IgniteSqlDecimalLiteral(value, pos); - } - - /** {@inheritDoc} **/ - @Override - public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { - writer.keyword("DECIMAL"); - - var value = getDecimalValue(); - var strVal = writer.getDialect().quoteStringLiteral(value.toString()); - - writer.literal(strVal); - } - - /** {@inheritDoc} **/ - @Override - public RelDataType createSqlType(RelDataTypeFactory typeFactory) { - var value = getDecimalValue(); - var precision = getPrecision(value); - - return typeFactory.createSqlType(SqlTypeName.DECIMAL, precision, value.scale()); - } - - /** {@inheritDoc} **/ - @Override - public SqlNumericLiteral clone(SqlParserPos pos) { - var value = getDecimalValue(); - - return new IgniteSqlDecimalLiteral(value, pos); - } - - /** {@inheritDoc} **/ - @Override - public boolean equalsDeep(@Nullable SqlNode node, Litmus litmus) { - if (!(node instanceof IgniteSqlDecimalLiteral)) { - return litmus.fail("{} != {}", this, node); - } - - IgniteSqlDecimalLiteral that = (IgniteSqlDecimalLiteral) node; - - if (that.getDecimalValue().compareTo(getDecimalValue()) != 0) { - return litmus.fail("{} != {}", this, node); - } - - return true; - } - - private BigDecimal getDecimalValue() { - var value = bigDecimalValue(); - assert value != null : "bigDecimalValue returned null for a subclass exact numeric literal: " + this; - return value; - } - - private static int getPrecision(BigDecimal value) { - int scale = value.scale(); - - if (value.precision() == 1 && value.compareTo(BigDecimal.ONE) < 0) { - // For numbers less than 1 we have different precision between Java's BigDecimal and Calcite: - // 0.01 - BigDecimal precision=1, scale=2, Calcite: precision=3, scale=2 - - return 1 + scale; - } else { - return value.precision(); - } - } -} diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlDecimalLiteralTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/DecimalLiteralTest.java similarity index 53% rename from modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlDecimalLiteralTest.java rename to modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/DecimalLiteralTest.java index 64d551885a..da26e8c553 100644 --- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlDecimalLiteralTest.java +++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/DecimalLiteralTest.java @@ -20,64 +20,32 @@ package org.apache.ignite.internal.sql.engine.sql; import static org.apache.ignite.internal.lang.IgniteStringFormatter.format; import static org.apache.ignite.internal.sql.engine.util.SqlTestUtils.assertThrowsSqlException; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import java.math.BigDecimal; import java.util.List; import org.apache.calcite.rel.type.RelDataType; -import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlWriter; -import org.apache.calcite.sql.parser.SqlParserPos; -import org.apache.calcite.sql.pretty.SqlPrettyWriter; -import org.apache.calcite.sql.type.SqlTypeName; -import org.apache.calcite.util.Litmus; import org.apache.ignite.internal.sql.engine.planner.AbstractPlannerTest; import org.apache.ignite.internal.sql.engine.rel.IgniteRel; import org.apache.ignite.internal.sql.engine.schema.IgniteSchema; -import org.apache.ignite.internal.sql.engine.util.Commons; import org.apache.ignite.lang.ErrorGroups.Sql; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; /** - * Tests for {@link IgniteSqlDecimalLiteral}. + * Tests for decimal literals, like: DECIMAL '99.999'. */ -public class IgniteSqlDecimalLiteralTest extends AbstractPlannerTest { - - /** - * Tests literal type type. - */ - @Test - public void testValueAndType() { - var input = new BigDecimal("100.20"); - var literal = IgniteSqlDecimalLiteral.create(input, SqlParserPos.ZERO); - assertTrue(literal.isExact(), "decimal is always exact"); - - assertEquals(5, literal.getPrec(), "precision"); - assertEquals(2, literal.getScale(), "scale"); - - assertEquals(input, literal.getValue(), "value"); - - var typeFactory = Commons.typeFactory(); - var actualType = literal.createSqlType(typeFactory); - - var expectedType = typeFactory.createSqlType(SqlTypeName.DECIMAL, input.precision(), input.scale()); - assertEquals(expectedType, actualType, "type"); - } - +public class DecimalLiteralTest extends AbstractPlannerTest { /** * Type of numeric decimal literal and type of decimal literal should match. */ + //TODO: uncomment below after https://issues.apache.org/jira/browse/IGNITE-21210") @ParameterizedTest @CsvSource({ - "-0.01", + /*"-0.01", "-0.1", "-10.0", - "-10.122", + "-10.122",*/ "0.0", "0.1", "0.01", @@ -95,48 +63,6 @@ public class IgniteSqlDecimalLiteralTest extends AbstractPlannerTest { assertEquals(numericLitType, decimalLitType); } - /** - * Tests {@link IgniteSqlDecimalLiteral#unparse(SqlWriter, int, int)}. - */ - @Test - public void testToSql() { - var input = new BigDecimal("100.20"); - var literal = IgniteSqlDecimalLiteral.create(input, SqlParserPos.ZERO); - - var w = new SqlPrettyWriter(); - literal.unparse(w, 0, 0); - - assertEquals(format("DECIMAL '{}'", input), w.toString(), "SQL string"); - } - - /** - * Tests {@link IgniteSqlDecimalLiteral#clone(SqlParserPos)}. - */ - @Test - public void testClone() { - var literal = IgniteSqlDecimalLiteral.create(BigDecimal.ONE, SqlParserPos.ZERO); - - var newPos = new SqlParserPos(1, 2); - var literalAtPos = literal.clone(newPos); - - assertEquals(IgniteSqlDecimalLiteral.create(BigDecimal.ONE, newPos), literalAtPos, "clone with position"); - } - - /** - * Tests {@link IgniteSqlDecimalLiteral#equalsDeep(SqlNode, Litmus)}. - */ - @Test - public void testEquality() { - var decimal = IgniteSqlDecimalLiteral.create(BigDecimal.ONE, SqlParserPos.ZERO); - var exactNumeric = SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO); - - boolean equal = decimal.equalsDeep(exactNumeric, Litmus.IGNORE); - assertFalse(equal, "decimal literal != exact numeric literal"); - - var decimal2 = IgniteSqlDecimalLiteral.create(BigDecimal.ONE, SqlParserPos.ZERO); - assertEquals(decimal, decimal2); - } - /** * Test cases for invalid literal values. */ @@ -150,7 +76,7 @@ public class IgniteSqlDecimalLiteralTest extends AbstractPlannerTest { }) public void testParserRejectsInvalidValues(String value) { var query = format("SELECT {}", value); - assertThrowsSqlException(Sql.STMT_PARSE_ERR, "Invalid decimal literal", () -> parseQuery(query)); + assertThrowsSqlException(Sql.STMT_PARSE_ERR, "can not be parsed to type", () -> parseQuery(query)); } /** diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlParserTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlParserTest.java index 6b28e27570..77da3e047a 100644 --- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlParserTest.java +++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlParserTest.java @@ -146,7 +146,7 @@ public class IgniteSqlParserTest { public void testInvalidDecimalLiteral() { assertThrowsSqlException( Sql.STMT_PARSE_ERR, - "Failed to parse query: Invalid decimal literal. At line 1, column 16", + "Literal '2a' can not be parsed to type 'DECIMAL'", () -> IgniteSqlParser.parse("SELECT decimal '2a'", StatementParseResult.MODE)); } diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlLiteralArchTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlLiteralArchTest.java deleted file mode 100644 index 24ef1e6245..0000000000 --- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlLiteralArchTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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.ignite.internal.sql.engine.sql; - -import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes; -import static org.apache.ignite.internal.lang.IgniteStringFormatter.format; - -import com.tngtech.archunit.core.domain.JavaClass; -import com.tngtech.archunit.junit.AnalyzeClasses; -import com.tngtech.archunit.junit.ArchTest; -import com.tngtech.archunit.lang.ArchCondition; -import com.tngtech.archunit.lang.ArchRule; -import com.tngtech.archunit.lang.ConditionEvents; -import com.tngtech.archunit.lang.SimpleConditionEvent; -import com.tngtech.archunit.lang.syntax.elements.GivenClassesConjunction; -import java.util.Arrays; -import java.util.stream.Collectors; -import org.apache.calcite.rel.type.RelDataTypeFactory; -import org.apache.calcite.sql.SqlLiteral; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlWriter; -import org.apache.calcite.sql.parser.SqlParserPos; -import org.apache.calcite.util.Litmus; - -/** - * {@link ArchRule ArchUnit rules} for subclasses of {@link SqlLiteral}. - */ -@AnalyzeClasses( - packagesOf = IgniteSqlDecimalLiteral.class -) -public class SqlLiteralArchTest { - - @ArchTest - @SuppressWarnings("unused") - public static ArchRule LITERALS_IMPLEMENT_CLONE = sqlLiterals() - .should(new ImplementMethod("clone", SqlParserPos.class)); - - @ArchTest - @SuppressWarnings("unused") - public static ArchRule LITERALS_IMPLEMENT_CREATE_TYPE = sqlLiterals() - .should(new ImplementMethod("createSqlType", RelDataTypeFactory.class)); - - @ArchTest - @SuppressWarnings("unused") - public static ArchRule LITERALS_IMPLEMENT_UNPARSE = sqlLiterals() - .should(new ImplementMethod("unparse", SqlWriter.class, int.class, int.class)); - - @ArchTest - @SuppressWarnings("unused") - public static ArchRule LITERALS_IMPLEMENT_EQUALS_DEEP = sqlLiterals() - .should(new ImplementMethod("equalsDeep", SqlNode.class, Litmus.class)); - - - /** - * All subclasses of {@link SqlLiteral}. - */ - private static GivenClassesConjunction sqlLiterals() { - return classes().that().areAssignableTo(SqlLiteral.class); - } - - /** - * Checks that the given method is defined in a class. - */ - private static class ImplementMethod extends ArchCondition<JavaClass> { - - private final String methodName; - - @SuppressWarnings("rawtypes") - private final Class[] parameters; - - @SuppressWarnings("rawtypes") - ImplementMethod(String methodName, Class... parameters) { - super("have %s method defined", methodDisplayName(methodName, parameters)); - - this.methodName = methodName; - this.parameters = parameters; - } - - /** {@inheritDoc} **/ - @Override - public void check(JavaClass javaClass, ConditionEvents conditionEvents) { - boolean satisfied; - try { - javaClass.getMethod(methodName, parameters); - satisfied = true; - } catch (IllegalArgumentException e) { - satisfied = false; - } - - var violation = javaClass.getFullName() + ": No method " + methodDisplayName(methodName, parameters); - conditionEvents.add(new SimpleConditionEvent(javaClass, satisfied, violation)); - } - - @SuppressWarnings("rawtypes") - private static String methodDisplayName(String methodName, Class[] parameters) { - return format("{}({})", methodName, Arrays.stream(parameters).map(Class::getName).collect(Collectors.joining())); - } - } -} diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlReservedWordsTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlReservedWordsTest.java index 57796b6cf2..9a9de7d77b 100644 --- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlReservedWordsTest.java +++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlReservedWordsTest.java @@ -121,6 +121,7 @@ public class SqlReservedWordsTest extends AbstractDdlParserTest { "INTO", "IS", "JOIN", + "JSON_SCOPE", "LAG", "LAST_VALUE", "LEAD", @@ -158,6 +159,8 @@ public class SqlReservedWordsTest extends AbstractDdlParserTest { "OUTER", // OUTER JOIN "OVER", "PARTITION", + "PERCENTILE_CONT", + "PERCENTILE_DISC", "PERCENT_RANK", "PERIOD", "PERMUTE",