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) {

Reply via email to