This is an automated email from the ASF dual-hosted git repository.
korlov 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 947c4e32e IGNITE-17213 Sql. Refactoring of SQL dialects and supported
functions enumeration (#893)
947c4e32e is described below
commit 947c4e32e41637f260b8301724647b8abecd8314
Author: korlov42 <[email protected]>
AuthorDate: Mon Jun 27 10:07:00 2022 +0300
IGNITE-17213 Sql. Refactoring of SQL dialects and supported functions
enumeration (#893)
---
.../internal/sql/engine/ItSqlOperatorsTest.java | 335 +++++++++++++++++++++
modules/sql-engine/src/main/codegen/config.fmpp | 4 +-
.../internal/sql/engine/exec/exp/RexImpTable.java | 103 +------
.../sql/engine/exec/exp/RexToLixTranslator.java | 16 +
.../internal/sql/engine/externalize/RelJson.java | 27 ++
.../sql/engine/prepare/IgniteConvertletTable.java | 3 +
.../sql/engine/sql/fun/IgniteSqlOperatorTable.java | 274 ++++++++++++++++-
.../ignite/internal/sql/engine/util/Commons.java | 12 +-
.../internal/sql/engine/planner/PlannerTest.java | 2 +-
9 files changed, 648 insertions(+), 128 deletions(-)
diff --git
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItSqlOperatorsTest.java
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItSqlOperatorsTest.java
new file mode 100644
index 000000000..f22e165bb
--- /dev/null
+++
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItSqlOperatorsTest.java
@@ -0,0 +1,335 @@
+/*
+ * 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;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.Period;
+import java.util.List;
+import java.util.Map;
+import org.apache.ignite.internal.sql.engine.sql.fun.IgniteSqlOperatorTable;
+import org.apache.ignite.internal.sql.engine.util.QueryChecker;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Ignite's SQL dialect test.
+ *
+ * <p>This test contains basic checks for standard SQL operators (only syntax
check and check ability to use it).
+ *
+ * @see IgniteSqlOperatorTable
+ */
+public class ItSqlOperatorsTest extends AbstractBasicIntegrationTest {
+ /** {@inheritDoc} */
+ @Override
+ protected int nodes() {
+ return 1;
+ }
+
+ @BeforeAll
+ public static void initTable() {
+ sql("CREATE TABLE t(id INT PRIMARY KEY, val INT)");
+ sql("INSERT INTO t VALUES (1, 1)");
+ }
+
+ @Test
+ public void testSet() {
+ assertQuery("SELECT 1 UNION SELECT 2").returns(1).returns(2).check();
+ assertQuery("SELECT 1 UNION ALL SELECT
1").returns(1).returns(1).check();
+ assertQuery("SELECT 1 EXCEPT SELECT 2").returns(1).check();
+ assertQuery("SELECT 1 EXCEPT ALL SELECT 2").returns(1).check();
+ assertQuery("SELECT 1 INTERSECT SELECT 1").returns(1).check();
+ assertQuery("SELECT 1 INTERSECT ALL SELECT 1").returns(1).check();
+ }
+
+ @Test
+ public void testLogical() {
+ assertExpression("FALSE AND TRUE").returns(false).check();
+ assertExpression("FALSE OR TRUE").returns(true).check();
+ assertExpression("NOT FALSE").returns(true).check();
+ }
+
+ @Test
+ public void testComparison() {
+ assertExpression("2 > 1").returns(true).check();
+ assertExpression("2 >= 1").returns(true).check();
+ assertExpression("2 < 1").returns(false).check();
+ assertExpression("2 <= 1").returns(false).check();
+ assertExpression("2 = 1").returns(false).check();
+ assertExpression("2 <> 1").returns(true).check();
+ assertExpression("2 BETWEEN 1 AND 3").returns(true).check();
+ assertExpression("2 NOT BETWEEN 1 AND 3").returns(false).check();
+ }
+
+ @Test
+ public void testArithmetic() {
+ assertExpression("1 + 2").returns(3).check();
+ assertExpression("2 - 1").returns(1).check();
+ assertExpression("2 * 3").returns(6).check();
+ assertExpression("3 / 2 ").returns(1).check();
+ assertExpression("-(1)").returns(-1).check();
+ assertExpression("+(1)").returns(1).check();
+ assertExpression("3 % 2").returns(1).check();
+ }
+
+ @Test
+ public void testAggregates() {
+ assertExpression("COUNT(*)").returns(1L).check();
+ assertExpression("SUM(val)").returns(1L).check();
+ assertExpression("AVG(val)").returns(1).check();
+ assertExpression("MIN(val)").returns(1).check();
+ assertExpression("MAX(val)").returns(1).check();
+ assertExpression("ANY_VALUE(val)").returns(1).check();
+ assertExpression("COUNT(*) FILTER(WHERE val <>
1)").returns(0L).check();
+ }
+
+ @Test
+ public void testIs() {
+ assertExpression("'a' IS NULL").returns(false).check();
+ assertExpression("'a' IS NOT NULL").returns(true).check();
+ assertExpression("1=1 IS TRUE").returns(true).check();
+ assertExpression("1=1 IS NOT TRUE").returns(false).check();
+ assertExpression("1=1 IS FALSE").returns(false).check();
+ assertExpression("1=1 IS NOT FALSE").returns(true).check();
+ }
+
+ @Test
+ public void testLike() {
+ assertExpression("'a' LIKE 'a%'").returns(true).check();
+ assertExpression("'a' NOT LIKE 'a%'").returns(false).check();
+ assertExpression("'a' SIMILAR TO '(a|A)%'").returns(true).check();
+ assertExpression("'A' NOT SIMILAR TO '(a|A)%'").returns(false).check();
+ }
+
+ @Test
+ public void testNullsOrdering() {
+ assertQuery("SELECT a FROM (SELECT 1 AS a) ORDER BY a NULLS
FIRST").returns(1).check();
+ assertQuery("SELECT a FROM (SELECT 1 AS a) ORDER BY a NULLS
LAST").returns(1).check();
+ assertQuery("SELECT a FROM (SELECT 1 AS a) ORDER BY a DESC NULLS
FIRST").returns(1).check();
+ assertQuery("SELECT a FROM (SELECT 1 AS a) ORDER BY a DESC NULLS
LAST").returns(1).check();
+ assertQuery("SELECT a FROM (SELECT 1 AS a) ORDER BY a ASC NULLS
FIRST").returns(1).check();
+ assertQuery("SELECT a FROM (SELECT 1 AS a) ORDER BY a ASC NULLS
LAST").returns(1).check();
+ }
+
+ @Test
+ public void testExists() {
+ assertExpression("EXISTS (SELECT 1)").returns(true).check();
+ assertExpression("NOT EXISTS (SELECT 1)").returns(false).check();
+ }
+
+ @Test
+ public void testStringFunctions() {
+ assertExpression("UPPER('aA')").returns("AA").check();
+ assertExpression("LOWER('aA')").returns("aa").check();
+ assertExpression("INITCAP('aA')").returns("Aa").check();
+ assertExpression("TO_BASE64('aA')").returns("YUE=").check();
+ assertExpression("FROM_BASE64('YUE=')::VARCHAR").returns("aA").check();
+
assertExpression("MD5('aa')").returns("4124bc0a9335c27f086f24ba207a4912").check();
+
assertExpression("SHA1('aa')").returns("e0c9035898dd52fc65c41454cec9c4d2611bfb37").check();
+ assertExpression("SUBSTRING('aAaA', 2, 2)").returns("Aa").check();
+ assertExpression("LEFT('aA', 1)").returns("a").check();
+ assertExpression("RIGHT('aA', 1)").returns("A").check();
+ assertExpression("REPLACE('aA', 'A', 'a')").returns("aa").check();
+ assertExpression("TRANSLATE('aA', 'A', 'a')").returns("aa").check();
+ assertExpression("CHR(97)").returns("a").check();
+ assertExpression("CHAR_LENGTH('aa')").returns(2).check();
+ assertExpression("CHARACTER_LENGTH('aa')").returns(2).check();
+ assertExpression("'a' || 'a'").returns("aa").check();
+ assertExpression("CONCAT('a', 'a')").returns("aa").check();
+ assertExpression("OVERLAY('aAaA' PLACING 'aA' FROM
2)").returns("aaAA").check();
+ assertExpression("POSITION('A' IN 'aA')").returns(2).check();
+ assertExpression("ASCII('a')").returns(97).check();
+ assertExpression("REPEAT('a', 2)").returns("aa").check();
+ assertExpression("SPACE(2)").returns(" ").check();
+ assertExpression("STRCMP('a', 'b')").returns(1).check();
+ assertExpression("SOUNDEX('a')").returns("A000").check();
+ assertExpression("DIFFERENCE('a', 'A')").returns(4).check();
+ assertExpression("REVERSE('aA')").returns("Aa").check();
+ assertExpression("TRIM('a' FROM 'aA')").returns("A").check();
+ assertExpression("LTRIM(' a ')").returns("a ").check();
+ assertExpression("RTRIM(' a ')").returns(" a").check();
+ }
+
+ @Test
+ public void testMathFunctions() {
+ assertExpression("MOD(3, 2)").returns(1).check();
+ assertExpression("EXP(2)").returns(Math.exp(2)).check();
+ assertExpression("POWER(2, 2)").returns(Math.pow(2, 2)).check();
+ assertExpression("LN(2)").returns(Math.log(2)).check();
+ assertExpression("LOG10(2) ").returns(Math.log10(2)).check();
+ assertExpression("ABS(-1)").returns(Math.abs(-1)).check();
+ assertExpression("RAND()").check();
+ assertExpression("RAND_INTEGER(10)").check();
+ assertExpression("ACOS(1)").returns(Math.acos(1)).check();
+ assertExpression("ASIN(1)").returns(Math.asin(1)).check();
+ assertExpression("ATAN(1)").returns(Math.atan(1)).check();
+ assertExpression("ATAN2(1, 1)").returns(Math.atan2(1, 1)).check();
+ assertExpression("SQRT(4)").returns(Math.sqrt(4)).check();
+ assertExpression("CBRT(8)").returns(Math.cbrt(8)).check();
+ assertExpression("COS(1)").returns(Math.cos(1)).check();
+ assertExpression("COSH(1)").returns(Math.cosh(1)).check();
+ assertExpression("COT(1)").returns(1.0d / Math.tan(1)).check();
+ assertExpression("DEGREES(1)").returns(Math.toDegrees(1)).check();
+ assertExpression("RADIANS(1)").returns(Math.toRadians(1)).check();
+ assertExpression("ROUND(1.7)").returns(BigDecimal.valueOf(2)).check();
+ assertExpression("SIGN(-5)").returns(-1).check();
+ assertExpression("SIN(1)").returns(Math.sin(1)).check();
+ assertExpression("SINH(1)").returns(Math.sinh(1)).check();
+ assertExpression("TAN(1)").returns(Math.tan(1)).check();
+ assertExpression("TANH(1)").returns(Math.tanh(1)).check();
+
assertExpression("TRUNCATE(1.7)").returns(BigDecimal.valueOf(1)).check();
+ assertExpression("PI").returns(Math.PI).check();
+ }
+
+ @Test
+ public void testDateAndTime() {
+ assertExpression("DATE '2021-01-01' + interval (1)
days").returns(LocalDate.parse("2021-01-02")).check();
+ assertExpression("(DATE '2021-03-01' - DATE '2021-01-01')
months").returns(Period.ofMonths(2)).check();
+ assertExpression("EXTRACT(DAY FROM DATE
'2021-01-15')").returns(15L).check();
+ assertExpression("FLOOR(DATE '2021-01-15' TO
MONTH)").returns(LocalDate.parse("2021-01-01")).check();
+ assertExpression("CEIL(DATE '2021-01-15' TO
MONTH)").returns(LocalDate.parse("2021-02-01")).check();
+ assertExpression("TIMESTAMPADD(DAY, 1, TIMESTAMP
'2021-01-01')").returns(LocalDateTime.parse("2021-01-02T00:00:00")).check();
+ assertExpression("TIMESTAMPDIFF(DAY, TIMESTAMP '2021-01-01', TIMESTAMP
'2021-01-02')").returns(1).check();
+ assertExpression("LAST_DAY(DATE
'2021-01-01')").returns(LocalDate.parse("2021-01-31")).check();
+ assertExpression("DAYNAME(DATE
'2021-01-01')").returns("Friday").check();
+ assertExpression("MONTHNAME(DATE
'2021-01-01')").returns("January").check();
+ assertExpression("DAYOFMONTH(DATE '2021-01-01')").returns(1L).check();
+ assertExpression("DAYOFWEEK(DATE '2021-01-01')").returns(6L).check();
+ assertExpression("DAYOFYEAR(DATE '2021-01-01')").returns(1L).check();
+ assertExpression("YEAR(DATE '2021-01-01')").returns(2021L).check();
+ assertExpression("QUARTER(DATE '2021-01-01')").returns(1L).check();
+ assertExpression("MONTH(DATE '2021-01-01')").returns(1L).check();
+ assertExpression("WEEK(DATE '2021-01-04')").returns(1L).check();
+ assertExpression("HOUR(TIMESTAMP '2021-01-01
01:01:01')").returns(1L).check();
+ assertExpression("MINUTE(TIMESTAMP '2021-01-01
01:01:01')").returns(1L).check();
+ assertExpression("SECOND(TIMESTAMP '2021-01-01
01:01:01')").returns(1L).check();
+
assertExpression("TIMESTAMP_SECONDS(1609459200)").returns(LocalDateTime.parse("2021-01-01T00:00:00")).check();
+
assertExpression("TIMESTAMP_MILLIS(1609459200000)").returns(LocalDateTime.parse("2021-01-01T00:00:00")).check();
+
assertExpression("TIMESTAMP_MICROS(1609459200000000)").returns(LocalDateTime.parse("2021-01-01T00:00:00")).check();
+ assertExpression("UNIX_SECONDS(TIMESTAMP '2021-01-01
00:00:00')").returns(1609459200L).check();
+ assertExpression("UNIX_MILLIS(TIMESTAMP '2021-01-01
00:00:00')").returns(1609459200000L).check();
+ assertExpression("UNIX_MICROS(TIMESTAMP '2021-01-01
00:00:00')").returns(1609459200000000L).check();
+ assertExpression("UNIX_DATE(DATE
'2021-01-01')").returns(18628).check();
+
assertExpression("DATE_FROM_UNIX_DATE(18628)").returns(LocalDate.parse("2021-01-01")).check();
+
assertExpression("DATE('2021-01-01')").returns(LocalDate.parse("2021-01-01")).check();
+ }
+
+ @Test
+ public void testPosixRegex() {
+ assertExpression("'aA' ~ '.*aa.*'").returns(false).check();
+ assertExpression("'aA' ~* '.*aa.*'").returns(true).check();
+ assertExpression("'aA' !~ '.*aa.*'").returns(true).check();
+ assertExpression("'aA' !~* '.*aa.*'").returns(false).check();
+ assertExpression("REGEXP_REPLACE('aA', '[Aa]+',
'X')").returns("X").check();
+ }
+
+ @Test
+ public void testCollections() {
+ assertExpression("MAP['a', 1, 'A', 2]").returns(Map.of("a", 1, "A",
2)).check();
+ assertExpression("ARRAY[1, 2, 3]").returns(List.of(1, 2, 3)).check();
+ assertExpression("ARRAY[1, 2, 3][2]").returns(2).check();
+ assertExpression("CARDINALITY(ARRAY[1, 2, 3])").returns(3).check();
+ assertExpression("ARRAY[1, 2, 3] IS EMPTY").returns(false).check();
+ assertExpression("ARRAY[1, 2, 3] IS NOT EMPTY").returns(true).check();
+ }
+
+ @Test
+ @Disabled("https://issues.apache.org/jira/browse/IGNITE-15550")
+ public void testQueryAsCollections() {
+ assertExpression("MAP(SELECT 'a', 1)").returns(Map.of("a", 1)).check();
+ assertExpression("ARRAY(SELECT 1)").returns(List.of(1)).check();
+ }
+
+ @Test
+ public void testOtherFunctions() {
+ assertQuery("SELECT * FROM (VALUES ROW('a', 1))").returns("a",
1).check();
+ assertExpression("CAST('1' AS INT)").returns(1).check();
+ assertExpression("'1'::INT").returns(1).check();
+ assertExpression("COALESCE(null, 'a', 'A')").returns("a").check();
+ assertExpression("NVL(null, 'a')").returns("a").check();
+ assertExpression("NULLIF(1, 2)").returns(1).check();
+ assertExpression("CASE WHEN 1=1 THEN 1 ELSE 2 END").returns(1).check();
+ assertExpression("DECODE(1, 1, 1, 2)").returns(1).check();
+ assertExpression("LEAST('a', 'b')").returns("a").check();
+ assertExpression("GREATEST('a', 'b')").returns("b").check();
+ assertExpression("COMPRESS('')::VARCHAR").returns("").check();
+ assertExpression("OCTET_LENGTH(x'01')").returns(1).check();
+ assertExpression("CAST(INTERVAL 1 SECONDS AS
INT)").returns(1).check(); // Converted to REINTERPRED.
+ }
+
+ @Test
+ public void testXml() {
+ assertExpression("EXTRACTVALUE('<a>b</a>',
'//a')").returns("b").check();
+ assertExpression("XMLTRANSFORM('<a>b</a>',"
+ + "'<?xml version=\"1.0\"?>\n"
+ + "<xsl:stylesheet version=\"1.0\"
xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">"
+ + " <xsl:output method=\"text\"/>"
+ + " <xsl:template match=\"/\">"
+ + " a - <xsl:value-of select=\"/a\"/>"
+ + " </xsl:template>"
+ + "</xsl:stylesheet>')"
+ ).returns(" a - b").check();
+ assertExpression("\"EXTRACT\"('<a><b>c</b></a>',
'/a/b')").returns("<b>c</b>").check();
+ assertExpression("EXISTSNODE('<a><b>c</b></a>',
'/a/b')").returns(1).check();
+ }
+
+ @Test
+ public void testJson() {
+ assertExpression("'{\"a\":1}' FORMAT JSON").check();
+ assertExpression("JSON_VALUE('{\"a\":1}',
'$.a')").returns("1").check();
+ assertExpression("JSON_VALUE('{\"a\":1}' FORMAT JSON,
'$.a')").returns("1").check();
+ assertExpression("JSON_QUERY('{\"a\":{\"b\":1}}',
'$.a')").returns("{\"b\":1}").check();
+ assertExpression("JSON_TYPE('{\"a\":1}')").returns("OBJECT").check();
+ assertExpression("JSON_EXISTS('{\"a\":1}',
'$.a')").returns(true).check();
+ assertExpression("JSON_DEPTH('{\"a\":1}')").returns(2).check();
+ assertExpression("JSON_KEYS('{\"a\":1}')").returns("[\"a\"]").check();
+ assertExpression("JSON_PRETTY('{\"a\":1}')").returns("{\n \"a\" :
1\n}").check();
+ assertExpression("JSON_LENGTH('{\"a\":1}')").returns(1).check();
+ assertExpression("JSON_REMOVE('{\"a\":1, \"b\":2}',
'$.a')").returns("{\"b\":2}").check();
+ assertExpression("JSON_STORAGE_SIZE('1')").returns(1).check();
+ assertExpression("JSON_OBJECT('a': 1)").returns("{\"a\":1}").check();
+ assertExpression("JSON_ARRAY('a',
'b')").returns("[\"a\",\"b\"]").check();
+ assertExpression("'{\"a\":1}' IS JSON").returns(true).check();
+ assertExpression("'{\"a\":1}' IS JSON VALUE").returns(true).check();
+ assertExpression("'{\"a\":1}' IS JSON OBJECT").returns(true).check();
+ assertExpression("'[1, 2]' IS JSON ARRAY").returns(true).check();
+ assertExpression("'1' IS JSON SCALAR").returns(true).check();
+ assertExpression("'{\"a\":1}' IS NOT JSON").returns(false).check();
+ assertExpression("'{\"a\":1}' IS NOT JSON
VALUE").returns(false).check();
+ assertExpression("'{\"a\":1}' IS NOT JSON
OBJECT").returns(false).check();
+ assertExpression("'[1, 2]' IS NOT JSON ARRAY").returns(false).check();
+ assertExpression("'1' IS NOT JSON SCALAR").returns(false).check();
+ }
+
+ @Test
+ public void testCurrentTimeFunctions() {
+ // Don't check returned value, only ability to use these functions.
+ assertExpression("CURRENT_TIME").check();
+ assertExpression("CURRENT_TIMESTAMP").check();
+ assertExpression("CURRENT_DATE").check();
+ assertExpression("LOCALTIME").check();
+ assertExpression("LOCALTIMESTAMP").check();
+ }
+
+ private QueryChecker assertExpression(String qry) {
+ // Select expressions from table to test plan serialization containing
these expressions.
+ return assertQuery("SELECT " + qry + " FROM t");
+ }
+}
diff --git a/modules/sql-engine/src/main/codegen/config.fmpp
b/modules/sql-engine/src/main/codegen/config.fmpp
index 349e84bab..6fa9a9b1a 100644
--- a/modules/sql-engine/src/main/codegen/config.fmpp
+++ b/modules/sql-engine/src/main/codegen/config.fmpp
@@ -170,7 +170,7 @@ data: {
# "CURSOR"
"CYCLE"
"DATA"
-# "DATE"
+ "DATE"
"DAY"
"DEALLOCATE"
"DEC"
@@ -393,6 +393,7 @@ data: {
"PRIVILEGES"
"PROCEDURE"
"PUBLIC"
+ "QUARTER"
# "RANGE"
"RANK"
"READ"
@@ -526,6 +527,7 @@ data: {
"VERSIONING"
# "VERSIONS" # not a keyword in Calcite
"VIEW"
+ "WEEK"
# "WHEN"
"WHENEVER"
# "WHERE"
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 1623ead2a..56e870f4f 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
@@ -32,7 +32,6 @@ import static
org.apache.calcite.linq4j.tree.ExpressionType.Subtract;
import static org.apache.calcite.linq4j.tree.ExpressionType.UnaryPlus;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.CHR;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.COMPRESS;
-import static org.apache.calcite.sql.fun.SqlLibraryOperators.CONCAT2;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.CONCAT_FUNCTION;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.COSH;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.DATE;
@@ -85,26 +84,19 @@ import static
org.apache.calcite.sql.fun.SqlStdOperatorTable.CARDINALITY;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CAST;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CBRT;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CEIL;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CHARACTER_LENGTH;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CHAR_LENGTH;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.COALESCE;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CONCAT;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.COS;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.COT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_CATALOG;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_DATE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_PATH;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_ROLE;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_TIME;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_TIMESTAMP;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_USER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.CURRENT_VALUE;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DATETIME_PLUS;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DEFAULT;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DEGREES;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DIVIDE;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.DIVIDE_INTEGER;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ELEMENT;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.EQUALS;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.EXP;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.EXTRACT;
@@ -112,14 +104,12 @@ import static
org.apache.calcite.sql.fun.SqlStdOperatorTable.FLOOR;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.GREATER_THAN;
import static
org.apache.calcite.sql.fun.SqlStdOperatorTable.GREATER_THAN_OR_EQUAL;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.INITCAP;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_A_SET;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_EMPTY;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_FALSE;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_JSON_ARRAY;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_JSON_OBJECT;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_JSON_SCALAR;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_JSON_VALUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_A_SET;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_EMPTY;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_FALSE;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_JSON_ARRAY;
@@ -147,23 +137,15 @@ import static
org.apache.calcite.sql.fun.SqlStdOperatorTable.LOCALTIMESTAMP;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LOG10;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.LOWER;
import static
org.apache.calcite.sql.fun.SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MEMBER_OF;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MINUS;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MINUS_DATE;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MOD;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTIPLY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_EXCEPT;
-import static
org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTISET_EXCEPT_DISTINCT;
-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.NEXT_VALUE;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NOT;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NOT_EQUALS;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NOT_LIKE;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NOT_SIMILAR_TO;
-import static
org.apache.calcite.sql.fun.SqlStdOperatorTable.NOT_SUBMULTISET_OF;
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.OCTET_LENGTH;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.OR;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.OVERLAY;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.PI;
@@ -177,28 +159,19 @@ import static
org.apache.calcite.sql.fun.SqlStdOperatorTable.REINTERPRET;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.REPLACE;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ROUND;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ROW;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SESSION_USER;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SIGN;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SIMILAR_TO;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SIN;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SLICE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.STRUCT_ACCESS;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUBMULTISET_OF;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SUBSTRING;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.SYSTEM_USER;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TAN;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TRIM;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.TRUNCATE;
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.ignite.internal.sql.engine.sql.fun.IgniteSqlOperatorTable.LENGTH;
import static
org.apache.ignite.internal.sql.engine.sql.fun.IgniteSqlOperatorTable.SYSTEM_RANGE;
import static
org.apache.ignite.internal.sql.engine.sql.fun.IgniteSqlOperatorTable.TYPEOF;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
@@ -209,7 +182,6 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.apache.calcite.adapter.enumerable.EnumUtils;
import org.apache.calcite.adapter.enumerable.NullPolicy;
@@ -291,12 +263,10 @@ public class RexImpTable {
defineMethod(REPLACE, BuiltInMethod.REPLACE.method, NullPolicy.STRICT);
defineMethod(TRANSLATE3, BuiltInMethod.TRANSLATE3.method,
NullPolicy.STRICT);
defineMethod(CHR, "chr", NullPolicy.STRICT);
- defineMethod(CHARACTER_LENGTH, BuiltInMethod.CHAR_LENGTH.method,
NullPolicy.STRICT);
defineMethod(CHAR_LENGTH, BuiltInMethod.CHAR_LENGTH.method,
NullPolicy.STRICT);
- defineMethod(LENGTH, BuiltInMethod.CHAR_LENGTH.method,
NullPolicy.STRICT);
+ defineMethod(OCTET_LENGTH, BuiltInMethod.OCTET_LENGTH.method,
NullPolicy.STRICT);
defineMethod(CONCAT, BuiltInMethod.STRING_CONCAT.method,
NullPolicy.STRICT);
defineMethod(CONCAT_FUNCTION,
BuiltInMethod.MULTI_STRING_CONCAT.method, NullPolicy.STRICT);
- defineMethod(CONCAT2, BuiltInMethod.STRING_CONCAT.method,
NullPolicy.STRICT);
defineMethod(OVERLAY, BuiltInMethod.OVERLAY.method, NullPolicy.STRICT);
defineMethod(POSITION, BuiltInMethod.POSITION.method,
NullPolicy.STRICT);
defineMethod(ASCII, BuiltInMethod.ASCII.method, NullPolicy.STRICT);
@@ -431,34 +401,11 @@ public class RexImpTable {
// Multisets & arrays
defineMethod(CARDINALITY, BuiltInMethod.COLLECTION_SIZE.method,
NullPolicy.STRICT);
- defineMethod(SLICE, BuiltInMethod.SLICE.method, NullPolicy.NONE);
- defineMethod(ELEMENT, BuiltInMethod.ELEMENT.method, NullPolicy.STRICT);
- defineMethod(STRUCT_ACCESS, BuiltInMethod.STRUCT_ACCESS.method,
NullPolicy.ANY);
- defineMethod(MEMBER_OF, BuiltInMethod.MEMBER_OF.method,
NullPolicy.NONE);
final MethodImplementor isEmptyImplementor =
new MethodImplementor(BuiltInMethod.IS_EMPTY.method,
NullPolicy.NONE,
false);
map.put(IS_EMPTY, isEmptyImplementor);
map.put(IS_NOT_EMPTY, NotImplementor.of(isEmptyImplementor));
- final MethodImplementor isSetImplementor =
- new MethodImplementor(BuiltInMethod.IS_A_SET.method,
NullPolicy.NONE,
- false);
- map.put(IS_A_SET, isSetImplementor);
- map.put(IS_NOT_A_SET, NotImplementor.of(isSetImplementor));
- defineMethod(MULTISET_INTERSECT_DISTINCT,
- BuiltInMethod.MULTISET_INTERSECT_DISTINCT.method,
NullPolicy.NONE);
- defineMethod(MULTISET_INTERSECT,
- BuiltInMethod.MULTISET_INTERSECT_ALL.method, NullPolicy.NONE);
- defineMethod(MULTISET_EXCEPT_DISTINCT,
- BuiltInMethod.MULTISET_EXCEPT_DISTINCT.method,
NullPolicy.NONE);
- defineMethod(MULTISET_EXCEPT,
BuiltInMethod.MULTISET_EXCEPT_ALL.method, NullPolicy.NONE);
- defineMethod(MULTISET_UNION_DISTINCT,
- BuiltInMethod.MULTISET_UNION_DISTINCT.method, NullPolicy.NONE);
- defineMethod(MULTISET_UNION, BuiltInMethod.MULTISET_UNION_ALL.method,
NullPolicy.NONE);
- final MethodImplementor subMultisetImplementor =
- new MethodImplementor(BuiltInMethod.SUBMULTISET_OF.method,
NullPolicy.NONE, false);
- map.put(SUBMULTISET_OF, subMultisetImplementor);
- map.put(NOT_SUBMULTISET_OF, NotImplementor.of(subMultisetImplementor));
map.put(COALESCE, new CoalesceImplementor());
map.put(CAST, new CastImplementor());
@@ -473,12 +420,6 @@ public class RexImpTable {
map.put(DEFAULT, new DefaultImplementor());
- // Sequences
- defineMethod(CURRENT_VALUE,
BuiltInMethod.SEQUENCE_CURRENT_VALUE.method,
- NullPolicy.STRICT);
- defineMethod(NEXT_VALUE, BuiltInMethod.SEQUENCE_NEXT_VALUE.method,
- NullPolicy.STRICT);
-
// Compression Operators
defineMethod(COMPRESS, BuiltInMethod.COMPRESS.method, NullPolicy.ARG0);
@@ -535,13 +476,6 @@ public class RexImpTable {
// System functions
final SystemFunctionImplementor systemFunctionImplementor = new
SystemFunctionImplementor();
- map.put(USER, systemFunctionImplementor);
- map.put(CURRENT_USER, systemFunctionImplementor);
- map.put(SESSION_USER, systemFunctionImplementor);
- map.put(SYSTEM_USER, systemFunctionImplementor);
- map.put(CURRENT_PATH, systemFunctionImplementor);
- map.put(CURRENT_ROLE, systemFunctionImplementor);
- map.put(CURRENT_CATALOG, systemFunctionImplementor);
map.put(SYSTEM_RANGE, systemFunctionImplementor);
// Current time functions
@@ -554,25 +488,6 @@ public class RexImpTable {
map.put(TYPEOF, systemFunctionImplementor);
}
- private <T> Supplier<T> constructorSupplier(Class<T> klass) {
- final Constructor<T> constructor;
- try {
- constructor = klass.getDeclaredConstructor();
- } catch (NoSuchMethodException e) {
- throw new IllegalArgumentException(
- klass + " should implement zero arguments constructor");
- }
- return () -> {
- try {
- return constructor.newInstance();
- } catch (InstantiationException | IllegalAccessException
- | InvocationTargetException e) {
- throw new IllegalStateException(
- "Error while creating aggregate implementor " +
constructor, e);
- }
- };
- }
-
private void defineMethod(SqlOperator operator, String functionName,
NullPolicy nullPolicy) {
map.put(operator, new MethodNameImplementor(functionName, nullPolicy,
false));
}
@@ -1697,19 +1612,7 @@ public class RexImpTable {
final RexCall call, final List<Expression> argValueList) {
final SqlOperator op = call.getOperator();
final Expression root = translator.getRoot();
- if (op == CURRENT_USER
- || op == SESSION_USER
- || op == USER) {
- return Expressions.call(BuiltInMethod.USER.method, root);
- } else if (op == SYSTEM_USER) {
- return Expressions.call(BuiltInMethod.SYSTEM_USER.method,
root);
- } else if (op == CURRENT_PATH
- || op == CURRENT_ROLE
- || op == CURRENT_CATALOG) {
- // By default, the CURRENT_ROLE and CURRENT_CATALOG functions
return the
- // empty string because a role or a catalog has to be set
explicitly.
- return Expressions.constant("");
- } else if (op == CURRENT_TIMESTAMP) {
+ if (op == CURRENT_TIMESTAMP) {
return
Expressions.call(BuiltInMethod.CURRENT_TIMESTAMP.method, root);
} else if (op == CURRENT_TIME) {
return Expressions.call(IgniteMethod.CURRENT_TIME.method(),
root);
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexToLixTranslator.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexToLixTranslator.java
index b50e57d30..fb8ec78d9 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexToLixTranslator.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexToLixTranslator.java
@@ -513,6 +513,12 @@ public class RexToLixTranslator implements
RexVisitor<RexToLixTranslator.Result>
BuiltInMethod.BOOLEAN_TO_STRING.method,
operand));
break;
+ case BINARY:
+ case VARBINARY:
+ convert = RexImpTable.optimize2(
+ operand,
+
Expressions.call(IgniteMethod.BYTESTRING_TO_STRING.method(), operand));
+ break;
default:
// No-Op.
}
@@ -554,6 +560,16 @@ public class RexToLixTranslator implements
RexVisitor<RexToLixTranslator.Result>
// No-Op.
}
break;
+ case BINARY:
+ case VARBINARY:
+ switch (sourceType.getSqlTypeName().getFamily()) {
+ case CHARACTER:
+ convert =
Expressions.call(IgniteMethod.STRING_TO_BYTESTRING.method(), operand);
+ break;
+ default:
+ // No-Op.
+ }
+ break;
default:
// No-Op.
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/externalize/RelJson.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/externalize/RelJson.java
index 6111ad311..8fcfccba3 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/externalize/RelJson.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/externalize/RelJson.java
@@ -38,6 +38,7 @@ import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.calcite.avatica.AvaticaUtils;
+import org.apache.calcite.avatica.util.ByteString;
import org.apache.calcite.avatica.util.TimeUnit;
import org.apache.calcite.avatica.util.TimeUnitRange;
import org.apache.calcite.linq4j.tree.BlockBuilder;
@@ -95,6 +96,7 @@ import org.apache.calcite.sql.SqlSyntax;
import org.apache.calcite.sql.SqlWindow;
import org.apache.calcite.sql.fun.SqlTrimFunction;
import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.type.SqlTypeFamily;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.sql.validate.SqlNameMatchers;
import org.apache.calcite.util.ImmutableBitSet;
@@ -294,12 +296,18 @@ class RelJson {
return toJson((RelDataType) value);
} else if (value instanceof RelDataTypeField) {
return toJson((RelDataTypeField) value);
+ } else if (value instanceof ByteString) {
+ return toJson((ByteString) value);
} else {
throw new UnsupportedOperationException("type not serializable: "
+ value + " (type " + value.getClass().getCanonicalName()
+ ")");
}
}
+ private Object toJson(ByteString val) {
+ return val.toString();
+ }
+
private Object toJson(Enum<?> enum0) {
String key = enum0.getDeclaringClass().getSimpleName() + "#" +
enum0.name();
@@ -345,6 +353,12 @@ class RelJson {
map.put("type", toJson(node.getSqlTypeName()));
map.put("elementType", toJson(node.getComponentType()));
return map;
+ } else if (node.getSqlTypeName() == SqlTypeName.MAP) {
+ Map<String, Object> map = map();
+ map.put("type", toJson(node.getSqlTypeName()));
+ map.put("keyType", toJson(node.getKeyType()));
+ map.put("valueType", toJson(node.getValueType()));
+ return map;
} else {
Map<String, Object> map = map();
map.put("type", toJson(node.getSqlTypeName()));
@@ -630,6 +644,11 @@ class RelJson {
new SqlIntervalQualifier(startUnit, endUnit,
SqlParserPos.ZERO));
} else if (sqlTypeName == SqlTypeName.ARRAY) {
type = typeFactory.createArrayType(toType(typeFactory,
map.get("elementType")), -1);
+ } else if (sqlTypeName == SqlTypeName.MAP) {
+ type = typeFactory.createMapType(
+ toType(typeFactory, map.get("keyType")),
+ toType(typeFactory, map.get("valueType"))
+ );
} else if (precision == null) {
type = typeFactory.createSqlType(sqlTypeName);
} else if (scale == null) {
@@ -754,6 +773,8 @@ class RelJson {
if (type.getSqlTypeName() == SqlTypeName.SYMBOL) {
literal = toEnum(literal);
+ } else if (type.getSqlTypeName().getFamily() ==
SqlTypeFamily.BINARY) {
+ literal = toByteString(literal);
}
return rexBuilder.makeLiteral(literal, type, true);
@@ -831,6 +852,12 @@ class RelJson {
return (T) ENUM_BY_NAME.get(name);
}
+ private ByteString toByteString(Object o) {
+ assert o instanceof String;
+
+ return ByteString.of((String) o, 16);
+ }
+
private RelFieldCollation toFieldCollation(Map<String, Object> map) {
Integer field = (Integer) map.get("field");
Direction direction = toEnum(map.get("direction"));
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteConvertletTable.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteConvertletTable.java
index 26b30dad2..0f7805271 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteConvertletTable.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteConvertletTable.java
@@ -37,6 +37,7 @@ import org.apache.calcite.sql2rel.SqlRexContext;
import org.apache.calcite.sql2rel.SqlRexConvertlet;
import org.apache.calcite.sql2rel.SqlRexConvertletTable;
import org.apache.calcite.sql2rel.StandardConvertletTable;
+import org.apache.ignite.internal.sql.engine.sql.fun.IgniteSqlOperatorTable;
/**
* Implementation of {@link SqlRexConvertletTable}.
@@ -47,6 +48,8 @@ public class IgniteConvertletTable extends
ReflectiveConvertletTable {
private IgniteConvertletTable() {
// Replace Calcite's convertlet with our own.
registerOp(SqlStdOperatorTable.TIMESTAMP_DIFF, new
TimestampDiffConvertlet());
+
+ addAlias(IgniteSqlOperatorTable.LENGTH,
SqlStdOperatorTable.CHAR_LENGTH);
}
/** {@inheritDoc} */
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/fun/IgniteSqlOperatorTable.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/fun/IgniteSqlOperatorTable.java
index 51d0f174f..58aff1d72 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/fun/IgniteSqlOperatorTable.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/fun/IgniteSqlOperatorTable.java
@@ -20,6 +20,8 @@ package org.apache.ignite.internal.sql.engine.sql.fun;
import org.apache.calcite.sql.SqlFunction;
import org.apache.calcite.sql.SqlFunctionCategory;
import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.fun.SqlLibraryOperators;
+import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.type.OperandTypes;
import org.apache.calcite.sql.type.ReturnTypes;
import org.apache.calcite.sql.util.ReflectiveSqlOperatorTable;
@@ -28,11 +30,6 @@ import
org.apache.calcite.sql.util.ReflectiveSqlOperatorTable;
* Operator table that contains only Ignite-specific functions and operators.
*/
public class IgniteSqlOperatorTable extends ReflectiveSqlOperatorTable {
- /**
- * The table of contains Ignite-specific operators.
- */
- private static IgniteSqlOperatorTable instance;
-
public static final SqlFunction LENGTH =
new SqlFunction(
"LENGTH",
@@ -53,17 +50,264 @@ public class IgniteSqlOperatorTable extends
ReflectiveSqlOperatorTable {
OperandTypes.ANY,
SqlFunctionCategory.SYSTEM);
+ /** Singleton instance. */
+ public static final IgniteSqlOperatorTable INSTANCE = new
IgniteSqlOperatorTable();
+
/**
- * Returns the Ignite operator table, creating it if necessary.
+ * Default constructor.
*/
- public static synchronized IgniteSqlOperatorTable instance() {
- if (instance == null) {
- // Creates and initializes the standard operator table.
- // Uses two-phase construction, because we can't initialize the
- // table until the constructor of the sub-class has completed.
- instance = new IgniteSqlOperatorTable();
- instance.init();
- }
- return instance;
+ public IgniteSqlOperatorTable() {
+ // Set operators.
+ register(SqlStdOperatorTable.UNION);
+ register(SqlStdOperatorTable.UNION_ALL);
+ register(SqlStdOperatorTable.EXCEPT);
+ register(SqlStdOperatorTable.EXCEPT_ALL);
+ register(SqlStdOperatorTable.INTERSECT);
+ register(SqlStdOperatorTable.INTERSECT_ALL);
+
+ // Logical.
+ register(SqlStdOperatorTable.AND);
+ register(SqlStdOperatorTable.OR);
+ register(SqlStdOperatorTable.NOT);
+
+ // Comparisons.
+ register(SqlStdOperatorTable.LESS_THAN);
+ register(SqlStdOperatorTable.LESS_THAN_OR_EQUAL);
+ register(SqlStdOperatorTable.GREATER_THAN);
+ register(SqlStdOperatorTable.GREATER_THAN_OR_EQUAL);
+ register(SqlStdOperatorTable.EQUALS);
+ register(SqlStdOperatorTable.NOT_EQUALS);
+ register(SqlStdOperatorTable.BETWEEN);
+ register(SqlStdOperatorTable.NOT_BETWEEN);
+
+ // Arithmetic.
+ register(SqlStdOperatorTable.PLUS);
+ register(SqlStdOperatorTable.MINUS);
+ register(SqlStdOperatorTable.MULTIPLY);
+ register(SqlStdOperatorTable.DIVIDE);
+ register(SqlStdOperatorTable.DIVIDE_INTEGER); // Used internally.
+ register(SqlStdOperatorTable.PERCENT_REMAINDER);
+ register(SqlStdOperatorTable.UNARY_MINUS);
+ register(SqlStdOperatorTable.UNARY_PLUS);
+
+ // Aggregates.
+ register(SqlStdOperatorTable.COUNT);
+ register(SqlStdOperatorTable.SUM);
+ register(SqlStdOperatorTable.AVG);
+ register(SqlStdOperatorTable.MIN);
+ register(SqlStdOperatorTable.MAX);
+ register(SqlStdOperatorTable.ANY_VALUE);
+ register(SqlStdOperatorTable.SINGLE_VALUE);
+ register(SqlStdOperatorTable.FILTER);
+
+ // IS ... operator.
+ register(SqlStdOperatorTable.IS_NULL);
+ register(SqlStdOperatorTable.IS_NOT_NULL);
+ register(SqlStdOperatorTable.IS_TRUE);
+ register(SqlStdOperatorTable.IS_NOT_TRUE);
+ register(SqlStdOperatorTable.IS_FALSE);
+ register(SqlStdOperatorTable.IS_NOT_FALSE);
+ register(SqlStdOperatorTable.IS_DISTINCT_FROM);
+ register(SqlStdOperatorTable.IS_NOT_DISTINCT_FROM);
+
+ // LIKE and SIMILAR.
+ register(SqlStdOperatorTable.LIKE);
+ register(SqlStdOperatorTable.NOT_LIKE);
+ register(SqlStdOperatorTable.SIMILAR_TO);
+ register(SqlStdOperatorTable.NOT_SIMILAR_TO);
+
+ // NULLS ordering.
+ register(SqlStdOperatorTable.NULLS_FIRST);
+ register(SqlStdOperatorTable.NULLS_LAST);
+ register(SqlStdOperatorTable.DESC);
+
+ // Exists.
+ register(SqlStdOperatorTable.EXISTS);
+
+ // String functions.
+ register(SqlStdOperatorTable.UPPER);
+ register(SqlStdOperatorTable.LOWER);
+ register(SqlStdOperatorTable.INITCAP);
+ register(SqlLibraryOperators.TO_BASE64);
+ register(SqlLibraryOperators.FROM_BASE64);
+ register(SqlLibraryOperators.MD5);
+ register(SqlLibraryOperators.SHA1);
+ register(SqlStdOperatorTable.SUBSTRING);
+ register(SqlLibraryOperators.LEFT);
+ register(SqlLibraryOperators.RIGHT);
+ register(SqlStdOperatorTable.REPLACE);
+ register(SqlLibraryOperators.TRANSLATE3);
+ register(SqlLibraryOperators.CHR);
+ register(SqlStdOperatorTable.CHAR_LENGTH);
+ register(SqlStdOperatorTable.CHARACTER_LENGTH);
+ register(SqlStdOperatorTable.CONCAT);
+ register(SqlLibraryOperators.CONCAT_FUNCTION);
+ register(SqlStdOperatorTable.OVERLAY);
+ register(SqlStdOperatorTable.POSITION);
+ register(SqlStdOperatorTable.ASCII);
+ register(SqlLibraryOperators.REPEAT);
+ register(SqlLibraryOperators.SPACE);
+ register(SqlLibraryOperators.STRCMP);
+ register(SqlLibraryOperators.SOUNDEX);
+ register(SqlLibraryOperators.DIFFERENCE);
+ register(SqlLibraryOperators.REVERSE);
+ register(SqlStdOperatorTable.TRIM);
+ register(SqlLibraryOperators.LTRIM);
+ register(SqlLibraryOperators.RTRIM);
+
+ // Math functions.
+ register(SqlStdOperatorTable.MOD); // Arithmetic remainder.
+ register(SqlStdOperatorTable.EXP); // Euler's number e raised to the
power of a value.
+ register(SqlStdOperatorTable.POWER);
+ register(SqlStdOperatorTable.LN); // Natural logarithm.
+ register(SqlStdOperatorTable.LOG10); // The base 10 logarithm.
+ register(SqlStdOperatorTable.ABS); // Absolute value.
+ register(SqlStdOperatorTable.RAND); // Random.
+ register(SqlStdOperatorTable.RAND_INTEGER); // Integer random.
+ register(SqlStdOperatorTable.ACOS); // Arc cosine.
+ register(SqlStdOperatorTable.ASIN); // Arc sine.
+ register(SqlStdOperatorTable.ATAN); // Arc tangent.
+ register(SqlStdOperatorTable.ATAN2); // Angle from coordinates.
+ register(SqlStdOperatorTable.SQRT); // Square root.
+ register(SqlStdOperatorTable.CBRT); // Cube root.
+ register(SqlStdOperatorTable.COS); // Cosine
+ register(SqlLibraryOperators.COSH); // Hyperbolic cosine.
+ register(SqlStdOperatorTable.COT); // Cotangent.
+ register(SqlStdOperatorTable.DEGREES); // Radians to degrees.
+ register(SqlStdOperatorTable.RADIANS); // Degrees to radians.
+ register(SqlStdOperatorTable.ROUND);
+ register(SqlStdOperatorTable.SIGN);
+ register(SqlStdOperatorTable.SIN); // Sine.
+ register(SqlLibraryOperators.SINH); // Hyperbolic sine.
+ register(SqlStdOperatorTable.TAN); // Tangent.
+ register(SqlLibraryOperators.TANH); // Hyperbolic tangent.
+ register(SqlStdOperatorTable.TRUNCATE);
+ register(SqlStdOperatorTable.PI);
+
+ // Date and time.
+ register(SqlStdOperatorTable.DATETIME_PLUS);
+ register(SqlStdOperatorTable.MINUS_DATE);
+ register(SqlStdOperatorTable.EXTRACT);
+ register(SqlStdOperatorTable.FLOOR);
+ register(SqlStdOperatorTable.CEIL);
+ register(SqlStdOperatorTable.TIMESTAMP_ADD);
+ register(SqlStdOperatorTable.TIMESTAMP_DIFF);
+ register(SqlStdOperatorTable.LAST_DAY);
+ register(SqlLibraryOperators.DAYNAME);
+ register(SqlLibraryOperators.MONTHNAME);
+ register(SqlStdOperatorTable.DAYOFMONTH);
+ register(SqlStdOperatorTable.DAYOFWEEK);
+ register(SqlStdOperatorTable.DAYOFYEAR);
+ register(SqlStdOperatorTable.YEAR);
+ register(SqlStdOperatorTable.QUARTER);
+ register(SqlStdOperatorTable.MONTH);
+ register(SqlStdOperatorTable.WEEK);
+ register(SqlStdOperatorTable.HOUR);
+ register(SqlStdOperatorTable.MINUTE);
+ register(SqlStdOperatorTable.SECOND);
+ register(SqlLibraryOperators.TIMESTAMP_SECONDS); // Seconds since
1970-01-01 to timestamp.
+ register(SqlLibraryOperators.TIMESTAMP_MILLIS); // Milliseconds since
1970-01-01 to timestamp.
+ register(SqlLibraryOperators.TIMESTAMP_MICROS); // Microseconds since
1970-01-01 to timestamp.
+ register(SqlLibraryOperators.UNIX_SECONDS); // Timestamp to seconds
since 1970-01-01.
+ register(SqlLibraryOperators.UNIX_MILLIS); // Timestamp to
milliseconds since 1970-01-01.
+ register(SqlLibraryOperators.UNIX_MICROS); // Timestamp to
microseconds since 1970-01-01.
+ register(SqlLibraryOperators.UNIX_DATE); // Date to days since
1970-01-01.
+ register(SqlLibraryOperators.DATE_FROM_UNIX_DATE); // Days since
1970-01-01 to date.
+ register(SqlLibraryOperators.DATE); // String to date.
+
+ // POSIX REGEX.
+ register(SqlStdOperatorTable.POSIX_REGEX_CASE_INSENSITIVE);
+ register(SqlStdOperatorTable.POSIX_REGEX_CASE_SENSITIVE);
+ register(SqlStdOperatorTable.NEGATED_POSIX_REGEX_CASE_INSENSITIVE);
+ register(SqlStdOperatorTable.NEGATED_POSIX_REGEX_CASE_SENSITIVE);
+ register(SqlLibraryOperators.REGEXP_REPLACE);
+
+ // Collections.
+ register(SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR);
+ register(SqlStdOperatorTable.ARRAY_VALUE_CONSTRUCTOR);
+ register(SqlStdOperatorTable.ITEM);
+ register(SqlStdOperatorTable.CARDINALITY);
+ register(SqlStdOperatorTable.IS_EMPTY);
+ register(SqlStdOperatorTable.IS_NOT_EMPTY);
+
+ // TODO https://issues.apache.org/jira/browse/IGNITE-15550
+ //register(SqlStdOperatorTable.MAP_QUERY);
+ //register(SqlStdOperatorTable.ARRAY_QUERY);
+
+ // Multiset.
+ // TODO https://issues.apache.org/jira/browse/IGNITE-15551
+ //register(SqlStdOperatorTable.MULTISET_VALUE);
+ //register(SqlStdOperatorTable.MULTISET_QUERY);
+ //register(SqlStdOperatorTable.SLICE);
+ //register(SqlStdOperatorTable.ELEMENT);
+ //register(SqlStdOperatorTable.STRUCT_ACCESS);
+ //register(SqlStdOperatorTable.MEMBER_OF);
+ //register(SqlStdOperatorTable.IS_A_SET);
+ //register(SqlStdOperatorTable.IS_NOT_A_SET);
+ //register(SqlStdOperatorTable.MULTISET_INTERSECT_DISTINCT);
+ //register(SqlStdOperatorTable.MULTISET_INTERSECT);
+ //register(SqlStdOperatorTable.MULTISET_EXCEPT_DISTINCT);
+ //register(SqlStdOperatorTable.MULTISET_EXCEPT);
+ //register(SqlStdOperatorTable.MULTISET_UNION_DISTINCT);
+ //register(SqlStdOperatorTable.MULTISET_UNION);
+ //register(SqlStdOperatorTable.SUBMULTISET_OF);
+ //register(SqlStdOperatorTable.NOT_SUBMULTISET_OF);
+
+ // Other functions and operators.
+ register(SqlStdOperatorTable.ROW);
+ register(SqlStdOperatorTable.CAST);
+ register(SqlLibraryOperators.INFIX_CAST);
+ register(SqlStdOperatorTable.COALESCE);
+ register(SqlLibraryOperators.NVL);
+ register(SqlStdOperatorTable.NULLIF);
+ register(SqlStdOperatorTable.CASE);
+ register(SqlLibraryOperators.DECODE);
+ register(SqlLibraryOperators.LEAST);
+ register(SqlLibraryOperators.GREATEST);
+ register(SqlLibraryOperators.COMPRESS);
+ register(SqlStdOperatorTable.OCTET_LENGTH);
+ register(SqlStdOperatorTable.DEFAULT);
+ register(SqlStdOperatorTable.REINTERPRET);
+
+ // XML Operators.
+ register(SqlLibraryOperators.EXTRACT_VALUE);
+ register(SqlLibraryOperators.XML_TRANSFORM);
+ register(SqlLibraryOperators.EXTRACT_XML);
+ register(SqlLibraryOperators.EXISTS_NODE);
+
+ // JSON Operators
+ register(SqlStdOperatorTable.JSON_VALUE_EXPRESSION);
+ register(SqlStdOperatorTable.JSON_VALUE);
+ register(SqlStdOperatorTable.JSON_QUERY);
+ register(SqlLibraryOperators.JSON_TYPE);
+ register(SqlStdOperatorTable.JSON_EXISTS);
+ register(SqlLibraryOperators.JSON_DEPTH);
+ register(SqlLibraryOperators.JSON_KEYS);
+ register(SqlLibraryOperators.JSON_PRETTY);
+ register(SqlLibraryOperators.JSON_LENGTH);
+ register(SqlLibraryOperators.JSON_REMOVE);
+ register(SqlLibraryOperators.JSON_STORAGE_SIZE);
+ register(SqlStdOperatorTable.JSON_OBJECT);
+ register(SqlStdOperatorTable.JSON_ARRAY);
+ register(SqlStdOperatorTable.IS_JSON_VALUE);
+ register(SqlStdOperatorTable.IS_JSON_OBJECT);
+ register(SqlStdOperatorTable.IS_JSON_ARRAY);
+ register(SqlStdOperatorTable.IS_JSON_SCALAR);
+ register(SqlStdOperatorTable.IS_NOT_JSON_VALUE);
+ register(SqlStdOperatorTable.IS_NOT_JSON_OBJECT);
+ register(SqlStdOperatorTable.IS_NOT_JSON_ARRAY);
+ register(SqlStdOperatorTable.IS_NOT_JSON_SCALAR);
+
+ // Current time functions.
+ register(SqlStdOperatorTable.CURRENT_TIME);
+ register(SqlStdOperatorTable.CURRENT_TIMESTAMP);
+ register(SqlStdOperatorTable.CURRENT_DATE);
+ register(SqlStdOperatorTable.LOCALTIME);
+ register(SqlStdOperatorTable.LOCALTIMESTAMP);
+
+ // Ignite specific operators
+ register(LENGTH);
+ register(SYSTEM_RANGE);
+ register(TYPEOF);
}
}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/Commons.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/Commons.java
index c968add06..dfd05afff 100644
---
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/Commons.java
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/Commons.java
@@ -63,11 +63,8 @@ import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Aggregate;
import org.apache.calcite.rel.hint.HintStrategyTable;
import org.apache.calcite.sql.SqlNodeList;
-import org.apache.calcite.sql.fun.SqlLibrary;
-import org.apache.calcite.sql.fun.SqlLibraryOperatorTableFactory;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.calcite.sql.parser.SqlParser;
-import org.apache.calcite.sql.util.SqlOperatorTables;
import org.apache.calcite.sql.validate.SqlValidator;
import org.apache.calcite.sql2rel.SqlToRelConverter;
import org.apache.calcite.tools.FrameworkConfig;
@@ -155,14 +152,7 @@ public final class Commons {
.withSqlConformance(IgniteSqlConformance.INSTANCE)
.withTypeCoercionFactory(IgniteTypeCoercion::new))
// Dialects support.
- .operatorTable(SqlOperatorTables.chain(
- SqlLibraryOperatorTableFactory.INSTANCE
- .getOperatorTable(
- SqlLibrary.STANDARD,
- SqlLibrary.POSTGRESQL,
- SqlLibrary.ORACLE,
- SqlLibrary.MYSQL),
- IgniteSqlOperatorTable.instance()))
+ .operatorTable(IgniteSqlOperatorTable.INSTANCE)
// Context provides a way to store data within the planner session
that can be accessed in planner rules.
.context(Contexts.empty())
// Custom cost factory to use during optimization
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/PlannerTest.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/PlannerTest.java
index 8edc0629d..722c40178 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/PlannerTest.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/PlannerTest.java
@@ -813,7 +813,7 @@ public class PlannerTest extends AbstractPlannerTest {
String[] queries = {
"select REVERSE(val) from TEST", // MYSQL
- "select TO_DATE(val, 'yyyymmdd') from TEST" // ORACLE
+ "select DECODE(id, 0, val, '') from TEST" // ORACLE
};
for (String sql : queries) {