You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by al...@apache.org on 2022/09/22 08:52:47 UTC

[ignite] branch master updated: IGNITE-17722 Upgrade Apache Calcite dependency to 1.32.0 - Fixes #10257.

This is an automated email from the ASF dual-hosted git repository.

alexpl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new c5bb2c99d29 IGNITE-17722 Upgrade Apache Calcite dependency to 1.32.0 - Fixes #10257.
c5bb2c99d29 is described below

commit c5bb2c99d29299b7bc4314763f34a90c53c46c7b
Author: Aleksey Plekhanov <pl...@gmail.com>
AuthorDate: Thu Sep 22 11:48:26 2022 +0300

    IGNITE-17722 Upgrade Apache Calcite dependency to 1.32.0 - Fixes #10257.
    
    Signed-off-by: Aleksey Plekhanov <pl...@gmail.com>
---
 modules/calcite/pom.xml                            |    11 +-
 .../query/calcite/exec/exp/RexImpTable.java        |     2 +-
 .../query/calcite/exec/exp/RexToLixTranslator.java |     7 +-
 .../calcite/sql/generated/IgniteSqlParserImpl.java | 16227 ++++++++++---------
 .../generated/IgniteSqlParserImplTokenManager.java |    11 +-
 .../query/calcite/type/IgniteTypeFactory.java      |    15 +-
 .../query/calcite/planner/PlannerTest.java         |     2 +-
 .../calcite/src/test/sql/sqlite/join/join1.test    |     5 -
 .../sqlite/join/{join1.test => join1.test_ignore}  |     1 +
 9 files changed, 8556 insertions(+), 7725 deletions(-)

diff --git a/modules/calcite/pom.xml b/modules/calcite/pom.xml
index 9b7e02018c9..6721982ed6f 100644
--- a/modules/calcite/pom.xml
+++ b/modules/calcite/pom.xml
@@ -35,10 +35,9 @@
 
     <!-- Module specific package versions -->
     <properties>
-        <avatica.version>1.20.0</avatica.version>
-        <calcite.version>1.30.0</calcite.version>
+        <avatica.version>1.22.0</avatica.version>
+        <calcite.version>1.32.0</calcite.version>
         <checker.version>3.10.0</checker.version>
-        <esri.geometry.version>2.2.0</esri.geometry.version>
         <immutables.version>2.8.2</immutables.version>
         <janino.version>3.1.6</janino.version>
         <javacc-maven-plugin>2.4</javacc-maven-plugin>
@@ -141,12 +140,6 @@
             <version>${javassist.version}</version>
         </dependency>
 
-        <dependency>
-            <groupId>com.esri.geometry</groupId>
-            <artifactId>esri-geometry-api</artifactId>
-            <version>${esri.geometry.version}</version>
-        </dependency>
-
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexImpTable.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexImpTable.java
index 437fcdc3601..ba043f871c5 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexImpTable.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexImpTable.java
@@ -274,7 +274,7 @@ public class RexImpTable {
         defineMethod(RIGHT, BuiltInMethod.RIGHT.method, NullPolicy.ANY);
         defineMethod(REPLACE, BuiltInMethod.REPLACE.method, NullPolicy.STRICT);
         defineMethod(TRANSLATE3, BuiltInMethod.TRANSLATE3.method, NullPolicy.STRICT);
-        defineMethod(CHR, "chr", NullPolicy.STRICT);
+        defineMethod(CHR, BuiltInMethod.CHAR_FROM_UTF8.method, NullPolicy.STRICT);
         defineMethod(CHAR_LENGTH, BuiltInMethod.CHAR_LENGTH.method, NullPolicy.STRICT);
         defineMethod(OCTET_LENGTH, BuiltInMethod.OCTET_LENGTH.method, NullPolicy.STRICT);
         defineMethod(CONCAT, BuiltInMethod.STRING_CONCAT.method, NullPolicy.STRICT);
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexToLixTranslator.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexToLixTranslator.java
index 23ae2d2486b..aeef8e8a4bb 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexToLixTranslator.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/RexToLixTranslator.java
@@ -58,8 +58,6 @@ import org.apache.calcite.rex.RexSubQuery;
 import org.apache.calcite.rex.RexTableInputRef;
 import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.rex.RexVisitor;
-import org.apache.calcite.runtime.GeoFunctions;
-import org.apache.calcite.runtime.Geometries;
 import org.apache.calcite.sql.SqlIntervalQualifier;
 import org.apache.calcite.sql.SqlOperator;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
@@ -742,10 +740,7 @@ public class RexToLixTranslator implements RexVisitor<RexToLixTranslator.Result>
                         literal.getValueAs(byte[].class),
                         byte[].class));
             case GEOMETRY:
-                final Geometries.Geom geom = literal.getValueAs(Geometries.Geom.class);
-                final String wkt = GeoFunctions.ST_AsWKT(geom);
-                return Expressions.call(null, BuiltInMethod.ST_GEOM_FROM_TEXT.method,
-                    Expressions.constant(wkt));
+                throw new IllegalStateException("Unsupported data type: " + literal.getType());
             case SYMBOL:
                 value2 = literal.getValueAs(Enum.class);
                 javaClass = value2.getClass();
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/sql/generated/IgniteSqlParserImpl.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/sql/generated/IgniteSqlParserImpl.java
index 6838c107663..c02c67db777 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/sql/generated/IgniteSqlParserImpl.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/sql/generated/IgniteSqlParserImpl.java
@@ -13,7 +13,6 @@ import org.apache.ignite.internal.processors.query.calcite.sql.*;
 import org.apache.ignite.internal.processors.query.calcite.sql.stat.*;
 
 import org.apache.calcite.avatica.util.Casing;
-import org.apache.calcite.avatica.util.DateTimeUtils;
 import org.apache.calcite.avatica.util.TimeUnit;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.runtime.CalciteContextException;
@@ -27,7 +26,6 @@ import org.apache.calcite.sql.SqlCharStringLiteral;
 import org.apache.calcite.sql.SqlCollation;
 import org.apache.calcite.sql.SqlCollectionTypeNameSpec;
 import org.apache.calcite.sql.SqlDataTypeSpec;
-import org.apache.calcite.sql.SqlDateLiteral;
 import org.apache.calcite.sql.SqlDelete;
 import org.apache.calcite.sql.SqlDescribeSchema;
 import org.apache.calcite.sql.SqlDescribeTable;
@@ -35,13 +33,11 @@ import org.apache.calcite.sql.SqlDynamicParam;
 import org.apache.calcite.sql.SqlExplain;
 import org.apache.calcite.sql.SqlExplainFormat;
 import org.apache.calcite.sql.SqlExplainLevel;
-import org.apache.calcite.sql.SqlFunction;
 import org.apache.calcite.sql.SqlFunctionCategory;
 import org.apache.calcite.sql.SqlHint;
 import org.apache.calcite.sql.SqlIdentifier;
 import org.apache.calcite.sql.SqlInsert;
 import org.apache.calcite.sql.SqlInsertKeyword;
-import org.apache.calcite.sql.SqlIntervalLiteral;
 import org.apache.calcite.sql.SqlIntervalQualifier;
 import org.apache.calcite.sql.SqlJdbcDataTypeName;
 import org.apache.calcite.sql.SqlJdbcFunctionCall;
@@ -73,8 +69,6 @@ import org.apache.calcite.sql.SqlSelectKeyword;
 import org.apache.calcite.sql.SqlSetOption;
 import org.apache.calcite.sql.SqlSnapshot;
 import org.apache.calcite.sql.SqlTableRef;
-import org.apache.calcite.sql.SqlTimeLiteral;
-import org.apache.calcite.sql.SqlTimestampLiteral;
 import org.apache.calcite.sql.SqlTypeNameSpec;
 import org.apache.calcite.sql.SqlUnnestOperator;
 import org.apache.calcite.sql.SqlUnpivot;
@@ -99,22 +93,23 @@ import org.apache.calcite.sql.parser.SqlParserUtil;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.sql.validate.SqlConformance;
 import org.apache.calcite.util.Glossary;
-import org.apache.calcite.util.NlsString;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.SourceStringReader;
 import org.apache.calcite.util.Util;
 import org.apache.calcite.util.trace.CalciteTrace;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import org.slf4j.Logger;
 
 import java.io.Reader;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Calendar;
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 
 import static org.apache.calcite.util.Static.RESOURCE;
 
@@ -132,12 +127,19 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     private static final char DOUBLE_QUOTE = 0x22;
     private static final String DQ = DOUBLE_QUOTE + "";
     private static final String DQDQ = DQ + DQ;
+    private static final SqlLiteral LITERAL_ZERO =
+        SqlLiteral.createExactNumeric("0", SqlParserPos.ZERO);
+    private static final SqlLiteral LITERAL_ONE =
+        SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO);
+    private static final SqlLiteral LITERAL_MINUS_ONE =
+        SqlLiteral.createExactNumeric("-1", SqlParserPos.ZERO);
 
     private static Metadata metadata;
 
     private Casing unquotedCasing;
     private Casing quotedCasing;
     private int identifierMaxLength;
+    private ImmutableMap<String, TimeUnit> timeUnitCodes;
     private SqlConformance conformance;
 
     /**
@@ -199,6 +201,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         this.identifierMaxLength = identifierMaxLength;
     }
 
+    public void setTimeUnitCodes(Map<String, TimeUnit> timeUnitCodes) {
+        this.timeUnitCodes = ImmutableMap.copyOf(timeUnitCodes);
+    }
+
     public void setConformance(SqlConformance conformance) {
         this.conformance = conformance;
     }
@@ -324,6 +330,14 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     }
   }
 
+  SqlNode checkNotJoin(SqlNode e) throws ParseException {
+    if (e instanceof SqlJoin) {
+        throw SqlUtil.newContextException(e.getParserPosition(),
+            RESOURCE.illegalJoinExpression());
+    }
+    return e;
+  }
+
   SqlParseException convertException(Throwable ex) throws ParseException {
     if (ex instanceof SqlParseException) {
         return (SqlParseException) ex;
@@ -365,7 +379,6 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                 token.endColumn);
         }
     } else if (ex instanceof TokenMgrError) {
-        TokenMgrError tme = (TokenMgrError) ex;
         expectedTokenSequences = null;
         tokenImage = null;
         // Example:
@@ -417,7 +430,6 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     // would yield
     //       {}
     //       {D}
-    boolean id = false;
     final List<int[]> prefixList = new ArrayList<int[]>();
     for (int i = 0; i < ex.expectedTokenSequences.length; ++i) {
         int[] seq = ex.expectedTokenSequences[i];
@@ -482,6 +494,41 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 /*****************************************
  * Syntactical Descriptions              *
  *****************************************/
+  final public SqlNode ExprOrJoinOrOrderedQuery(ExprContext exprContext) throws ParseException {
+    SqlNode e;
+    final List<Object> list = new ArrayList<Object>();
+    if (jj_2_3(2)) {
+      e = Query(exprContext);
+      e = OrderByLimitOpt(e);
+          {if (true) return e;}
+    } else if (jj_2_4(2)) {
+      e = TableRef1(ExprContext.ACCEPT_QUERY_OR_JOIN);
+      label_1:
+      while (true) {
+        if (jj_2_1(2)) {
+          ;
+        } else {
+          break label_1;
+        }
+        e = JoinTable(e);
+      }
+          list.add(e);
+      label_2:
+      while (true) {
+        if (jj_2_2(2)) {
+          ;
+        } else {
+          break label_2;
+        }
+        AddSetOpQuery(list, exprContext);
+      }
+          {if (true) return SqlParserUtil.toTree(list);}
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    throw new Error("Missing return statement in function");
+  }
 
 /**
  * Parses either a row expression or a query expression with an optional
@@ -494,6 +541,13 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  *    [ OFFSET start ]</pre>
  * </blockquote>
  *
+ * <p>Trino syntax for limit:
+ *
+ * <blockquote><pre>
+ *    [ OFFSET start ]
+ *    [ LIMIT { count | ALL } ]</pre>
+ * </blockquote>
+ *
  * <p>MySQL syntax for limit:
  *
  * <blockquote><pre>
@@ -509,30 +563,55 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlNode OrderedQueryOrExpr(ExprContext exprContext) throws ParseException {
     SqlNode e;
-    SqlNodeList orderBy = null;
-    SqlNode start = null;
-    SqlNode count = null;
     e = QueryOrExpr(exprContext);
-    if (jj_2_1(2)) {
+    e = OrderByLimitOpt(e);
+      {if (true) return e;}
+    throw new Error("Missing return statement in function");
+  }
+
+/** Reads optional "ORDER BY", "LIMIT", "OFFSET", "FETCH" following a query,
+ * {@code e}. If any of them are present, adds them to the query;
+ * otherwise returns the query unchanged.
+ * Throws if they are present and {@code e} is not a query. */
+  final public SqlNode OrderByLimitOpt(SqlNode e) throws ParseException {
+    final SqlNodeList orderBy;
+    final Span s = Span.of();
+    SqlNode[] offsetFetch = {null, null};
+    if (jj_2_5(2)) {
       // use the syntactic type of the expression we just parsed
               // to decide whether ORDER BY makes sense
               orderBy = OrderBy(e.isA(SqlKind.QUERY));
     } else {
-      ;
+          orderBy = null;
     }
-    if (jj_2_5(2)) {
-      jj_consume_token(LIMIT);
-      if (jj_2_2(2)) {
-        start = UnsignedNumericLiteralOrParam();
-        jj_consume_token(COMMA);
-        count = UnsignedNumericLiteralOrParam();
-                if (!this.conformance.isLimitStartCountAllowed()) {
-                    {if (true) throw SqlUtil.newContextException(getPos(), RESOURCE.limitStartCountNotAllowed());}
+    if (jj_2_13(2)) {
+      if (jj_2_10(2)) {
+        LimitClause(s, offsetFetch);
+        if (jj_2_6(2)) {
+          OffsetClause(s, offsetFetch);
+        } else {
+          ;
+        }
+      } else if (jj_2_11(2)) {
+        OffsetClause(s, offsetFetch);
+        if (jj_2_9(2)) {
+          if (jj_2_7(2)) {
+            LimitClause(s, offsetFetch);
+                if (!this.conformance.isOffsetLimitAllowed()) {
+                    {if (true) throw SqlUtil.newContextException(s.end(this),
+                        RESOURCE.offsetLimitNotAllowed());}
                 }
-      } else if (jj_2_3(2)) {
-        count = UnsignedNumericLiteralOrParam();
-      } else if (jj_2_4(2)) {
-        jj_consume_token(ALL);
+          } else if (jj_2_8(2)) {
+            FetchClause(offsetFetch);
+          } else {
+            jj_consume_token(-1);
+            throw new ParseException();
+          }
+        } else {
+          ;
+        }
+      } else if (jj_2_12(2)) {
+        FetchClause(offsetFetch);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
@@ -540,56 +619,83 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     } else {
       ;
     }
-    if (jj_2_9(2)) {
-      jj_consume_token(OFFSET);
-      start = UnsignedNumericLiteralOrParam();
-      if (jj_2_8(2)) {
-        if (jj_2_6(2)) {
-          jj_consume_token(ROW);
-        } else if (jj_2_7(2)) {
-          jj_consume_token(ROWS);
-        } else {
-          jj_consume_token(-1);
-          throw new ParseException();
+        if (orderBy != null || offsetFetch[0] != null || offsetFetch[1] != null) {
+            {if (true) return new SqlOrderBy(getPos(), e,
+                Util.first(orderBy, SqlNodeList.EMPTY),
+                offsetFetch[0], offsetFetch[1]);}
         }
-      } else {
-        ;
-      }
-    } else {
-      ;
-    }
-    if (jj_2_14(2)) {
-      jj_consume_token(FETCH);
-      if (jj_2_10(2)) {
-        jj_consume_token(FIRST);
-      } else if (jj_2_11(2)) {
-        jj_consume_token(NEXT);
-      } else {
-        jj_consume_token(-1);
-        throw new ParseException();
-      }
-      count = UnsignedNumericLiteralOrParam();
-      if (jj_2_12(2)) {
+        {if (true) return e;}
+    throw new Error("Missing return statement in function");
+  }
+
+/**
+ * Parses an OFFSET clause in an ORDER BY expression.
+ */
+  final public void OffsetClause(Span s, SqlNode[] offsetFetch) throws ParseException {
+    jj_consume_token(OFFSET);
+               s.add(this);
+    offsetFetch[0] = UnsignedNumericLiteralOrParam();
+    if (jj_2_16(2)) {
+      if (jj_2_14(2)) {
         jj_consume_token(ROW);
-      } else if (jj_2_13(2)) {
+      } else if (jj_2_15(2)) {
         jj_consume_token(ROWS);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
-      jj_consume_token(ONLY);
     } else {
       ;
     }
-        if (orderBy != null || start != null || count != null) {
-            if (orderBy == null) {
-                orderBy = SqlNodeList.EMPTY;
-            }
-            e = new SqlOrderBy(getPos(), e, orderBy, start, count);
+  }
 
-        }
-        {if (true) return e;}
-    throw new Error("Missing return statement in function");
+/**
+ * Parses a FETCH clause in an ORDER BY expression.
+ */
+  final public void FetchClause(SqlNode[] offsetFetch) throws ParseException {
+    jj_consume_token(FETCH);
+    if (jj_2_17(2)) {
+      jj_consume_token(FIRST);
+    } else if (jj_2_18(2)) {
+      jj_consume_token(NEXT);
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    offsetFetch[1] = UnsignedNumericLiteralOrParam();
+    if (jj_2_19(2)) {
+      jj_consume_token(ROW);
+    } else if (jj_2_20(2)) {
+      jj_consume_token(ROWS);
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    jj_consume_token(ONLY);
+  }
+
+/**
+ * Parses a LIMIT clause in an ORDER BY expression.
+ */
+  final public void LimitClause(Span s, SqlNode[] offsetFetch) throws ParseException {
+    jj_consume_token(LIMIT);
+              s.add(this);
+    if (jj_2_21(2)) {
+      offsetFetch[0] = UnsignedNumericLiteralOrParam();
+      jj_consume_token(COMMA);
+      offsetFetch[1] = UnsignedNumericLiteralOrParam();
+            if (!this.conformance.isLimitStartCountAllowed()) {
+                {if (true) throw SqlUtil.newContextException(s.end(this),
+                    RESOURCE.limitStartCountNotAllowed());}
+            }
+    } else if (jj_2_22(2)) {
+      offsetFetch[1] = UnsignedNumericLiteralOrParam();
+    } else if (jj_2_23(2)) {
+      jj_consume_token(ALL);
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
   }
 
 /**
@@ -597,15 +703,15 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlNode LeafQuery(ExprContext exprContext) throws ParseException {
     SqlNode e;
-    if (jj_2_15(2)) {
+    if (jj_2_24(2)) {
         // ensure a query is legal in this context
         checkQueryExpression(exprContext);
       e = SqlSelect();
                       {if (true) return e;}
-    } else if (jj_2_16(2)) {
+    } else if (jj_2_25(2)) {
       e = TableConstructor();
                              {if (true) return e;}
-    } else if (jj_2_17(2)) {
+    } else if (jj_2_26(2)) {
       e = ExplicitTable(getPos());
                                   {if (true) return e;}
     } else {
@@ -617,6 +723,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
 /**
  * Parses a parenthesized query or single row expression.
+ * Depending on {@code exprContext}, may also accept a join.
  */
   final public SqlNode ParenthesizedExpression(ExprContext exprContext) throws ParseException {
     SqlNode e;
@@ -631,8 +738,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             exprContext = ExprContext.ACCEPT_ALL;
             break;
         }
-    e = OrderedQueryOrExpr(exprContext);
+    e = ExprOrJoinOrOrderedQuery(exprContext);
     jj_consume_token(RPAREN);
+        exprContext.throwIfNotCompatible(e);
         {if (true) return e;}
     throw new Error("Missing return statement in function");
   }
@@ -663,7 +771,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlNodeList ParenthesizedQueryOrCommaList(ExprContext exprContext) throws ParseException {
     SqlNode e;
-    List<SqlNode> list;
+    final List<SqlNode> list = new ArrayList<SqlNode>();
     ExprContext firstExprContext = exprContext;
     final Span s;
     jj_consume_token(LPAREN);
@@ -679,19 +787,18 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             break;
         }
     e = OrderedQueryOrExpr(firstExprContext);
-        list = startList(e);
-    label_1:
+                                               list.add(e);
+    label_3:
     while (true) {
-      if (jj_2_18(2)) {
+      if (jj_2_27(2)) {
         ;
       } else {
-        break label_1;
+        break label_3;
       }
       jj_consume_token(COMMA);
             // a comma-list can't appear where only a query is expected
             checkNonQueryExpression(exprContext);
-      e = Expression(exprContext);
-            list.add(e);
+      AddExpression(list, exprContext);
     }
     jj_consume_token(RPAREN);
         {if (true) return new SqlNodeList(list, s.end(this));}
@@ -703,7 +810,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * {@code (x, DEFAULT, null, DEFAULT)}. */
   final public SqlNodeList ParenthesizedQueryOrCommaListWithDefault(ExprContext exprContext) throws ParseException {
     SqlNode e;
-    List<SqlNode> list;
+    final List<SqlNode> list = new ArrayList<SqlNode>();
     ExprContext firstExprContext = exprContext;
     final Span s;
     jj_consume_token(LPAREN);
@@ -718,34 +825,36 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             firstExprContext = ExprContext.ACCEPT_ALL;
             break;
         }
-    if (jj_2_19(2)) {
+    if (jj_2_28(2)) {
       e = OrderedQueryOrExpr(firstExprContext);
-    } else if (jj_2_20(2)) {
+                                                   list.add(e);
+    } else if (jj_2_29(2)) {
       e = Default();
+                        list.add(e);
     } else {
       jj_consume_token(-1);
       throw new ParseException();
     }
-        list = startList(e);
-    label_2:
+    label_4:
     while (true) {
-      if (jj_2_21(2)) {
+      if (jj_2_30(2)) {
         ;
       } else {
-        break label_2;
+        break label_4;
       }
       jj_consume_token(COMMA);
             // a comma-list can't appear where only a query is expected
             checkNonQueryExpression(exprContext);
-      if (jj_2_22(2)) {
+      if (jj_2_31(2)) {
         e = Expression(exprContext);
-      } else if (jj_2_23(2)) {
+                                          list.add(e);
+      } else if (jj_2_32(2)) {
         e = Default();
+                            list.add(e);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
-            list.add(e);
     }
     jj_consume_token(RPAREN);
         {if (true) return new SqlNodeList(list, s.end(this));}
@@ -756,10 +865,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses function parameter lists.
  * If the list starts with DISTINCT or ALL, it is discarded.
  */
-  final public List UnquantifiedFunctionParameterList(ExprContext exprContext) throws ParseException {
-    final List args;
+  final public List<SqlNode> UnquantifiedFunctionParameterList(ExprContext exprContext) throws ParseException {
+    final List<SqlNode> args;
     args = FunctionParameterList(exprContext);
-        final SqlLiteral quantifier = (SqlLiteral) args.get(0);
         args.remove(0); // remove DISTINCT or ALL, if present
         {if (true) return args;}
     throw new Error("Missing return statement in function");
@@ -769,28 +877,28 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses function parameter lists including DISTINCT keyword recognition,
  * DEFAULT, and named argument assignment.
  */
-  final public List FunctionParameterList(ExprContext exprContext) throws ParseException {
+  final public List<SqlNode> FunctionParameterList(ExprContext exprContext) throws ParseException {
     final SqlLiteral qualifier;
-    final List list = new ArrayList();
+    final List<SqlNode> list = new ArrayList<SqlNode>();
     jj_consume_token(LPAREN);
-    if (jj_2_24(2)) {
+    if (jj_2_33(2)) {
       qualifier = AllOrDistinct();
                                       list.add(qualifier);
     } else {
           list.add(null);
     }
-    Arg0(list, exprContext);
-    label_3:
+    AddArg0(list, exprContext);
+    label_5:
     while (true) {
-      if (jj_2_25(2)) {
+      if (jj_2_34(2)) {
         ;
       } else {
-        break label_3;
+        break label_5;
       }
       jj_consume_token(COMMA);
             // a comma-list can't appear where only a query is expected
             checkNonQueryExpression(exprContext);
-      Arg(list, exprContext);
+      AddArg(list, exprContext);
     }
     jj_consume_token(RPAREN);
         {if (true) return list;}
@@ -798,10 +906,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public SqlLiteral AllOrDistinct() throws ParseException {
-    if (jj_2_26(2)) {
+    if (jj_2_35(2)) {
       jj_consume_token(DISTINCT);
                  {if (true) return SqlSelectKeyword.DISTINCT.symbol(getPos());}
-    } else if (jj_2_27(2)) {
+    } else if (jj_2_36(2)) {
       jj_consume_token(ALL);
             {if (true) return SqlSelectKeyword.ALL.symbol(getPos());}
     } else {
@@ -811,9 +919,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     throw new Error("Missing return statement in function");
   }
 
-  final public void Arg0(List list, ExprContext exprContext) throws ParseException {
-    SqlIdentifier name = null;
-    SqlNode e = null;
+  final public void AddArg0(List<SqlNode> list, ExprContext exprContext) throws ParseException {
+    final SqlIdentifier name;
+    SqlNode e;
     final ExprContext firstExprContext;
     {
         // we've now seen left paren, so queries inside should
@@ -830,53 +938,53 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             break;
         }
     }
-    if (jj_2_28(2)) {
+    if (jj_2_37(2)) {
       name = SimpleIdentifier();
       jj_consume_token(NAMED_ARGUMENT_ASSIGNMENT);
     } else {
-      ;
+          name = null;
     }
-    if (jj_2_29(2)) {
+    if (jj_2_38(2)) {
       e = Default();
-    } else if (jj_2_30(2)) {
-      e = OrderedQueryOrExpr(firstExprContext);
+    } else if (jj_2_39(3)) {
+      e = TableParam();
+    } else if (jj_2_40(2)) {
+      e = PartitionedQueryOrQueryOrExpr(firstExprContext);
     } else {
       jj_consume_token(-1);
       throw new ParseException();
     }
-        if (e != null) {
-            if (name != null) {
-                e = SqlStdOperatorTable.ARGUMENT_ASSIGNMENT.createCall(
-                    Span.of(name, e).pos(), e, name);
-            }
-            list.add(e);
+        if (name != null) {
+            e = SqlStdOperatorTable.ARGUMENT_ASSIGNMENT.createCall(
+                Span.of(name, e).pos(), e, name);
         }
+        list.add(e);
   }
 
-  final public void Arg(List list, ExprContext exprContext) throws ParseException {
-    SqlIdentifier name = null;
-    SqlNode e = null;
-    if (jj_2_31(2)) {
+  final public void AddArg(List<SqlNode> list, ExprContext exprContext) throws ParseException {
+    final SqlIdentifier name;
+    SqlNode e;
+    if (jj_2_41(2)) {
       name = SimpleIdentifier();
       jj_consume_token(NAMED_ARGUMENT_ASSIGNMENT);
     } else {
-      ;
+          name = null;
     }
-    if (jj_2_32(2)) {
+    if (jj_2_42(2)) {
       e = Default();
-    } else if (jj_2_33(2)) {
+    } else if (jj_2_43(2)) {
       e = Expression(exprContext);
+    } else if (jj_2_44(2)) {
+      e = TableParam();
     } else {
       jj_consume_token(-1);
       throw new ParseException();
     }
-        if (e != null) {
-            if (name != null) {
-                e = SqlStdOperatorTable.ARGUMENT_ASSIGNMENT.createCall(
-                    Span.of(name, e).pos(), e, name);
-            }
-            list.add(e);
+        if (name != null) {
+            e = SqlStdOperatorTable.ARGUMENT_ASSIGNMENT.createCall(
+                Span.of(name, e).pos(), e, name);
         }
+        list.add(e);
   }
 
   final public SqlNode Default() throws ParseException {
@@ -907,15 +1015,15 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     SqlNode stmt;
     stmt = SqlStmt();
         stmtList.add(stmt);
-    label_4:
+    label_6:
     while (true) {
-      if (jj_2_34(2)) {
+      if (jj_2_45(2)) {
         ;
       } else {
-        break label_4;
+        break label_6;
       }
       jj_consume_token(SEMICOLON);
-      if (jj_2_35(2)) {
+      if (jj_2_46(2)) {
         stmt = SqlStmt();
                 stmtList.add(stmt);
       } else {
@@ -932,55 +1040,55 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlNode SqlStmt() throws ParseException {
     SqlNode stmt;
-    if (jj_2_36(2)) {
+    if (jj_2_47(2)) {
       stmt = SqlAlterTable();
-    } else if (jj_2_37(2)) {
+    } else if (jj_2_48(2)) {
       stmt = SqlAlterUser();
-    } else if (jj_2_38(2)) {
+    } else if (jj_2_49(2)) {
       stmt = SqlKillScanQuery();
-    } else if (jj_2_39(2)) {
+    } else if (jj_2_50(2)) {
       stmt = SqlKillContinuousQuery();
-    } else if (jj_2_40(2)) {
+    } else if (jj_2_51(2)) {
       stmt = SqlKillService();
-    } else if (jj_2_41(2)) {
+    } else if (jj_2_52(2)) {
       stmt = SqlKillTransaction();
-    } else if (jj_2_42(2)) {
+    } else if (jj_2_53(2)) {
       stmt = SqlKillComputeTask();
-    } else if (jj_2_43(2)) {
+    } else if (jj_2_54(2)) {
       stmt = SqlKillQuery();
-    } else if (jj_2_44(2)) {
+    } else if (jj_2_55(2)) {
       stmt = SqlCommitTransaction();
-    } else if (jj_2_45(2)) {
+    } else if (jj_2_56(2)) {
       stmt = SqlRollbackTransaction();
-    } else if (jj_2_46(2)) {
+    } else if (jj_2_57(2)) {
       stmt = SqlStatisticsAnalyze();
-    } else if (jj_2_47(2)) {
+    } else if (jj_2_58(2)) {
       stmt = SqlStatisticsRefresh();
-    } else if (jj_2_48(2)) {
+    } else if (jj_2_59(2)) {
       stmt = SqlStatisticsDrop();
-    } else if (jj_2_49(2)) {
+    } else if (jj_2_60(2)) {
       stmt = SqlSetOption(Span.of(), null);
-    } else if (jj_2_50(2)) {
+    } else if (jj_2_61(2)) {
       stmt = SqlAlter();
-    } else if (jj_2_51(2)) {
+    } else if (jj_2_62(2)) {
       stmt = SqlCreate();
-    } else if (jj_2_52(2)) {
+    } else if (jj_2_63(2)) {
       stmt = SqlDrop();
-    } else if (jj_2_53(2)) {
+    } else if (jj_2_64(2)) {
       stmt = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY);
-    } else if (jj_2_54(2)) {
+    } else if (jj_2_65(2)) {
       stmt = SqlExplain();
-    } else if (jj_2_55(2)) {
+    } else if (jj_2_66(2)) {
       stmt = SqlDescribe();
-    } else if (jj_2_56(2)) {
+    } else if (jj_2_67(2)) {
       stmt = SqlInsert();
-    } else if (jj_2_57(2)) {
+    } else if (jj_2_68(2)) {
       stmt = SqlDelete();
-    } else if (jj_2_58(2)) {
+    } else if (jj_2_69(2)) {
       stmt = SqlUpdate();
-    } else if (jj_2_59(2)) {
+    } else if (jj_2_70(2)) {
       stmt = SqlMerge();
-    } else if (jj_2_60(2)) {
+    } else if (jj_2_71(2)) {
       stmt = SqlProcedureCall();
     } else {
       jj_consume_token(-1);
@@ -1002,7 +1110,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public boolean IfNotExistsOpt() throws ParseException {
-    if (jj_2_61(2)) {
+    if (jj_2_72(2)) {
       jj_consume_token(IF);
       jj_consume_token(NOT);
       jj_consume_token(EXISTS);
@@ -1016,23 +1124,23 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlNodeList WithCreateTableOptionList() throws ParseException {
     List<SqlNode> list = new ArrayList<SqlNode>();
     final Span s;
-    if (jj_2_65(2)) {
+    if (jj_2_76(2)) {
       jj_consume_token(WITH);
                  s = span();
-      if (jj_2_63(2)) {
+      if (jj_2_74(2)) {
         jj_consume_token(QUOTED_IDENTIFIER);
                 {if (true) return IgniteSqlCreateTableOption.parseOptionList(
                     SqlParserUtil.stripQuotes(token.image, DQ, DQ, DQDQ, quotedCasing),
                     getPos().withQuoting(true)
                 );}
-      } else if (jj_2_64(2)) {
+      } else if (jj_2_75(2)) {
         CreateTableOption(list);
-        label_5:
+        label_7:
         while (true) {
-          if (jj_2_62(2)) {
+          if (jj_2_73(2)) {
             ;
           } else {
-            break label_5;
+            break label_7;
           }
           jj_consume_token(COMMA);
                           s.add(this);
@@ -1051,37 +1159,37 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public SqlLiteral CreateTableOptionKey() throws ParseException {
-    if (jj_2_66(2)) {
+    if (jj_2_77(2)) {
       jj_consume_token(TEMPLATE);
                  {if (true) return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.TEMPLATE, getPos());}
-    } else if (jj_2_67(2)) {
+    } else if (jj_2_78(2)) {
       jj_consume_token(BACKUPS);
                 {if (true) return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.BACKUPS, getPos());}
-    } else if (jj_2_68(2)) {
+    } else if (jj_2_79(2)) {
       jj_consume_token(AFFINITY_KEY);
                      {if (true) return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.AFFINITY_KEY, getPos());}
-    } else if (jj_2_69(2)) {
+    } else if (jj_2_80(2)) {
       jj_consume_token(ATOMICITY);
                   {if (true) return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.ATOMICITY, getPos());}
-    } else if (jj_2_70(2)) {
+    } else if (jj_2_81(2)) {
       jj_consume_token(WRITE_SYNCHRONIZATION_MODE);
                                    {if (true) return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.WRITE_SYNCHRONIZATION_MODE, getPos());}
-    } else if (jj_2_71(2)) {
+    } else if (jj_2_82(2)) {
       jj_consume_token(CACHE_GROUP);
                     {if (true) return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.CACHE_GROUP, getPos());}
-    } else if (jj_2_72(2)) {
+    } else if (jj_2_83(2)) {
       jj_consume_token(CACHE_NAME);
                    {if (true) return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.CACHE_NAME, getPos());}
-    } else if (jj_2_73(2)) {
+    } else if (jj_2_84(2)) {
       jj_consume_token(DATA_REGION);
                     {if (true) return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.DATA_REGION, getPos());}
-    } else if (jj_2_74(2)) {
+    } else if (jj_2_85(2)) {
       jj_consume_token(KEY_TYPE);
                  {if (true) return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.KEY_TYPE, getPos());}
-    } else if (jj_2_75(2)) {
+    } else if (jj_2_86(2)) {
       jj_consume_token(VALUE_TYPE);
                    {if (true) return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.VALUE_TYPE, getPos());}
-    } else if (jj_2_76(2)) {
+    } else if (jj_2_87(2)) {
       jj_consume_token(ENCRYPTED);
                   {if (true) return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.ENCRYPTED, getPos());}
     } else {
@@ -1098,9 +1206,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     key = CreateTableOptionKey();
                                    s = span();
     jj_consume_token(EQ);
-    if (jj_2_77(2)) {
+    if (jj_2_88(2)) {
       val = Literal();
-    } else if (jj_2_78(2)) {
+    } else if (jj_2_89(2)) {
       val = SimpleIdentifier();
     } else {
       jj_consume_token(-1);
@@ -1111,9 +1219,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
   final public SqlDataTypeSpec DataTypeEx() throws ParseException {
     final SqlDataTypeSpec dt;
-    if (jj_2_79(2)) {
+    if (jj_2_90(2)) {
       dt = DataType();
-    } else if (jj_2_80(2)) {
+    } else if (jj_2_91(2)) {
       dt = IntervalType();
     } else {
       jj_consume_token(-1);
@@ -1141,11 +1249,11 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final ColumnStrategy strategy;
     final SqlNode dflt;
     SqlIdentifier id = null;
-    if (jj_2_84(2)) {
+    if (jj_2_95(2)) {
       id = SimpleIdentifier();
       type = DataTypeEx();
       nullable = NullableOptDefaultTrue();
-      if (jj_2_81(2)) {
+      if (jj_2_92(2)) {
         jj_consume_token(DEFAULT_);
                      s.add(this);
         dflt = Literal();
@@ -1155,7 +1263,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             strategy = nullable ? ColumnStrategy.NULLABLE
                 : ColumnStrategy.NOT_NULLABLE;
       }
-      if (jj_2_82(2)) {
+      if (jj_2_93(2)) {
         jj_consume_token(PRIMARY);
                     s.add(this);
         jj_consume_token(KEY);
@@ -1167,8 +1275,8 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         list.add(
             SqlDdlNodes.column(s.add(id).end(this), id,
                 type.withNullable(nullable), dflt, strategy));
-    } else if (jj_2_85(2)) {
-      if (jj_2_83(2)) {
+    } else if (jj_2_96(2)) {
+      if (jj_2_94(2)) {
         jj_consume_token(CONSTRAINT);
                      s.add(this);
         id = SimpleIdentifier();
@@ -1192,12 +1300,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     jj_consume_token(LPAREN);
                s = span();
     TableElement(list);
-    label_6:
+    label_8:
     while (true) {
-      if (jj_2_86(2)) {
+      if (jj_2_97(2)) {
         ;
       } else {
-        break label_6;
+        break label_8;
       }
       jj_consume_token(COMMA);
       TableElement(list);
@@ -1216,12 +1324,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     jj_consume_token(TABLE);
     ifNotExists = IfNotExistsOpt();
     id = CompoundIdentifier();
-    if (jj_2_88(3)) {
+    if (jj_2_99(3)) {
       columnList = TableElementList();
       optionList = WithCreateTableOptionList();
           query = null;
-    } else if (jj_2_89(2)) {
-      if (jj_2_87(2)) {
+    } else if (jj_2_100(2)) {
+      if (jj_2_98(2)) {
         columnList = ParenthesizedSimpleIdentifierList();
       } else {
               columnList = null;
@@ -1242,10 +1350,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final Span s;
     SqlNode col;
     col = SimpleIdentifier();
-    if (jj_2_92(2)) {
-      if (jj_2_90(2)) {
+    if (jj_2_103(2)) {
+      if (jj_2_101(2)) {
         jj_consume_token(ASC);
-      } else if (jj_2_91(2)) {
+      } else if (jj_2_102(2)) {
         jj_consume_token(DESC);
             col = SqlStdOperatorTable.DESC.createCall(getPos(), col);
       } else {
@@ -1267,12 +1375,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                s = span();
     col = IndexedColumn();
                             list.add(col);
-    label_7:
+    label_9:
     while (true) {
-      if (jj_2_93(2)) {
+      if (jj_2_104(2)) {
         ;
       } else {
-        break label_7;
+        break label_9;
       }
       jj_consume_token(COMMA);
       col = IndexedColumn();
@@ -1292,7 +1400,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     SqlNumericLiteral inlineSize = null;
     jj_consume_token(INDEX);
     ifNotExists = IfNotExistsOpt();
-    if (jj_2_94(2)) {
+    if (jj_2_105(2)) {
       idxId = SimpleIdentifier();
     } else {
       ;
@@ -1300,21 +1408,21 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     jj_consume_token(ON);
     tblId = CompoundIdentifier();
     columnList = IndexedColumnList();
-    label_8:
+    label_10:
     while (true) {
-      if (jj_2_95(2)) {
+      if (jj_2_106(2)) {
         ;
       } else {
-        break label_8;
+        break label_10;
       }
-      if (jj_2_96(2)) {
+      if (jj_2_107(2)) {
         jj_consume_token(PARALLEL);
         jj_consume_token(UNSIGNED_INTEGER_LITERAL);
             if (parallel != null)
                 {if (true) throw SqlUtil.newContextException(getPos(), IgniteResource.INSTANCE.optionAlreadyDefined("PARALLEL"));}
 
             parallel = SqlLiteral.createExactNumeric(token.image, getPos());
-      } else if (jj_2_97(2)) {
+      } else if (jj_2_108(2)) {
         jj_consume_token(INLINE_SIZE);
         jj_consume_token(UNSIGNED_INTEGER_LITERAL);
             if (inlineSize != null)
@@ -1331,7 +1439,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public boolean IfExistsOpt() throws ParseException {
-    if (jj_2_98(2)) {
+    if (jj_2_109(2)) {
       jj_consume_token(IF);
       jj_consume_token(EXISTS);
                     {if (true) return true;}
@@ -1380,12 +1488,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                s = span();
     col = ColumnWithType();
                              list.add(col);
-    label_9:
+    label_11:
     while (true) {
-      if (jj_2_99(2)) {
+      if (jj_2_110(2)) {
         ;
       } else {
-        break label_9;
+        break label_11;
       }
       jj_consume_token(COMMA);
       col = ColumnWithType();
@@ -1403,7 +1511,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final Span s = Span.of();
     id = SimpleIdentifier();
     type = DataTypeEx();
-    if (jj_2_100(2)) {
+    if (jj_2_111(2)) {
       jj_consume_token(NOT);
       jj_consume_token(NULL);
             nullable = false;
@@ -1417,10 +1525,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlNodeList ColumnWithTypeOrList() throws ParseException {
     SqlNode col;
     SqlNodeList list;
-    if (jj_2_101(2)) {
+    if (jj_2_112(2)) {
       col = ColumnWithType();
                              {if (true) return new SqlNodeList(Collections.singletonList(col), col.getParserPosition());}
-    } else if (jj_2_102(2)) {
+    } else if (jj_2_113(2)) {
       list = ColumnWithTypeList();
                                   {if (true) return list;}
     } else {
@@ -1442,15 +1550,15 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     jj_consume_token(TABLE);
     ifExists = IfExistsOpt();
     id = CompoundIdentifier();
-    if (jj_2_105(2)) {
+    if (jj_2_116(2)) {
       jj_consume_token(LOGGING);
                     {if (true) return new IgniteSqlAlterTable(s.end(this), ifExists, id, true);}
-    } else if (jj_2_106(2)) {
+    } else if (jj_2_117(2)) {
       jj_consume_token(NOLOGGING);
                        {if (true) return new IgniteSqlAlterTable(s.end(this), ifExists, id, false);}
-    } else if (jj_2_107(2)) {
+    } else if (jj_2_118(2)) {
       jj_consume_token(ADD);
-      if (jj_2_103(2)) {
+      if (jj_2_114(2)) {
         jj_consume_token(COLUMN);
       } else {
         ;
@@ -1458,9 +1566,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
       colIgnoreErr = IfNotExistsOpt();
       cols = ColumnWithTypeOrList();
             {if (true) return new IgniteSqlAlterTableAddColumn(s.end(this), ifExists, id, colIgnoreErr, cols);}
-    } else if (jj_2_108(2)) {
+    } else if (jj_2_119(2)) {
       jj_consume_token(DROP);
-      if (jj_2_104(2)) {
+      if (jj_2_115(2)) {
         jj_consume_token(COLUMN);
       } else {
         ;
@@ -1512,16 +1620,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
   final public SqlNumericLiteral SignedIntegerLiteral() throws ParseException {
     final Span s;
-    if (jj_2_109(2)) {
+    if (jj_2_120(2)) {
       jj_consume_token(PLUS);
       jj_consume_token(UNSIGNED_INTEGER_LITERAL);
         {if (true) return SqlLiteral.createExactNumeric(token.image, getPos());}
-    } else if (jj_2_110(2)) {
+    } else if (jj_2_121(2)) {
       jj_consume_token(MINUS);
               s = span();
       jj_consume_token(UNSIGNED_INTEGER_LITERAL);
         {if (true) return SqlLiteral.createNegative(SqlLiteral.createExactNumeric(token.image, getPos()), s.end(this));}
-    } else if (jj_2_111(2)) {
+    } else if (jj_2_122(2)) {
       jj_consume_token(UNSIGNED_INTEGER_LITERAL);
         {if (true) return SqlLiteral.createExactNumeric(token.image, getPos());}
     } else {
@@ -1625,7 +1733,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public boolean IsAsyncOpt() throws ParseException {
-    if (jj_2_112(2)) {
+    if (jj_2_123(2)) {
       jj_consume_token(ASYNC);
               {if (true) return true;}
     } else {
@@ -1656,7 +1764,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final Span s;
     jj_consume_token(COMMIT);
                s = span();
-    if (jj_2_113(2)) {
+    if (jj_2_124(2)) {
       jj_consume_token(TRANSACTION);
     } else {
       ;
@@ -1669,7 +1777,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final Span s;
     jj_consume_token(ROLLBACK);
                  s = span();
-    if (jj_2_114(2)) {
+    if (jj_2_125(2)) {
       jj_consume_token(TRANSACTION);
     } else {
       ;
@@ -1683,7 +1791,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final SqlIdentifier id;
     final SqlNodeList columnList;
     id = CompoundIdentifier();
-    if (jj_2_115(2)) {
+    if (jj_2_126(2)) {
       columnList = ParenthesizedSimpleIdentifierList();
     } else {
           columnList = null;
@@ -1698,12 +1806,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     SqlNode tbl;
     tbl = StatisticsTable();
                               tbls.add(tbl);
-    label_10:
+    label_12:
     while (true) {
-      if (jj_2_116(2)) {
+      if (jj_2_127(2)) {
         ;
       } else {
-        break label_10;
+        break label_12;
       }
       jj_consume_token(COMMA);
       tbl = StatisticsTable();
@@ -1716,24 +1824,24 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlNodeList WithStatisticsAnalyzeOptionList() throws ParseException {
     List<SqlNode> list = new ArrayList<SqlNode>();
     final Span s;
-    if (jj_2_120(2)) {
+    if (jj_2_131(2)) {
       jj_consume_token(WITH);
                  s = span();
-      if (jj_2_118(2)) {
+      if (jj_2_129(2)) {
         StatisticsAnalyzeOption(list);
-        label_11:
+        label_13:
         while (true) {
-          if (jj_2_117(2)) {
+          if (jj_2_128(2)) {
             ;
           } else {
-            break label_11;
+            break label_13;
           }
           jj_consume_token(COMMA);
                           s.add(this);
           StatisticsAnalyzeOption(list);
         }
                 {if (true) return new SqlNodeList(list, s.end(this));}
-      } else if (jj_2_119(2)) {
+      } else if (jj_2_130(2)) {
         jj_consume_token(QUOTED_IDENTIFIER);
                 {if (true) return IgniteSqlStatisticsAnalyzeOption.parseOptionList(
                     SqlParserUtil.stripQuotes(token.image, DQ, DQ, DQDQ, quotedCasing),
@@ -1751,19 +1859,19 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public SqlLiteral StatisticsAnalyzeOptionKey() throws ParseException {
-    if (jj_2_121(2)) {
+    if (jj_2_132(2)) {
       jj_consume_token(DISTINCT);
                  {if (true) return SqlLiteral.createSymbol(IgniteSqlStatisticsAnalyzeOptionEnum.DISTINCT, getPos());}
-    } else if (jj_2_122(2)) {
+    } else if (jj_2_133(2)) {
       jj_consume_token(TOTAL);
               {if (true) return SqlLiteral.createSymbol(IgniteSqlStatisticsAnalyzeOptionEnum.TOTAL, getPos());}
-    } else if (jj_2_123(2)) {
+    } else if (jj_2_134(2)) {
       jj_consume_token(SIZE);
              {if (true) return SqlLiteral.createSymbol(IgniteSqlStatisticsAnalyzeOptionEnum.SIZE, getPos());}
-    } else if (jj_2_124(2)) {
+    } else if (jj_2_135(2)) {
       jj_consume_token(NULLS);
               {if (true) return SqlLiteral.createSymbol(IgniteSqlStatisticsAnalyzeOptionEnum.NULLS, getPos());}
-    } else if (jj_2_125(2)) {
+    } else if (jj_2_136(2)) {
       jj_consume_token(MAX_CHANGED_PARTITION_ROWS_PERCENT);
                                            {if (true) return SqlLiteral.createSymbol(IgniteSqlStatisticsAnalyzeOptionEnum.MAX_CHANGED_PARTITION_ROWS_PERCENT, getPos());}
     } else {
@@ -1780,9 +1888,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     key = StatisticsAnalyzeOptionKey();
                                          s = span();
     jj_consume_token(EQ);
-    if (jj_2_126(2)) {
+    if (jj_2_137(2)) {
       val = Literal();
-    } else if (jj_2_127(2)) {
+    } else if (jj_2_138(2)) {
       val = SimpleIdentifier();
     } else {
       jj_consume_token(-1);
@@ -1830,16 +1938,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final List<SqlNode> list = new ArrayList<SqlNode>();
       s = span();
     jj_consume_token(LPAREN);
-    KeyValueOption(list);
-    label_12:
+    AddKeyValueOption(list);
+    label_14:
     while (true) {
-      if (jj_2_128(2)) {
+      if (jj_2_139(2)) {
         ;
       } else {
-        break label_12;
+        break label_14;
       }
       jj_consume_token(COMMA);
-      KeyValueOption(list);
+      AddKeyValueOption(list);
     }
     jj_consume_token(RPAREN);
         {if (true) return new SqlNodeList(list, s.end(this));}
@@ -1850,12 +1958,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 * Parses an option with format key=val whose key is a simple identifier or string literal
 * and value is a string literal.
 */
-  final public void KeyValueOption(List<SqlNode> list) throws ParseException {
+  final public void AddKeyValueOption(List<SqlNode> list) throws ParseException {
     final SqlNode key;
     final SqlNode value;
-    if (jj_2_129(2)) {
+    if (jj_2_140(2)) {
       key = SimpleIdentifier();
-    } else if (jj_2_130(2)) {
+    } else if (jj_2_141(2)) {
       key = StringLiteral();
     } else {
       jj_consume_token(-1);
@@ -1867,21 +1975,19 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         list.add(value);
   }
 
-/**
-* Parses an option value, it's either a string or a numeric.
-*/
-  final public SqlNode OptionValue() throws ParseException {
+/** Parses an option value (either a string or a numeric) and adds to a list. */
+  final public void AddOptionValue(List<SqlNode> list) throws ParseException {
     final SqlNode value;
-    if (jj_2_131(2)) {
+    if (jj_2_142(2)) {
       value = NumericLiteral();
-    } else if (jj_2_132(2)) {
+                                   list.add(value);
+    } else if (jj_2_143(2)) {
       value = StringLiteral();
+                                  list.add(value);
     } else {
       jj_consume_token(-1);
       throw new ParseException();
     }
-        {if (true) return value;}
-    throw new Error("Missing return statement in function");
   }
 
 /**
@@ -1890,44 +1996,40 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlNodeList ParenthesizedLiteralOptionCommaList() throws ParseException {
     final Span s;
     final List<SqlNode> list = new ArrayList<SqlNode>();
-    SqlNode optionVal;
       s = span();
     jj_consume_token(LPAREN);
-    optionVal = OptionValue();
-        list.add(optionVal);
-    label_13:
+    AddOptionValue(list);
+    label_15:
     while (true) {
-      if (jj_2_133(2)) {
+      if (jj_2_144(2)) {
         ;
       } else {
-        break label_13;
+        break label_15;
       }
       jj_consume_token(COMMA);
-      optionVal = OptionValue();
-            list.add(optionVal);
+      AddOptionValue(list);
     }
     jj_consume_token(RPAREN);
         {if (true) return new SqlNodeList(list, s.end(this));}
     throw new Error("Missing return statement in function");
   }
 
-  final public void CommaSeparatedSqlHints(List<SqlNode> hints) throws ParseException {
-    SqlIdentifier hintName;
-    SqlNodeList hintOptions;
-    SqlNode optionVal;
-    SqlHint.HintOptionFormat optionFormat;
+  final public void AddHint(List<SqlNode> hints) throws ParseException {
+    final SqlIdentifier hintName;
+    final SqlNodeList hintOptions;
+    final SqlHint.HintOptionFormat optionFormat;
     hintName = SimpleIdentifier();
-    if (jj_2_135(5)) {
+    if (jj_2_146(5)) {
       hintOptions = ParenthesizedKeyValueOptionCommaList();
             optionFormat = SqlHint.HintOptionFormat.KV_LIST;
-    } else if (jj_2_136(3)) {
+    } else if (jj_2_147(3)) {
       hintOptions = ParenthesizedSimpleIdentifierList();
             optionFormat = SqlHint.HintOptionFormat.ID_LIST;
-    } else if (jj_2_137(3)) {
+    } else if (jj_2_148(3)) {
       hintOptions = ParenthesizedLiteralOptionCommaList();
             optionFormat = SqlHint.HintOptionFormat.LITERAL_LIST;
     } else {
-      if (jj_2_134(2)) {
+      if (jj_2_145(2)) {
         jj_consume_token(LPAREN);
         jj_consume_token(RPAREN);
       } else {
@@ -1936,60 +2038,31 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             hintOptions = SqlNodeList.EMPTY;
             optionFormat = SqlHint.HintOptionFormat.EMPTY;
     }
-        hints.add(new SqlHint(Span.of(hintOptions).end(this), hintName, hintOptions, optionFormat));
-    label_14:
+        hints.add(
+           new SqlHint(Span.of(hintOptions).end(this), hintName, hintOptions,
+               optionFormat));
+  }
+
+/** Parses hints following a table reference,
+ * and returns the wrapped table reference. */
+  final public SqlNode TableHints(SqlIdentifier tableName) throws ParseException {
+    final List<SqlNode> hints = new ArrayList<SqlNode>();
+    jj_consume_token(HINT_BEG);
+    AddHint(hints);
+    label_16:
     while (true) {
-      if (jj_2_138(2)) {
+      if (jj_2_149(2)) {
         ;
       } else {
-        break label_14;
+        break label_16;
       }
       jj_consume_token(COMMA);
-      hintName = SimpleIdentifier();
-      if (jj_2_140(5)) {
-        hintOptions = ParenthesizedKeyValueOptionCommaList();
-                optionFormat = SqlHint.HintOptionFormat.KV_LIST;
-      } else if (jj_2_141(3)) {
-        hintOptions = ParenthesizedSimpleIdentifierList();
-                optionFormat = SqlHint.HintOptionFormat.ID_LIST;
-      } else if (jj_2_142(3)) {
-        hintOptions = ParenthesizedLiteralOptionCommaList();
-                optionFormat = SqlHint.HintOptionFormat.LITERAL_LIST;
-      } else {
-        if (jj_2_139(2)) {
-          jj_consume_token(LPAREN);
-          jj_consume_token(RPAREN);
-        } else {
-          ;
-        }
-                hintOptions = SqlNodeList.EMPTY;
-                optionFormat = SqlHint.HintOptionFormat.EMPTY;
-      }
-            hints.add(new SqlHint(Span.of(hintOptions).end(this), hintName, hintOptions, optionFormat));
+      AddHint(hints);
     }
-  }
-
-/**
- * Parses a table reference with optional hints.
- */
-  final public SqlNode TableRefWithHintsOpt() throws ParseException {
-    SqlNode tableRef;
-    SqlNodeList hintList;
-    final List<SqlNode> hints = new ArrayList<SqlNode>();
-    final Span s;
-      s = span();
-    tableRef = CompoundTableIdentifier();
-    if (jj_2_143(2)) {
-      jj_consume_token(HINT_BEG);
-      CommaSeparatedSqlHints(hints);
-      jj_consume_token(COMMENT_END);
-            hintList = new SqlNodeList(hints, s.addAll(hints).end(this));
-            tableRef = new SqlTableRef(Span.of(tableRef, hintList).pos(),
-                    (SqlIdentifier) tableRef, hintList);
-    } else {
-      ;
-    }
-        {if (true) return tableRef;}
+    jj_consume_token(COMMENT_END);
+        final SqlParserPos pos = Span.of(tableName).addAll(hints).end(this);
+        final SqlNodeList hintList = new SqlNodeList(hints, pos);
+        {if (true) return new SqlTableRef(pos, tableName, hintList);}
     throw new Error("Missing return statement in function");
   }
 
@@ -2000,7 +2073,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final List<SqlLiteral> keywords = new ArrayList<SqlLiteral>();
     final SqlLiteral keyword;
     final SqlNodeList keywordList;
-    List<SqlNode> selectList;
+    final List<SqlNode> selectList = new ArrayList<SqlNode>();
     final SqlNode fromClause;
     final SqlNode where;
     final SqlNodeList groupBy;
@@ -2009,36 +2082,72 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final List<SqlNode> hints = new ArrayList<SqlNode>();
     final Span s;
     jj_consume_token(SELECT);
-        s = span();
-    if (jj_2_144(2)) {
+               s = span();
+    if (jj_2_151(2)) {
       jj_consume_token(HINT_BEG);
-      CommaSeparatedSqlHints(hints);
+      AddHint(hints);
+      label_17:
+      while (true) {
+        if (jj_2_150(2)) {
+          ;
+        } else {
+          break label_17;
+        }
+        jj_consume_token(COMMA);
+        AddHint(hints);
+      }
       jj_consume_token(COMMENT_END);
     } else {
       ;
     }
     SqlSelectKeywords(keywords);
-    if (jj_2_145(2)) {
+    if (jj_2_152(2)) {
       jj_consume_token(STREAM);
             keywords.add(SqlSelectKeyword.STREAM.symbol(getPos()));
     } else {
       ;
     }
-    if (jj_2_146(2)) {
+    if (jj_2_153(2)) {
       keyword = AllOrDistinct();
                                     keywords.add(keyword);
     } else {
       ;
     }
         keywordList = new SqlNodeList(keywords, s.addAll(keywords).pos());
-    selectList = SelectList();
-    if (jj_2_147(2)) {
+    AddSelectItem(selectList);
+    label_18:
+    while (true) {
+      if (jj_2_154(2)) {
+        ;
+      } else {
+        break label_18;
+      }
+      jj_consume_token(COMMA);
+      AddSelectItem(selectList);
+    }
+    if (jj_2_159(2)) {
       jj_consume_token(FROM);
       fromClause = FromClause();
-      where = WhereOpt();
-      groupBy = GroupByOpt();
-      having = HavingOpt();
-      windowDecls = WindowOpt();
+      if (jj_2_155(2)) {
+        where = Where();
+      } else {
+                              where = null;
+      }
+      if (jj_2_156(2)) {
+        groupBy = GroupBy();
+      } else {
+                                  groupBy = null;
+      }
+      if (jj_2_157(2)) {
+        having = Having();
+      } else {
+                                having = null;
+      }
+      if (jj_2_158(2)) {
+        windowDecls = Window();
+      } else {
+                                     windowDecls = null;
+      }
     } else {
       E();
             fromClause = null;
@@ -2072,21 +2181,21 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final SqlExplainFormat format;
     jj_consume_token(EXPLAIN);
     jj_consume_token(PLAN);
-    if (jj_2_148(2)) {
+    if (jj_2_160(2)) {
       detailLevel = ExplainDetailLevel();
     } else {
       ;
     }
     depth = ExplainDepth();
-    if (jj_2_149(2)) {
+    if (jj_2_161(2)) {
       jj_consume_token(AS);
       jj_consume_token(XML);
                      format = SqlExplainFormat.XML;
-    } else if (jj_2_150(2)) {
+    } else if (jj_2_162(2)) {
       jj_consume_token(AS);
       jj_consume_token(JSON);
                       format = SqlExplainFormat.JSON;
-    } else if (jj_2_151(2)) {
+    } else if (jj_2_163(2)) {
       jj_consume_token(AS);
       jj_consume_token(DOT_FORMAT);
                             format = SqlExplainFormat.DOT;
@@ -2108,15 +2217,15 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * or DML statement (INSERT, UPDATE, DELETE, MERGE). */
   final public SqlNode SqlQueryOrDml() throws ParseException {
     SqlNode stmt;
-    if (jj_2_152(2)) {
+    if (jj_2_164(2)) {
       stmt = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY);
-    } else if (jj_2_153(2)) {
+    } else if (jj_2_165(2)) {
       stmt = SqlInsert();
-    } else if (jj_2_154(2)) {
+    } else if (jj_2_166(2)) {
       stmt = SqlDelete();
-    } else if (jj_2_155(2)) {
+    } else if (jj_2_167(2)) {
       stmt = SqlUpdate();
-    } else if (jj_2_156(2)) {
+    } else if (jj_2_168(2)) {
       stmt = SqlMerge();
     } else {
       jj_consume_token(-1);
@@ -2131,15 +2240,15 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * EXPLAIN PLAN.
  */
   final public SqlExplain.Depth ExplainDepth() throws ParseException {
-    if (jj_2_157(2)) {
+    if (jj_2_169(2)) {
       jj_consume_token(WITH);
       jj_consume_token(TYPE);
             {if (true) return SqlExplain.Depth.TYPE;}
-    } else if (jj_2_158(2)) {
+    } else if (jj_2_170(2)) {
       jj_consume_token(WITH);
       jj_consume_token(IMPLEMENTATION);
             {if (true) return SqlExplain.Depth.PHYSICAL;}
-    } else if (jj_2_159(2)) {
+    } else if (jj_2_171(2)) {
       jj_consume_token(WITHOUT);
       jj_consume_token(IMPLEMENTATION);
             {if (true) return SqlExplain.Depth.LOGICAL;}
@@ -2154,13 +2263,13 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlExplainLevel ExplainDetailLevel() throws ParseException {
     SqlExplainLevel level = SqlExplainLevel.EXPPLAN_ATTRIBUTES;
-    if (jj_2_161(2)) {
+    if (jj_2_173(2)) {
       jj_consume_token(EXCLUDING);
       jj_consume_token(ATTRIBUTES);
             level = SqlExplainLevel.NO_ATTRIBUTES;
-    } else if (jj_2_162(2)) {
+    } else if (jj_2_174(2)) {
       jj_consume_token(INCLUDING);
-      if (jj_2_160(2)) {
+      if (jj_2_172(2)) {
         jj_consume_token(ALL);
                   level = SqlExplainLevel.ALL_ATTRIBUTES;
       } else {
@@ -2187,12 +2296,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
    final SqlNode stmt;
     jj_consume_token(DESCRIBE);
                  s = span();
-    if (jj_2_168(2)) {
-      if (jj_2_163(2)) {
+    if (jj_2_180(2)) {
+      if (jj_2_175(2)) {
         jj_consume_token(DATABASE);
-      } else if (jj_2_164(2)) {
+      } else if (jj_2_176(2)) {
         jj_consume_token(CATALOG);
-      } else if (jj_2_165(2)) {
+      } else if (jj_2_177(2)) {
         jj_consume_token(SCHEMA);
       } else {
         jj_consume_token(-1);
@@ -2203,22 +2312,21 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             // DESCRIBE SCHEMA but should be different. See
             //   [CALCITE-1221] Implement DESCRIBE DATABASE, CATALOG, STATEMENT
             {if (true) return new SqlDescribeSchema(s.end(id), id);}
-    } else if (jj_2_169(2147483647)) {
-      if (jj_2_166(2)) {
+    } else if (jj_2_181(2147483647)) {
+      if (jj_2_178(2)) {
         jj_consume_token(TABLE);
       } else {
         ;
       }
       table = CompoundIdentifier();
-      if (jj_2_167(2)) {
+      if (jj_2_179(2)) {
         column = SimpleIdentifier();
       } else {
-        E();
-                  column = null;
+                                          column = null;
       }
             {if (true) return new SqlDescribeTable(s.add(table).addIf(column).pos(),
                 table, column);}
-    } else if (jj_2_170(2)) {
+    } else if (jj_2_182(2)) {
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
       case STATEMENT:
         jj_consume_token(STATEMENT);
@@ -2263,25 +2371,25 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
   final public SqlNode NamedRoutineCall(SqlFunctionCategory routineType,
     ExprContext exprContext) throws ParseException {
-    SqlIdentifier name;
+    final SqlIdentifier name;
     final List<SqlNode> list = new ArrayList<SqlNode>();
     final Span s;
     name = CompoundIdentifier();
         s = span();
     jj_consume_token(LPAREN);
-    if (jj_2_172(2)) {
-      Arg0(list, exprContext);
-      label_15:
+    if (jj_2_184(2)) {
+      AddArg0(list, exprContext);
+      label_19:
       while (true) {
-        if (jj_2_171(2)) {
+        if (jj_2_183(2)) {
           ;
         } else {
-          break label_15;
+          break label_19;
         }
         jj_consume_token(COMMA);
                 // a comma-list can't appear where only a query is expected
                 checkNonQueryExpression(exprContext);
-        Arg(list, exprContext);
+        AddArg(list, exprContext);
       }
     } else {
       ;
@@ -2291,20 +2399,121 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     throw new Error("Missing return statement in function");
   }
 
+/**
+ * Table parameter of a table function.
+ * The input table with set semantics may be partitioned/ordered on one or more columns.
+ */
+  final public SqlNode TableParam() throws ParseException {
+    final Span s;
+    final SqlNodeList partitionList;
+    final SqlNodeList orderList;
+    SqlNode tableRef;
+      s = span();
+    tableRef = ExplicitTable(getPos());
+    if (jj_2_185(2)) {
+      jj_consume_token(PARTITION);
+      jj_consume_token(BY);
+      partitionList = SimpleIdentifierOrList();
+    } else {
+          partitionList = SqlNodeList.EMPTY;
+    }
+    if (jj_2_186(2)) {
+      orderList = OrderByOfSetSemanticsTable();
+    } else {
+          orderList = SqlNodeList.EMPTY;
+    }
+      {if (true) return CreateSetSemanticsTableIfNeeded(s, tableRef, partitionList, orderList);}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public SqlNode PartitionedQueryOrQueryOrExpr(ExprContext exprContext) throws ParseException {
+    SqlNode e;
+    e = OrderedQueryOrExpr(exprContext);
+    e = PartitionedByAndOrderBy(e);
+      {if (true) return e;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public SqlNode PartitionedByAndOrderBy(SqlNode e) throws ParseException {
+    final Span s;
+    final SqlNodeList partitionList;
+    final SqlNodeList orderList;
+      s = span();
+    if (jj_2_187(2)) {
+      jj_consume_token(PARTITION);
+      jj_consume_token(BY);
+      partitionList = SimpleIdentifierOrList();
+    } else {
+          partitionList = SqlNodeList.EMPTY;
+    }
+    if (jj_2_188(2)) {
+      orderList = OrderByOfSetSemanticsTable();
+    } else {
+          orderList = SqlNodeList.EMPTY;
+    }
+      {if (true) return CreateSetSemanticsTableIfNeeded(s, e, partitionList, orderList);}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public SqlNodeList OrderByOfSetSemanticsTable() throws ParseException {
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    final Span s;
+    jj_consume_token(ORDER);
+    s = span();
+    jj_consume_token(BY);
+    if (jj_2_190(2)) {
+      jj_consume_token(LPAREN);
+      AddOrderItem(list);
+      label_20:
+      while (true) {
+        if (jj_2_189(2)) {
+          ;
+        } else {
+          break label_20;
+        }
+        jj_consume_token(COMMA);
+        AddOrderItem(list);
+      }
+      jj_consume_token(RPAREN);
+          {if (true) return new SqlNodeList(list, s.addAll(list).pos());}
+    } else if (jj_2_191(2)) {
+      AddOrderItem(list);
+          {if (true) return new SqlNodeList(list, s.addAll(list).pos());}
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  final public SqlNode CreateSetSemanticsTableIfNeeded(final Span s,
+    final SqlNode e,
+    final SqlNodeList partitionList,
+    final SqlNodeList orderList) throws ParseException {
+        if (partitionList.isEmpty() && orderList.isEmpty()) {
+            {if (true) return e;}
+        } else {
+            {if (true) return SqlStdOperatorTable.SET_SEMANTICS_TABLE.createCall(
+                s.pos(), e, partitionList, orderList);}
+        }
+    throw new Error("Missing return statement in function");
+  }
+
 /**
  * Parses an INSERT statement.
  */
   final public SqlNode SqlInsert() throws ParseException {
     final List<SqlLiteral> keywords = new ArrayList<SqlLiteral>();
     final SqlNodeList keywordList;
-    SqlNode table;
-    SqlNodeList extendList = null;
+    final SqlIdentifier tableName;
+    SqlNode tableRef;
     SqlNode source;
-    SqlNodeList columnList = null;
+    final SqlNodeList columnList;
     final Span s;
-    if (jj_2_173(2)) {
+    final Pair<SqlNodeList, SqlNodeList> p;
+    if (jj_2_192(2)) {
       jj_consume_token(INSERT);
-    } else if (jj_2_174(2)) {
+    } else if (jj_2_193(2)) {
       jj_consume_token(UPSERT);
                    keywords.add(SqlInsertKeyword.UPSERT.symbol(getPos()));
     } else {
@@ -2315,32 +2524,32 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     SqlInsertKeywords(keywords);
         keywordList = new SqlNodeList(keywords, s.addAll(keywords).pos());
     jj_consume_token(INTO);
-    table = TableRefWithHintsOpt();
-    if (jj_2_176(5)) {
-      if (jj_2_175(2)) {
-        jj_consume_token(EXTEND);
-      } else {
-        ;
-      }
-      extendList = ExtendList();
-            table = extend(table, extendList);
+    tableName = CompoundTableIdentifier();
+    if (jj_2_194(2)) {
+      tableRef = TableHints(tableName);
+    } else {
+                                           tableRef = tableName;
+    }
+    if (jj_2_195(5)) {
+      tableRef = ExtendTable(tableRef);
     } else {
       ;
     }
-    if (jj_2_177(2)) {
-          final Pair<SqlNodeList, SqlNodeList> p;
+    if (jj_2_196(2)) {
       p = ParenthesizedCompoundIdentifierList();
             if (p.right.size() > 0) {
-                table = extend(table, p.right);
+                tableRef = extend(tableRef, p.right);
             }
             if (p.left.size() > 0) {
                 columnList = p.left;
+            } else {
+                columnList = null;
             }
     } else {
-      ;
+          columnList = null;
     }
     source = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY);
-        {if (true) return new SqlInsert(s.end(source), keywordList, table, source,
+        {if (true) return new SqlInsert(s.end(source), keywordList, tableRef, source,
             columnList);}
     throw new Error("Missing return statement in function");
   }
@@ -2357,39 +2566,42 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses a DELETE statement.
  */
   final public SqlNode SqlDelete() throws ParseException {
-    SqlNode table;
-    SqlNodeList extendList = null;
-    SqlIdentifier alias = null;
-    final SqlNode condition;
+    final SqlIdentifier tableName;
+    SqlNode tableRef;
+    final SqlIdentifier alias;
+    final SqlNode where;
     final Span s;
     jj_consume_token(DELETE);
         s = span();
     jj_consume_token(FROM);
-    table = TableRefWithHintsOpt();
-    if (jj_2_179(2)) {
-      if (jj_2_178(2)) {
-        jj_consume_token(EXTEND);
-      } else {
-        ;
-      }
-      extendList = ExtendList();
-            table = extend(table, extendList);
+    tableName = CompoundTableIdentifier();
+    if (jj_2_197(2)) {
+      tableRef = TableHints(tableName);
+    } else {
+                                           tableRef = tableName;
+    }
+    if (jj_2_198(2)) {
+      tableRef = ExtendTable(tableRef);
     } else {
       ;
     }
-    if (jj_2_181(2)) {
-      if (jj_2_180(2)) {
+    if (jj_2_200(2)) {
+      if (jj_2_199(2)) {
         jj_consume_token(AS);
       } else {
         ;
       }
       alias = SimpleIdentifier();
     } else {
-      ;
+                                              alias = null;
+    }
+    if (jj_2_201(2)) {
+      where = Where();
+    } else {
+                          where = null;
     }
-    condition = WhereOpt();
-        {if (true) return new SqlDelete(s.add(table).addIf(extendList).addIf(alias)
-            .addIf(condition).pos(), table, condition, null, alias);}
+        {if (true) return new SqlDelete(s.add(tableRef).addIf(alias).addIf(where).pos(),
+            tableRef, where, null, alias);}
     throw new Error("Missing return statement in function");
   }
 
@@ -2397,66 +2609,66 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses an UPDATE statement.
  */
   final public SqlNode SqlUpdate() throws ParseException {
-    SqlNode table;
-    SqlNodeList extendList = null;
-    SqlIdentifier alias = null;
-    SqlNode condition;
-    SqlNodeList sourceExpressionList;
-    SqlNodeList targetColumnList;
+    final SqlIdentifier tableName;
+    SqlNode tableRef;
+    final SqlIdentifier alias;
+    final SqlNode where;
+    final SqlNodeList sourceExpressionList;
+    final SqlNodeList targetColumnList;
     SqlIdentifier id;
-    SqlNode exp;
     final Span s;
     jj_consume_token(UPDATE);
-               s = span();
-    table = TableRefWithHintsOpt();
+        s = span();
         targetColumnList = new SqlNodeList(s.pos());
         sourceExpressionList = new SqlNodeList(s.pos());
-    if (jj_2_183(2)) {
-      if (jj_2_182(2)) {
-        jj_consume_token(EXTEND);
-      } else {
-        ;
-      }
-      extendList = ExtendList();
-            table = extend(table, extendList);
+    tableName = CompoundTableIdentifier();
+    if (jj_2_202(2)) {
+      tableRef = TableHints(tableName);
+    } else {
+                                           tableRef = tableName;
+    }
+    if (jj_2_203(2)) {
+      tableRef = ExtendTable(tableRef);
     } else {
       ;
     }
-    if (jj_2_185(2)) {
-      if (jj_2_184(2)) {
+    if (jj_2_205(2)) {
+      if (jj_2_204(2)) {
         jj_consume_token(AS);
       } else {
         ;
       }
       alias = SimpleIdentifier();
     } else {
-      ;
+                                              alias = null;
     }
     jj_consume_token(SET);
     id = SimpleIdentifier();
         targetColumnList.add(id);
     jj_consume_token(EQ);
-    exp = Expression(ExprContext.ACCEPT_SUB_QUERY);
-        // TODO:  support DEFAULT also
-        sourceExpressionList.add(exp);
-    label_16:
+    AddExpression(sourceExpressionList, ExprContext.ACCEPT_SUB_QUERY);
+    label_21:
     while (true) {
-      if (jj_2_186(2)) {
+      if (jj_2_206(2)) {
         ;
       } else {
-        break label_16;
+        break label_21;
       }
       jj_consume_token(COMMA);
       id = SimpleIdentifier();
-            targetColumnList.add(id);
+                                  targetColumnList.add(id);
       jj_consume_token(EQ);
-      exp = Expression(ExprContext.ACCEPT_SUB_QUERY);
-            sourceExpressionList.add(exp);
+      AddExpression(sourceExpressionList, ExprContext.ACCEPT_SUB_QUERY);
+    }
+    if (jj_2_207(2)) {
+      where = Where();
+    } else {
+                          where = null;
     }
-    condition = WhereOpt();
-        {if (true) return new SqlUpdate(s.addAll(targetColumnList)
-            .addAll(sourceExpressionList).addIf(condition).pos(), table,
-            targetColumnList, sourceExpressionList, condition, null, alias);}
+        final SqlParserPos pos = s.addAll(targetColumnList)
+            .addAll(sourceExpressionList).addIf(where).pos();
+        {if (true) return new SqlUpdate(pos, tableRef, targetColumnList,
+            sourceExpressionList, where, null, alias);}
     throw new Error("Missing return statement in function");
   }
 
@@ -2464,58 +2676,59 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses a MERGE statement.
  */
   final public SqlNode SqlMerge() throws ParseException {
-    SqlNode table;
-    SqlNodeList extendList = null;
-    SqlIdentifier alias = null;
-    SqlNode sourceTableRef;
-    SqlNode condition;
-    SqlUpdate updateCall = null;
-    SqlInsert insertCall = null;
+    final SqlIdentifier tableName;
+    SqlNode tableRef;
+    final SqlIdentifier alias;
+    final SqlNode sourceTableRef;
+    final SqlNode condition;
+    final SqlUpdate updateCall;
+    final SqlInsert insertCall;
     final Span s;
     jj_consume_token(MERGE);
               s = span();
     jj_consume_token(INTO);
-    table = TableRefWithHintsOpt();
-    if (jj_2_188(2)) {
-      if (jj_2_187(2)) {
-        jj_consume_token(EXTEND);
-      } else {
-        ;
-      }
-      extendList = ExtendList();
-            table = extend(table, extendList);
+    tableName = CompoundTableIdentifier();
+    if (jj_2_208(2)) {
+      tableRef = TableHints(tableName);
+    } else {
+                                           tableRef = tableName;
+    }
+    if (jj_2_209(2)) {
+      tableRef = ExtendTable(tableRef);
     } else {
       ;
     }
-    if (jj_2_190(2)) {
-      if (jj_2_189(2)) {
+    if (jj_2_211(2)) {
+      if (jj_2_210(2)) {
         jj_consume_token(AS);
       } else {
         ;
       }
       alias = SimpleIdentifier();
     } else {
-      ;
+                                              alias = null;
     }
     jj_consume_token(USING);
     sourceTableRef = TableRef();
     jj_consume_token(ON);
     condition = Expression(ExprContext.ACCEPT_SUB_QUERY);
-    if (jj_2_192(2)) {
-      updateCall = WhenMatchedClause(table, alias);
-      if (jj_2_191(2)) {
-        insertCall = WhenNotMatchedClause(table);
+    if (jj_2_213(2)) {
+      updateCall = WhenMatchedClause(tableRef, alias);
+      if (jj_2_212(2)) {
+        insertCall = WhenNotMatchedClause(tableRef);
       } else {
-        ;
+                                                          insertCall = null;
       }
-    } else if (jj_2_193(2)) {
-      insertCall = WhenNotMatchedClause(table);
+    } else if (jj_2_214(2)) {
+          updateCall = null;
+      insertCall = WhenNotMatchedClause(tableRef);
     } else {
       jj_consume_token(-1);
       throw new ParseException();
     }
-        {if (true) return new SqlMerge(s.addIf(updateCall).addIf(insertCall).pos(), table,
-            condition, sourceTableRef, updateCall, insertCall, null, alias);}
+        final SqlParserPos pos = s.addIf(updateCall).addIf(insertCall).pos();
+        {if (true) return new SqlMerge(pos, tableRef, condition, sourceTableRef,
+            updateCall, insertCall, null, alias);}
     throw new Error("Missing return statement in function");
   }
 
@@ -2523,7 +2736,6 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     SqlIdentifier id;
     final Span s;
     final SqlNodeList updateColumnList = new SqlNodeList(SqlParserPos.ZERO);
-    SqlNode exp;
     final SqlNodeList updateExprList = new SqlNodeList(SqlParserPos.ZERO);
     jj_consume_token(WHEN);
              s = span();
@@ -2534,21 +2746,19 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     id = CompoundIdentifier();
         updateColumnList.add(id);
     jj_consume_token(EQ);
-    exp = Expression(ExprContext.ACCEPT_SUB_QUERY);
-        updateExprList.add(exp);
-    label_17:
+    AddExpression(updateExprList, ExprContext.ACCEPT_SUB_QUERY);
+    label_22:
     while (true) {
-      if (jj_2_194(2)) {
+      if (jj_2_215(2)) {
         ;
       } else {
-        break label_17;
+        break label_22;
       }
       jj_consume_token(COMMA);
       id = CompoundIdentifier();
             updateColumnList.add(id);
       jj_consume_token(EQ);
-      exp = Expression(ExprContext.ACCEPT_SUB_QUERY);
-            updateExprList.add(exp);
+      AddExpression(updateExprList, ExprContext.ACCEPT_SUB_QUERY);
     }
         {if (true) return new SqlUpdate(s.addAll(updateExprList).pos(), table,
             updateColumnList, updateExprList, null, null, alias);}
@@ -2559,7 +2769,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final Span insertSpan, valuesSpan;
     final List<SqlLiteral> keywords = new ArrayList<SqlLiteral>();
     final SqlNodeList keywordList;
-    SqlNodeList insertColumnList = null;
+    final SqlNodeList insertColumnList;
     SqlNode rowConstructor;
     SqlNode insertValues;
     jj_consume_token(WHEN);
@@ -2570,23 +2780,24 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         insertSpan = span();
     SqlInsertKeywords(keywords);
         keywordList = new SqlNodeList(keywords, insertSpan.end(this));
-    if (jj_2_195(2)) {
+    if (jj_2_216(2)) {
       insertColumnList = ParenthesizedSimpleIdentifierList();
     } else {
-      ;
+          insertColumnList = null;
     }
-    if (jj_2_196(2)) {
+    if (jj_2_217(2)) {
       jj_consume_token(LPAREN);
-    } else {
-      ;
-    }
-    jj_consume_token(VALUES);
-               valuesSpan = span();
-    rowConstructor = RowConstructor();
-    if (jj_2_197(2)) {
+      jj_consume_token(VALUES);
+                   valuesSpan = span();
+      rowConstructor = RowConstructor();
       jj_consume_token(RPAREN);
+    } else if (jj_2_218(2)) {
+      jj_consume_token(VALUES);
+                   valuesSpan = span();
+      rowConstructor = RowConstructor();
     } else {
-      ;
+      jj_consume_token(-1);
+      throw new ParseException();
     }
         // TODO zfong 5/26/06: note that extra parentheses are accepted above
         // around the VALUES clause as a hack for unparse, but this is
@@ -2598,43 +2809,20 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     throw new Error("Missing return statement in function");
   }
 
-/**
- * Parses the select list of a SELECT statement.
- */
-  final public List<SqlNode> SelectList() throws ParseException {
-    final List<SqlNode> list = new ArrayList<SqlNode>();
-    SqlNode item;
-    item = SelectItem();
-        list.add(item);
-    label_18:
-    while (true) {
-      if (jj_2_198(2)) {
-        ;
-      } else {
-        break label_18;
-      }
-      jj_consume_token(COMMA);
-      item = SelectItem();
-            list.add(item);
-    }
-        {if (true) return list;}
-    throw new Error("Missing return statement in function");
-  }
-
 /**
  * Parses one item in a select list.
  */
-  final public SqlNode SelectItem() throws ParseException {
-    SqlNode e;
+  final public void AddSelectItem(List<SqlNode> list) throws ParseException {
+    final SqlNode e;
     final SqlIdentifier id;
     e = SelectExpression();
-    if (jj_2_201(2)) {
-      if (jj_2_199(2)) {
+    if (jj_2_221(2)) {
+      if (jj_2_219(2)) {
         jj_consume_token(AS);
       } else {
         ;
       }
-      if (jj_2_200(2)) {
+      if (jj_2_220(2)) {
         id = SimpleIdentifier();
       } else {
         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
@@ -2647,12 +2835,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
           throw new ParseException();
         }
       }
-            e = SqlStdOperatorTable.AS.createCall(span().end(e), e, id);
+          list.add(SqlStdOperatorTable.AS.createCall(span().end(e), e, id));
     } else {
-      ;
+          list.add(e);
     }
-        {if (true) return e;}
-    throw new Error("Missing return statement in function");
   }
 
 /**
@@ -2660,10 +2846,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlNode SelectExpression() throws ParseException {
     SqlNode e;
-    if (jj_2_202(2)) {
+    if (jj_2_222(2)) {
       jj_consume_token(STAR);
         {if (true) return SqlIdentifier.star(getPos());}
-    } else if (jj_2_203(2)) {
+    } else if (jj_2_223(2)) {
       e = Expression(ExprContext.ACCEPT_SUB_QUERY);
         {if (true) return e;}
     } else {
@@ -2674,7 +2860,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public SqlLiteral Natural() throws ParseException {
-    if (jj_2_204(2)) {
+    if (jj_2_224(2)) {
       jj_consume_token(NATURAL);
                 {if (true) return SqlLiteral.createBoolean(true, getPos());}
     } else {
@@ -2685,41 +2871,41 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
   final public SqlLiteral JoinType() throws ParseException {
     JoinType joinType;
-    if (jj_2_208(3)) {
+    if (jj_2_228(3)) {
       jj_consume_token(JOIN);
                  joinType = JoinType.INNER;
-    } else if (jj_2_209(2)) {
+    } else if (jj_2_229(2)) {
       jj_consume_token(INNER);
       jj_consume_token(JOIN);
                          joinType = JoinType.INNER;
-    } else if (jj_2_210(2)) {
+    } else if (jj_2_230(2)) {
       jj_consume_token(LEFT);
-      if (jj_2_205(2)) {
+      if (jj_2_225(2)) {
         jj_consume_token(OUTER);
       } else {
         ;
       }
       jj_consume_token(JOIN);
                                     joinType = JoinType.LEFT;
-    } else if (jj_2_211(2)) {
+    } else if (jj_2_231(2)) {
       jj_consume_token(RIGHT);
-      if (jj_2_206(2)) {
+      if (jj_2_226(2)) {
         jj_consume_token(OUTER);
       } else {
         ;
       }
       jj_consume_token(JOIN);
                                      joinType = JoinType.RIGHT;
-    } else if (jj_2_212(2)) {
+    } else if (jj_2_232(2)) {
       jj_consume_token(FULL);
-      if (jj_2_207(2)) {
+      if (jj_2_227(2)) {
         jj_consume_token(OUTER);
       } else {
         ;
       }
       jj_consume_token(JOIN);
                                     joinType = JoinType.FULL;
-    } else if (jj_2_213(2)) {
+    } else if (jj_2_233(2)) {
       jj_consume_token(CROSS);
       jj_consume_token(JOIN);
                          joinType = JoinType.CROSS;
@@ -2731,29 +2917,82 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     throw new Error("Missing return statement in function");
   }
 
-/** Matches "LEFT JOIN t ON ...", "RIGHT JOIN t USING ...", "JOIN t". */
-  final public SqlNode JoinTable(SqlNode e) throws ParseException {
-    SqlNode e2, condition;
-    final SqlLiteral natural, joinType, on, using;
-    SqlNodeList list;
-    natural = Natural();
-    joinType = JoinType();
-    e2 = TableRef();
-    if (jj_2_214(2)) {
-      jj_consume_token(ON);
-               on = JoinConditionType.ON.symbol(getPos());
-      condition = Expression(ExprContext.ACCEPT_SUB_QUERY);
-            {if (true) return new SqlJoin(joinType.getParserPosition(),
+/**
+ * Parses the FROM clause for a SELECT.
+ *
+ * <p>FROM is mandatory in standard SQL, optional in dialects such as MySQL,
+ * PostgreSQL. The parser allows SELECT without FROM, but the validator fails
+ * if conformance is, say, STRICT_2003.
+ */
+  final public SqlNode FromClause() throws ParseException {
+    SqlNode e, e2;
+    SqlLiteral joinType;
+    e = Join();
+    label_23:
+    while (true) {
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case COMMA:
+        ;
+        break;
+      default:
+        jj_la1[2] = jj_gen;
+        break label_23;
+      }
+      jj_consume_token(COMMA);
+                  joinType = JoinType.COMMA.symbol(getPos());
+      e2 = Join();
+            e = new SqlJoin(joinType.getParserPosition(),
                 e,
-                natural,
+                SqlLiteral.createBoolean(false, joinType.getParserPosition()),
                 joinType,
                 e2,
-                on,
-                condition);}
-    } else if (jj_2_215(2)) {
-      jj_consume_token(USING);
+                JoinConditionType.NONE.symbol(SqlParserPos.ZERO),
+                null);
+    }
+      {if (true) return e;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public SqlNode Join() throws ParseException {
+    SqlNode e;
+    e = TableRef1(ExprContext.ACCEPT_QUERY_OR_JOIN);
+    label_24:
+    while (true) {
+      if (jj_2_234(2)) {
+        ;
+      } else {
+        break label_24;
+      }
+      e = JoinTable(e);
+    }
+        {if (true) return e;}
+    throw new Error("Missing return statement in function");
+  }
+
+/** Matches "LEFT JOIN t ON ...", "RIGHT JOIN t USING ...", "JOIN t". */
+  final public SqlNode JoinTable(SqlNode e) throws ParseException {
+    SqlNode e2, condition;
+    final SqlLiteral natural, joinType, on, using;
+    SqlNodeList list;
+    if (jj_2_237(3)) {
+      natural = Natural();
+      joinType = JoinType();
+      e2 = TableRef1(ExprContext.ACCEPT_QUERY_OR_JOIN);
+      if (jj_2_235(2)) {
+        jj_consume_token(ON);
+               on = JoinConditionType.ON.symbol(getPos());
+        condition = Expression(ExprContext.ACCEPT_SUB_QUERY);
+            {if (true) return new SqlJoin(joinType.getParserPosition(),
+                e,
+                natural,
+                joinType,
+                e2,
+                on,
+                condition);}
+      } else if (jj_2_236(2)) {
+        jj_consume_token(USING);
                   using = JoinConditionType.USING.symbol(getPos());
-      list = ParenthesizedSimpleIdentifierList();
+        list = ParenthesizedSimpleIdentifierList();
             {if (true) return new SqlJoin(joinType.getParserPosition(),
                 e,
                 natural,
@@ -2761,7 +3000,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                 e2,
                 using,
                 new SqlNodeList(list, Span.of(using).end(this)));}
-    } else {
+      } else {
             {if (true) return new SqlJoin(joinType.getParserPosition(),
                 e,
                 natural,
@@ -2769,120 +3008,41 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                 e2,
                 JoinConditionType.NONE.symbol(joinType.getParserPosition()),
                 null);}
-    }
-    throw new Error("Missing return statement in function");
-  }
-
-// TODO jvs 15-Nov-2003:  SQL standard allows parentheses in the FROM list for
-// building up non-linear join trees (e.g. OUTER JOIN two tables, and then INNER
-// JOIN the result).  Also note that aliases on parenthesized FROM expressions
-// "hide" all table names inside the parentheses (without aliases, they're
-// visible).
-//
-// We allow CROSS JOIN to have a join condition, even though that is not valid
-// SQL; the validator will catch it.
-/**
- * Parses the FROM clause for a SELECT.
- *
- * <p>FROM is mandatory in standard SQL, optional in dialects such as MySQL,
- * PostgreSQL. The parser allows SELECT without FROM, but the validator fails
- * if conformance is, say, STRICT_2003.
- */
-  final public SqlNode FromClause() throws ParseException {
-    SqlNode e, e2, condition;
-    SqlLiteral natural, joinType, joinConditionType;
-    SqlNodeList list;
-    SqlParserPos pos;
-    e = TableRef();
-    label_19:
-    while (true) {
-      if (jj_2_216(2)) {
-        ;
-      } else {
-        break label_19;
       }
-      if (jj_2_219(3)) {
-        natural = Natural();
-        joinType = JoinType();
-        e2 = TableRef();
-        if (jj_2_217(2)) {
-          jj_consume_token(ON);
-                    joinConditionType = JoinConditionType.ON.symbol(getPos());
-          condition = Expression(ExprContext.ACCEPT_SUB_QUERY);
-                    e = new SqlJoin(joinType.getParserPosition(),
-                        e,
-                        natural,
-                        joinType,
-                        e2,
-                        joinConditionType,
-                        condition);
-        } else if (jj_2_218(2)) {
-          jj_consume_token(USING);
-                    joinConditionType = JoinConditionType.USING.symbol(getPos());
-          list = ParenthesizedSimpleIdentifierList();
-                    e = new SqlJoin(joinType.getParserPosition(),
-                        e,
-                        natural,
-                        joinType,
-                        e2,
-                        joinConditionType,
-                        new SqlNodeList(list.getList(), Span.of(joinConditionType).end(this)));
-        } else {
-                    e = new SqlJoin(joinType.getParserPosition(),
-                        e,
-                        natural,
-                        joinType,
-                        e2,
-                        JoinConditionType.NONE.symbol(joinType.getParserPosition()),
-                        null);
+    } else if (jj_2_238(2)) {
+      jj_consume_token(CROSS);
+              joinType = JoinType.CROSS.symbol(getPos());
+      jj_consume_token(APPLY);
+      e2 = TableRef2(true);
+        if (!this.conformance.isApplyAllowed()) {
+            {if (true) throw SqlUtil.newContextException(getPos(), RESOURCE.applyNotAllowed());}
         }
-      } else if (jj_2_220(2)) {
-        jj_consume_token(COMMA);
-                      joinType = JoinType.COMMA.symbol(getPos());
-        e2 = TableRef();
-                e = new SqlJoin(joinType.getParserPosition(),
-                    e,
-                    SqlLiteral.createBoolean(false, joinType.getParserPosition()),
-                    joinType,
-                    e2,
-                    JoinConditionType.NONE.symbol(SqlParserPos.ZERO),
-                    null);
-      } else if (jj_2_221(2)) {
-        jj_consume_token(CROSS);
-                      joinType = JoinType.CROSS.symbol(getPos());
-        jj_consume_token(APPLY);
-        e2 = TableRef2(true);
-                if (!this.conformance.isApplyAllowed()) {
-                    {if (true) throw SqlUtil.newContextException(getPos(), RESOURCE.applyNotAllowed());}
-                }
-                e = new SqlJoin(joinType.getParserPosition(),
-                    e,
-                    SqlLiteral.createBoolean(false, joinType.getParserPosition()),
-                    joinType,
-                    e2,
-                    JoinConditionType.NONE.symbol(SqlParserPos.ZERO),
-                    null);
-      } else if (jj_2_222(2)) {
-        jj_consume_token(OUTER);
-                      joinType = JoinType.LEFT.symbol(getPos());
-        jj_consume_token(APPLY);
-        e2 = TableRef2(true);
-                if (!this.conformance.isApplyAllowed()) {
-                    {if (true) throw SqlUtil.newContextException(getPos(), RESOURCE.applyNotAllowed());}
-                }
-                e = new SqlJoin(joinType.getParserPosition(),
-                    e,
-                    SqlLiteral.createBoolean(false, joinType.getParserPosition()),
-                    joinType,
-                    e2,
-                    JoinConditionType.ON.symbol(SqlParserPos.ZERO),
-                    SqlLiteral.createBoolean(true, joinType.getParserPosition()));
-      } else {
-        jj_consume_token(-1);
-        throw new ParseException();
-      }
+        {if (true) return new SqlJoin(joinType.getParserPosition(),
+            e,
+            SqlLiteral.createBoolean(false, joinType.getParserPosition()),
+            joinType,
+            e2,
+            JoinConditionType.NONE.symbol(SqlParserPos.ZERO),
+            null);}
+    } else if (jj_2_239(2)) {
+      jj_consume_token(OUTER);
+              joinType = JoinType.LEFT.symbol(getPos());
+      jj_consume_token(APPLY);
+      e2 = TableRef2(true);
+        if (!this.conformance.isApplyAllowed()) {
+            {if (true) throw SqlUtil.newContextException(getPos(), RESOURCE.applyNotAllowed());}
+        }
+        {if (true) return new SqlJoin(joinType.getParserPosition(),
+            e,
+            SqlLiteral.createBoolean(false, joinType.getParserPosition()),
+            joinType,
+            e2,
+            JoinConditionType.ON.symbol(SqlParserPos.ZERO),
+            SqlLiteral.createBoolean(true, joinType.getParserPosition()));}
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
     }
-        {if (true) return e;}
     throw new Error("Missing return statement in function");
   }
 
@@ -2892,8 +3052,15 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlNode TableRef() throws ParseException {
     final SqlNode e;
-    e = TableRef2(false);
-                           {if (true) return e;}
+    e = TableRef3(ExprContext.ACCEPT_QUERY, false);
+                                                     {if (true) return e;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public SqlNode TableRef1(ExprContext exprContext) throws ParseException {
+    final SqlNode e;
+    e = TableRef3(exprContext, false);
+                                        {if (true) return e;}
     throw new Error("Missing return statement in function");
   }
 
@@ -2901,76 +3068,63 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses a table reference in a FROM clause.
  */
   final public SqlNode TableRef2(boolean lateral) throws ParseException {
+    final SqlNode e;
+    e = TableRef3(ExprContext.ACCEPT_QUERY, lateral);
+                                                       {if (true) return e;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public SqlNode TableRef3(ExprContext exprContext, boolean lateral) throws ParseException {
+    final SqlIdentifier tableName;
     SqlNode tableRef;
-    final SqlNode over;
-    final SqlNode snapshot;
-    final SqlNode match;
-    SqlNodeList extendList = null;
     final SqlIdentifier alias;
-    final Span s, s2;
+    final Span s;
     SqlNodeList args;
-    SqlNode sample;
-    boolean isBernoulli;
-    SqlNumericLiteral samplePercentage;
-    boolean isRepeatable = false;
-    int repeatableSeed = 0;
-    SqlNodeList columnAliasList = null;
+    final SqlNodeList columnAliasList;
     SqlUnnestOperator unnestOp = SqlStdOperatorTable.UNNEST;
-    if (jj_2_231(2)) {
-      tableRef = TableRefWithHintsOpt();
-      if (jj_2_224(2)) {
-        if (jj_2_223(2)) {
-          jj_consume_token(EXTEND);
-        } else {
-          ;
-        }
-        extendList = ExtendList();
-                tableRef = extend(tableRef, extendList);
+    if (jj_2_248(2)) {
+      tableName = CompoundTableIdentifier();
+      if (jj_2_240(2)) {
+        tableRef = TableHints(tableName);
+      } else {
+                                               tableRef = tableName;
+      }
+      if (jj_2_241(2)) {
+        tableRef = ExtendTable(tableRef);
       } else {
         ;
       }
-      over = TableOverOpt();
-            if (over != null) {
-                tableRef = SqlStdOperatorTable.OVER.createCall(
-                    getPos(), tableRef, over);
-            }
-      if (jj_2_225(2)) {
+      tableRef = Over(tableRef);
+      if (jj_2_242(2)) {
         tableRef = Snapshot(tableRef);
       } else {
         ;
       }
-      if (jj_2_226(2)) {
+      if (jj_2_243(2)) {
         tableRef = MatchRecognize(tableRef);
       } else {
         ;
       }
-    } else if (jj_2_232(2)) {
-      if (jj_2_227(2)) {
+    } else if (jj_2_249(2)) {
+      if (jj_2_244(2)) {
         jj_consume_token(LATERAL);
                       lateral = true;
       } else {
         ;
       }
-      tableRef = ParenthesizedExpression(ExprContext.ACCEPT_QUERY);
-      over = TableOverOpt();
-            if (over != null) {
-                tableRef = SqlStdOperatorTable.OVER.createCall(
-                    getPos(), tableRef, over);
-            }
-            if (lateral) {
-                tableRef = SqlStdOperatorTable.LATERAL.createCall(
-                    getPos(), tableRef);
-            }
-      if (jj_2_228(2)) {
+      tableRef = ParenthesizedExpression(exprContext);
+      tableRef = Over(tableRef);
+      tableRef = addLateral(tableRef, lateral);
+      if (jj_2_245(2)) {
         tableRef = MatchRecognize(tableRef);
       } else {
         ;
       }
-    } else if (jj_2_233(2)) {
+    } else if (jj_2_250(2)) {
       jj_consume_token(UNNEST);
                    s = span();
       args = ParenthesizedQueryOrCommaList(ExprContext.ACCEPT_SUB_QUERY);
-      if (jj_2_229(2)) {
+      if (jj_2_246(2)) {
         jj_consume_token(WITH);
         jj_consume_token(ORDINALITY);
                 unnestOp = SqlStdOperatorTable.UNNEST_WITH_ORDINALITY;
@@ -2978,50 +3132,49 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         ;
       }
             tableRef = unnestOp.createCall(s.end(this), (List<SqlNode>) args);
-    } else if (jj_2_234(2)) {
-      if (jj_2_230(2)) {
+    } else if (jj_2_251(2)) {
+      if (jj_2_247(2)) {
         jj_consume_token(LATERAL);
-                     lateral = true;
+                      lateral = true;
       } else {
         ;
       }
-      jj_consume_token(TABLE);
-                  s = span();
-      jj_consume_token(LPAREN);
-      tableRef = TableFunctionCall(s.pos());
-      jj_consume_token(RPAREN);
-            if (lateral) {
-                tableRef = SqlStdOperatorTable.LATERAL.createCall(
-                    s.end(this), tableRef);
-            }
-    } else if (jj_2_235(2)) {
+      tableRef = TableFunctionCall();
+      tableRef = addLateral(tableRef, lateral);
+    } else if (jj_2_252(2)) {
       tableRef = ExtendedTableRef();
     } else {
       jj_consume_token(-1);
       throw new ParseException();
     }
-    if (jj_2_236(2)) {
+    if (jj_2_253(2)) {
       tableRef = Pivot(tableRef);
     } else {
       ;
     }
-    if (jj_2_237(2)) {
+    if (jj_2_254(2)) {
       tableRef = Unpivot(tableRef);
     } else {
       ;
     }
-    if (jj_2_240(2)) {
-      if (jj_2_238(2)) {
+    if (jj_2_257(2)) {
+      if (jj_2_255(2)) {
         jj_consume_token(AS);
       } else {
         ;
       }
       alias = SimpleIdentifier();
-      if (jj_2_239(2)) {
+      if (jj_2_256(2)) {
         columnAliasList = ParenthesizedSimpleIdentifierList();
       } else {
-        ;
+              columnAliasList = null;
       }
+            // Standard SQL (and Postgres) allow applying "AS alias" to a JOIN,
+            // e.g. "FROM (a CROSS JOIN b) AS c". The new alias obscures the
+            // internal aliases, and columns cannot be referenced if they are
+            // not unique. TODO: Support this behavior; see
+            // [CALCITE-5168] Allow AS after parenthesized JOIN
+            checkNotJoin(tableRef);
             if (columnAliasList == null) {
                 tableRef = SqlStdOperatorTable.AS.createCall(
                     Span.of(tableRef).end(this), tableRef, alias);
@@ -3036,79 +3189,105 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     } else {
       ;
     }
-    if (jj_2_246(2)) {
-      jj_consume_token(TABLESAMPLE);
-                        s2 = span();
-      if (jj_2_244(2)) {
-        jj_consume_token(SUBSTITUTE);
-        jj_consume_token(LPAREN);
-        sample = StringLiteral();
-        jj_consume_token(RPAREN);
-                String sampleName =
-                    SqlLiteral.unchain(sample).getValueAs(String.class);
-                SqlSampleSpec sampleSpec = SqlSampleSpec.createNamed(sampleName);
-                final SqlLiteral sampleLiteral =
-                    SqlLiteral.createSample(sampleSpec, s2.end(this));
-                tableRef = SqlStdOperatorTable.TABLESAMPLE.createCall(
-                    s2.add(tableRef).end(this), tableRef, sampleLiteral);
-      } else if (jj_2_245(2)) {
-        if (jj_2_241(2)) {
-          jj_consume_token(BERNOULLI);
-                    isBernoulli = true;
-        } else if (jj_2_242(2)) {
-          jj_consume_token(SYSTEM);
-                    isBernoulli = false;
-        } else {
-          jj_consume_token(-1);
-          throw new ParseException();
-        }
+    if (jj_2_258(2)) {
+      tableRef = Tablesample(tableRef);
+    } else {
+      ;
+    }
+      {if (true) return tableRef;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public SqlNode Tablesample(SqlNode tableRef) throws ParseException {
+    final Span s;
+    final SqlNode sample;
+    final boolean isBernoulli;
+    final SqlNumericLiteral samplePercentage;
+    boolean isRepeatable = false;
+    int repeatableSeed = 0;
+    jj_consume_token(TABLESAMPLE);
+                    s = span(); checkNotJoin(tableRef);
+    if (jj_2_262(2)) {
+      jj_consume_token(SUBSTITUTE);
+      jj_consume_token(LPAREN);
+      sample = StringLiteral();
+      jj_consume_token(RPAREN);
+            String sampleName =
+                SqlLiteral.unchain(sample).getValueAs(String.class);
+            SqlSampleSpec sampleSpec = SqlSampleSpec.createNamed(sampleName);
+            final SqlLiteral sampleLiteral =
+                SqlLiteral.createSample(sampleSpec, s.end(this));
+            tableRef = SqlStdOperatorTable.TABLESAMPLE.createCall(
+                s.add(tableRef).end(this), tableRef, sampleLiteral);
+    } else if (jj_2_263(2)) {
+      if (jj_2_259(2)) {
+        jj_consume_token(BERNOULLI);
+                          isBernoulli = true;
+      } else if (jj_2_260(2)) {
+        jj_consume_token(SYSTEM);
+                       isBernoulli = false;
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+      jj_consume_token(LPAREN);
+      samplePercentage = UnsignedNumericLiteral();
+      jj_consume_token(RPAREN);
+      if (jj_2_261(2)) {
+        jj_consume_token(REPEATABLE);
         jj_consume_token(LPAREN);
-        samplePercentage = UnsignedNumericLiteral();
+        repeatableSeed = IntLiteral();
         jj_consume_token(RPAREN);
-        if (jj_2_243(2)) {
-          jj_consume_token(REPEATABLE);
-          jj_consume_token(LPAREN);
-          repeatableSeed = IntLiteral();
-          jj_consume_token(RPAREN);
-                    isRepeatable = true;
-        } else {
-          ;
-        }
-                final BigDecimal ONE_HUNDRED = BigDecimal.valueOf(100L);
-                BigDecimal rate = samplePercentage.bigDecimalValue();
-                if (rate.compareTo(BigDecimal.ZERO) < 0
-                    || rate.compareTo(ONE_HUNDRED) > 0)
-                {
-                    {if (true) throw SqlUtil.newContextException(getPos(), RESOURCE.invalidSampleSize());}
-                }
+                isRepeatable = true;
+      } else {
+        ;
+      }
+            final BigDecimal ONE_HUNDRED = BigDecimal.valueOf(100L);
+            BigDecimal rate = samplePercentage.bigDecimalValue();
+            if (rate.compareTo(BigDecimal.ZERO) < 0
+                || rate.compareTo(ONE_HUNDRED) > 0)
+            {
+                {if (true) throw SqlUtil.newContextException(getPos(), RESOURCE.invalidSampleSize());}
+            }
 
-                // Treat TABLESAMPLE(0) and TABLESAMPLE(100) as no table
-                // sampling at all.  Not strictly correct: TABLESAMPLE(0)
-                // should produce no output, but it simplifies implementation
-                // to know that some amount of sampling will occur.
-                // In practice values less than ~1E-43% are treated as 0.0 and
-                // values greater than ~99.999997% are treated as 1.0
-                float fRate = rate.divide(ONE_HUNDRED).floatValue();
-                if (fRate > 0.0f && fRate < 1.0f) {
-                    SqlSampleSpec tableSampleSpec =
+            // Treat TABLESAMPLE(0) and TABLESAMPLE(100) as no table
+            // sampling at all.  Not strictly correct: TABLESAMPLE(0)
+            // should produce no output, but it simplifies implementation
+            // to know that some amount of sampling will occur.
+            // In practice values less than ~1E-43% are treated as 0.0 and
+            // values greater than ~99.999997% are treated as 1.0
+            float fRate = rate.divide(ONE_HUNDRED).floatValue();
+            if (fRate > 0.0f && fRate < 1.0f) {
+                SqlSampleSpec tableSampleSpec =
                     isRepeatable
                         ? SqlSampleSpec.createTableSample(
                             isBernoulli, fRate, repeatableSeed)
                         : SqlSampleSpec.createTableSample(isBernoulli, fRate);
 
-                    SqlLiteral tableSampleLiteral =
-                        SqlLiteral.createSample(tableSampleSpec, s2.end(this));
-                    tableRef = SqlStdOperatorTable.TABLESAMPLE.createCall(
-                        s2.end(this), tableRef, tableSampleLiteral);
-                }
-      } else {
-        jj_consume_token(-1);
-        throw new ParseException();
-      }
+                SqlLiteral tableSampleLiteral =
+                    SqlLiteral.createSample(tableSampleSpec, s.end(this));
+                tableRef = SqlStdOperatorTable.TABLESAMPLE.createCall(
+                    s.end(this), tableRef, tableSampleLiteral);
+            }
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+      {if (true) return tableRef;}
+    throw new Error("Missing return statement in function");
+  }
+
+/** Wraps a table reference in a call to EXTEND if an optional "EXTEND" clause
+ * is present. */
+  final public SqlNode ExtendTable(SqlNode tableRef) throws ParseException {
+    final SqlNodeList extendList;
+    if (jj_2_264(2)) {
+      jj_consume_token(EXTEND);
     } else {
       ;
     }
-        {if (true) return tableRef;}
+    extendList = ExtendList();
+        {if (true) return extend(tableRef, extendList);}
     throw new Error("Missing return statement in function");
   }
 
@@ -3117,35 +3296,29 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     List<SqlNode> list = new ArrayList<SqlNode>();
     jj_consume_token(LPAREN);
                s = span();
-    ColumnType(list);
-    label_20:
+    AddColumnType(list);
+    label_25:
     while (true) {
-      if (jj_2_247(2)) {
+      if (jj_2_265(2)) {
         ;
       } else {
-        break label_20;
+        break label_25;
       }
       jj_consume_token(COMMA);
-      ColumnType(list);
+      AddColumnType(list);
     }
     jj_consume_token(RPAREN);
         {if (true) return new SqlNodeList(list, s.end(this));}
     throw new Error("Missing return statement in function");
   }
 
-  final public void ColumnType(List<SqlNode> list) throws ParseException {
-    SqlIdentifier name;
-    SqlDataTypeSpec type;
-    boolean nullable = true;
+  final public void AddColumnType(List<SqlNode> list) throws ParseException {
+    final SqlIdentifier name;
+    final SqlDataTypeSpec type;
+    final boolean nullable;
     name = CompoundIdentifier();
     type = DataType();
-    if (jj_2_248(2)) {
-      jj_consume_token(NOT);
-      jj_consume_token(NULL);
-            nullable = false;
-    } else {
-      ;
-    }
+    nullable = NotNullOpt();
         list.add(name);
         list.add(type.withNullable(nullable, getPos()));
   }
@@ -3153,22 +3326,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 /**
  * Parses a compound identifier with optional type.
  */
-  final public void CompoundIdentifierType(List<SqlNode> list, List<SqlNode> extendList) throws ParseException {
+  final public void AddCompoundIdentifierType(List<SqlNode> list, List<SqlNode> extendList) throws ParseException {
     final SqlIdentifier name;
-    SqlDataTypeSpec type = null;
-    boolean nullable = true;
+    final SqlDataTypeSpec type;
+    final boolean nullable;
     name = CompoundIdentifier();
-    if (jj_2_250(2)) {
+    if (jj_2_266(2)) {
       type = DataType();
-      if (jj_2_249(2)) {
-        jj_consume_token(NOT);
-        jj_consume_token(NULL);
-                nullable = false;
-      } else {
-        ;
-      }
+      nullable = NotNullOpt();
     } else {
-      ;
+          type = null; nullable = true;
     }
         if (type != null) {
             if (!this.conformance.allowExtend()) {
@@ -3181,17 +3348,22 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         list.add(name);
   }
 
-  final public SqlNode TableFunctionCall(SqlParserPos pos) throws ParseException {
-    SqlNode call;
+  final public SqlNode TableFunctionCall() throws ParseException {
+    final Span s;
+    final SqlNode call;
     SqlFunctionCategory funcType = SqlFunctionCategory.USER_DEFINED_TABLE_FUNCTION;
-    if (jj_2_251(2)) {
+    jj_consume_token(TABLE);
+              s = span();
+    jj_consume_token(LPAREN);
+    if (jj_2_267(2)) {
       jj_consume_token(SPECIFIC);
             funcType = SqlFunctionCategory.USER_DEFINED_TABLE_SPECIFIC_FUNCTION;
     } else {
       ;
     }
     call = NamedRoutineCall(funcType, ExprContext.ACCEPT_CURSOR);
-        {if (true) return SqlStdOperatorTable.COLLECTION_TABLE.createCall(pos, call);}
+    jj_consume_token(RPAREN);
+        {if (true) return SqlStdOperatorTable.COLLECTION_TABLE.createCall(s.end(this), call);}
     throw new Error("Missing return statement in function");
   }
 
@@ -3227,68 +3399,64 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses a VALUES leaf query expression.
  */
   final public SqlNode TableConstructor() throws ParseException {
-    final List<SqlNode> rowConstructorList = new ArrayList<SqlNode>();
+    final List<SqlNode> list = new ArrayList<SqlNode>();
     final Span s;
     jj_consume_token(VALUES);
                s = span();
-    RowConstructorList(rowConstructorList);
-        {if (true) return SqlStdOperatorTable.VALUES.createCall(
-            s.end(this), rowConstructorList);}
-    throw new Error("Missing return statement in function");
-  }
-
-/**
- * Parses one or more rows in a VALUES expression.
- */
-  final public void RowConstructorList(List<SqlNode> list) throws ParseException {
-    SqlNode rowConstructor;
-    rowConstructor = RowConstructor();
-                                        list.add(rowConstructor);
-    label_21:
+    AddRowConstructor(list);
+    label_26:
     while (true) {
-      if (jj_2_252(2)) {
+      if (jj_2_268(2)) {
         ;
       } else {
-        break label_21;
+        break label_26;
       }
       jj_consume_token(COMMA);
-      rowConstructor = RowConstructor();
-                                                    list.add(rowConstructor);
+      AddRowConstructor(list);
     }
+        {if (true) return SqlStdOperatorTable.VALUES.createCall(s.end(this), list);}
+    throw new Error("Missing return statement in function");
+  }
+
+/** Parses a row constructor and adds it to a list. */
+  final public void AddRowConstructor(List<SqlNode> list) throws ParseException {
+    SqlNode e;
+    e = RowConstructor();
+                           list.add(e);
   }
 
 /**
  * Parses a row constructor in the context of a VALUES expression.
  */
   final public SqlNode RowConstructor() throws ParseException {
-    SqlNodeList valueList;
-    SqlNode value;
+    final SqlNodeList valueList;
+    final SqlNode value;
     final Span s;
-    if (jj_2_254(3)) {
+    if (jj_2_270(3)) {
       jj_consume_token(LPAREN);
                    s = span();
       jj_consume_token(ROW);
       valueList = ParenthesizedQueryOrCommaListWithDefault(ExprContext.ACCEPT_NONCURSOR);
       jj_consume_token(RPAREN);
                    s.add(this);
-    } else if (jj_2_255(3)) {
-      if (jj_2_253(2)) {
+    } else if (jj_2_271(3)) {
+      if (jj_2_269(2)) {
         jj_consume_token(ROW);
                     s = span();
       } else {
               s = Span.of();
       }
       valueList = ParenthesizedQueryOrCommaListWithDefault(ExprContext.ACCEPT_NONCURSOR);
-    } else if (jj_2_256(2)) {
+    } else if (jj_2_272(2)) {
       value = Expression(ExprContext.ACCEPT_NONCURSOR);
             // NOTE: A bare value here is standard SQL syntax, believe it or
             // not.  Taken together with multi-row table constructors, it leads
             // to very easy mistakes if you forget the parentheses on a
             // single-row constructor.  This is also the reason for the
-            // LOOKAHEAD in RowConstructorList().  It would be so much more
+            // LOOKAHEAD in TableConstructor().  It would be so much more
             // reasonable to require parentheses.  Sigh.
             s = Span.of(value);
-            valueList = new SqlNodeList(Collections.singletonList(value),
+            valueList = new SqlNodeList(ImmutableList.of(value),
                 value.getParserPosition());
     } else {
       jj_consume_token(-1);
@@ -3302,100 +3470,99 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     throw new Error("Missing return statement in function");
   }
 
-/**
- * Parses the optional WHERE clause for SELECT, DELETE, and UPDATE.
- */
-  final public SqlNode WhereOpt() throws ParseException {
+/** Parses a WHERE clause for SELECT, DELETE, and UPDATE. */
+  final public SqlNode Where() throws ParseException {
     SqlNode condition;
-    if (jj_2_257(2)) {
-      jj_consume_token(WHERE);
-      condition = Expression(ExprContext.ACCEPT_SUB_QUERY);
+    jj_consume_token(WHERE);
+    condition = Expression(ExprContext.ACCEPT_SUB_QUERY);
         {if (true) return condition;}
-    } else {
-        {if (true) return null;}
-    }
     throw new Error("Missing return statement in function");
   }
 
-/**
- * Parses the optional GROUP BY clause for SELECT.
- */
-  final public SqlNodeList GroupByOpt() throws ParseException {
-    List<SqlNode> list = new ArrayList<SqlNode>();
+/** Parses a GROUP BY clause for SELECT. */
+  final public SqlNodeList GroupBy() throws ParseException {
+    final List<SqlNode> list;
+    final boolean distinct;
     final Span s;
-    if (jj_2_258(2)) {
-      jj_consume_token(GROUP);
+    jj_consume_token(GROUP);
               s = span();
-      jj_consume_token(BY);
-      list = GroupingElementList();
-        {if (true) return new SqlNodeList(list, s.addAll(list).pos());}
+    jj_consume_token(BY);
+    if (jj_2_273(2)) {
+      jj_consume_token(DISTINCT);
+                     distinct = true;
+    } else if (jj_2_274(2)) {
+      jj_consume_token(ALL);
+                distinct = false;
     } else {
-        {if (true) return null;}
-    }
+          distinct = false;
+    }
+    list = GroupingElementList();
+        final SqlParserPos pos = s.end(this);
+        final List<SqlNode> list2 = distinct
+            ? ImmutableList.of(
+                SqlInternalOperators.GROUP_BY_DISTINCT.createCall(pos, list))
+            : list;
+        {if (true) return new SqlNodeList(list2, pos);}
     throw new Error("Missing return statement in function");
   }
 
   final public List<SqlNode> GroupingElementList() throws ParseException {
-    List<SqlNode> list = new ArrayList<SqlNode>();
-    SqlNode e;
-    e = GroupingElement();
-                            list.add(e);
-    label_22:
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    AddGroupingElement(list);
+    label_27:
     while (true) {
-      if (jj_2_259(2)) {
+      if (jj_2_275(2)) {
         ;
       } else {
-        break label_22;
+        break label_27;
       }
       jj_consume_token(COMMA);
-      e = GroupingElement();
-                                list.add(e);
+      AddGroupingElement(list);
     }
       {if (true) return list;}
     throw new Error("Missing return statement in function");
   }
 
-  final public SqlNode GroupingElement() throws ParseException {
-    List<SqlNode> list;
+  final public void AddGroupingElement(List<SqlNode> list) throws ParseException {
+    final List<SqlNode> subList;
     final SqlNodeList nodes;
-    final SqlNode e;
     final Span s;
-    if (jj_2_260(2)) {
+    if (jj_2_276(2)) {
       jj_consume_token(GROUPING);
                  s = span();
       jj_consume_token(SETS);
       jj_consume_token(LPAREN);
-      list = GroupingElementList();
+      subList = GroupingElementList();
       jj_consume_token(RPAREN);
-        {if (true) return SqlStdOperatorTable.GROUPING_SETS.createCall(s.end(this), list);}
-    } else if (jj_2_261(2)) {
+        list.add(
+            SqlStdOperatorTable.GROUPING_SETS.createCall(s.end(this), subList));
+    } else if (jj_2_277(2)) {
       jj_consume_token(ROLLUP);
                s = span();
       jj_consume_token(LPAREN);
       nodes = ExpressionCommaList(s, ExprContext.ACCEPT_SUB_QUERY);
       jj_consume_token(RPAREN);
-        {if (true) return SqlStdOperatorTable.ROLLUP.createCall(s.end(this),
-            nodes.getList());}
-    } else if (jj_2_262(2)) {
+        list.add(
+            SqlStdOperatorTable.ROLLUP.createCall(s.end(this), nodes.getList()));
+    } else if (jj_2_278(2)) {
       jj_consume_token(CUBE);
              s = span();
       jj_consume_token(LPAREN);
       nodes = ExpressionCommaList(s, ExprContext.ACCEPT_SUB_QUERY);
       jj_consume_token(RPAREN);
-        {if (true) return SqlStdOperatorTable.CUBE.createCall(s.end(this),
-            nodes.getList());}
-    } else if (jj_2_263(3)) {
+        list.add(
+            SqlStdOperatorTable.CUBE.createCall(s.end(this), nodes.getList()));
+    } else if (jj_2_279(3)) {
       jj_consume_token(LPAREN);
+               s = span();
       jj_consume_token(RPAREN);
-        {if (true) return new SqlNodeList(getPos());}
-    } else if (jj_2_264(2)) {
-      e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-        {if (true) return e;}
+        list.add(new SqlNodeList(s.end(this)));
+    } else if (jj_2_280(2)) {
+      AddExpression(list, ExprContext.ACCEPT_SUB_QUERY);
     } else {
       jj_consume_token(-1);
       throw new ParseException();
     }
-    throw new Error("Missing return statement in function");
   }
 
 /**
@@ -3404,7 +3571,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlNodeList ExpressionCommaList(final Span s,
     ExprContext exprContext) throws ParseException {
     final List<SqlNode> list = new ArrayList<SqlNode>();
-    ExpressionCommaList2(list, exprContext);
+    AddExpressions(list, exprContext);
         {if (true) return new SqlNodeList(list, s.addAll(list).pos());}
     throw new Error("Missing return statement in function");
   }
@@ -3413,96 +3580,79 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses a list of expressions separated by commas,
  * appending expressions to a given list.
  */
-  final public void ExpressionCommaList2(List<SqlNode> list, ExprContext exprContext) throws ParseException {
-    SqlNode e;
-    e = Expression(exprContext);
-                                  list.add(e);
-    label_23:
+  final public void AddExpressions(List<SqlNode> list, ExprContext exprContext) throws ParseException {
+    AddExpression(list, exprContext);
+    label_28:
     while (true) {
-      if (jj_2_265(2)) {
+      if (jj_2_281(2)) {
         ;
       } else {
-        break label_23;
+        break label_28;
       }
       jj_consume_token(COMMA);
-      e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-            list.add(e);
+      AddExpression(list, ExprContext.ACCEPT_SUB_QUERY);
     }
   }
 
-/**
- * Parses the optional HAVING clause for SELECT.
- */
-  final public SqlNode HavingOpt() throws ParseException {
+/** Parses a HAVING clause for SELECT. */
+  final public SqlNode Having() throws ParseException {
     SqlNode e;
-    if (jj_2_266(2)) {
-      jj_consume_token(HAVING);
-      e = Expression(ExprContext.ACCEPT_SUB_QUERY);
+    jj_consume_token(HAVING);
+    e = Expression(ExprContext.ACCEPT_SUB_QUERY);
                                                             {if (true) return e;}
-    } else {
-      {if (true) return null;}
-    }
     throw new Error("Missing return statement in function");
   }
 
-/**
- * Parses the optional WINDOW clause for SELECT
- */
-  final public SqlNodeList WindowOpt() throws ParseException {
-    SqlIdentifier id;
-    SqlWindow e;
-    List<SqlNode> list;
+/** Parses a WINDOW clause for SELECT. */
+  final public SqlNodeList Window() throws ParseException {
+    final List<SqlNode> list = new ArrayList<SqlNode>();
     final Span s;
-    if (jj_2_268(2)) {
-      jj_consume_token(WINDOW);
+    jj_consume_token(WINDOW);
                s = span();
-      id = SimpleIdentifier();
-      jj_consume_token(AS);
-      e = WindowSpecification();
-        e.setDeclName(id);
-        list = startList(e);
-      label_24:
-      while (true) {
-        if (jj_2_267(2)) {
-          ;
-        } else {
-          break label_24;
-        }
-        jj_consume_token(COMMA);
-        id = SimpleIdentifier();
-        jj_consume_token(AS);
-        e = WindowSpecification();
-            e.setDeclName(id);
-            list.add(e);
+    AddWindowSpec(list);
+    label_29:
+    while (true) {
+      if (jj_2_282(2)) {
+        ;
+      } else {
+        break label_29;
       }
-        {if (true) return new SqlNodeList(list, s.addAll(list).pos());}
-    } else {
-        {if (true) return null;}
+      jj_consume_token(COMMA);
+      AddWindowSpec(list);
     }
+        {if (true) return new SqlNodeList(list, s.addAll(list).pos());}
     throw new Error("Missing return statement in function");
   }
 
+  final public void AddWindowSpec(List<SqlNode> list) throws ParseException {
+    final SqlIdentifier id;
+    final SqlWindow e;
+    id = SimpleIdentifier();
+    jj_consume_token(AS);
+    e = WindowSpecification();
+        e.setDeclName(id);
+        list.add(e);
+  }
+
 /**
  * Parses a window specification.
  */
   final public SqlWindow WindowSpecification() throws ParseException {
-    SqlIdentifier id;
-    List list;
-    SqlNodeList partitionList;
-    SqlNodeList orderList;
-    SqlLiteral isRows = SqlLiteral.createBoolean(false, SqlParserPos.ZERO);
-    SqlNode lowerBound = null, upperBound = null;
-    SqlParserPos startPos;
+    final SqlIdentifier id;
+    final SqlNodeList partitionList;
+    final SqlNodeList orderList;
+    final SqlLiteral isRows;
+    final SqlNode lowerBound, upperBound;
     final Span s, s1, s2;
-    SqlLiteral allowPartial = null;
+    final SqlLiteral allowPartial;
     jj_consume_token(LPAREN);
                s = span();
-    if (jj_2_269(2)) {
+    if (jj_2_283(2)) {
       id = SimpleIdentifier();
     } else {
           id = null;
     }
-    if (jj_2_270(2)) {
+    if (jj_2_284(2)) {
       jj_consume_token(PARTITION);
                       s1 = span();
       jj_consume_token(BY);
@@ -3510,57 +3660,53 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     } else {
           partitionList = SqlNodeList.EMPTY;
     }
-    if (jj_2_271(2)) {
+    if (jj_2_285(2)) {
       orderList = OrderBy(true);
     } else {
           orderList = SqlNodeList.EMPTY;
     }
-    if (jj_2_276(2)) {
-      if (jj_2_272(2)) {
+    if (jj_2_290(2)) {
+      if (jj_2_286(2)) {
         jj_consume_token(ROWS);
                      isRows = SqlLiteral.createBoolean(true, getPos());
-      } else if (jj_2_273(2)) {
+      } else if (jj_2_287(2)) {
         jj_consume_token(RANGE);
                       isRows = SqlLiteral.createBoolean(false, getPos());
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
-      if (jj_2_274(2)) {
+      if (jj_2_288(2)) {
         jj_consume_token(BETWEEN);
         lowerBound = WindowRange();
         jj_consume_token(AND);
         upperBound = WindowRange();
-      } else if (jj_2_275(2)) {
+      } else if (jj_2_289(2)) {
         lowerBound = WindowRange();
+              upperBound = null;
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
     } else {
-      ;
+            isRows = SqlLiteral.createBoolean(false, SqlParserPos.ZERO);
+            lowerBound = upperBound = null;
     }
-    if (jj_2_279(2)) {
-      if (jj_2_277(2)) {
-        jj_consume_token(ALLOW);
+    if (jj_2_291(2)) {
+      jj_consume_token(ALLOW);
                   s2 = span();
-        jj_consume_token(PARTIAL);
+      jj_consume_token(PARTIAL);
             allowPartial = SqlLiteral.createBoolean(true, s2.end(this));
-      } else if (jj_2_278(2)) {
-        jj_consume_token(DISALLOW);
+    } else if (jj_2_292(2)) {
+      jj_consume_token(DISALLOW);
                      s2 = span();
-        jj_consume_token(PARTIAL);
+      jj_consume_token(PARTIAL);
             allowPartial = SqlLiteral.createBoolean(false, s2.end(this));
-      } else {
-        jj_consume_token(-1);
-        throw new ParseException();
-      }
     } else {
-      ;
+          allowPartial = null;
     }
     jj_consume_token(RPAREN);
-        {if (true) return SqlWindow.create(
-            null, id, partitionList, orderList,
+        {if (true) return SqlWindow.create(null, id, partitionList, orderList,
             isRows, lowerBound, upperBound, allowPartial, s.end(this));}
     throw new Error("Missing return statement in function");
   }
@@ -3568,30 +3714,30 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlNode WindowRange() throws ParseException {
     final SqlNode e;
     final Span s;
-    if (jj_2_284(2)) {
+    if (jj_2_297(2)) {
       jj_consume_token(CURRENT);
                 s = span();
       jj_consume_token(ROW);
         {if (true) return SqlWindow.createCurrentRow(s.end(this));}
-    } else if (jj_2_285(2)) {
+    } else if (jj_2_298(2)) {
       jj_consume_token(UNBOUNDED);
                   s = span();
-      if (jj_2_280(2)) {
+      if (jj_2_293(2)) {
         jj_consume_token(PRECEDING);
             {if (true) return SqlWindow.createUnboundedPreceding(s.end(this));}
-      } else if (jj_2_281(2)) {
+      } else if (jj_2_294(2)) {
         jj_consume_token(FOLLOWING);
             {if (true) return SqlWindow.createUnboundedFollowing(s.end(this));}
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
-    } else if (jj_2_286(2)) {
+    } else if (jj_2_299(2)) {
       e = Expression(ExprContext.ACCEPT_NON_QUERY);
-      if (jj_2_282(2)) {
+      if (jj_2_295(2)) {
         jj_consume_token(PRECEDING);
             {if (true) return SqlWindow.createPreceding(e, getPos());}
-      } else if (jj_2_283(2)) {
+      } else if (jj_2_296(2)) {
         jj_consume_token(FOLLOWING);
             {if (true) return SqlWindow.createFollowing(e, getPos());}
       } else {
@@ -3609,8 +3755,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses an ORDER BY clause.
  */
   final public SqlNodeList OrderBy(boolean accept) throws ParseException {
-    List<SqlNode> list;
-    SqlNode e;
+    final List<SqlNode> list = new ArrayList<SqlNode>();
     final Span s;
     jj_consume_token(ORDER);
         s = span();
@@ -3621,33 +3766,31 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             {if (true) throw SqlUtil.newContextException(s.pos(), RESOURCE.illegalOrderBy());}
         }
     jj_consume_token(BY);
-    e = OrderItem();
-        list = startList(e);
-    label_25:
+    AddOrderItem(list);
+    label_30:
     while (true) {
-      if (jj_2_287(2)) {
+      if (jj_2_300(2)) {
         ;
       } else {
-        break label_25;
+        break label_30;
       }
       jj_consume_token(COMMA);
-      e = OrderItem();
-                                               list.add(e);
+      AddOrderItem(list);
     }
         {if (true) return new SqlNodeList(list, s.addAll(list).pos());}
     throw new Error("Missing return statement in function");
   }
 
 /**
- * Parses one list item in an ORDER BY clause.
+ * Parses one item in an ORDER BY clause, and adds it to a list.
  */
-  final public SqlNode OrderItem() throws ParseException {
+  final public void AddOrderItem(List<SqlNode> list) throws ParseException {
     SqlNode e;
     e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-    if (jj_2_290(2)) {
-      if (jj_2_288(2)) {
+    if (jj_2_303(2)) {
+      if (jj_2_301(2)) {
         jj_consume_token(ASC);
-      } else if (jj_2_289(2)) {
+      } else if (jj_2_302(2)) {
         jj_consume_token(DESC);
             e = SqlStdOperatorTable.DESC.createCall(getPos(), e);
       } else {
@@ -3657,12 +3800,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     } else {
       ;
     }
-    if (jj_2_293(2)) {
-      if (jj_2_291(2)) {
+    if (jj_2_306(2)) {
+      if (jj_2_304(2)) {
         jj_consume_token(NULLS);
         jj_consume_token(FIRST);
             e = SqlStdOperatorTable.NULLS_FIRST.createCall(getPos(), e);
-      } else if (jj_2_292(2)) {
+      } else if (jj_2_305(2)) {
         jj_consume_token(NULLS);
         jj_consume_token(LAST);
             e = SqlStdOperatorTable.NULLS_LAST.createCall(getPos(), e);
@@ -3673,10 +3816,30 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     } else {
       ;
     }
-        {if (true) return e;}
+        list.add(e);
+  }
+
+/** Wraps a table reference in a call to OVER if an optional "OVER" clause
+ * is present (if the dialect supports OVER for table expressions). */
+  final public SqlNode Over(SqlNode tableRef) throws ParseException {
+    final SqlNode over;
+    over = TableOverOpt();
+        if (over != null) {
+            {if (true) return SqlStdOperatorTable.OVER.createCall(
+                getPos(), checkNotJoin(tableRef), over);}
+        } else {
+            {if (true) return tableRef;}
+        }
     throw new Error("Missing return statement in function");
   }
 
+  SqlNode addLateral(SqlNode tableRef, boolean lateral) throws ParseException {
+    return lateral
+        ? SqlStdOperatorTable.LATERAL.createCall(getPos(),
+            checkNotJoin(tableRef))
+        : tableRef;
+  }
+
 /**
  * Parses a FOR SYSTEM_TIME clause following a table expression.
  */
@@ -3711,35 +3874,35 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final SqlNodeList axisList;
     final SqlNodeList inList;
     jj_consume_token(PIVOT);
-              s = span();
+              s = span(); checkNotJoin(tableRef);
     jj_consume_token(LPAREN);
-    PivotAgg(aggList);
-    label_26:
+    AddPivotAgg(aggList);
+    label_31:
     while (true) {
-      if (jj_2_294(2)) {
+      if (jj_2_307(2)) {
         ;
       } else {
-        break label_26;
+        break label_31;
       }
       jj_consume_token(COMMA);
-      PivotAgg(aggList);
+      AddPivotAgg(aggList);
     }
     jj_consume_token(FOR);
     axisList = SimpleIdentifierOrList();
     jj_consume_token(IN);
     jj_consume_token(LPAREN);
                     s2 = span();
-    if (jj_2_296(2)) {
-      PivotValue(valueList);
-      label_27:
+    if (jj_2_309(2)) {
+      AddPivotValue(valueList);
+      label_32:
       while (true) {
-        if (jj_2_295(2)) {
+        if (jj_2_308(2)) {
           ;
         } else {
-          break label_27;
+          break label_32;
         }
         jj_consume_token(COMMA);
-        PivotValue(valueList);
+        AddPivotValue(valueList);
       }
     } else {
       ;
@@ -3753,12 +3916,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     throw new Error("Missing return statement in function");
   }
 
-  final public void PivotAgg(List<SqlNode> list) throws ParseException {
+  final public void AddPivotAgg(List<SqlNode> list) throws ParseException {
     final SqlNode e;
     final SqlIdentifier alias;
     e = NamedFunctionCall();
-    if (jj_2_298(2)) {
-      if (jj_2_297(2)) {
+    if (getToken(1).kind != COMMA && getToken(1).kind != FOR) {
+      if (jj_2_310(2)) {
         jj_consume_token(AS);
       } else {
         ;
@@ -3772,14 +3935,14 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     }
   }
 
-  final public void PivotValue(List<SqlNode> list) throws ParseException {
+  final public void AddPivotValue(List<SqlNode> list) throws ParseException {
     final SqlNode e;
     final SqlNodeList tuple;
     final SqlIdentifier alias;
     e = RowConstructor();
                            tuple = SqlParserUtil.stripRow(e);
-    if (jj_2_300(2)) {
-      if (jj_2_299(2)) {
+    if (jj_2_312(2)) {
+      if (jj_2_311(2)) {
         jj_consume_token(AS);
       } else {
         ;
@@ -3803,12 +3966,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final List<SqlNode> values = new ArrayList<SqlNode>();
     final SqlNodeList inList;
     jj_consume_token(UNPIVOT);
-                s = span();
-    if (jj_2_301(2)) {
+                s = span(); checkNotJoin(tableRef);
+    if (jj_2_313(2)) {
       jj_consume_token(INCLUDE);
       jj_consume_token(NULLS);
                             includeNulls = true;
-    } else if (jj_2_302(2)) {
+    } else if (jj_2_314(2)) {
       jj_consume_token(EXCLUDE);
       jj_consume_token(NULLS);
                             includeNulls = false;
@@ -3822,16 +3985,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     jj_consume_token(IN);
     jj_consume_token(LPAREN);
                s2 = span();
-    UnpivotValue(values);
-    label_28:
+    AddUnpivotValue(values);
+    label_33:
     while (true) {
-      if (jj_2_303(2)) {
+      if (jj_2_315(2)) {
         ;
       } else {
-        break label_28;
+        break label_33;
       }
       jj_consume_token(COMMA);
-      UnpivotValue(values);
+      AddUnpivotValue(values);
     }
     jj_consume_token(RPAREN);
       inList = new SqlNodeList(values, s2.end(this));
@@ -3841,11 +4004,11 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     throw new Error("Missing return statement in function");
   }
 
-  final public void UnpivotValue(List<SqlNode> list) throws ParseException {
+  final public void AddUnpivotValue(List<SqlNode> list) throws ParseException {
     final SqlNodeList columnList;
     final SqlNode values;
     columnList = SimpleIdentifierOrList();
-    if (jj_2_304(2)) {
+    if (jj_2_316(2)) {
       jj_consume_token(AS);
       values = RowConstructor();
             final SqlNodeList valueList = SqlParserUtil.stripRow(values);
@@ -3862,49 +4025,48 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlMatchRecognize MatchRecognize(SqlNode tableRef) throws ParseException {
     final Span s, s0, s1, s2;
-    SqlNodeList measureList = SqlNodeList.EMPTY;
-    SqlNodeList partitionList = SqlNodeList.EMPTY;
-    SqlNodeList orderList = SqlNodeList.EMPTY;
-    SqlNode pattern;
-    SqlLiteral interval;
-    SqlNodeList patternDefList;
+    final SqlNodeList measureList;
+    final SqlNodeList partitionList;
+    final SqlNodeList orderList;
+    final SqlNode pattern;
+    final SqlLiteral interval;
+    final SqlNodeList patternDefList;
     final SqlNode after;
-    SqlParserPos pos;
     final SqlNode var;
     final SqlLiteral rowsPerMatch;
-    SqlNodeList subsetList = SqlNodeList.EMPTY;
-    SqlLiteral isStrictStarts = SqlLiteral.createBoolean(false, getPos());
-    SqlLiteral isStrictEnds = SqlLiteral.createBoolean(false, getPos());
+    final SqlNodeList subsetList;
+    final SqlLiteral isStrictStarts;
+    final SqlLiteral isStrictEnds;
     jj_consume_token(MATCH_RECOGNIZE);
-                        s = span();
+                        s = span(); checkNotJoin(tableRef);
     jj_consume_token(LPAREN);
-    if (jj_2_305(2)) {
+    if (jj_2_317(2)) {
       jj_consume_token(PARTITION);
                       s2 = span();
       jj_consume_token(BY);
       partitionList = ExpressionCommaList(s2, ExprContext.ACCEPT_NON_QUERY);
     } else {
-      ;
+          partitionList = SqlNodeList.EMPTY;
     }
-    if (jj_2_306(2)) {
+    if (jj_2_318(2)) {
       orderList = OrderBy(true);
     } else {
-      ;
+          orderList = SqlNodeList.EMPTY;
     }
-    if (jj_2_307(2)) {
+    if (jj_2_319(2)) {
       jj_consume_token(MEASURES);
       measureList = MeasureColumnCommaList(span());
     } else {
-      ;
+          measureList = SqlNodeList.EMPTY;
     }
-    if (jj_2_308(2)) {
+    if (jj_2_320(2)) {
       jj_consume_token(ONE);
                 s0 = span();
       jj_consume_token(ROW);
       jj_consume_token(PER);
       jj_consume_token(MATCH);
             rowsPerMatch = SqlMatchRecognize.RowsPerMatchOption.ONE_ROW.symbol(s0.end(this));
-    } else if (jj_2_309(2)) {
+    } else if (jj_2_321(2)) {
       jj_consume_token(ALL);
                 s0 = span();
       jj_consume_token(ROWS);
@@ -3912,27 +4074,27 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
       jj_consume_token(MATCH);
             rowsPerMatch = SqlMatchRecognize.RowsPerMatchOption.ALL_ROWS.symbol(s0.end(this));
     } else {
-            rowsPerMatch = null;
+          rowsPerMatch = null;
     }
-    if (jj_2_315(2)) {
+    if (jj_2_327(2)) {
       jj_consume_token(AFTER);
                   s1 = span();
       jj_consume_token(MATCH);
       jj_consume_token(SKIP_);
-      if (jj_2_313(2)) {
+      if (jj_2_325(2)) {
         jj_consume_token(TO);
-        if (jj_2_311(2)) {
+        if (jj_2_323(2)) {
           jj_consume_token(NEXT);
           jj_consume_token(ROW);
                     after = SqlMatchRecognize.AfterOption.SKIP_TO_NEXT_ROW
                         .symbol(s1.end(this));
-        } else if (jj_2_312(2)) {
+        } else if (jj_2_324(2)) {
           jj_consume_token(FIRST);
           var = SimpleIdentifier();
                     after = SqlMatchRecognize.SKIP_TO_FIRST.createCall(
                         s1.end(var), var);
         } else if (true) {
-          if (jj_2_310(2)) {
+          if (jj_2_322(2)) {
             jj_consume_token(LAST);
           } else {
             ;
@@ -3944,7 +4106,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
           jj_consume_token(-1);
           throw new ParseException();
         }
-      } else if (jj_2_314(2)) {
+      } else if (jj_2_326(2)) {
         jj_consume_token(PAST);
         jj_consume_token(LAST);
         jj_consume_token(ROW);
@@ -3959,31 +4121,31 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     }
     jj_consume_token(PATTERN);
     jj_consume_token(LPAREN);
-    if (jj_2_316(2)) {
+    if (jj_2_328(2)) {
       jj_consume_token(CARET);
                   isStrictStarts = SqlLiteral.createBoolean(true, getPos());
     } else {
           isStrictStarts = SqlLiteral.createBoolean(false, getPos());
     }
     pattern = PatternExpression();
-    if (jj_2_317(2)) {
+    if (jj_2_329(2)) {
       jj_consume_token(DOLLAR);
                    isStrictEnds = SqlLiteral.createBoolean(true, getPos());
     } else {
           isStrictEnds = SqlLiteral.createBoolean(false, getPos());
     }
     jj_consume_token(RPAREN);
-    if (jj_2_318(2)) {
+    if (jj_2_330(2)) {
       jj_consume_token(WITHIN);
       interval = IntervalLiteral();
     } else {
           interval = null;
     }
-    if (jj_2_319(2)) {
+    if (jj_2_331(2)) {
       jj_consume_token(SUBSET);
       subsetList = SubsetDefinitionCommaList(span());
     } else {
-      ;
+          subsetList = SqlNodeList.EMPTY;
     }
     jj_consume_token(DEFINE);
     patternDefList = PatternDefinitionCommaList(span());
@@ -3995,45 +4157,41 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public SqlNodeList MeasureColumnCommaList(Span s) throws ParseException {
-    SqlNode e;
-    final List<SqlNode> eList = new ArrayList<SqlNode>();
-    e = MeasureColumn();
-        eList.add(e);
-    label_29:
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    AddMeasureColumn(list);
+    label_34:
     while (true) {
-      if (jj_2_320(2)) {
+      if (jj_2_332(2)) {
         ;
       } else {
-        break label_29;
+        break label_34;
       }
       jj_consume_token(COMMA);
-      e = MeasureColumn();
-            eList.add(e);
+      AddMeasureColumn(list);
     }
-        {if (true) return new SqlNodeList(eList, s.addAll(eList).pos());}
+      {if (true) return new SqlNodeList(list, s.addAll(list).pos());}
     throw new Error("Missing return statement in function");
   }
 
-  final public SqlNode MeasureColumn() throws ParseException {
-    SqlNode e;
-    SqlIdentifier alias;
+  final public void AddMeasureColumn(List<SqlNode> list) throws ParseException {
+    final SqlNode e;
+    final SqlIdentifier alias;
     e = Expression(ExprContext.ACCEPT_NON_QUERY);
     jj_consume_token(AS);
     alias = SimpleIdentifier();
-        {if (true) return SqlStdOperatorTable.AS.createCall(Span.of(e).end(this), e, alias);}
-    throw new Error("Missing return statement in function");
+        list.add(SqlStdOperatorTable.AS.createCall(Span.of(e).end(this), e, alias));
   }
 
   final public SqlNode PatternExpression() throws ParseException {
     SqlNode left;
     SqlNode right;
     left = PatternTerm();
-    label_30:
+    label_35:
     while (true) {
-      if (jj_2_321(2)) {
+      if (jj_2_333(2)) {
         ;
       } else {
-        break label_30;
+        break label_35;
       }
       jj_consume_token(VERTICAL_BAR);
       right = PatternTerm();
@@ -4048,12 +4206,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     SqlNode left;
     SqlNode right;
     left = PatternFactor();
-    label_31:
+    label_36:
     while (true) {
-      if (jj_2_322(2)) {
+      if (jj_2_334(2)) {
         ;
       } else {
-        break label_31;
+        break label_36;
       }
       right = PatternFactor();
             left = SqlStdOperatorTable.PATTERN_CONCAT.createCall(
@@ -4064,61 +4222,58 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public SqlNode PatternFactor() throws ParseException {
-    SqlNode e;
-    SqlNode extra;
-    SqlLiteral startNum = null;
-    SqlLiteral endNum = null;
-    SqlLiteral reluctant = SqlLiteral.createBoolean(false, SqlParserPos.ZERO);
+    final SqlNode e;
+    final SqlNode extra;
+    final SqlLiteral startNum;
+    final SqlLiteral endNum;
+    final SqlLiteral reluctant;
     e = PatternPrimary();
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case LBRACE:
     case HOOK:
     case PLUS:
     case STAR:
-      if (jj_2_328(2)) {
+      if (jj_2_340(2)) {
         jj_consume_token(STAR);
-                startNum = SqlLiteral.createExactNumeric("0", SqlParserPos.ZERO);
-                endNum = SqlLiteral.createExactNumeric("-1", SqlParserPos.ZERO);
-      } else if (jj_2_329(2)) {
+                startNum = LITERAL_ZERO;
+                endNum = LITERAL_MINUS_ONE;
+      } else if (jj_2_341(2)) {
         jj_consume_token(PLUS);
-                startNum = SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO);
-                endNum = SqlLiteral.createExactNumeric("-1", SqlParserPos.ZERO);
-      } else if (jj_2_330(2)) {
+                startNum = LITERAL_ONE;
+                endNum = LITERAL_MINUS_ONE;
+      } else if (jj_2_342(2)) {
         jj_consume_token(HOOK);
-                startNum = SqlLiteral.createExactNumeric("0", SqlParserPos.ZERO);
-                endNum = SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO);
-      } else if (jj_2_331(2)) {
+                startNum = LITERAL_ZERO;
+                endNum = LITERAL_ONE;
+      } else if (jj_2_343(2)) {
         jj_consume_token(LBRACE);
-        if (jj_2_325(2)) {
+        if (jj_2_337(2)) {
           startNum = UnsignedNumericLiteral();
-                                                      endNum = startNum;
-          if (jj_2_324(2)) {
+          if (jj_2_336(2)) {
             jj_consume_token(COMMA);
-                        endNum = SqlLiteral.createExactNumeric("-1", SqlParserPos.ZERO);
-            if (jj_2_323(2)) {
+            if (jj_2_335(2)) {
               endNum = UnsignedNumericLiteral();
             } else {
-              ;
+                          endNum = LITERAL_MINUS_ONE;
             }
           } else {
-            ;
+                       endNum = startNum;
           }
           jj_consume_token(RBRACE);
-        } else if (jj_2_326(2)) {
-                    startNum = SqlLiteral.createExactNumeric("-1", SqlParserPos.ZERO);
+        } else if (jj_2_338(2)) {
           jj_consume_token(COMMA);
           endNum = UnsignedNumericLiteral();
           jj_consume_token(RBRACE);
-        } else if (jj_2_327(2)) {
+                  startNum = LITERAL_MINUS_ONE;
+        } else if (jj_2_339(2)) {
           jj_consume_token(MINUS);
           extra = PatternExpression();
           jj_consume_token(MINUS);
           jj_consume_token(RBRACE);
-                    extra = SqlStdOperatorTable.PATTERN_EXCLUDE.createCall(
-                        Span.of(extra).end(this), extra);
-                    e = SqlStdOperatorTable.PATTERN_CONCAT.createCall(
-                        Span.of(e).end(this), e, extra);
-                    {if (true) return e;}
+                    {if (true) return SqlStdOperatorTable.PATTERN_CONCAT.createCall(
+                        Span.of(e).end(this), e,
+                        SqlStdOperatorTable.PATTERN_EXCLUDE.createCall(
+                            Span.of(extra).end(this), extra));}
         } else {
           jj_consume_token(-1);
           throw new ParseException();
@@ -4127,96 +4282,89 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         jj_consume_token(-1);
         throw new ParseException();
       }
-      if (jj_2_332(2)) {
+      if (jj_2_344(2)) {
         jj_consume_token(HOOK);
-                if (startNum.intValue(true) != endNum.intValue(true)) {
-                    reluctant = SqlLiteral.createBoolean(true, SqlParserPos.ZERO);
-                }
+                reluctant = SqlLiteral.createBoolean(
+                    startNum.intValue(true) != endNum.intValue(true),
+                    SqlParserPos.ZERO);
       } else {
-        ;
+              reluctant = SqlLiteral.createBoolean(false, SqlParserPos.ZERO);
       }
       break;
     default:
-      jj_la1[2] = jj_gen;
-      ;
+      jj_la1[3] = jj_gen;
+          {if (true) return e;}
     }
-        if (startNum == null) {
-            {if (true) return e;}
-        } else {
-            {if (true) return SqlStdOperatorTable.PATTERN_QUANTIFIER.createCall(
-                span().end(e), e, startNum, endNum, reluctant);}
-        }
+        {if (true) return SqlStdOperatorTable.PATTERN_QUANTIFIER.createCall(
+            span().end(e), e, startNum, endNum, reluctant);}
     throw new Error("Missing return statement in function");
   }
 
   final public SqlNode PatternPrimary() throws ParseException {
     final Span s;
     SqlNode e;
-    List<SqlNode> eList;
-    if (jj_2_334(2)) {
+    final List<SqlNode> list;
+    if (jj_2_346(2)) {
       e = SimpleIdentifier();
-    } else if (jj_2_335(2)) {
+                             {if (true) return e;}
+    } else if (jj_2_347(2)) {
       jj_consume_token(LPAREN);
       e = PatternExpression();
       jj_consume_token(RPAREN);
-    } else if (jj_2_336(2)) {
+                                                {if (true) return e;}
+    } else if (jj_2_348(2)) {
       jj_consume_token(LBRACE);
-                   s = span();
+               s = span();
       jj_consume_token(MINUS);
       e = PatternExpression();
       jj_consume_token(MINUS);
       jj_consume_token(RBRACE);
-            e = SqlStdOperatorTable.PATTERN_EXCLUDE.createCall(s.end(this), e);
-    } else if (jj_2_337(2)) {
+        {if (true) return SqlStdOperatorTable.PATTERN_EXCLUDE.createCall(s.end(this), e);}
+    } else if (jj_2_349(2)) {
       jj_consume_token(PERMUTE);
-                        s = span();
+                    s = span(); list = new ArrayList<SqlNode>();
       jj_consume_token(LPAREN);
       e = PatternExpression();
-                eList = new ArrayList<SqlNode>();
-                eList.add(e);
-      label_32:
+                                  list.add(e);
+      label_37:
       while (true) {
-        if (jj_2_333(2)) {
+        if (jj_2_345(2)) {
           ;
         } else {
-          break label_32;
+          break label_37;
         }
         jj_consume_token(COMMA);
         e = PatternExpression();
-                    eList.add(e);
+                                            list.add(e);
       }
       jj_consume_token(RPAREN);
-                e = SqlStdOperatorTable.PATTERN_PERMUTE.createCall(
-                    s.end(this), eList);
+            {if (true) return SqlStdOperatorTable.PATTERN_PERMUTE.createCall(
+                s.end(this), list);}
     } else {
       jj_consume_token(-1);
       throw new ParseException();
     }
-        {if (true) return e;}
     throw new Error("Missing return statement in function");
   }
 
   final public SqlNodeList SubsetDefinitionCommaList(Span s) throws ParseException {
-    SqlNode e;
-    final List<SqlNode> eList = new ArrayList<SqlNode>();
-    e = SubsetDefinition();
-        eList.add(e);
-    label_33:
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    AddSubsetDefinition(list);
+    label_38:
     while (true) {
-      if (jj_2_338(2)) {
+      if (jj_2_350(2)) {
         ;
       } else {
-        break label_33;
+        break label_38;
       }
       jj_consume_token(COMMA);
-      e = SubsetDefinition();
-            eList.add(e);
+      AddSubsetDefinition(list);
     }
-        {if (true) return new SqlNodeList(eList, s.addAll(eList).pos());}
+      {if (true) return new SqlNodeList(list, s.addAll(list).pos());}
     throw new Error("Missing return statement in function");
   }
 
-  final public SqlNode SubsetDefinition() throws ParseException {
+  final public void AddSubsetDefinition(List<SqlNode> list) throws ParseException {
     final SqlNode var;
     final SqlNodeList varList;
     var = SimpleIdentifier();
@@ -4224,9 +4372,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     jj_consume_token(LPAREN);
     varList = ExpressionCommaList(span(), ExprContext.ACCEPT_NON_QUERY);
     jj_consume_token(RPAREN);
-        {if (true) return SqlStdOperatorTable.EQUALS.createCall(span().end(var), var,
-            varList);}
-    throw new Error("Missing return statement in function");
+        list.add(
+            SqlStdOperatorTable.EQUALS.createCall(span().end(var), var,
+                varList));
   }
 
   final public SqlNodeList PatternDefinitionCommaList(Span s) throws ParseException {
@@ -4234,12 +4382,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final List<SqlNode> eList = new ArrayList<SqlNode>();
     e = PatternDefinition();
         eList.add(e);
-    label_34:
+    label_39:
     while (true) {
-      if (jj_2_339(2)) {
+      if (jj_2_351(2)) {
         ;
       } else {
-        break label_34;
+        break label_39;
       }
       jj_consume_token(COMMA);
       e = PatternDefinition();
@@ -4276,88 +4424,155 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
 /**
  * Parses either a row expression or a query expression without ORDER BY.
+ *
+ * <p>Examples of valid queries:
+ * <ul>
+ * <li>{@code SELECT c FROM t}
+ * <li>{@code SELECT c} (valid in some dialects)
+ * <li>{@code SELECT c FROM t UNION SELECT c2 FROM t2}
+ * <li>{@code WITH q AS (SELECT 1) SELECT * FROM q}
+ * <li>{@code VALUES (1, 2)}
+ * <li>{@code TABLE t}
+ * </ul>
+ *
+ * <p>Non-examples:
+ * <ul>
+ * <li>{@code emp CROSS JOIN dept}
+ * <li>{@code SELECT c FROM t ORDER BY c}
+ * <li>{@code (SELECT c FROM t)}
+ * </ul>
  */
   final public SqlNode QueryOrExpr(ExprContext exprContext) throws ParseException {
     SqlNodeList withList = null;
-    SqlNode e;
-    SqlOperator op;
-    SqlParserPos pos;
-    SqlParserPos withPos;
-    List<Object> list;
-    if (jj_2_340(2)) {
+    final SqlNode e;
+    final List<Object> list = new ArrayList<Object>();
+    if (jj_2_352(2)) {
       withList = WithList();
     } else {
       ;
     }
     e = LeafQueryOrExpr(exprContext);
-        list = startList(e);
-    label_35:
+                                       list.add(e);
+    label_40:
     while (true) {
-      if (jj_2_341(2)) {
+      if (jj_2_353(2)) {
         ;
       } else {
-        break label_35;
+        break label_40;
       }
-            if (!e.isA(SqlKind.QUERY)) {
-                // whoops, expression we just parsed wasn't a query,
-                // but we're about to see something like UNION, so
-                // force an exception retroactively
-                checkNonQueryExpression(ExprContext.ACCEPT_QUERY);
-            }
-      op = BinaryQueryOperator();
-            // ensure a query is legal in this context
-            pos = getPos();
-            checkQueryExpression(exprContext);
-      e = LeafQueryOrExpr(ExprContext.ACCEPT_QUERY);
-            list.add(new SqlParserUtil.ToTreeListItem(op, pos));
-            list.add(e);
-    }
-        e = SqlParserUtil.toTree(list);
-        if (withList != null) {
-            e = new SqlWith(withList.getParserPosition(), withList, e);
-        }
-        {if (true) return e;}
+      AddSetOpQuery(list, exprContext);
+    }
+      {if (true) return addWith(withList, SqlParserUtil.toTree(list));}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public SqlNode Query(ExprContext exprContext) throws ParseException {
+    SqlNodeList withList = null;
+    final SqlNode e;
+    final List<Object> list = new ArrayList<Object>();
+    if (jj_2_354(2)) {
+      withList = WithList();
+    } else {
+      ;
+    }
+    e = LeafQuery(exprContext);
+                                 list.add(e);
+    label_41:
+    while (true) {
+      if (jj_2_355(2)) {
+        ;
+      } else {
+        break label_41;
+      }
+      AddSetOpQuery(list, exprContext);
+    }
+      {if (true) return addWith(withList, SqlParserUtil.toTree(list));}
     throw new Error("Missing return statement in function");
   }
 
+  SqlNode addWith(SqlNodeList withList, SqlNode e) throws ParseException {
+    return withList == null
+        ? e
+        : new SqlWith(withList.getParserPosition(), withList, e);
+  }
+
+/** Parses a set operator (e.g. UNION or INTERSECT)
+ * followed by a query or expression,
+ * and adds both to {@code list}. */
+  final public void AddSetOpQueryOrExpr(List<Object> list, ExprContext exprContext) throws ParseException {
+    final SqlOperator op;
+    final SqlParserPos pos;
+    final SqlNode e;
+        if (list.size() == 1 && !((SqlNode) list.get(0)).isA(SqlKind.QUERY)) {
+            // whoops, expression we just parsed wasn't a query,
+            // but we're about to see something like UNION, so
+            // force an exception retroactively
+            checkNonQueryExpression(ExprContext.ACCEPT_QUERY);
+        }
+    op = BinaryQueryOperator();
+        // ensure a query is legal in this context
+        pos = getPos();
+        checkQueryExpression(exprContext);
+    e = LeafQueryOrExpr(ExprContext.ACCEPT_QUERY);
+        list.add(new SqlParserUtil.ToTreeListItem(op, pos));
+        list.add(e);
+  }
+
+/** Parses a set operator (e.g. UNION or INTERSECT)
+ * followed by a query,
+ * and adds both to {@code list}. */
+  final public void AddSetOpQuery(List<Object> list, ExprContext exprContext) throws ParseException {
+    final SqlOperator op;
+    final SqlParserPos pos;
+    final SqlNode e;
+        if (list.size() == 1 && !((SqlNode) list.get(0)).isA(SqlKind.QUERY)) {
+            // whoops, expression we just parsed wasn't a query,
+            // but we're about to see something like UNION, so
+            // force an exception retroactively
+            checkNonQueryExpression(ExprContext.ACCEPT_QUERY);
+        }
+    op = BinaryQueryOperator();
+        // ensure a query is legal in this context
+        pos = getPos();
+        checkQueryExpression(exprContext);
+    e = LeafQueryOrExpr(ExprContext.ACCEPT_QUERY);
+        list.add(new SqlParserUtil.ToTreeListItem(op, pos));
+        list.add(e);
+  }
+
   final public SqlNodeList WithList() throws ParseException {
-    SqlWithItem withItem;
-    SqlParserPos pos;
-    SqlNodeList list;
+    final Span s;
+    final List<SqlWithItem> list = new ArrayList<SqlWithItem>();
     jj_consume_token(WITH);
-             list = new SqlNodeList(getPos());
-    withItem = WithItem();
-                           list.add(withItem);
-    label_36:
+             s = span();
+    AddWithItem(list);
+    label_42:
     while (true) {
-      if (jj_2_342(2)) {
+      if (jj_2_356(2)) {
         ;
       } else {
-        break label_36;
+        break label_42;
       }
       jj_consume_token(COMMA);
-      withItem = WithItem();
-                                       list.add(withItem);
+      AddWithItem(list);
     }
-      {if (true) return list;}
+      {if (true) return new SqlNodeList(list, s.end(this));}
     throw new Error("Missing return statement in function");
   }
 
-  final public SqlWithItem WithItem() throws ParseException {
-    SqlIdentifier id;
-    SqlNodeList columnList = null;
-    SqlNode definition;
+  final public void AddWithItem(List<SqlWithItem> list) throws ParseException {
+    final SqlIdentifier id;
+    final SqlNodeList columnList;
+    final SqlNode definition;
     id = SimpleIdentifier();
-    if (jj_2_343(2)) {
+    if (jj_2_357(2)) {
       columnList = ParenthesizedSimpleIdentifierList();
     } else {
-      ;
+                                                           columnList = null;
     }
     jj_consume_token(AS);
     definition = ParenthesizedExpression(ExprContext.ACCEPT_QUERY);
-        {if (true) return new SqlWithItem(id.getParserPosition(), id, columnList,
-            definition);}
-    throw new Error("Missing return statement in function");
+      list.add(new SqlWithItem(id.getParserPosition(), id, columnList, definition));
   }
 
 /**
@@ -4366,10 +4581,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlNode LeafQueryOrExpr(ExprContext exprContext) throws ParseException {
     SqlNode e;
-    if (jj_2_344(2)) {
+    if (jj_2_358(2)) {
       e = Expression(exprContext);
                                   {if (true) return e;}
-    } else if (jj_2_345(2)) {
+    } else if (jj_2_359(2)) {
       e = LeafQuery(exprContext);
                                  {if (true) return e;}
     } else {
@@ -4379,24 +4594,28 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     throw new Error("Missing return statement in function");
   }
 
+/** As {@link #Expression} but appends to a list. */
+  final public void AddExpression(List<SqlNode> list, ExprContext exprContext) throws ParseException {
+    final SqlNode e;
+    e = Expression(exprContext);
+                                  list.add(e);
+  }
+
 /**
  * Parses a row expression or a parenthesized expression of any kind.
  */
   final public SqlNode Expression(ExprContext exprContext) throws ParseException {
-    List<Object> list;
-    SqlNode e;
+    final List<Object> list;
     list = Expression2(exprContext);
-        e = SqlParserUtil.toTree(list);
-        {if (true) return e;}
+                                      {if (true) return SqlParserUtil.toTree(list);}
     throw new Error("Missing return statement in function");
   }
 
-// TODO jvs 15-Nov-2003:  ANY/ALL
-  final public void Expression2b(ExprContext exprContext, List<Object> list) throws ParseException {
+  final public void AddExpression2b(List<Object> list, ExprContext exprContext) throws ParseException {
     SqlNode e;
     SqlOperator op;
     SqlNode ext;
-    label_37:
+    label_43:
     while (true) {
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
       case EXISTS:
@@ -4407,8 +4626,8 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         ;
         break;
       default:
-        jj_la1[3] = jj_gen;
-        break label_37;
+        jj_la1[4] = jj_gen;
+        break label_43;
       }
       op = PrefixRowOperator();
             checkNonQueryExpression(exprContext);
@@ -4416,12 +4635,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     }
     e = Expression3(exprContext);
         list.add(e);
-    label_38:
+    label_44:
     while (true) {
-      if (jj_2_346(2)) {
+      if (jj_2_360(2)) {
         ;
       } else {
-        break label_38;
+        break label_44;
       }
       jj_consume_token(DOT);
       ext = RowExpressionExtension();
@@ -4455,29 +4674,29 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     SqlOperator op;
     SqlIdentifier p;
     final Span s = span();
-    Expression2b(exprContext, list);
-    if (jj_2_385(2)) {
-      label_39:
+    AddExpression2b(list, exprContext);
+    if (jj_2_399(2)) {
+      label_45:
       while (true) {
-        if (jj_2_377(2)) {
+        if (jj_2_391(2)) {
                     checkNonQueryExpression(exprContext);
-          if (jj_2_350(2)) {
+          if (jj_2_364(2)) {
             jj_consume_token(NOT);
             jj_consume_token(IN);
                                  op = SqlStdOperatorTable.NOT_IN;
-          } else if (jj_2_351(2)) {
+          } else if (jj_2_365(2)) {
             jj_consume_token(IN);
                            op = SqlStdOperatorTable.IN;
-          } else if (jj_2_352(2)) {
+          } else if (jj_2_366(2)) {
                       final SqlKind k;
             k = comp();
-            if (jj_2_347(2)) {
+            if (jj_2_361(2)) {
               jj_consume_token(SOME);
                                  op = SqlStdOperatorTable.some(k);
-            } else if (jj_2_348(2)) {
+            } else if (jj_2_362(2)) {
               jj_consume_token(ANY);
                                 op = SqlStdOperatorTable.some(k);
-            } else if (jj_2_349(2)) {
+            } else if (jj_2_363(2)) {
               jj_consume_token(ALL);
                                 op = SqlStdOperatorTable.all(k);
             } else {
@@ -4503,18 +4722,18 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                     } else {
                         list.add(nodeList);
                     }
-        } else if (jj_2_378(2)) {
+        } else if (jj_2_392(2)) {
                     checkNonQueryExpression(exprContext);
-          if (jj_2_359(2)) {
+          if (jj_2_373(2)) {
             jj_consume_token(NOT);
             jj_consume_token(BETWEEN);
                         op = SqlStdOperatorTable.NOT_BETWEEN;
                         s.clear().add(this);
-            if (jj_2_355(2)) {
-              if (jj_2_353(2)) {
+            if (jj_2_369(2)) {
+              if (jj_2_367(2)) {
                 jj_consume_token(SYMMETRIC);
                                       op = SqlStdOperatorTable.SYMMETRIC_NOT_BETWEEN;
-              } else if (jj_2_354(2)) {
+              } else if (jj_2_368(2)) {
                 jj_consume_token(ASYMMETRIC);
               } else {
                 jj_consume_token(-1);
@@ -4523,15 +4742,15 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             } else {
               ;
             }
-          } else if (jj_2_360(2)) {
+          } else if (jj_2_374(2)) {
             jj_consume_token(BETWEEN);
                         op = SqlStdOperatorTable.BETWEEN;
                         s.clear().add(this);
-            if (jj_2_358(2)) {
-              if (jj_2_356(2)) {
+            if (jj_2_372(2)) {
+              if (jj_2_370(2)) {
                 jj_consume_token(SYMMETRIC);
                                       op = SqlStdOperatorTable.SYMMETRIC_BETWEEN;
-              } else if (jj_2_357(2)) {
+              } else if (jj_2_371(2)) {
                 jj_consume_token(ASYMMETRIC);
               } else {
                 jj_consume_token(-1);
@@ -4544,26 +4763,26 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             jj_consume_token(-1);
             throw new ParseException();
           }
-          Expression2b(ExprContext.ACCEPT_SUB_QUERY, list3);
+          AddExpression2b(list3, ExprContext.ACCEPT_SUB_QUERY);
                     list.add(new SqlParserUtil.ToTreeListItem(op, s.pos()));
                     list.addAll(list3);
                     list3.clear();
-        } else if (jj_2_379(2)) {
+        } else if (jj_2_393(2)) {
                     checkNonQueryExpression(exprContext);
                     s.clear().add(this);
-          if (jj_2_372(2)) {
-            if (jj_2_365(2)) {
+          if (jj_2_386(2)) {
+            if (jj_2_379(2)) {
               jj_consume_token(NOT);
-              if (jj_2_361(2)) {
+              if (jj_2_375(2)) {
                 jj_consume_token(LIKE);
                                      op = SqlStdOperatorTable.NOT_LIKE;
-              } else if (jj_2_362(2)) {
+              } else if (jj_2_376(2)) {
                 jj_consume_token(ILIKE);
                                       op = SqlLibraryOperators.NOT_ILIKE;
-              } else if (jj_2_363(2)) {
+              } else if (jj_2_377(2)) {
                 jj_consume_token(RLIKE);
                                       op = SqlLibraryOperators.NOT_RLIKE;
-              } else if (jj_2_364(2)) {
+              } else if (jj_2_378(2)) {
                 jj_consume_token(SIMILAR);
                 jj_consume_token(TO);
                                              op = SqlStdOperatorTable.NOT_SIMILAR_TO;
@@ -4571,16 +4790,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                 jj_consume_token(-1);
                 throw new ParseException();
               }
-            } else if (jj_2_366(2)) {
+            } else if (jj_2_380(2)) {
               jj_consume_token(LIKE);
                                  op = SqlStdOperatorTable.LIKE;
-            } else if (jj_2_367(2)) {
+            } else if (jj_2_381(2)) {
               jj_consume_token(ILIKE);
                                   op = SqlLibraryOperators.ILIKE;
-            } else if (jj_2_368(2)) {
+            } else if (jj_2_382(2)) {
               jj_consume_token(RLIKE);
                                   op = SqlLibraryOperators.RLIKE;
-            } else if (jj_2_369(2)) {
+            } else if (jj_2_383(2)) {
               jj_consume_token(SIMILAR);
               jj_consume_token(TO);
                                          op = SqlStdOperatorTable.SIMILAR_TO;
@@ -4588,20 +4807,20 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
               jj_consume_token(-1);
               throw new ParseException();
             }
-          } else if (jj_2_373(2)) {
+          } else if (jj_2_387(2)) {
             jj_consume_token(NEGATE);
             jj_consume_token(TILDE);
                                        op = SqlStdOperatorTable.NEGATED_POSIX_REGEX_CASE_SENSITIVE;
-            if (jj_2_370(2)) {
+            if (jj_2_384(2)) {
               jj_consume_token(STAR);
                                op = SqlStdOperatorTable.NEGATED_POSIX_REGEX_CASE_INSENSITIVE;
             } else {
               ;
             }
-          } else if (jj_2_374(2)) {
+          } else if (jj_2_388(2)) {
             jj_consume_token(TILDE);
                               op = SqlStdOperatorTable.POSIX_REGEX_CASE_SENSITIVE;
-            if (jj_2_371(2)) {
+            if (jj_2_385(2)) {
               jj_consume_token(STAR);
                                op = SqlStdOperatorTable.POSIX_REGEX_CASE_INSENSITIVE;
             } else {
@@ -4614,7 +4833,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
           list2 = Expression2(ExprContext.ACCEPT_SUB_QUERY);
                     list.add(new SqlParserUtil.ToTreeListItem(op, s.pos()));
                     list.addAll(list2);
-          if (jj_2_375(2)) {
+          if (jj_2_389(2)) {
             jj_consume_token(ESCAPE);
             e = Expression3(ExprContext.ACCEPT_SUB_QUERY);
                         s.clear().add(this);
@@ -4625,14 +4844,14 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
           } else {
             ;
           }
-        } else if (jj_2_380(2)) {
+        } else if (jj_2_394(2)) {
           InfixCast(list, exprContext, s);
-        } else if (jj_2_381(3)) {
+        } else if (jj_2_395(3)) {
           op = BinaryRowOperator();
                     checkNonQueryExpression(exprContext);
                     list.add(new SqlParserUtil.ToTreeListItem(op, getPos()));
-          Expression2b(ExprContext.ACCEPT_SUB_QUERY, list);
-        } else if (jj_2_382(2)) {
+          AddExpression2b(list, ExprContext.ACCEPT_SUB_QUERY);
+        } else if (jj_2_396(2)) {
           jj_consume_token(LBRACKET);
           e = Expression(ExprContext.ACCEPT_SUB_QUERY);
           jj_consume_token(RBRACKET);
@@ -4640,12 +4859,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                         new SqlParserUtil.ToTreeListItem(
                             SqlStdOperatorTable.ITEM, getPos()));
                     list.add(e);
-          label_40:
+          label_46:
           while (true) {
-            if (jj_2_376(2)) {
+            if (jj_2_390(2)) {
               ;
             } else {
-              break label_40;
+              break label_46;
             }
             jj_consume_token(DOT);
             p = SimpleIdentifier();
@@ -4654,7 +4873,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                                 SqlStdOperatorTable.DOT, getPos()));
                         list.add(p);
           }
-        } else if (jj_2_383(2)) {
+        } else if (jj_2_397(2)) {
                     checkNonQueryExpression(exprContext);
           op = PostfixRowOperator();
                     list.add(new SqlParserUtil.ToTreeListItem(op, getPos()));
@@ -4662,10 +4881,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
           jj_consume_token(-1);
           throw new ParseException();
         }
-        if (jj_2_384(2)) {
+        if (jj_2_398(2)) {
           ;
         } else {
-          break label_39;
+          break label_45;
         }
       }
             {if (true) return list;}
@@ -4677,25 +4896,25 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
 /** Parses a comparison operator inside a SOME / ALL predicate. */
   final public SqlKind comp() throws ParseException {
-    if (jj_2_386(2)) {
+    if (jj_2_400(2)) {
       jj_consume_token(LT);
            {if (true) return SqlKind.LESS_THAN;}
-    } else if (jj_2_387(2)) {
+    } else if (jj_2_401(2)) {
       jj_consume_token(LE);
            {if (true) return SqlKind.LESS_THAN_OR_EQUAL;}
-    } else if (jj_2_388(2)) {
+    } else if (jj_2_402(2)) {
       jj_consume_token(GT);
            {if (true) return SqlKind.GREATER_THAN;}
-    } else if (jj_2_389(2)) {
+    } else if (jj_2_403(2)) {
       jj_consume_token(GE);
            {if (true) return SqlKind.GREATER_THAN_OR_EQUAL;}
-    } else if (jj_2_390(2)) {
+    } else if (jj_2_404(2)) {
       jj_consume_token(EQ);
            {if (true) return SqlKind.EQUALS;}
-    } else if (jj_2_391(2)) {
+    } else if (jj_2_405(2)) {
       jj_consume_token(NE);
            {if (true) return SqlKind.NOT_EQUALS;}
-    } else if (jj_2_392(2)) {
+    } else if (jj_2_406(2)) {
       jj_consume_token(NE2);
         if (!this.conformance.isBangEqualAllowed()) {
             {if (true) throw SqlUtil.newContextException(getPos(), RESOURCE.bangEqualNotAllowed());}
@@ -4716,18 +4935,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final SqlNode e;
     final SqlNodeList list;
     final SqlNodeList list1;
-    final SqlNodeList list2;
-    final SqlOperator op;
     final Span s;
-    Span rowSpan = null;
-    if (jj_2_395(2)) {
+    final Span rowSpan;
+    if (jj_2_409(2)) {
       e = AtomicRowExpression();
         checkNonQueryExpression(exprContext);
         {if (true) return e;}
-    } else if (jj_2_396(2)) {
+    } else if (jj_2_410(2)) {
       e = CursorExpression(exprContext);
                                         {if (true) return e;}
-    } else if (jj_2_397(3)) {
+    } else if (jj_2_411(3)) {
       jj_consume_token(ROW);
         s = span();
       list = ParenthesizedQueryOrCommaList(exprContext);
@@ -4739,12 +4956,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                 RESOURCE.illegalRowExpression());}
         }
         {if (true) return SqlStdOperatorTable.ROW.createCall(list);}
-    } else if (jj_2_398(2)) {
-      if (jj_2_393(2)) {
+    } else if (jj_2_412(2)) {
+      if (jj_2_407(2)) {
         jj_consume_token(ROW);
                 rowSpan = span();
       } else {
-        ;
+          rowSpan = null;
       }
       list1 = ParenthesizedQueryOrCommaList(exprContext);
         if (rowSpan != null) {
@@ -4752,7 +4969,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             {if (true) return SqlStdOperatorTable.ROW.createCall(rowSpan.end(list1),
                 (List<SqlNode>) list1);}
         }
-      if (jj_2_394(2)) {
+      if (jj_2_408(2)) {
         e = IntervalQualifier();
                 if ((list1.size() == 1)
                     && list1.get(0) instanceof SqlCall)
@@ -4760,11 +4977,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                     final SqlCall call = (SqlCall) list1.get(0);
                     if (call.getKind() == SqlKind.MINUS
                             && call.operandCount() == 2) {
-                        List<SqlNode> list3 = startList(call.operand(0));
-                        list3.add(call.operand(1));
-                        list3.add(e);
                         {if (true) return SqlStdOperatorTable.MINUS_DATE.createCall(
-                            Span.of(list1).end(this), list3);}
+                            Span.of(list1).end(this), call.operand(0),
+                            call.operand(1), e);}
                      }
                 }
                 {if (true) throw SqlUtil.newContextException(span().end(list1),
@@ -4788,24 +5003,24 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public SqlOperator periodOperator() throws ParseException {
-    if (jj_2_399(2)) {
+    if (jj_2_413(2)) {
       jj_consume_token(OVERLAPS);
                   {if (true) return SqlStdOperatorTable.OVERLAPS;}
-    } else if (jj_2_400(2)) {
+    } else if (jj_2_414(2)) {
       jj_consume_token(IMMEDIATELY);
       jj_consume_token(PRECEDES);
                                 {if (true) return SqlStdOperatorTable.IMMEDIATELY_PRECEDES;}
-    } else if (jj_2_401(2)) {
+    } else if (jj_2_415(2)) {
       jj_consume_token(PRECEDES);
                   {if (true) return SqlStdOperatorTable.PRECEDES;}
-    } else if (jj_2_402(2)) {
+    } else if (jj_2_416(2)) {
       jj_consume_token(IMMEDIATELY);
       jj_consume_token(SUCCEEDS);
                                 {if (true) return SqlStdOperatorTable.IMMEDIATELY_SUCCEEDS;}
-    } else if (jj_2_403(2)) {
+    } else if (jj_2_417(2)) {
       jj_consume_token(SUCCEEDS);
                   {if (true) return SqlStdOperatorTable.SUCCEEDS;}
-    } else if (jj_2_404(2)) {
+    } else if (jj_2_418(2)) {
       jj_consume_token(EQUALS);
                 {if (true) return SqlStdOperatorTable.PERIOD_EQUALS;}
     } else {
@@ -4831,9 +5046,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlNode UnsignedNumericLiteralOrParam() throws ParseException {
     final SqlNode e;
-    if (jj_2_405(2)) {
+    if (jj_2_419(2)) {
       e = UnsignedNumericLiteral();
-    } else if (jj_2_406(2)) {
+    } else if (jj_2_420(2)) {
       e = DynamicParam();
     } else {
       jj_consume_token(-1);
@@ -4848,28 +5063,26 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * or a call to a named function.
  */
   final public SqlNode RowExpressionExtension() throws ParseException {
-    final SqlFunctionCategory funcType;
+    final SqlFunctionCategory funcType = SqlFunctionCategory.USER_DEFINED_FUNCTION;
     final SqlIdentifier p;
     final Span s;
     final List<SqlNode> args;
-    SqlCall call;
-    SqlNode e;
-    SqlLiteral quantifier = null;
+    final SqlLiteral quantifier;
     p = SimpleIdentifier();
-        e = p;
-    if (jj_2_410(2147483647)) {
+    if (jj_2_424(2147483647)) {
                                 s = span();
-            funcType = SqlFunctionCategory.USER_DEFINED_FUNCTION;
-      if (jj_2_407(2)) {
+      if (jj_2_421(2)) {
         jj_consume_token(LPAREN);
         jj_consume_token(STAR);
-                args = startList(SqlIdentifier.star(getPos()));
+                quantifier = null;
+                args = ImmutableList.of(SqlIdentifier.star(getPos()));
         jj_consume_token(RPAREN);
-      } else if (jj_2_408(2)) {
+      } else if (jj_2_422(2)) {
         jj_consume_token(LPAREN);
         jj_consume_token(RPAREN);
-                args = Collections.emptyList();
-      } else if (jj_2_409(2)) {
+                quantifier = null;
+                args = ImmutableList.of();
+      } else if (jj_2_423(2)) {
         args = FunctionParameterList(ExprContext.ACCEPT_SUB_QUERY);
                 quantifier = (SqlLiteral) args.get(0);
                 args.remove(0);
@@ -4877,12 +5090,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         jj_consume_token(-1);
         throw new ParseException();
       }
-            call = createCall(p, s.end(this), funcType, quantifier, args);
-            e = call;
+          {if (true) return createCall(p, s.end(this), funcType, quantifier, args);}
     } else {
-      ;
+          {if (true) return p;}
     }
-        {if (true) return e;}
     throw new Error("Missing return statement in function");
   }
 
@@ -4893,21 +5104,21 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlCall StringAggFunctionCall() throws ParseException {
     final Span s, s2;
     final SqlOperator op;
-    final List<SqlNode> args = new ArrayList();
+    final List<SqlNode> args = new ArrayList<SqlNode>();
     final SqlLiteral qualifier;
     final SqlNodeList orderBy;
     final Pair<SqlParserPos, SqlOperator> nullTreatment;
     final SqlNode separator;
-    if (jj_2_411(2)) {
+    if (jj_2_425(2)) {
       jj_consume_token(ARRAY_AGG);
                       s = span(); op = SqlLibraryOperators.ARRAY_AGG;
-    } else if (jj_2_412(2)) {
+    } else if (jj_2_426(2)) {
       jj_consume_token(ARRAY_CONCAT_AGG);
                              s = span(); op = SqlLibraryOperators.ARRAY_CONCAT_AGG;
-    } else if (jj_2_413(2)) {
+    } else if (jj_2_427(2)) {
       jj_consume_token(GROUP_CONCAT);
                          s = span(); op = SqlLibraryOperators.GROUP_CONCAT;
-    } else if (jj_2_414(2)) {
+    } else if (jj_2_428(2)) {
       jj_consume_token(STRING_AGG);
                        s = span(); op = SqlLibraryOperators.STRING_AGG;
     } else {
@@ -4915,36 +5126,37 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
       throw new ParseException();
     }
     jj_consume_token(LPAREN);
-    if (jj_2_415(2)) {
+    if (jj_2_429(2)) {
       qualifier = AllOrDistinct();
     } else {
           qualifier = null;
     }
-    Arg(args, ExprContext.ACCEPT_SUB_QUERY);
-    label_41:
+    AddArg(args, ExprContext.ACCEPT_SUB_QUERY);
+    label_47:
     while (true) {
-      if (jj_2_416(2)) {
+      if (jj_2_430(2)) {
         ;
       } else {
-        break label_41;
+        break label_47;
       }
       jj_consume_token(COMMA);
             // a comma-list can't appear where only a query is expected
+            // TODO: the following line is a no-op; remove it?
             checkNonQueryExpression(ExprContext.ACCEPT_SUB_QUERY);
-      Arg(args, ExprContext.ACCEPT_SUB_QUERY);
+      AddArg(args, ExprContext.ACCEPT_SUB_QUERY);
     }
-    if (jj_2_417(2)) {
+    if (jj_2_431(2)) {
       nullTreatment = NullTreatment();
     } else {
           nullTreatment = null;
     }
-    if (jj_2_418(2)) {
+    if (jj_2_432(2)) {
       orderBy = OrderBy(true);
             args.add(orderBy);
     } else {
       ;
     }
-    if (jj_2_419(2)) {
+    if (jj_2_433(2)) {
       jj_consume_token(SEPARATOR);
                       s2 = span();
       separator = StringLiteral();
@@ -4967,33 +5179,33 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlNode AtomicRowExpression() throws ParseException {
     final SqlNode e;
-    if (jj_2_420(2)) {
+    if (jj_2_434(2)) {
       e = LiteralOrIntervalExpression();
-    } else if (jj_2_421(2)) {
+    } else if (jj_2_435(2)) {
       e = DynamicParam();
-    } else if (jj_2_422(2)) {
+    } else if (jj_2_436(2)) {
       e = BuiltinFunctionCall();
-    } else if (jj_2_423(2)) {
+    } else if (jj_2_437(2)) {
       e = JdbcFunctionCall();
-    } else if (jj_2_424(2)) {
+    } else if (jj_2_438(2)) {
       e = MultisetConstructor();
-    } else if (jj_2_425(2)) {
+    } else if (jj_2_439(2)) {
       e = ArrayConstructor();
-    } else if (jj_2_426(3)) {
+    } else if (jj_2_440(3)) {
       e = MapConstructor();
-    } else if (jj_2_427(2)) {
+    } else if (jj_2_441(2)) {
       e = PeriodConstructor();
-    } else if (jj_2_428(2147483647)) {
+    } else if (jj_2_442(2147483647)) {
       e = NamedFunctionCall();
-    } else if (jj_2_429(2)) {
+    } else if (jj_2_443(2)) {
       e = ContextVariable();
-    } else if (jj_2_430(2)) {
+    } else if (jj_2_444(2)) {
       e = CompoundIdentifier();
-    } else if (jj_2_431(2)) {
+    } else if (jj_2_445(2)) {
       e = NewSpecification();
-    } else if (jj_2_432(2)) {
+    } else if (jj_2_446(2)) {
       e = CaseExpression();
-    } else if (jj_2_433(2)) {
+    } else if (jj_2_447(2)) {
       e = SequenceExpression();
     } else {
       jj_consume_token(-1);
@@ -5008,18 +5220,18 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final Span thenSpan = Span.of();
     final Span s;
     SqlNode e;
-    SqlNode caseIdentifier = null;
-    SqlNode elseClause = null;
-    List<SqlNode> whenList = new ArrayList<SqlNode>();
-    List<SqlNode> thenList = new ArrayList<SqlNode>();
+    final SqlNode caseIdentifier;
+    final SqlNode elseClause;
+    final List<SqlNode> whenList = new ArrayList<SqlNode>();
+    final List<SqlNode> thenList = new ArrayList<SqlNode>();
     jj_consume_token(CASE);
              s = span();
-    if (jj_2_434(2)) {
+    if (jj_2_448(2)) {
       caseIdentifier = Expression(ExprContext.ACCEPT_SUB_QUERY);
     } else {
-      ;
+          caseIdentifier = null;
     }
-    label_42:
+    label_48:
     while (true) {
       jj_consume_token(WHEN);
                  whenSpan.add(this);
@@ -5032,17 +5244,17 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                  thenSpan.add(this);
       e = Expression(ExprContext.ACCEPT_SUB_QUERY);
             thenList.add(e);
-      if (jj_2_435(2)) {
+      if (jj_2_449(2)) {
         ;
       } else {
-        break label_42;
+        break label_48;
       }
     }
-    if (jj_2_436(2)) {
+    if (jj_2_450(2)) {
       jj_consume_token(ELSE);
       elseClause = Expression(ExprContext.ACCEPT_SUB_QUERY);
     } else {
-      ;
+          elseClause = null;
     }
     jj_consume_token(END);
         {if (true) return SqlCase.createSwitched(s.end(this), caseIdentifier,
@@ -5056,10 +5268,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final Span s;
     final SqlOperator f;
     final SqlNode sequenceRef;
-    if (jj_2_437(2)) {
+    if (jj_2_451(2)) {
       jj_consume_token(NEXT);
                  f = SqlStdOperatorTable.NEXT_VALUE; s = span();
-    } else if (jj_2_438(3)) {
+    } else if (jj_2_452(3)) {
       jj_consume_token(CURRENT);
                     f = SqlStdOperatorTable.CURRENT_VALUE; s = span();
     } else {
@@ -5080,16 +5292,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlSetOption SqlSetOption(Span s, String scope) throws ParseException {
     SqlIdentifier name;
     final SqlNode val;
-    if (jj_2_444(2)) {
+    if (jj_2_458(2)) {
       jj_consume_token(SET);
             s.add(this);
       name = CompoundIdentifier();
       jj_consume_token(EQ);
-      if (jj_2_439(2)) {
+      if (jj_2_453(2)) {
         val = Literal();
-      } else if (jj_2_440(2)) {
+      } else if (jj_2_454(2)) {
         val = SimpleIdentifier();
-      } else if (jj_2_441(2)) {
+      } else if (jj_2_455(2)) {
         jj_consume_token(ON);
                 // OFF is handled by SimpleIdentifier, ON handled here.
                 val = new SqlIdentifier(token.image.toUpperCase(Locale.ROOT),
@@ -5099,12 +5311,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         throw new ParseException();
       }
             {if (true) return new SqlSetOption(s.end(val), scope, name, val);}
-    } else if (jj_2_445(2)) {
+    } else if (jj_2_459(2)) {
       jj_consume_token(RESET);
             s.add(this);
-      if (jj_2_442(2)) {
+      if (jj_2_456(2)) {
         name = CompoundIdentifier();
-      } else if (jj_2_443(2)) {
+      } else if (jj_2_457(2)) {
         jj_consume_token(ALL);
                 name = new SqlIdentifier(token.image.toUpperCase(Locale.ROOT),
                     getPos());
@@ -5137,9 +5349,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public String Scope() throws ParseException {
-    if (jj_2_446(2)) {
+    if (jj_2_460(2)) {
       jj_consume_token(SYSTEM);
-    } else if (jj_2_447(2)) {
+    } else if (jj_2_461(2)) {
       jj_consume_token(SESSION);
     } else {
       jj_consume_token(-1);
@@ -5158,18 +5370,18 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final SqlCreate create;
     jj_consume_token(CREATE);
                s = span();
-    if (jj_2_448(2)) {
+    if (jj_2_462(2)) {
       jj_consume_token(OR);
       jj_consume_token(REPLACE);
             replace = true;
     } else {
       ;
     }
-    if (jj_2_449(2)) {
+    if (jj_2_463(2)) {
       create = SqlCreateTable(s, replace);
-    } else if (jj_2_450(2)) {
+    } else if (jj_2_464(2)) {
       create = SqlCreateIndex(s, replace);
-    } else if (jj_2_451(2)) {
+    } else if (jj_2_465(2)) {
       create = SqlCreateUser(s, replace);
     } else {
       jj_consume_token(-1);
@@ -5188,11 +5400,11 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final SqlDrop drop;
     jj_consume_token(DROP);
              s = span();
-    if (jj_2_452(2)) {
+    if (jj_2_466(2)) {
       drop = SqlDropTable(s, replace);
-    } else if (jj_2_453(2)) {
+    } else if (jj_2_467(2)) {
       drop = SqlDropIndex(s, replace);
-    } else if (jj_2_454(2)) {
+    } else if (jj_2_468(2)) {
       drop = SqlDropUser(s, replace);
     } else {
       jj_consume_token(-1);
@@ -5214,9 +5426,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlNode Literal() throws ParseException {
     SqlNode e;
-    if (jj_2_455(2)) {
+    if (jj_2_469(2)) {
       e = NonIntervalLiteral();
-    } else if (jj_2_456(2)) {
+    } else if (jj_2_470(2)) {
       e = IntervalLiteral();
     } else {
       jj_consume_token(-1);
@@ -5229,13 +5441,13 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 /** Parses a literal that is not an interval literal. */
   final public SqlNode NonIntervalLiteral() throws ParseException {
     final SqlNode e;
-    if (jj_2_457(2)) {
+    if (jj_2_471(2)) {
       e = NumericLiteral();
-    } else if (jj_2_458(2)) {
+    } else if (jj_2_472(2)) {
       e = StringLiteral();
-    } else if (jj_2_459(2)) {
+    } else if (jj_2_473(2)) {
       e = SpecialLiteral();
-    } else if (jj_2_460(2)) {
+    } else if (jj_2_474(2)) {
       e = DateTimeLiteral();
     } else {
       jj_consume_token(-1);
@@ -5253,9 +5465,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * LOOKAHEAD. */
   final public SqlNode LiteralOrIntervalExpression() throws ParseException {
     final SqlNode e;
-    if (jj_2_461(2)) {
+    if (jj_2_475(2)) {
       e = IntervalLiteralOrExpression();
-    } else if (jj_2_462(2)) {
+    } else if (jj_2_476(2)) {
       e = NonIntervalLiteral();
     } else {
       jj_consume_token(-1);
@@ -5267,13 +5479,13 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
 /** Parses a unsigned numeric literal */
   final public SqlNumericLiteral UnsignedNumericLiteral() throws ParseException {
-    if (jj_2_463(2)) {
+    if (jj_2_477(2)) {
       jj_consume_token(UNSIGNED_INTEGER_LITERAL);
         {if (true) return SqlLiteral.createExactNumeric(token.image, getPos());}
-    } else if (jj_2_464(2)) {
+    } else if (jj_2_478(2)) {
       jj_consume_token(DECIMAL_NUMERIC_LITERAL);
         {if (true) return SqlLiteral.createExactNumeric(token.image, getPos());}
-    } else if (jj_2_465(2)) {
+    } else if (jj_2_479(2)) {
       jj_consume_token(APPROX_NUMERIC_LITERAL);
         {if (true) return SqlLiteral.createApproxNumeric(token.image, getPos());}
     } else {
@@ -5287,16 +5499,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlLiteral NumericLiteral() throws ParseException {
     final SqlNumericLiteral num;
     final Span s;
-    if (jj_2_466(2)) {
+    if (jj_2_480(2)) {
       jj_consume_token(PLUS);
       num = UnsignedNumericLiteral();
         {if (true) return num;}
-    } else if (jj_2_467(2)) {
+    } else if (jj_2_481(2)) {
       jj_consume_token(MINUS);
               s = span();
       num = UnsignedNumericLiteral();
         {if (true) return SqlLiteral.createNegative(num, s.end(this));}
-    } else if (jj_2_468(2)) {
+    } else if (jj_2_482(2)) {
       num = UnsignedNumericLiteral();
         {if (true) return num;}
     } else {
@@ -5308,16 +5520,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
 /** Parse a special literal keyword */
   final public SqlLiteral SpecialLiteral() throws ParseException {
-    if (jj_2_469(2)) {
+    if (jj_2_483(2)) {
       jj_consume_token(TRUE);
              {if (true) return SqlLiteral.createBoolean(true, getPos());}
-    } else if (jj_2_470(2)) {
+    } else if (jj_2_484(2)) {
       jj_consume_token(FALSE);
               {if (true) return SqlLiteral.createBoolean(false, getPos());}
-    } else if (jj_2_471(2)) {
+    } else if (jj_2_485(2)) {
       jj_consume_token(UNKNOWN);
                 {if (true) return SqlLiteral.createUnknown(getPos());}
-    } else if (jj_2_472(2)) {
+    } else if (jj_2_486(2)) {
       jj_consume_token(NULL);
              {if (true) return SqlLiteral.createNull(getPos());}
     } else {
@@ -5340,55 +5552,53 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlNode StringLiteral() throws ParseException {
     String p;
-    int nfrags = 0;
-    List<SqlLiteral> frags = null;
+    final List<SqlLiteral> frags;
     char unicodeEscapeChar = 0;
     String charSet = null;
     SqlCharStringLiteral literal;
-    if (jj_2_477(2)) {
+    if (jj_2_491(2)) {
       jj_consume_token(BINARY_STRING_LITERAL);
+        frags = new ArrayList<SqlLiteral>();
         try {
             p = SqlParserUtil.trim(token.image, "xX'");
-            frags = startList(SqlLiteral.createBinaryString(p, getPos()));
-            nfrags++;
+            frags.add(SqlLiteral.createBinaryString(p, getPos()));
         } catch (NumberFormatException ex) {
             {if (true) throw SqlUtil.newContextException(getPos(),
                 RESOURCE.illegalBinaryString(token.image));}
         }
-      label_43:
+      label_49:
       while (true) {
         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
         case QUOTED_STRING:
           ;
           break;
         default:
-          jj_la1[4] = jj_gen;
-          break label_43;
+          jj_la1[5] = jj_gen;
+          break label_49;
         }
         jj_consume_token(QUOTED_STRING);
             try {
                 p = SqlParserUtil.trim(token.image, "'"); // no embedded quotes
                 frags.add(SqlLiteral.createBinaryString(p, getPos()));
-                nfrags++;
             } catch (NumberFormatException ex) {
                 {if (true) throw SqlUtil.newContextException(getPos(),
                     RESOURCE.illegalBinaryString(token.image));}
             }
       }
-        assert (nfrags > 0);
-        if (nfrags == 1) {
+        assert !frags.isEmpty();
+        if (frags.size() == 1) {
             {if (true) return frags.get(0);} // just the head fragment
         } else {
             SqlParserPos pos2 = SqlParserPos.sum(frags);
             {if (true) return SqlStdOperatorTable.LITERAL_CHAIN.createCall(pos2, frags);}
         }
-    } else if (jj_2_478(2)) {
-      if (jj_2_473(2)) {
+    } else if (jj_2_492(2)) {
+      if (jj_2_487(2)) {
         jj_consume_token(PREFIXED_STRING_LITERAL);
           charSet = SqlParserUtil.getCharacterSet(token.image);
-      } else if (jj_2_474(2)) {
+      } else if (jj_2_488(2)) {
         jj_consume_token(QUOTED_STRING);
-      } else if (jj_2_475(2)) {
+      } else if (jj_2_489(2)) {
         jj_consume_token(UNICODE_STRING_LITERAL);
             // TODO jvs 2-Feb-2009:  support the explicit specification of
             // a character set for Unicode string literals, per SQL:2003
@@ -5398,37 +5608,36 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         jj_consume_token(-1);
         throw new ParseException();
       }
+        frags = new ArrayList<SqlLiteral>();
         p = SqlParserUtil.parseString(token.image);
         try {
             literal = SqlLiteral.createCharString(p, charSet, getPos());
+            frags.add(literal);
         } catch (java.nio.charset.UnsupportedCharsetException e) {
             {if (true) throw SqlUtil.newContextException(getPos(),
                 RESOURCE.unknownCharacterSet(charSet));}
         }
-        frags = startList(literal);
-        nfrags++;
-      label_44:
+      label_50:
       while (true) {
         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
         case QUOTED_STRING:
           ;
           break;
         default:
-          jj_la1[5] = jj_gen;
-          break label_44;
+          jj_la1[6] = jj_gen;
+          break label_50;
         }
         jj_consume_token(QUOTED_STRING);
             p = SqlParserUtil.parseString(token.image);
             try {
                 literal = SqlLiteral.createCharString(p, charSet, getPos());
+                frags.add(literal);
             } catch (java.nio.charset.UnsupportedCharsetException e) {
                 {if (true) throw SqlUtil.newContextException(getPos(),
                     RESOURCE.unknownCharacterSet(charSet));}
             }
-            frags.add(literal);
-            nfrags++;
       }
-      if (jj_2_476(2)) {
+      if (jj_2_490(2)) {
         jj_consume_token(UESCAPE);
         jj_consume_token(QUOTED_STRING);
             if (unicodeEscapeChar == 0) {
@@ -5440,13 +5649,13 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
       } else {
         ;
       }
-        assert nfrags > 0;
-        if (nfrags == 1) {
+        assert !frags.isEmpty();
+        if (frags.size() == 1) {
             // just the head fragment
             SqlLiteral lit = (SqlLiteral) frags.get(0);
             {if (true) return lit.unescapeUnicode(unicodeEscapeChar);}
         } else {
-            SqlNode[] rands = (SqlNode[]) frags.toArray(new SqlNode[nfrags]);
+            SqlNode[] rands = (SqlNode[]) frags.toArray(new SqlNode[0]);
             for (int i = 0; i < rands.length; ++i) {
                 rands[i] = ((SqlLiteral) rands[i]).unescapeUnicode(
                     unicodeEscapeChar);
@@ -5454,7 +5663,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             SqlParserPos pos2 = SqlParserPos.sum(rands);
             {if (true) return SqlStdOperatorTable.LITERAL_CHAIN.createCall(pos2, rands);}
         }
-    } else if (jj_2_479(2)) {
+    } else if (jj_2_493(2)) {
       jj_consume_token(BIG_QUERY_DOUBLE_QUOTED_STRING);
         p = SqlParserUtil.stripQuotes(getToken(0).image, DQ, DQ, "\\\"",
             Casing.UNCHANGED);
@@ -5464,7 +5673,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             {if (true) throw SqlUtil.newContextException(getPos(),
                 RESOURCE.unknownCharacterSet(charSet));}
         }
-    } else if (jj_2_480(2)) {
+    } else if (jj_2_494(2)) {
       jj_consume_token(BIG_QUERY_QUOTED_STRING);
         p = SqlParserUtil.stripQuotes(getToken(0).image, "'", "'", "\\'",
             Casing.UNCHANGED);
@@ -5481,46 +5690,67 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     throw new Error("Missing return statement in function");
   }
 
+/** Parses a character literal.
+ * Matches a single-quoted string, such as 'foo';
+ * on BigQuery also matches a double-quoted string, such as "foo".
+ * Returns the value of the string with quotes removed. */
+  final public String SimpleStringLiteral() throws ParseException {
+    if (jj_2_495(2)) {
+      jj_consume_token(QUOTED_STRING);
+        {if (true) return SqlParserUtil.parseString(token.image);}
+    } else if (jj_2_496(2)) {
+      jj_consume_token(BIG_QUERY_QUOTED_STRING);
+        {if (true) return SqlParserUtil.stripQuotes(token.image, "'", "'", "\\'", Casing.UNCHANGED);}
+    } else if (jj_2_497(2)) {
+      jj_consume_token(BIG_QUERY_DOUBLE_QUOTED_STRING);
+        {if (true) return SqlParserUtil.stripQuotes(token.image, DQ, DQ, "\\\"", Casing.UNCHANGED);}
+    } else {
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    throw new Error("Missing return statement in function");
+  }
+
 /**
  * Parses a date/time literal.
  */
   final public SqlLiteral DateTimeLiteral() throws ParseException {
-    final String  p;
+    final String p;
     final Span s;
-    if (jj_2_481(2)) {
+    if (jj_2_498(2)) {
       jj_consume_token(LBRACE_D);
       jj_consume_token(QUOTED_STRING);
-        p = token.image;
+        p = SqlParserUtil.parseString(token.image);
       jj_consume_token(RBRACE);
         {if (true) return SqlParserUtil.parseDateLiteral(p, getPos());}
-    } else if (jj_2_482(2)) {
+    } else if (jj_2_499(2)) {
       jj_consume_token(LBRACE_T);
       jj_consume_token(QUOTED_STRING);
-        p = token.image;
+        p = SqlParserUtil.parseString(token.image);
       jj_consume_token(RBRACE);
         {if (true) return SqlParserUtil.parseTimeLiteral(p, getPos());}
-    } else if (jj_2_483(2)) {
+    } else if (jj_2_500(2)) {
       jj_consume_token(LBRACE_TS);
                   s = span();
       jj_consume_token(QUOTED_STRING);
-        p = token.image;
+        p = SqlParserUtil.parseString(token.image);
       jj_consume_token(RBRACE);
         {if (true) return SqlParserUtil.parseTimestampLiteral(p, s.end(this));}
-    } else if (jj_2_484(2)) {
+    } else if (jj_2_501(2)) {
       jj_consume_token(DATE);
              s = span();
-      jj_consume_token(QUOTED_STRING);
-        {if (true) return SqlParserUtil.parseDateLiteral(token.image, s.end(this));}
-    } else if (jj_2_485(2)) {
+      p = SimpleStringLiteral();
+      {if (true) return SqlParserUtil.parseDateLiteral(p, s.end(this));}
+    } else if (jj_2_502(2)) {
       jj_consume_token(TIME);
              s = span();
-      jj_consume_token(QUOTED_STRING);
-        {if (true) return SqlParserUtil.parseTimeLiteral(token.image, s.end(this));}
-    } else if (jj_2_486(2)) {
+      p = SimpleStringLiteral();
+        {if (true) return SqlParserUtil.parseTimeLiteral(p, s.end(this));}
+    } else if (jj_2_503(2)) {
       jj_consume_token(TIMESTAMP);
                   s = span();
-      jj_consume_token(QUOTED_STRING);
-        {if (true) return SqlParserUtil.parseTimestampLiteral(token.image, s.end(this));}
+      p = SimpleStringLiteral();
+        {if (true) return SqlParserUtil.parseTimestampLiteral(p, s.end(this));}
     } else {
       jj_consume_token(-1);
       throw new ParseException();
@@ -5530,33 +5760,30 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
 /** Parses a MULTISET constructor */
   final public SqlNode MultisetConstructor() throws ParseException {
-    List<SqlNode> args;
+    final List<SqlNode> args = new ArrayList<SqlNode>();
     SqlNode e;
     final Span s;
     jj_consume_token(MULTISET);
                  s = span();
-    if (jj_2_488(2)) {
+    if (jj_2_505(2)) {
       jj_consume_token(LPAREN);
       // by sub query "MULTISET(SELECT * FROM T)"
               e = LeafQueryOrExpr(ExprContext.ACCEPT_QUERY);
       jj_consume_token(RPAREN);
             {if (true) return SqlStdOperatorTable.MULTISET_QUERY.createCall(
                 s.end(this), e);}
-    } else if (jj_2_489(2)) {
+    } else if (jj_2_506(2)) {
       jj_consume_token(LBRACKET);
-      // TODO: do trigraph as well ??( ??)
-              e = Expression(ExprContext.ACCEPT_NON_QUERY);
-                                                       args = startList(e);
-      label_45:
+      AddExpression(args, ExprContext.ACCEPT_NON_QUERY);
+      label_51:
       while (true) {
-        if (jj_2_487(2)) {
+        if (jj_2_504(2)) {
           ;
         } else {
-          break label_45;
+          break label_51;
         }
         jj_consume_token(COMMA);
-        e = Expression(ExprContext.ACCEPT_NON_QUERY);
-                                                                   args.add(e);
+        AddExpression(args, ExprContext.ACCEPT_NON_QUERY);
       }
       jj_consume_token(RBRACKET);
             {if (true) return SqlStdOperatorTable.MULTISET_VALUE.createCall(
@@ -5579,16 +5806,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     case LPAREN:
       jj_consume_token(LPAREN);
       // by sub query "MULTISET(SELECT * FROM T)"
-              e = LeafQueryOrExpr(ExprContext.ACCEPT_QUERY);
+              e = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY);
       jj_consume_token(RPAREN);
             {if (true) return SqlStdOperatorTable.ARRAY_QUERY.createCall(
                 s.end(this), e);}
       break;
     default:
-      jj_la1[6] = jj_gen;
-      if (jj_2_491(2)) {
+      jj_la1[7] = jj_gen;
+      if (jj_2_508(2)) {
         jj_consume_token(LBRACKET);
-        if (jj_2_490(2)) {
+        if (jj_2_507(2)) {
           args = ExpressionCommaList(s, ExprContext.ACCEPT_NON_QUERY);
         } else {
               args = SqlNodeList.EMPTY;
@@ -5621,10 +5848,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                 s.end(this), e);}
       break;
     default:
-      jj_la1[7] = jj_gen;
-      if (jj_2_493(2)) {
+      jj_la1[8] = jj_gen;
+      if (jj_2_510(2)) {
         jj_consume_token(LBRACKET);
-        if (jj_2_492(2)) {
+        if (jj_2_509(2)) {
           args = ExpressionCommaList(s, ExprContext.ACCEPT_NON_QUERY);
         } else {
               args = SqlNodeList.EMPTY;
@@ -5642,16 +5869,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
 /** Parses a PERIOD constructor */
   final public SqlNode PeriodConstructor() throws ParseException {
-    final SqlNode e0, e1;
+    final List<SqlNode> args = new ArrayList<SqlNode>();
     final Span s;
     jj_consume_token(PERIOD);
                s = span();
     jj_consume_token(LPAREN);
-    e0 = Expression(ExprContext.ACCEPT_SUB_QUERY);
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
     jj_consume_token(COMMA);
-    e1 = Expression(ExprContext.ACCEPT_SUB_QUERY);
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
     jj_consume_token(RPAREN);
-        {if (true) return SqlStdOperatorTable.ROW.createCall(s.end(this), e0, e1);}
+        {if (true) return SqlStdOperatorTable.ROW.createCall(s.end(this), args);}
     throw new Error("Missing return statement in function");
   }
 
@@ -5665,11 +5892,11 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final Span s;
     jj_consume_token(INTERVAL);
                  s = span();
-    if (jj_2_496(2)) {
-      if (jj_2_494(2)) {
+    if (jj_2_513(2)) {
+      if (jj_2_511(2)) {
         jj_consume_token(MINUS);
                   sign = -1;
-      } else if (jj_2_495(2)) {
+      } else if (jj_2_512(2)) {
         jj_consume_token(PLUS);
                  sign = 1;
       } else {
@@ -5679,8 +5906,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     } else {
       ;
     }
-    jj_consume_token(QUOTED_STRING);
-                      p = token.image;
+    p = SimpleStringLiteral();
     intervalQualifier = IntervalQualifier();
         {if (true) return SqlParserUtil.parseIntervalLiteral(s.end(intervalQualifier),
             sign, p, intervalQualifier);}
@@ -5698,11 +5924,11 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     SqlNode e;
     jj_consume_token(INTERVAL);
                  s = span();
-    if (jj_2_499(2)) {
-      if (jj_2_497(2)) {
+    if (jj_2_516(2)) {
+      if (jj_2_514(2)) {
         jj_consume_token(MINUS);
                   sign = -1;
-      } else if (jj_2_498(2)) {
+      } else if (jj_2_515(2)) {
         jj_consume_token(PLUS);
                  sign = 1;
       } else {
@@ -5712,20 +5938,20 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     } else {
       ;
     }
-    if (jj_2_503(2)) {
-      jj_consume_token(QUOTED_STRING);
-                          p = token.image;
+    if (jj_2_520(2)) {
+      // literal (with quoted string)
+              p = SimpleStringLiteral();
       intervalQualifier = IntervalQualifier();
             {if (true) return SqlParserUtil.parseIntervalLiteral(s.end(intervalQualifier),
                 sign, p, intervalQualifier);}
-    } else if (jj_2_504(2)) {
-      if (jj_2_500(2)) {
+    } else if (jj_2_521(2)) {
+      if (jj_2_517(2)) {
         jj_consume_token(LPAREN);
         e = Expression(ExprContext.ACCEPT_SUB_QUERY);
         jj_consume_token(RPAREN);
-      } else if (jj_2_501(2)) {
+      } else if (jj_2_518(2)) {
         e = UnsignedNumericLiteral();
-      } else if (jj_2_502(2)) {
+      } else if (jj_2_519(2)) {
         e = CompoundIdentifier();
       } else {
         jj_consume_token(-1);
@@ -5745,10 +5971,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public TimeUnit Year() throws ParseException {
-    if (jj_2_505(2)) {
+    if (jj_2_522(2)) {
       jj_consume_token(YEAR);
              {if (true) return TimeUnit.YEAR;}
-    } else if (jj_2_506(2)) {
+    } else if (jj_2_523(2)) {
       jj_consume_token(YEARS);
               {if (true) return warn(TimeUnit.YEAR);}
     } else {
@@ -5759,10 +5985,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public TimeUnit Month() throws ParseException {
-    if (jj_2_507(2)) {
+    if (jj_2_524(2)) {
       jj_consume_token(MONTH);
               {if (true) return TimeUnit.MONTH;}
-    } else if (jj_2_508(2)) {
+    } else if (jj_2_525(2)) {
       jj_consume_token(MONTHS);
                {if (true) return warn(TimeUnit.MONTH);}
     } else {
@@ -5773,10 +5999,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public TimeUnit Day() throws ParseException {
-    if (jj_2_509(2)) {
+    if (jj_2_526(2)) {
       jj_consume_token(DAY);
             {if (true) return TimeUnit.DAY;}
-    } else if (jj_2_510(2)) {
+    } else if (jj_2_527(2)) {
       jj_consume_token(DAYS);
              {if (true) return warn(TimeUnit.DAY);}
     } else {
@@ -5787,10 +6013,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public TimeUnit Hour() throws ParseException {
-    if (jj_2_511(2)) {
+    if (jj_2_528(2)) {
       jj_consume_token(HOUR);
              {if (true) return TimeUnit.HOUR;}
-    } else if (jj_2_512(2)) {
+    } else if (jj_2_529(2)) {
       jj_consume_token(HOURS);
               {if (true) return warn(TimeUnit.HOUR);}
     } else {
@@ -5801,10 +6027,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public TimeUnit Minute() throws ParseException {
-    if (jj_2_513(2)) {
+    if (jj_2_530(2)) {
       jj_consume_token(MINUTE);
                {if (true) return TimeUnit.MINUTE;}
-    } else if (jj_2_514(2)) {
+    } else if (jj_2_531(2)) {
       jj_consume_token(MINUTES);
                 {if (true) return warn(TimeUnit.MINUTE);}
     } else {
@@ -5815,10 +6041,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public TimeUnit Second() throws ParseException {
-    if (jj_2_515(2)) {
+    if (jj_2_532(2)) {
       jj_consume_token(SECOND);
                {if (true) return TimeUnit.SECOND;}
-    } else if (jj_2_516(2)) {
+    } else if (jj_2_533(2)) {
       jj_consume_token(SECONDS);
                 {if (true) return warn(TimeUnit.SECOND);}
     } else {
@@ -5831,34 +6057,35 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlIntervalQualifier IntervalQualifier() throws ParseException {
     final Span s;
     final TimeUnit start;
-    TimeUnit end = null;
-    int startPrec = RelDataType.PRECISION_NOT_SPECIFIED;
+    final TimeUnit end;
+    final int startPrec;
     int secondFracPrec = RelDataType.PRECISION_NOT_SPECIFIED;
-    if (jj_2_530(2)) {
+    if (jj_2_547(2)) {
       start = Year();
                          s = span();
       startPrec = PrecisionOpt();
-      if (jj_2_517(2)) {
+      if (jj_2_534(2)) {
         jj_consume_token(TO);
         end = Month();
       } else {
-        ;
+              end = null;
       }
-    } else if (jj_2_531(2)) {
+    } else if (jj_2_548(2)) {
       start = Month();
                           s = span();
       startPrec = PrecisionOpt();
-    } else if (jj_2_532(2)) {
+          end = null;
+    } else if (jj_2_549(2)) {
       start = Day();
                         s = span();
       startPrec = PrecisionOpt();
-      if (jj_2_521(2)) {
+      if (jj_2_538(2)) {
         jj_consume_token(TO);
-        if (jj_2_518(2)) {
+        if (jj_2_535(2)) {
           end = Hour();
-        } else if (jj_2_519(2)) {
+        } else if (jj_2_536(2)) {
           end = Minute();
-        } else if (jj_2_520(2)) {
+        } else if (jj_2_537(2)) {
           end = Second();
           secondFracPrec = PrecisionOpt();
         } else {
@@ -5866,19 +6093,19 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
           throw new ParseException();
         }
       } else {
-        ;
+              end = null;
       }
-    } else if (jj_2_533(2)) {
+    } else if (jj_2_550(2)) {
       start = Hour();
                          s = span();
       startPrec = PrecisionOpt();
-      if (jj_2_525(2)) {
+      if (jj_2_542(2)) {
         jj_consume_token(TO);
-        if (jj_2_523(2)) {
+        if (jj_2_540(2)) {
           end = Minute();
-        } else if (jj_2_524(2)) {
+        } else if (jj_2_541(2)) {
           end = Second();
-          if (jj_2_522(2)) {
+          if (jj_2_539(2)) {
             jj_consume_token(LPAREN);
             secondFracPrec = UnsignedIntLiteral();
             jj_consume_token(RPAREN);
@@ -5890,16 +6117,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
           throw new ParseException();
         }
       } else {
-        ;
+              end = null;
       }
-    } else if (jj_2_534(2)) {
+    } else if (jj_2_551(2)) {
       start = Minute();
                            s = span();
       startPrec = PrecisionOpt();
-      if (jj_2_527(2)) {
+      if (jj_2_544(2)) {
         jj_consume_token(TO);
         end = Second();
-        if (jj_2_526(2)) {
+        if (jj_2_543(2)) {
           jj_consume_token(LPAREN);
           secondFracPrec = UnsignedIntLiteral();
           jj_consume_token(RPAREN);
@@ -5907,15 +6134,15 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
           ;
         }
       } else {
-        ;
+              end = null;
       }
-    } else if (jj_2_535(2)) {
+    } else if (jj_2_552(2)) {
       start = Second();
                            s = span();
-      if (jj_2_529(2)) {
+      if (jj_2_546(2)) {
         jj_consume_token(LPAREN);
         startPrec = UnsignedIntLiteral();
-        if (jj_2_528(2)) {
+        if (jj_2_545(2)) {
           jj_consume_token(COMMA);
           secondFracPrec = UnsignedIntLiteral();
         } else {
@@ -5923,8 +6150,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         }
         jj_consume_token(RPAREN);
       } else {
-        ;
+              startPrec = -1;
       }
+          end = null;
     } else {
       jj_consume_token(-1);
       throw new ParseException();
@@ -5940,16 +6168,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final TimeUnit start;
     int startPrec = RelDataType.PRECISION_NOT_SPECIFIED;
     int secondFracPrec = RelDataType.PRECISION_NOT_SPECIFIED;
-    if (jj_2_543(2)) {
-      if (jj_2_536(2)) {
+    if (jj_2_560(2)) {
+      if (jj_2_553(2)) {
         start = Year();
-      } else if (jj_2_537(2)) {
+      } else if (jj_2_554(2)) {
         start = Month();
-      } else if (jj_2_538(2)) {
+      } else if (jj_2_555(2)) {
         start = Day();
-      } else if (jj_2_539(2)) {
+      } else if (jj_2_556(2)) {
         start = Hour();
-      } else if (jj_2_540(2)) {
+      } else if (jj_2_557(2)) {
         start = Minute();
       } else {
         jj_consume_token(-1);
@@ -5957,13 +6185,13 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
       }
           s = span();
       startPrec = PrecisionOpt();
-    } else if (jj_2_544(2)) {
+    } else if (jj_2_561(2)) {
       start = Second();
                            s = span();
-      if (jj_2_542(2)) {
+      if (jj_2_559(2)) {
         jj_consume_token(LPAREN);
         startPrec = UnsignedIntLiteral();
-        if (jj_2_541(2)) {
+        if (jj_2_558(2)) {
           jj_consume_token(COMMA);
           secondFracPrec = UnsignedIntLiteral();
         } else {
@@ -5983,130 +6211,208 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
 /**
- * Parses time unit for EXTRACT, CEIL and FLOOR functions.
- * Note that it does't include NANOSECOND and MICROSECOND.
+ * Parses time unit for CEIL and FLOOR functions.
  */
   final public TimeUnit TimeUnit() throws ParseException {
-    if (jj_2_545(2)) {
-      jj_consume_token(MILLISECOND);
-                    {if (true) return TimeUnit.MILLISECOND;}
-    } else if (jj_2_546(2)) {
-      jj_consume_token(SECOND);
-               {if (true) return TimeUnit.SECOND;}
-    } else if (jj_2_547(2)) {
-      jj_consume_token(MINUTE);
-               {if (true) return TimeUnit.MINUTE;}
-    } else if (jj_2_548(2)) {
-      jj_consume_token(HOUR);
-             {if (true) return TimeUnit.HOUR;}
-    } else if (jj_2_549(2)) {
-      jj_consume_token(DAY);
-            {if (true) return TimeUnit.DAY;}
-    } else if (jj_2_550(2)) {
-      jj_consume_token(DOW);
-            {if (true) return TimeUnit.DOW;}
-    } else if (jj_2_551(2)) {
-      jj_consume_token(DOY);
-            {if (true) return TimeUnit.DOY;}
-    } else if (jj_2_552(2)) {
-      jj_consume_token(ISODOW);
-               {if (true) return TimeUnit.ISODOW;}
-    } else if (jj_2_553(2)) {
-      jj_consume_token(ISOYEAR);
-                {if (true) return TimeUnit.ISOYEAR;}
-    } else if (jj_2_554(2)) {
-      jj_consume_token(WEEK);
-             {if (true) return TimeUnit.WEEK;}
-    } else if (jj_2_555(2)) {
-      jj_consume_token(MONTH);
-              {if (true) return TimeUnit.MONTH;}
-    } else if (jj_2_556(2)) {
-      jj_consume_token(QUARTER);
-                {if (true) return TimeUnit.QUARTER;}
-    } else if (jj_2_557(2)) {
-      jj_consume_token(YEAR);
-             {if (true) return TimeUnit.YEAR;}
-    } else if (jj_2_558(2)) {
-      jj_consume_token(EPOCH);
-              {if (true) return TimeUnit.EPOCH;}
-    } else if (jj_2_559(2)) {
-      jj_consume_token(DECADE);
-               {if (true) return TimeUnit.DECADE;}
-    } else if (jj_2_560(2)) {
-      jj_consume_token(CENTURY);
-                {if (true) return TimeUnit.CENTURY;}
-    } else if (jj_2_561(2)) {
-      jj_consume_token(MILLENNIUM);
-                   {if (true) return TimeUnit.MILLENNIUM;}
-    } else {
-      jj_consume_token(-1);
-      throw new ParseException();
+    final TimeUnit unit;
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+    case CENTURY:
+    case DAY:
+    case DECADE:
+    case DOW:
+    case DOY:
+    case EPOCH:
+    case HOUR:
+    case ISODOW:
+    case ISOYEAR:
+    case MILLISECOND:
+    case MILLENNIUM:
+    case MINUTE:
+    case MONTH:
+    case QUARTER:
+    case SECOND:
+    case WEEK:
+    case YEAR:
+      if (jj_2_562(2)) {
+        jj_consume_token(MILLISECOND);
+                        {if (true) return TimeUnit.MILLISECOND;}
+      } else if (jj_2_563(2)) {
+        jj_consume_token(SECOND);
+                   {if (true) return TimeUnit.SECOND;}
+      } else if (jj_2_564(2)) {
+        jj_consume_token(MINUTE);
+                   {if (true) return TimeUnit.MINUTE;}
+      } else if (jj_2_565(2)) {
+        jj_consume_token(HOUR);
+                 {if (true) return TimeUnit.HOUR;}
+      } else if (jj_2_566(2)) {
+        jj_consume_token(DAY);
+                {if (true) return TimeUnit.DAY;}
+      } else if (jj_2_567(2)) {
+        jj_consume_token(DOW);
+                {if (true) return TimeUnit.DOW;}
+      } else if (jj_2_568(2)) {
+        jj_consume_token(DOY);
+                {if (true) return TimeUnit.DOY;}
+      } else if (jj_2_569(2)) {
+        jj_consume_token(ISODOW);
+                   {if (true) return TimeUnit.ISODOW;}
+      } else if (jj_2_570(2)) {
+        jj_consume_token(ISOYEAR);
+                    {if (true) return TimeUnit.ISOYEAR;}
+      } else if (jj_2_571(2)) {
+        jj_consume_token(WEEK);
+                 {if (true) return TimeUnit.WEEK;}
+      } else if (jj_2_572(2)) {
+        jj_consume_token(MONTH);
+                  {if (true) return TimeUnit.MONTH;}
+      } else if (jj_2_573(2)) {
+        jj_consume_token(QUARTER);
+                    {if (true) return TimeUnit.QUARTER;}
+      } else if (jj_2_574(2)) {
+        jj_consume_token(YEAR);
+                 {if (true) return TimeUnit.YEAR;}
+      } else if (jj_2_575(2)) {
+        jj_consume_token(EPOCH);
+                  {if (true) return TimeUnit.EPOCH;}
+      } else if (jj_2_576(2)) {
+        jj_consume_token(DECADE);
+                   {if (true) return TimeUnit.DECADE;}
+      } else if (jj_2_577(2)) {
+        jj_consume_token(CENTURY);
+                    {if (true) return TimeUnit.CENTURY;}
+      } else if (jj_2_578(2)) {
+        jj_consume_token(MILLENNIUM);
+                       {if (true) return TimeUnit.MILLENNIUM;}
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+      break;
+    default:
+      jj_la1[9] = jj_gen;
+      if (jj_2_579(2)) {
+        unit = TimeUnitIdentifier();
+                                  {if (true) return unit;}
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+/**
+ * Parses time unit for the EXTRACT function.
+ * As for FLOOR and CEIL, but also includes NANOSECOND and MICROSECOND.
+ */
+  final public TimeUnit TimeUnitForExtract() throws ParseException {
+    final TimeUnit unit;
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+    case MICROSECOND:
+    case NANOSECOND:
+      if (jj_2_580(2)) {
+        jj_consume_token(NANOSECOND);
+                       {if (true) return TimeUnit.NANOSECOND;}
+      } else if (jj_2_581(2)) {
+        jj_consume_token(MICROSECOND);
+                        {if (true) return TimeUnit.MICROSECOND;}
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+      break;
+    default:
+      jj_la1[10] = jj_gen;
+      if (jj_2_582(2)) {
+        unit = TimeUnit();
+                        {if (true) return unit;}
+      } else {
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
     }
     throw new Error("Missing return statement in function");
   }
 
+/**
+ * Parses a simple identifier as a TimeUnit.
+ */
+  final public TimeUnit TimeUnitIdentifier() throws ParseException {
+    final List<String> names = new ArrayList<String>();
+    final List<SqlParserPos> positions = new ArrayList<SqlParserPos>();
+    AddIdentifierSegment(names, positions);
+        TimeUnit unit = timeUnitCodes.get(names.get(0));
+        if (unit != null) {
+          {if (true) return unit;}
+        }
+        {if (true) throw SqlUtil.newContextException(positions.get(0),
+            RESOURCE.invalidDatetimeFormat(SqlIdentifier.getString(names)));}
+    throw new Error("Missing return statement in function");
+  }
+
   final public TimeUnit TimestampInterval() throws ParseException {
-    if (jj_2_562(2)) {
+    if (jj_2_583(2)) {
       jj_consume_token(FRAC_SECOND);
                     {if (true) return TimeUnit.MICROSECOND;}
-    } else if (jj_2_563(2)) {
+    } else if (jj_2_584(2)) {
       jj_consume_token(MICROSECOND);
                     {if (true) return TimeUnit.MICROSECOND;}
-    } else if (jj_2_564(2)) {
+    } else if (jj_2_585(2)) {
       jj_consume_token(NANOSECOND);
                    {if (true) return TimeUnit.NANOSECOND;}
-    } else if (jj_2_565(2)) {
+    } else if (jj_2_586(2)) {
       jj_consume_token(SQL_TSI_FRAC_SECOND);
                             {if (true) return TimeUnit.NANOSECOND;}
-    } else if (jj_2_566(2)) {
+    } else if (jj_2_587(2)) {
       jj_consume_token(SQL_TSI_MICROSECOND);
                             {if (true) return TimeUnit.MICROSECOND;}
-    } else if (jj_2_567(2)) {
+    } else if (jj_2_588(2)) {
       jj_consume_token(SECOND);
                {if (true) return TimeUnit.SECOND;}
-    } else if (jj_2_568(2)) {
+    } else if (jj_2_589(2)) {
       jj_consume_token(SQL_TSI_SECOND);
                        {if (true) return TimeUnit.SECOND;}
-    } else if (jj_2_569(2)) {
+    } else if (jj_2_590(2)) {
       jj_consume_token(MINUTE);
                {if (true) return TimeUnit.MINUTE;}
-    } else if (jj_2_570(2)) {
+    } else if (jj_2_591(2)) {
       jj_consume_token(SQL_TSI_MINUTE);
                        {if (true) return TimeUnit.MINUTE;}
-    } else if (jj_2_571(2)) {
+    } else if (jj_2_592(2)) {
       jj_consume_token(HOUR);
              {if (true) return TimeUnit.HOUR;}
-    } else if (jj_2_572(2)) {
+    } else if (jj_2_593(2)) {
       jj_consume_token(SQL_TSI_HOUR);
                      {if (true) return TimeUnit.HOUR;}
-    } else if (jj_2_573(2)) {
+    } else if (jj_2_594(2)) {
       jj_consume_token(DAY);
             {if (true) return TimeUnit.DAY;}
-    } else if (jj_2_574(2)) {
+    } else if (jj_2_595(2)) {
       jj_consume_token(SQL_TSI_DAY);
                     {if (true) return TimeUnit.DAY;}
-    } else if (jj_2_575(2)) {
+    } else if (jj_2_596(2)) {
       jj_consume_token(WEEK);
              {if (true) return TimeUnit.WEEK;}
-    } else if (jj_2_576(2)) {
+    } else if (jj_2_597(2)) {
       jj_consume_token(SQL_TSI_WEEK);
                      {if (true) return TimeUnit.WEEK;}
-    } else if (jj_2_577(2)) {
+    } else if (jj_2_598(2)) {
       jj_consume_token(MONTH);
               {if (true) return TimeUnit.MONTH;}
-    } else if (jj_2_578(2)) {
+    } else if (jj_2_599(2)) {
       jj_consume_token(SQL_TSI_MONTH);
                       {if (true) return TimeUnit.MONTH;}
-    } else if (jj_2_579(2)) {
+    } else if (jj_2_600(2)) {
       jj_consume_token(QUARTER);
                 {if (true) return TimeUnit.QUARTER;}
-    } else if (jj_2_580(2)) {
+    } else if (jj_2_601(2)) {
       jj_consume_token(SQL_TSI_QUARTER);
                         {if (true) return TimeUnit.QUARTER;}
-    } else if (jj_2_581(2)) {
+    } else if (jj_2_602(2)) {
       jj_consume_token(YEAR);
              {if (true) return TimeUnit.YEAR;}
-    } else if (jj_2_582(2)) {
+    } else if (jj_2_603(2)) {
       jj_consume_token(SQL_TSI_YEAR);
                      {if (true) return TimeUnit.YEAR;}
     } else {
@@ -6132,46 +6438,46 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * the entry in {@code positions} records its position and whether the
  * segment was quoted.
  */
-  final public void IdentifierSegment(List<String> names, List<SqlParserPos> positions) throws ParseException {
+  final public void AddIdentifierSegment(List<String> names, List<SqlParserPos> positions) throws ParseException {
     final String id;
     char unicodeEscapeChar = BACKSLASH;
     final SqlParserPos pos;
     final Span span;
-    if (jj_2_584(2)) {
+    if (jj_2_605(2)) {
       jj_consume_token(IDENTIFIER);
             id = unquotedIdentifier();
             pos = getPos();
-    } else if (jj_2_585(2)) {
+    } else if (jj_2_606(2)) {
       jj_consume_token(HYPHENATED_IDENTIFIER);
             id = unquotedIdentifier();
             pos = getPos();
-    } else if (jj_2_586(2)) {
+    } else if (jj_2_607(2)) {
       jj_consume_token(QUOTED_IDENTIFIER);
             id = SqlParserUtil.stripQuotes(getToken(0).image, DQ, DQ, DQDQ,
                 quotedCasing);
             pos = getPos().withQuoting(true);
-    } else if (jj_2_587(2)) {
+    } else if (jj_2_608(2)) {
       jj_consume_token(BACK_QUOTED_IDENTIFIER);
             id = SqlParserUtil.stripQuotes(getToken(0).image, "`", "`", "``",
                 quotedCasing);
             pos = getPos().withQuoting(true);
-    } else if (jj_2_588(2)) {
+    } else if (jj_2_609(2)) {
       jj_consume_token(BIG_QUERY_BACK_QUOTED_IDENTIFIER);
             id = SqlParserUtil.stripQuotes(getToken(0).image, "`", "`", "\\`",
                 quotedCasing);
             pos = getPos().withQuoting(true);
-    } else if (jj_2_589(2)) {
+    } else if (jj_2_610(2)) {
       jj_consume_token(BRACKET_QUOTED_IDENTIFIER);
             id = SqlParserUtil.stripQuotes(getToken(0).image, "[", "]", "]]",
                 quotedCasing);
             pos = getPos().withQuoting(true);
-    } else if (jj_2_590(2)) {
+    } else if (jj_2_611(2)) {
       jj_consume_token(UNICODE_QUOTED_IDENTIFIER);
             span = span();
             String image = getToken(0).image;
             image = image.substring(image.indexOf('"'));
             image = SqlParserUtil.stripQuotes(image, DQ, DQ, DQDQ, quotedCasing);
-      if (jj_2_583(2)) {
+      if (jj_2_604(2)) {
         jj_consume_token(UESCAPE);
         jj_consume_token(QUOTED_STRING);
                 String s = SqlParserUtil.parseString(token.image);
@@ -6183,7 +6489,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             SqlLiteral lit = SqlLiteral.createCharString(image, "UTF16", pos);
             lit = lit.unescapeUnicode(unicodeEscapeChar);
             id = lit.toValue();
-    } else if (jj_2_591(2)) {
+    } else if (jj_2_612(2)) {
       id = NonReservedKeyWord();
             pos = getPos();
     } else {
@@ -6200,14 +6506,14 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         }
   }
 
-/** As {@link #IdentifierSegment} but part of a table name (for example,
+/** As {@link #AddIdentifierSegment} but part of a table name (for example,
  * following {@code FROM}, {@code INSERT} or {@code UPDATE}).
  *
  * <p>In some dialects the lexical rules for table names are different from
  * for other identifiers. For example, in BigQuery, table names may contain
  * hyphens. */
-  final public void TableIdentifierSegment(List<String> names, List<SqlParserPos> positions) throws ParseException {
-    IdentifierSegment(names, positions);
+  final public void AddTableIdentifierSegment(List<String> names, List<SqlParserPos> positions) throws ParseException {
+    AddIdentifierSegment(names, positions);
         final int n = names.size();
         if (n > 0
                 && positions.size() == n
@@ -6229,7 +6535,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public String Identifier() throws ParseException {
     final List<String> names = new ArrayList<String>();
-    IdentifierSegment(names, null);
+    AddIdentifierSegment(names, null);
         {if (true) return names.get(0);}
     throw new Error("Missing return statement in function");
   }
@@ -6240,7 +6546,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlIdentifier SimpleIdentifier() throws ParseException {
     final List<String> names = new ArrayList<String>();
     final List<SqlParserPos> positions = new ArrayList<SqlParserPos>();
-    IdentifierSegment(names, positions);
+    AddIdentifierSegment(names, positions);
         {if (true) return new SqlIdentifier(names.get(0), positions.get(0));}
     throw new Error("Missing return statement in function");
   }
@@ -6262,16 +6568,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 /**
  * Parses a comma-separated list of simple identifiers.
  */
-  final public void SimpleIdentifierCommaList(List<SqlNode> list) throws ParseException {
+  final public void AddSimpleIdentifiers(List<SqlNode> list) throws ParseException {
     SqlIdentifier id;
     id = SimpleIdentifier();
                              list.add(id);
-    label_46:
+    label_52:
     while (true) {
-      if (jj_2_592(2)) {
+      if (jj_2_613(2)) {
         ;
       } else {
-        break label_46;
+        break label_52;
       }
       jj_consume_token(COMMA);
       id = SimpleIdentifier();
@@ -6288,7 +6594,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final List<SqlNode> list = new ArrayList<SqlNode>();
     jj_consume_token(LPAREN);
                s = span();
-    SimpleIdentifierCommaList(list);
+    AddSimpleIdentifiers(list);
     jj_consume_token(RPAREN);
         {if (true) return new SqlNodeList(list, s.end(this));}
     throw new Error("Missing return statement in function");
@@ -6304,10 +6610,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlNodeList SimpleIdentifierOrList() throws ParseException {
     SqlIdentifier id;
     SqlNodeList list;
-    if (jj_2_593(2)) {
+    if (jj_2_614(2)) {
       id = SimpleIdentifier();
         {if (true) return new SqlNodeList(Collections.singletonList(id), id.getParserPosition());}
-    } else if (jj_2_594(2)) {
+    } else if (jj_2_615(2)) {
       list = ParenthesizedSimpleIdentifierList();
         {if (true) return list;}
     } else {
@@ -6324,18 +6630,18 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final List<String> nameList = new ArrayList<String>();
     final List<SqlParserPos> posList = new ArrayList<SqlParserPos>();
     boolean star = false;
-    IdentifierSegment(nameList, posList);
-    label_47:
+    AddIdentifierSegment(nameList, posList);
+    label_53:
     while (true) {
-      if (jj_2_595(2)) {
+      if (jj_2_616(2)) {
         ;
       } else {
-        break label_47;
+        break label_53;
       }
       jj_consume_token(DOT);
-      IdentifierSegment(nameList, posList);
+      AddIdentifierSegment(nameList, posList);
     }
-    if (jj_2_596(2)) {
+    if (jj_2_617(2)) {
       jj_consume_token(DOT);
       jj_consume_token(STAR);
             star = true;
@@ -6358,16 +6664,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlIdentifier CompoundTableIdentifier() throws ParseException {
     final List<String> nameList = new ArrayList<String>();
     final List<SqlParserPos> posList = new ArrayList<SqlParserPos>();
-    TableIdentifierSegment(nameList, posList);
-    label_48:
+    AddTableIdentifierSegment(nameList, posList);
+    label_54:
     while (true) {
-      if (jj_2_597(2)) {
+      if (jj_2_618(2)) {
         ;
       } else {
-        break label_48;
+        break label_54;
       }
       jj_consume_token(DOT);
-      TableIdentifierSegment(nameList, posList);
+      AddTableIdentifierSegment(nameList, posList);
     }
         SqlParserPos pos = SqlParserPos.sum(posList);
         {if (true) return new SqlIdentifier(nameList, null, pos, posList);}
@@ -6377,17 +6683,17 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 /**
  * Parses a comma-separated list of compound identifiers.
  */
-  final public void CompoundIdentifierTypeCommaList(List<SqlNode> list, List<SqlNode> extendList) throws ParseException {
-    CompoundIdentifierType(list, extendList);
-    label_49:
+  final public void AddCompoundIdentifierTypes(List<SqlNode> list, List<SqlNode> extendList) throws ParseException {
+    AddCompoundIdentifierType(list, extendList);
+    label_55:
     while (true) {
-      if (jj_2_598(2)) {
+      if (jj_2_619(2)) {
         ;
       } else {
-        break label_49;
+        break label_55;
       }
       jj_consume_token(COMMA);
-      CompoundIdentifierType(list, extendList);
+      AddCompoundIdentifierType(list, extendList);
     }
   }
 
@@ -6401,7 +6707,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final List<SqlNode> extendList = new ArrayList<SqlNode>();
     jj_consume_token(LPAREN);
                s = span();
-    CompoundIdentifierTypeCommaList(list, extendList);
+    AddCompoundIdentifierTypes(list, extendList);
     jj_consume_token(RPAREN);
         {if (true) return Pair.of(new SqlNodeList(list, s.end(this)), new SqlNodeList(extendList, s.end(this)));}
     throw new Error("Missing return statement in function");
@@ -6436,10 +6742,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
   final public int IntLiteral() throws ParseException {
     Token t;
-    if (jj_2_601(2)) {
-      if (jj_2_599(2)) {
+    if (jj_2_622(2)) {
+      if (jj_2_620(2)) {
         t = jj_consume_token(UNSIGNED_INTEGER_LITERAL);
-      } else if (jj_2_600(2)) {
+      } else if (jj_2_621(2)) {
         jj_consume_token(PLUS);
         t = jj_consume_token(UNSIGNED_INTEGER_LITERAL);
       } else {
@@ -6452,7 +6758,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             {if (true) throw SqlUtil.newContextException(getPos(),
                 RESOURCE.invalidLiteral(t.image, Integer.class.getCanonicalName()));}
         }
-    } else if (jj_2_602(2)) {
+    } else if (jj_2_623(2)) {
       jj_consume_token(MINUS);
       t = jj_consume_token(UNSIGNED_INTEGER_LITERAL);
         try {
@@ -6474,12 +6780,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final Span s;
     typeName = TypeName();
         s = Span.of(typeName.getParserPos());
-    label_50:
+    label_56:
     while (true) {
-      if (jj_2_603(2)) {
+      if (jj_2_624(2)) {
         ;
       } else {
-        break label_50;
+        break label_56;
       }
       typeName = CollectionsTypeName(typeName);
     }
@@ -6493,11 +6799,11 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final SqlTypeNameSpec typeNameSpec;
     final SqlIdentifier typeName;
     final Span s = Span.of();
-    if (jj_2_604(2)) {
+    if (jj_2_625(2)) {
       typeNameSpec = SqlTypeName(s);
-    } else if (jj_2_605(2)) {
+    } else if (jj_2_626(2)) {
       typeNameSpec = RowTypeName();
-    } else if (jj_2_606(2)) {
+    } else if (jj_2_627(2)) {
       typeName = CompoundIdentifier();
             typeNameSpec = new SqlUserDefinedTypeNameSpec(typeName, s.end(this));
     } else {
@@ -6511,15 +6817,15 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 // Types used for JDBC and ODBC scalar conversion function
   final public SqlTypeNameSpec SqlTypeName(Span s) throws ParseException {
     final SqlTypeNameSpec sqlTypeNameSpec;
-    if (jj_2_607(2)) {
+    if (jj_2_628(2)) {
       sqlTypeNameSpec = SqlTypeName1(s);
-    } else if (jj_2_608(2)) {
+    } else if (jj_2_629(2)) {
       sqlTypeNameSpec = SqlTypeName2(s);
-    } else if (jj_2_609(2)) {
+    } else if (jj_2_630(2)) {
       sqlTypeNameSpec = SqlTypeName3(s);
-    } else if (jj_2_610(2)) {
+    } else if (jj_2_631(2)) {
       sqlTypeNameSpec = CharacterTypeName(s);
-    } else if (jj_2_611(2)) {
+    } else if (jj_2_632(2)) {
       sqlTypeNameSpec = DateTimeTypeName();
     } else {
       jj_consume_token(-1);
@@ -6533,48 +6839,48 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 // For extra specification, we mean precision, scale, charSet, etc.
   final public SqlTypeNameSpec SqlTypeName1(Span s) throws ParseException {
     final SqlTypeName sqlTypeName;
-    if (jj_2_615(2)) {
+    if (jj_2_636(2)) {
       jj_consume_token(GEOMETRY);
             if (!this.conformance.allowGeometry()) {
                 {if (true) throw SqlUtil.newContextException(getPos(), RESOURCE.geometryDisabled());}
             }
             s.add(this);
             sqlTypeName = SqlTypeName.GEOMETRY;
-    } else if (jj_2_616(2)) {
+    } else if (jj_2_637(2)) {
       jj_consume_token(BOOLEAN);
                     s.add(this); sqlTypeName = SqlTypeName.BOOLEAN;
-    } else if (jj_2_617(2)) {
-      if (jj_2_612(2)) {
+    } else if (jj_2_638(2)) {
+      if (jj_2_633(2)) {
         jj_consume_token(INTEGER);
-      } else if (jj_2_613(2)) {
+      } else if (jj_2_634(2)) {
         jj_consume_token(INT);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                 s.add(this); sqlTypeName = SqlTypeName.INTEGER;
-    } else if (jj_2_618(2)) {
+    } else if (jj_2_639(2)) {
       jj_consume_token(TINYINT);
                     s.add(this); sqlTypeName = SqlTypeName.TINYINT;
-    } else if (jj_2_619(2)) {
+    } else if (jj_2_640(2)) {
       jj_consume_token(SMALLINT);
                      s.add(this); sqlTypeName = SqlTypeName.SMALLINT;
-    } else if (jj_2_620(2)) {
+    } else if (jj_2_641(2)) {
       jj_consume_token(BIGINT);
                    s.add(this); sqlTypeName = SqlTypeName.BIGINT;
-    } else if (jj_2_621(2)) {
+    } else if (jj_2_642(2)) {
       jj_consume_token(REAL);
                  s.add(this); sqlTypeName = SqlTypeName.REAL;
-    } else if (jj_2_622(2)) {
+    } else if (jj_2_643(2)) {
       jj_consume_token(DOUBLE);
                    s.add(this);
-      if (jj_2_614(2)) {
+      if (jj_2_635(2)) {
         jj_consume_token(PRECISION);
       } else {
         ;
       }
                           sqlTypeName = SqlTypeName.DOUBLE;
-    } else if (jj_2_623(2)) {
+    } else if (jj_2_644(2)) {
       jj_consume_token(FLOAT);
                   s.add(this); sqlTypeName = SqlTypeName.FLOAT;
     } else {
@@ -6589,16 +6895,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlTypeNameSpec SqlTypeName2(Span s) throws ParseException {
     final SqlTypeName sqlTypeName;
     int precision = -1;
-    if (jj_2_625(2)) {
+    if (jj_2_646(2)) {
       jj_consume_token(BINARY);
                    s.add(this);
-      if (jj_2_624(2)) {
+      if (jj_2_645(2)) {
         jj_consume_token(VARYING);
                         sqlTypeName = SqlTypeName.VARBINARY;
       } else {
               sqlTypeName = SqlTypeName.BINARY;
       }
-    } else if (jj_2_626(2)) {
+    } else if (jj_2_647(2)) {
       jj_consume_token(VARBINARY);
                       s.add(this); sqlTypeName = SqlTypeName.VARBINARY;
     } else {
@@ -6615,29 +6921,29 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final SqlTypeName sqlTypeName;
     int precision = -1;
     int scale = -1;
-    if (jj_2_630(2)) {
-      if (jj_2_627(2)) {
+    if (jj_2_651(2)) {
+      if (jj_2_648(2)) {
         jj_consume_token(DECIMAL);
-      } else if (jj_2_628(2)) {
+      } else if (jj_2_649(2)) {
         jj_consume_token(DEC);
-      } else if (jj_2_629(2)) {
+      } else if (jj_2_650(2)) {
         jj_consume_token(NUMERIC);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                           s.add(this); sqlTypeName = SqlTypeName.DECIMAL;
-    } else if (jj_2_631(2)) {
+    } else if (jj_2_652(2)) {
       jj_consume_token(ANY);
                 s.add(this); sqlTypeName = SqlTypeName.ANY;
     } else {
       jj_consume_token(-1);
       throw new ParseException();
     }
-    if (jj_2_633(2)) {
+    if (jj_2_654(2)) {
       jj_consume_token(LPAREN);
       precision = UnsignedIntLiteral();
-      if (jj_2_632(2)) {
+      if (jj_2_653(2)) {
         jj_consume_token(COMMA);
         scale = UnsignedIntLiteral();
       } else {
@@ -6653,213 +6959,213 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
 // Types used for for JDBC and ODBC scalar conversion function
   final public SqlJdbcDataTypeName JdbcOdbcDataTypeName() throws ParseException {
-    if (jj_2_668(2)) {
-      if (jj_2_634(2)) {
+    if (jj_2_689(2)) {
+      if (jj_2_655(2)) {
         jj_consume_token(SQL_CHAR);
-      } else if (jj_2_635(2)) {
+      } else if (jj_2_656(2)) {
         jj_consume_token(CHAR);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                             {if (true) return SqlJdbcDataTypeName.SQL_CHAR;}
-    } else if (jj_2_669(2)) {
-      if (jj_2_636(2)) {
+    } else if (jj_2_690(2)) {
+      if (jj_2_657(2)) {
         jj_consume_token(SQL_VARCHAR);
-      } else if (jj_2_637(2)) {
+      } else if (jj_2_658(2)) {
         jj_consume_token(VARCHAR);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                   {if (true) return SqlJdbcDataTypeName.SQL_VARCHAR;}
-    } else if (jj_2_670(2)) {
-      if (jj_2_638(2)) {
+    } else if (jj_2_691(2)) {
+      if (jj_2_659(2)) {
         jj_consume_token(SQL_DATE);
-      } else if (jj_2_639(2)) {
+      } else if (jj_2_660(2)) {
         jj_consume_token(DATE);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                             {if (true) return SqlJdbcDataTypeName.SQL_DATE;}
-    } else if (jj_2_671(2)) {
-      if (jj_2_640(2)) {
+    } else if (jj_2_692(2)) {
+      if (jj_2_661(2)) {
         jj_consume_token(SQL_TIME);
-      } else if (jj_2_641(2)) {
+      } else if (jj_2_662(2)) {
         jj_consume_token(TIME);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                             {if (true) return SqlJdbcDataTypeName.SQL_TIME;}
-    } else if (jj_2_672(2)) {
-      if (jj_2_642(2)) {
+    } else if (jj_2_693(2)) {
+      if (jj_2_663(2)) {
         jj_consume_token(SQL_TIMESTAMP);
-      } else if (jj_2_643(2)) {
+      } else if (jj_2_664(2)) {
         jj_consume_token(TIMESTAMP);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                       {if (true) return SqlJdbcDataTypeName.SQL_TIMESTAMP;}
-    } else if (jj_2_673(2)) {
-      if (jj_2_644(2)) {
+    } else if (jj_2_694(2)) {
+      if (jj_2_665(2)) {
         jj_consume_token(SQL_DECIMAL);
-      } else if (jj_2_645(2)) {
+      } else if (jj_2_666(2)) {
         jj_consume_token(DECIMAL);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                   {if (true) return SqlJdbcDataTypeName.SQL_DECIMAL;}
-    } else if (jj_2_674(2)) {
-      if (jj_2_646(2)) {
+    } else if (jj_2_695(2)) {
+      if (jj_2_667(2)) {
         jj_consume_token(SQL_NUMERIC);
-      } else if (jj_2_647(2)) {
+      } else if (jj_2_668(2)) {
         jj_consume_token(NUMERIC);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                   {if (true) return SqlJdbcDataTypeName.SQL_NUMERIC;}
-    } else if (jj_2_675(2)) {
-      if (jj_2_648(2)) {
+    } else if (jj_2_696(2)) {
+      if (jj_2_669(2)) {
         jj_consume_token(SQL_BOOLEAN);
-      } else if (jj_2_649(2)) {
+      } else if (jj_2_670(2)) {
         jj_consume_token(BOOLEAN);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                   {if (true) return SqlJdbcDataTypeName.SQL_BOOLEAN;}
-    } else if (jj_2_676(2)) {
-      if (jj_2_650(2)) {
+    } else if (jj_2_697(2)) {
+      if (jj_2_671(2)) {
         jj_consume_token(SQL_INTEGER);
-      } else if (jj_2_651(2)) {
+      } else if (jj_2_672(2)) {
         jj_consume_token(INTEGER);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                   {if (true) return SqlJdbcDataTypeName.SQL_INTEGER;}
-    } else if (jj_2_677(2)) {
-      if (jj_2_652(2)) {
+    } else if (jj_2_698(2)) {
+      if (jj_2_673(2)) {
         jj_consume_token(SQL_BINARY);
-      } else if (jj_2_653(2)) {
+      } else if (jj_2_674(2)) {
         jj_consume_token(BINARY);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                 {if (true) return SqlJdbcDataTypeName.SQL_BINARY;}
-    } else if (jj_2_678(2)) {
-      if (jj_2_654(2)) {
+    } else if (jj_2_699(2)) {
+      if (jj_2_675(2)) {
         jj_consume_token(SQL_VARBINARY);
-      } else if (jj_2_655(2)) {
+      } else if (jj_2_676(2)) {
         jj_consume_token(VARBINARY);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                       {if (true) return SqlJdbcDataTypeName.SQL_VARBINARY;}
-    } else if (jj_2_679(2)) {
-      if (jj_2_656(2)) {
+    } else if (jj_2_700(2)) {
+      if (jj_2_677(2)) {
         jj_consume_token(SQL_TINYINT);
-      } else if (jj_2_657(2)) {
+      } else if (jj_2_678(2)) {
         jj_consume_token(TINYINT);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                   {if (true) return SqlJdbcDataTypeName.SQL_TINYINT;}
-    } else if (jj_2_680(2)) {
-      if (jj_2_658(2)) {
+    } else if (jj_2_701(2)) {
+      if (jj_2_679(2)) {
         jj_consume_token(SQL_SMALLINT);
-      } else if (jj_2_659(2)) {
+      } else if (jj_2_680(2)) {
         jj_consume_token(SMALLINT);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                     {if (true) return SqlJdbcDataTypeName.SQL_SMALLINT;}
-    } else if (jj_2_681(2)) {
-      if (jj_2_660(2)) {
+    } else if (jj_2_702(2)) {
+      if (jj_2_681(2)) {
         jj_consume_token(SQL_BIGINT);
-      } else if (jj_2_661(2)) {
+      } else if (jj_2_682(2)) {
         jj_consume_token(BIGINT);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                 {if (true) return SqlJdbcDataTypeName.SQL_BIGINT;}
-    } else if (jj_2_682(2)) {
-      if (jj_2_662(2)) {
+    } else if (jj_2_703(2)) {
+      if (jj_2_683(2)) {
         jj_consume_token(SQL_REAL);
-      } else if (jj_2_663(2)) {
+      } else if (jj_2_684(2)) {
         jj_consume_token(REAL);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                            {if (true) return SqlJdbcDataTypeName.SQL_REAL;}
-    } else if (jj_2_683(2)) {
-      if (jj_2_664(2)) {
+    } else if (jj_2_704(2)) {
+      if (jj_2_685(2)) {
         jj_consume_token(SQL_DOUBLE);
-      } else if (jj_2_665(2)) {
+      } else if (jj_2_686(2)) {
         jj_consume_token(DOUBLE);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                 {if (true) return SqlJdbcDataTypeName.SQL_DOUBLE;}
-    } else if (jj_2_684(2)) {
-      if (jj_2_666(2)) {
+    } else if (jj_2_705(2)) {
+      if (jj_2_687(2)) {
         jj_consume_token(SQL_FLOAT);
-      } else if (jj_2_667(2)) {
+      } else if (jj_2_688(2)) {
         jj_consume_token(FLOAT);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                               {if (true) return SqlJdbcDataTypeName.SQL_FLOAT;}
-    } else if (jj_2_685(2)) {
+    } else if (jj_2_706(2)) {
       jj_consume_token(SQL_INTERVAL_YEAR);
                           {if (true) return SqlJdbcDataTypeName.SQL_INTERVAL_YEAR;}
-    } else if (jj_2_686(2)) {
+    } else if (jj_2_707(2)) {
       jj_consume_token(SQL_INTERVAL_YEAR_TO_MONTH);
                                    {if (true) return SqlJdbcDataTypeName.SQL_INTERVAL_YEAR_TO_MONTH;}
-    } else if (jj_2_687(2)) {
+    } else if (jj_2_708(2)) {
       jj_consume_token(SQL_INTERVAL_MONTH);
                            {if (true) return SqlJdbcDataTypeName.SQL_INTERVAL_MONTH;}
-    } else if (jj_2_688(2)) {
+    } else if (jj_2_709(2)) {
       jj_consume_token(SQL_INTERVAL_DAY);
                          {if (true) return SqlJdbcDataTypeName.SQL_INTERVAL_DAY;}
-    } else if (jj_2_689(2)) {
+    } else if (jj_2_710(2)) {
       jj_consume_token(SQL_INTERVAL_DAY_TO_HOUR);
                                  {if (true) return SqlJdbcDataTypeName.SQL_INTERVAL_DAY_TO_HOUR;}
-    } else if (jj_2_690(2)) {
+    } else if (jj_2_711(2)) {
       jj_consume_token(SQL_INTERVAL_DAY_TO_MINUTE);
                                    {if (true) return SqlJdbcDataTypeName.SQL_INTERVAL_DAY_TO_MINUTE;}
-    } else if (jj_2_691(2)) {
+    } else if (jj_2_712(2)) {
       jj_consume_token(SQL_INTERVAL_DAY_TO_SECOND);
                                    {if (true) return SqlJdbcDataTypeName.SQL_INTERVAL_DAY_TO_SECOND;}
-    } else if (jj_2_692(2)) {
+    } else if (jj_2_713(2)) {
       jj_consume_token(SQL_INTERVAL_HOUR);
                           {if (true) return SqlJdbcDataTypeName.SQL_INTERVAL_HOUR;}
-    } else if (jj_2_693(2)) {
+    } else if (jj_2_714(2)) {
       jj_consume_token(SQL_INTERVAL_HOUR_TO_MINUTE);
                                     {if (true) return SqlJdbcDataTypeName.SQL_INTERVAL_HOUR_TO_MINUTE;}
-    } else if (jj_2_694(2)) {
+    } else if (jj_2_715(2)) {
       jj_consume_token(SQL_INTERVAL_HOUR_TO_SECOND);
                                     {if (true) return SqlJdbcDataTypeName.SQL_INTERVAL_HOUR_TO_SECOND;}
-    } else if (jj_2_695(2)) {
+    } else if (jj_2_716(2)) {
       jj_consume_token(SQL_INTERVAL_MINUTE);
                             {if (true) return SqlJdbcDataTypeName.SQL_INTERVAL_MINUTE;}
-    } else if (jj_2_696(2)) {
+    } else if (jj_2_717(2)) {
       jj_consume_token(SQL_INTERVAL_MINUTE_TO_SECOND);
                                       {if (true) return SqlJdbcDataTypeName.SQL_INTERVAL_MINUTE_TO_SECOND;}
-    } else if (jj_2_697(2)) {
+    } else if (jj_2_718(2)) {
       jj_consume_token(SQL_INTERVAL_SECOND);
                             {if (true) return SqlJdbcDataTypeName.SQL_INTERVAL_SECOND;}
     } else {
@@ -6882,10 +7188,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 */
   final public SqlTypeNameSpec CollectionsTypeName(SqlTypeNameSpec elementTypeName) throws ParseException {
     final SqlTypeName collectionTypeName;
-    if (jj_2_698(2)) {
+    if (jj_2_719(2)) {
       jj_consume_token(MULTISET);
                      collectionTypeName = SqlTypeName.MULTISET;
-    } else if (jj_2_699(2)) {
+    } else if (jj_2_720(2)) {
       jj_consume_token(ARRAY);
                   collectionTypeName = SqlTypeName.ARRAY;
     } else {
@@ -6901,10 +7207,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 * Parse a nullable option, default is true.
 */
   final public boolean NullableOptDefaultTrue() throws ParseException {
-    if (jj_2_700(2)) {
+    if (jj_2_721(2)) {
       jj_consume_token(NULL);
              {if (true) return true;}
-    } else if (jj_2_701(2)) {
+    } else if (jj_2_722(2)) {
       jj_consume_token(NOT);
       jj_consume_token(NULL);
                    {if (true) return false;}
@@ -6918,10 +7224,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 * Parse a nullable option, default is false.
 */
   final public boolean NullableOptDefaultFalse() throws ParseException {
-    if (jj_2_702(2)) {
+    if (jj_2_723(2)) {
       jj_consume_token(NULL);
              {if (true) return true;}
-    } else if (jj_2_703(2)) {
+    } else if (jj_2_724(2)) {
       jj_consume_token(NOT);
       jj_consume_token(NULL);
                    {if (true) return false;}
@@ -6931,36 +7237,49 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     throw new Error("Missing return statement in function");
   }
 
+/** Parses NOT NULL and returns false, or parses nothing and returns true. */
+  final public boolean NotNullOpt() throws ParseException {
+    if (jj_2_725(2)) {
+      jj_consume_token(NOT);
+      jj_consume_token(NULL);
+                   {if (true) return false;}
+    } else {
+      {if (true) return true;}
+    }
+    throw new Error("Missing return statement in function");
+  }
+
 /**
 * Parse a "name1 type1 [NULL | NOT NULL], name2 type2 [NULL | NOT NULL] ..." list,
 * the field type default is not nullable.
 */
-  final public void FieldNameTypeCommaList(List<SqlIdentifier> fieldNames,
-        List<SqlDataTypeSpec> fieldTypes) throws ParseException {
-    SqlIdentifier fName;
-    SqlDataTypeSpec fType;
-    boolean nullable;
-    fName = SimpleIdentifier();
-    fType = DataType();
-    nullable = NullableOptDefaultFalse();
-        fieldNames.add(fName);
-        fieldTypes.add(fType.withNullable(nullable, getPos()));
-    label_51:
+  final public void AddFieldNameTypes(List<SqlIdentifier> fieldNames,
+    List<SqlDataTypeSpec> fieldTypes) throws ParseException {
+    AddFieldNameType(fieldNames, fieldTypes);
+    label_57:
     while (true) {
-      if (jj_2_704(2)) {
+      if (jj_2_726(2)) {
         ;
       } else {
-        break label_51;
+        break label_57;
       }
       jj_consume_token(COMMA);
-      fName = SimpleIdentifier();
-      fType = DataType();
-      nullable = NullableOptDefaultFalse();
-            fieldNames.add(fName);
-            fieldTypes.add(fType.withNullable(nullable, getPos()));
+      AddFieldNameType(fieldNames, fieldTypes);
     }
   }
 
+  final public void AddFieldNameType(List<SqlIdentifier> fieldNames,
+    List<SqlDataTypeSpec> fieldTypes) throws ParseException {
+    final SqlIdentifier fName;
+    final SqlDataTypeSpec fType;
+    final boolean nullable;
+    fName = SimpleIdentifier();
+    fType = DataType();
+    nullable = NullableOptDefaultFalse();
+        fieldNames.add(fName);
+        fieldTypes.add(fType.withNullable(nullable, getPos()));
+  }
+
 /**
 * Parse Row type with format: Row(name1 type1, name2 type2).
 * Every field type can have suffix of `NULL` or `NOT NULL` to indicate if this type is nullable.
@@ -6971,7 +7290,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     List<SqlDataTypeSpec> fieldTypes = new ArrayList<SqlDataTypeSpec>();
     jj_consume_token(ROW);
     jj_consume_token(LPAREN);
-    FieldNameTypeCommaList(fieldNames, fieldTypes);
+    AddFieldNameTypes(fieldNames, fieldTypes);
     jj_consume_token(RPAREN);
         {if (true) return new SqlRowTypeNameSpec(getPos(), fieldNames, fieldTypes);}
     throw new Error("Missing return statement in function");
@@ -6984,23 +7303,23 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     int precision = -1;
     final SqlTypeName sqlTypeName;
     String charSetName = null;
-    if (jj_2_708(2)) {
-      if (jj_2_705(2)) {
+    if (jj_2_730(2)) {
+      if (jj_2_727(2)) {
         jj_consume_token(CHARACTER);
-      } else if (jj_2_706(2)) {
+      } else if (jj_2_728(2)) {
         jj_consume_token(CHAR);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
                                  s.add(this);
-      if (jj_2_707(2)) {
+      if (jj_2_729(2)) {
         jj_consume_token(VARYING);
                         sqlTypeName = SqlTypeName.VARCHAR;
       } else {
               sqlTypeName = SqlTypeName.CHAR;
       }
-    } else if (jj_2_709(2)) {
+    } else if (jj_2_731(2)) {
       jj_consume_token(VARCHAR);
                     s.add(this); sqlTypeName = SqlTypeName.VARCHAR;
     } else {
@@ -7008,7 +7327,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
       throw new ParseException();
     }
     precision = PrecisionOpt();
-    if (jj_2_710(2)) {
+    if (jj_2_732(2)) {
       jj_consume_token(CHARACTER);
       jj_consume_token(SET);
       charSetName = Identifier();
@@ -7027,11 +7346,11 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     SqlTypeName typeName;
     boolean withLocalTimeZone = false;
     final Span s;
-    if (jj_2_711(2)) {
+    if (jj_2_733(2)) {
       jj_consume_token(DATE);
         typeName = SqlTypeName.DATE;
         {if (true) return new SqlBasicTypeNameSpec(typeName, getPos());}
-    } else if (jj_2_712(2)) {
+    } else if (jj_2_734(2)) {
       jj_consume_token(TIME);
              s = span();
       precision = PrecisionOpt();
@@ -7042,7 +7361,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             typeName = SqlTypeName.TIME;
         }
         {if (true) return new SqlBasicTypeNameSpec(typeName, precision, s.end(this));}
-    } else if (jj_2_713(2)) {
+    } else if (jj_2_735(2)) {
       jj_consume_token(TIMESTAMP);
                   s = span();
       precision = PrecisionOpt();
@@ -7063,7 +7382,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 // Parse an optional data type precision, default is -1.
   final public int PrecisionOpt() throws ParseException {
     int precision = -1;
-    if (jj_2_714(2)) {
+    if (jj_2_736(2)) {
       jj_consume_token(LPAREN);
       precision = UnsignedIntLiteral();
       jj_consume_token(RPAREN);
@@ -7084,12 +7403,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 * @return true if this is "with local time zone".
 */
   final public boolean TimeZoneOpt() throws ParseException {
-    if (jj_2_715(3)) {
+    if (jj_2_737(3)) {
       jj_consume_token(WITHOUT);
       jj_consume_token(TIME);
       jj_consume_token(ZONE);
                               {if (true) return false;}
-    } else if (jj_2_716(2)) {
+    } else if (jj_2_738(2)) {
       jj_consume_token(WITH);
       jj_consume_token(LOCAL);
       jj_consume_token(TIME);
@@ -7126,24 +7445,22 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlNode BuiltinFunctionCall() throws ParseException {
     final SqlIdentifier name;
-    List<SqlNode> args = null;
-    SqlNode e = null;
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    SqlNode e;
     final Span s;
     SqlDataTypeSpec dt;
-    TimeUnit interval;
     final TimeUnit unit;
     final SqlNode node;
-    if (jj_2_742(2)) {
+    if (jj_2_761(2)) {
       jj_consume_token(CAST);
                  s = span();
       jj_consume_token(LPAREN);
-      e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-                                                                args = startList(e);
+      AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
       jj_consume_token(AS);
-      if (jj_2_717(2)) {
+      if (jj_2_739(2)) {
         dt = DataType();
                               args.add(dt);
-      } else if (jj_2_718(2)) {
+      } else if (jj_2_740(2)) {
         jj_consume_token(INTERVAL);
         e = IntervalQualifier();
                                                  args.add(e);
@@ -7153,29 +7470,17 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
       }
       jj_consume_token(RPAREN);
             {if (true) return SqlStdOperatorTable.CAST.createCall(s.end(this), args);}
-    } else if (jj_2_743(2)) {
+    } else if (jj_2_762(2)) {
       jj_consume_token(EXTRACT);
-            s = span();
+                    s = span();
       jj_consume_token(LPAREN);
-      if (jj_2_719(2)) {
-        jj_consume_token(NANOSECOND);
-                           unit = TimeUnit.NANOSECOND;
-      } else if (jj_2_720(2)) {
-        jj_consume_token(MICROSECOND);
-                            unit = TimeUnit.MICROSECOND;
-      } else if (jj_2_721(2)) {
-        unit = TimeUnit();
-      } else {
-        jj_consume_token(-1);
-        throw new ParseException();
-      }
-          args = startList(new SqlIntervalQualifier(unit, null, getPos()));
+      unit = TimeUnitForExtract();
+            args.add(new SqlIntervalQualifier(unit, null, getPos()));
       jj_consume_token(FROM);
-      e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-                                                       args.add(e);
+      AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
       jj_consume_token(RPAREN);
             {if (true) return SqlStdOperatorTable.EXTRACT.createCall(s.end(this), args);}
-    } else if (jj_2_744(2)) {
+    } else if (jj_2_763(2)) {
       jj_consume_token(POSITION);
                      s = span();
       jj_consume_token(LPAREN);
@@ -7183,54 +7488,49 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
               // Expression(ExprContext.ACCEPT_SUB_QUERY), but that doesn't work
               // because it matches the other kind of IN.
               e = AtomicRowExpression();
-                                    args = startList(e);
+                                    args.add(e);
       jj_consume_token(IN);
-      e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-                                                       args.add(e);
-      if (jj_2_722(2)) {
+      AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
+      if (jj_2_741(2)) {
         jj_consume_token(FROM);
-        e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-                                                           args.add(e);
+        AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
       } else {
         ;
       }
       jj_consume_token(RPAREN);
             {if (true) return SqlStdOperatorTable.POSITION.createCall(s.end(this), args);}
-    } else if (jj_2_745(2)) {
+    } else if (jj_2_764(2)) {
       jj_consume_token(CONVERT);
                     s = span();
       jj_consume_token(LPAREN);
-      e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-            args = startList(e);
+      AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
       jj_consume_token(USING);
       name = SimpleIdentifier();
-            args.add(name);
+                                            args.add(name);
       jj_consume_token(RPAREN);
             {if (true) return SqlStdOperatorTable.CONVERT.createCall(s.end(this), args);}
-    } else if (jj_2_746(2)) {
+    } else if (jj_2_765(2)) {
       jj_consume_token(TRANSLATE);
                       s = span();
       jj_consume_token(LPAREN);
-      e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-            args = startList(e);
-      if (jj_2_724(2)) {
+      AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
+      if (jj_2_743(2)) {
         jj_consume_token(USING);
         name = SimpleIdentifier();
-                args.add(name);
+                                                args.add(name);
         jj_consume_token(RPAREN);
                 {if (true) return SqlStdOperatorTable.TRANSLATE.createCall(s.end(this),
                     args);}
-      } else if (jj_2_725(2)) {
-        label_52:
+      } else if (jj_2_744(2)) {
+        label_58:
         while (true) {
-          if (jj_2_723(2)) {
+          if (jj_2_742(2)) {
             ;
           } else {
-            break label_52;
+            break label_58;
           }
           jj_consume_token(COMMA);
-          e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-                    args.add(e);
+          AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
         }
         jj_consume_token(RPAREN);
                 {if (true) return SqlLibraryOperators.TRANSLATE3.createCall(s.end(this),
@@ -7239,36 +7539,32 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         jj_consume_token(-1);
         throw new ParseException();
       }
-    } else if (jj_2_747(2)) {
+    } else if (jj_2_766(2)) {
       jj_consume_token(OVERLAY);
                     s = span();
       jj_consume_token(LPAREN);
-      e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-            args = startList(e);
+      AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
       jj_consume_token(PLACING);
-      e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-            args.add(e);
+      AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
       jj_consume_token(FROM);
-      e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-            args.add(e);
-      if (jj_2_726(2)) {
+      AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
+      if (jj_2_745(2)) {
         jj_consume_token(FOR);
-        e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-                args.add(e);
+        AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
       } else {
         ;
       }
       jj_consume_token(RPAREN);
             {if (true) return SqlStdOperatorTable.OVERLAY.createCall(s.end(this), args);}
-    } else if (jj_2_748(2)) {
+    } else if (jj_2_767(2)) {
       jj_consume_token(FLOOR);
                   s = span();
       e = FloorCeilOptions(s, true);
             {if (true) return e;}
-    } else if (jj_2_749(2)) {
-      if (jj_2_727(2)) {
+    } else if (jj_2_768(2)) {
+      if (jj_2_746(2)) {
         jj_consume_token(CEIL);
-      } else if (jj_2_728(2)) {
+      } else if (jj_2_747(2)) {
         jj_consume_token(CEILING);
       } else {
         jj_consume_token(-1);
@@ -7277,56 +7573,53 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                                 s = span();
       e = FloorCeilOptions(s, false);
             {if (true) return e;}
-    } else if (jj_2_750(2)) {
+    } else if (jj_2_769(2)) {
       jj_consume_token(SUBSTRING);
                       s = span();
       jj_consume_token(LPAREN);
-      e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-          args = startList(e);
-      if (jj_2_729(2)) {
+      AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
+      if (jj_2_748(2)) {
         jj_consume_token(FROM);
-      } else if (jj_2_730(2)) {
+      } else if (jj_2_749(2)) {
         jj_consume_token(COMMA);
       } else {
         jj_consume_token(-1);
         throw new ParseException();
       }
-      e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-          args.add(e);
-      if (jj_2_733(2)) {
-        if (jj_2_731(2)) {
+      AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
+      if (jj_2_752(2)) {
+        if (jj_2_750(2)) {
           jj_consume_token(FOR);
-        } else if (jj_2_732(2)) {
+        } else if (jj_2_751(2)) {
           jj_consume_token(COMMA);
         } else {
           jj_consume_token(-1);
           throw new ParseException();
         }
-        e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-              args.add(e);
+        AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
       } else {
         ;
       }
       jj_consume_token(RPAREN);
             {if (true) return SqlStdOperatorTable.SUBSTRING.createCall(
                 s.end(this), args);}
-    } else if (jj_2_751(2)) {
+    } else if (jj_2_770(2)) {
       jj_consume_token(TRIM);
             SqlLiteral flag = null;
             SqlNode trimChars = null;
             s = span();
       jj_consume_token(LPAREN);
-      if (jj_2_741(2)) {
-        if (jj_2_737(2)) {
-          if (jj_2_734(2)) {
+      if (jj_2_760(2)) {
+        if (jj_2_756(2)) {
+          if (jj_2_753(2)) {
             jj_consume_token(BOTH);
                     s.add(this);
                     flag = SqlTrimFunction.Flag.BOTH.symbol(getPos());
-          } else if (jj_2_735(2)) {
+          } else if (jj_2_754(2)) {
             jj_consume_token(TRAILING);
                     s.add(this);
                     flag = SqlTrimFunction.Flag.TRAILING.symbol(getPos());
-          } else if (jj_2_736(2)) {
+          } else if (jj_2_755(2)) {
             jj_consume_token(LEADING);
                     s.add(this);
                     flag = SqlTrimFunction.Flag.LEADING.symbol(getPos());
@@ -7337,25 +7630,25 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         } else {
           ;
         }
-        if (jj_2_738(2)) {
+        if (jj_2_757(2)) {
           trimChars = Expression(ExprContext.ACCEPT_SUB_QUERY);
         } else {
           ;
         }
-        if (jj_2_739(2)) {
+        if (jj_2_758(2)) {
           jj_consume_token(FROM);
                     if (null == flag && null == trimChars) {
                         {if (true) throw SqlUtil.newContextException(getPos(),
                             RESOURCE.illegalFromEmpty());}
                     }
-        } else if (jj_2_740(2)) {
+        } else if (jj_2_759(2)) {
           jj_consume_token(RPAREN);
                     // This is to handle the case of TRIM(x)
                     // (FRG-191).
                     if (flag == null) {
                         flag = SqlTrimFunction.Flag.BOTH.symbol(SqlParserPos.ZERO);
                     }
-                    args = startList(flag);
+                    args.add(flag);
                     args.add(null); // no trim chars
                     args.add(trimChars); // reinterpret trimChars as source
                     {if (true) return SqlStdOperatorTable.TRIM.createCall(s.end(this),
@@ -7371,42 +7664,42 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             if (flag == null) {
                 flag = SqlTrimFunction.Flag.BOTH.symbol(SqlParserPos.ZERO);
             }
-            args = startList(flag);
+            args.add(flag);
             args.add(trimChars);
             args.add(e);
       jj_consume_token(RPAREN);
             {if (true) return SqlStdOperatorTable.TRIM.createCall(s.end(this), args);}
-    } else if (jj_2_752(2)) {
+    } else if (jj_2_771(2)) {
       node = TimestampAddFunctionCall();
                                             {if (true) return node;}
-    } else if (jj_2_753(2)) {
+    } else if (jj_2_772(2)) {
       node = TimestampDiffFunctionCall();
                                              {if (true) return node;}
-    } else if (jj_2_754(2)) {
+    } else if (jj_2_773(2)) {
       node = MatchRecognizeFunctionCall();
                                               {if (true) return node;}
-    } else if (jj_2_755(2)) {
+    } else if (jj_2_774(2)) {
       node = JsonExistsFunctionCall();
                                           {if (true) return node;}
-    } else if (jj_2_756(2)) {
+    } else if (jj_2_775(2)) {
       node = JsonValueFunctionCall();
                                          {if (true) return node;}
-    } else if (jj_2_757(2)) {
+    } else if (jj_2_776(2)) {
       node = JsonQueryFunctionCall();
                                          {if (true) return node;}
-    } else if (jj_2_758(2)) {
+    } else if (jj_2_777(2)) {
       node = JsonObjectFunctionCall();
                                           {if (true) return node;}
-    } else if (jj_2_759(2)) {
+    } else if (jj_2_778(2)) {
       node = JsonObjectAggFunctionCall();
                                              {if (true) return node;}
-    } else if (jj_2_760(2)) {
+    } else if (jj_2_779(2)) {
       node = JsonArrayFunctionCall();
                                          {if (true) return node;}
-    } else if (jj_2_761(2)) {
+    } else if (jj_2_780(2)) {
       node = JsonArrayAggFunctionCall();
                                             {if (true) return node;}
-    } else if (jj_2_762(2)) {
+    } else if (jj_2_781(2)) {
       node = GroupByWindowingCall();
                                         {if (true) return node;}
     } else {
@@ -7418,15 +7711,15 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
   final public SqlJsonEncoding JsonRepresentation() throws ParseException {
     jj_consume_token(JSON);
-    if (jj_2_766(2)) {
+    if (jj_2_785(2)) {
       jj_consume_token(ENCODING);
-      if (jj_2_763(2)) {
+      if (jj_2_782(2)) {
         jj_consume_token(UTF8);
                      {if (true) return SqlJsonEncoding.UTF8;}
-      } else if (jj_2_764(2)) {
+      } else if (jj_2_783(2)) {
         jj_consume_token(UTF16);
                       {if (true) return SqlJsonEncoding.UTF16;}
-      } else if (jj_2_765(2)) {
+      } else if (jj_2_784(2)) {
         jj_consume_token(UTF32);
                       {if (true) return SqlJsonEncoding.UTF32;}
       } else {
@@ -7456,7 +7749,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlDataTypeSpec JsonOutputClause() throws ParseException {
     SqlDataTypeSpec dataType;
     dataType = JsonReturningClause();
-    if (jj_2_767(2)) {
+    if (jj_2_786(2)) {
       jj_consume_token(FORMAT);
       JsonRepresentation();
     } else {
@@ -7475,25 +7768,23 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
   final public List<SqlNode> JsonApiCommonSyntax() throws ParseException {
     SqlNode e;
-    List<SqlNode> args = new ArrayList<SqlNode>();
-    e = Expression(ExprContext.ACCEPT_NON_QUERY);
-        args.add(e);
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    AddExpression(args, ExprContext.ACCEPT_NON_QUERY);
     jj_consume_token(COMMA);
-    e = Expression(ExprContext.ACCEPT_NON_QUERY);
-            args.add(e);
-    if (jj_2_769(2)) {
+    AddExpression(args, ExprContext.ACCEPT_NON_QUERY);
+    if (jj_2_788(2)) {
       jj_consume_token(PASSING);
       e = Expression(ExprContext.ACCEPT_NON_QUERY);
 
       jj_consume_token(AS);
       e = SimpleIdentifier();
 
-      label_53:
+      label_59:
       while (true) {
-        if (jj_2_768(2)) {
+        if (jj_2_787(2)) {
           ;
         } else {
-          break label_53;
+          break label_59;
         }
         jj_consume_token(COMMA);
         e = Expression(ExprContext.ACCEPT_NON_QUERY);
@@ -7510,16 +7801,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public SqlJsonExistsErrorBehavior JsonExistsErrorBehavior() throws ParseException {
-    if (jj_2_770(2)) {
+    if (jj_2_789(2)) {
       jj_consume_token(TRUE);
              {if (true) return SqlJsonExistsErrorBehavior.TRUE;}
-    } else if (jj_2_771(2)) {
+    } else if (jj_2_790(2)) {
       jj_consume_token(FALSE);
               {if (true) return SqlJsonExistsErrorBehavior.FALSE;}
-    } else if (jj_2_772(2)) {
+    } else if (jj_2_791(2)) {
       jj_consume_token(UNKNOWN);
                 {if (true) return SqlJsonExistsErrorBehavior.UNKNOWN;}
-    } else if (jj_2_773(2)) {
+    } else if (jj_2_792(2)) {
       jj_consume_token(ERROR);
               {if (true) return SqlJsonExistsErrorBehavior.ERROR;}
     } else {
@@ -7539,7 +7830,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     jj_consume_token(LPAREN);
     commonSyntax = JsonApiCommonSyntax();
         args.addAll(commonSyntax);
-    if (jj_2_774(2)) {
+    if (jj_2_793(2)) {
       errorBehavior = JsonExistsErrorBehavior();
                                                     args.add(errorBehavior.symbol(getPos()));
       jj_consume_token(ON);
@@ -7554,27 +7845,25 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
   final public List<SqlNode> JsonValueEmptyOrErrorBehavior() throws ParseException {
     final List<SqlNode> list = new ArrayList<SqlNode>();
-    final SqlNode e;
-    if (jj_2_775(2)) {
+    if (jj_2_794(2)) {
       jj_consume_token(ERROR);
             list.add(SqlJsonValueEmptyOrErrorBehavior.ERROR.symbol(getPos()));
-    } else if (jj_2_776(2)) {
+    } else if (jj_2_795(2)) {
       jj_consume_token(NULL);
             list.add(SqlJsonValueEmptyOrErrorBehavior.NULL.symbol(getPos()));
-    } else if (jj_2_777(2)) {
+    } else if (jj_2_796(2)) {
       jj_consume_token(DEFAULT_);
-      e = Expression(ExprContext.ACCEPT_NON_QUERY);
             list.add(SqlJsonValueEmptyOrErrorBehavior.DEFAULT.symbol(getPos()));
-            list.add(e);
+      AddExpression(list, ExprContext.ACCEPT_NON_QUERY);
     } else {
       jj_consume_token(-1);
       throw new ParseException();
     }
     jj_consume_token(ON);
-    if (jj_2_778(2)) {
+    if (jj_2_797(2)) {
       jj_consume_token(EMPTY);
             list.add(SqlJsonEmptyOrError.EMPTY.symbol(getPos()));
-    } else if (jj_2_779(2)) {
+    } else if (jj_2_798(2)) {
       jj_consume_token(ERROR);
             list.add(SqlJsonEmptyOrError.ERROR.symbol(getPos()));
     } else {
@@ -7596,19 +7885,19 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     jj_consume_token(LPAREN);
     commonSyntax = JsonApiCommonSyntax();
         args.addAll(commonSyntax);
-    if (jj_2_780(2)) {
+    if (jj_2_799(2)) {
       e = JsonReturningClause();
             args.add(SqlJsonValueReturning.RETURNING.symbol(getPos()));
             args.add(e);
     } else {
       ;
     }
-    label_54:
+    label_60:
     while (true) {
-      if (jj_2_781(2)) {
+      if (jj_2_800(2)) {
         ;
       } else {
-        break label_54;
+        break label_60;
       }
       behavior = JsonValueEmptyOrErrorBehavior();
             args.addAll(behavior);
@@ -7620,18 +7909,17 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
   final public List<SqlNode> JsonQueryEmptyOrErrorBehavior() throws ParseException {
     final List<SqlNode> list = new ArrayList<SqlNode>();
-    SqlNode e;
-    if (jj_2_782(2)) {
+    if (jj_2_801(2)) {
       jj_consume_token(ERROR);
             list.add(SqlLiteral.createSymbol(SqlJsonQueryEmptyOrErrorBehavior.ERROR, getPos()));
-    } else if (jj_2_783(2)) {
+    } else if (jj_2_802(2)) {
       jj_consume_token(NULL);
             list.add(SqlLiteral.createSymbol(SqlJsonQueryEmptyOrErrorBehavior.NULL, getPos()));
-    } else if (jj_2_784(2)) {
+    } else if (jj_2_803(2)) {
       jj_consume_token(EMPTY);
       jj_consume_token(ARRAY);
             list.add(SqlLiteral.createSymbol(SqlJsonQueryEmptyOrErrorBehavior.EMPTY_ARRAY, getPos()));
-    } else if (jj_2_785(2)) {
+    } else if (jj_2_804(2)) {
       jj_consume_token(EMPTY);
       jj_consume_token(OBJECT);
             list.add(SqlLiteral.createSymbol(SqlJsonQueryEmptyOrErrorBehavior.EMPTY_OBJECT, getPos()));
@@ -7640,10 +7928,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
       throw new ParseException();
     }
     jj_consume_token(ON);
-    if (jj_2_786(2)) {
+    if (jj_2_805(2)) {
       jj_consume_token(EMPTY);
             list.add(SqlLiteral.createSymbol(SqlJsonEmptyOrError.EMPTY, getPos()));
-    } else if (jj_2_787(2)) {
+    } else if (jj_2_806(2)) {
       jj_consume_token(ERROR);
             list.add(SqlLiteral.createSymbol(SqlJsonEmptyOrError.ERROR, getPos()));
     } else {
@@ -7655,32 +7943,31 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public SqlNode JsonQueryWrapperBehavior() throws ParseException {
-    SqlNode e;
-    if (jj_2_792(2)) {
+    if (jj_2_811(2)) {
       jj_consume_token(WITHOUT);
-      if (jj_2_788(2)) {
+      if (jj_2_807(2)) {
         jj_consume_token(ARRAY);
       } else {
         ;
       }
         {if (true) return SqlLiteral.createSymbol(SqlJsonQueryWrapperBehavior.WITHOUT_ARRAY, getPos());}
-    } else if (jj_2_793(2)) {
+    } else if (jj_2_812(2)) {
       jj_consume_token(WITH);
       jj_consume_token(CONDITIONAL);
-      if (jj_2_789(2)) {
+      if (jj_2_808(2)) {
         jj_consume_token(ARRAY);
       } else {
         ;
       }
         {if (true) return SqlLiteral.createSymbol(SqlJsonQueryWrapperBehavior.WITH_CONDITIONAL_ARRAY, getPos());}
-    } else if (jj_2_794(2)) {
+    } else if (jj_2_813(2)) {
       jj_consume_token(WITH);
-      if (jj_2_790(2)) {
+      if (jj_2_809(2)) {
         jj_consume_token(UNCONDITIONAL);
       } else {
         ;
       }
-      if (jj_2_791(2)) {
+      if (jj_2_810(2)) {
         jj_consume_token(ARRAY);
       } else {
         ;
@@ -7705,19 +7992,19 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     commonSyntax = JsonApiCommonSyntax();
         args[0] = commonSyntax.get(0);
         args[1] = commonSyntax.get(1);
-    if (jj_2_795(2)) {
+    if (jj_2_814(2)) {
       e = JsonQueryWrapperBehavior();
       jj_consume_token(WRAPPER);
             args[2] = e;
     } else {
       ;
     }
-    label_55:
+    label_61:
     while (true) {
-      if (jj_2_796(2)) {
+      if (jj_2_815(2)) {
         ;
       } else {
-        break label_55;
+        break label_61;
       }
       behavior = JsonQueryEmptyOrErrorBehavior();
             final SqlJsonEmptyOrError symbol =
@@ -7745,9 +8032,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
   final public List<SqlNode> JsonNameAndValue() throws ParseException {
     final List<SqlNode> list = new ArrayList<SqlNode>();
-    SqlNode e;
+    final SqlNode e;
     boolean kvMode = false;
-    if (jj_2_797(2)) {
+    if (jj_2_816(2)) {
       jj_consume_token(KEY);
                 kvMode = true;
     } else {
@@ -7755,9 +8042,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     }
     e = JsonName();
         list.add(e);
-    if (jj_2_798(2)) {
+    if (jj_2_817(2)) {
       jj_consume_token(VALUE);
-    } else if (jj_2_799(2)) {
+    } else if (jj_2_818(2)) {
       jj_consume_token(COLON);
             if (kvMode) {
                 {if (true) throw SqlUtil.newContextException(getPos(), RESOURCE.illegalColon());}
@@ -7766,19 +8053,18 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
       jj_consume_token(-1);
       throw new ParseException();
     }
-    e = Expression(ExprContext.ACCEPT_NON_QUERY);
-        list.add(e);
+    AddExpression(list, ExprContext.ACCEPT_NON_QUERY);
         {if (true) return list;}
     throw new Error("Missing return statement in function");
   }
 
   final public SqlNode JsonConstructorNullClause() throws ParseException {
-    if (jj_2_800(2)) {
+    if (jj_2_819(2)) {
       jj_consume_token(NULL);
       jj_consume_token(ON);
       jj_consume_token(NULL);
         {if (true) return SqlLiteral.createSymbol(SqlJsonConstructorNullClause.NULL_ON_NULL, getPos());}
-    } else if (jj_2_801(2)) {
+    } else if (jj_2_820(2)) {
       jj_consume_token(ABSENT);
       jj_consume_token(ON);
       jj_consume_token(NULL);
@@ -7799,15 +8085,15 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     jj_consume_token(JSON_OBJECT);
                     span = span();
     jj_consume_token(LPAREN);
-    if (jj_2_803(2)) {
+    if (jj_2_822(2)) {
       list = JsonNameAndValue();
             nvArgs.addAll(list);
-      label_56:
+      label_62:
       while (true) {
-        if (jj_2_802(2)) {
+        if (jj_2_821(2)) {
           ;
         } else {
-          break label_56;
+          break label_62;
         }
         jj_consume_token(COMMA);
         list = JsonNameAndValue();
@@ -7816,7 +8102,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     } else {
       ;
     }
-    if (jj_2_804(2)) {
+    if (jj_2_823(2)) {
       e = JsonConstructorNullClause();
             otherArgs[0] = e;
     } else {
@@ -7843,7 +8129,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     list = JsonNameAndValue();
         args[0] = list.get(0);
         args[1] = list.get(1);
-    if (jj_2_805(2)) {
+    if (jj_2_824(2)) {
       e = JsonConstructorNullClause();
             nullClause = (SqlJsonConstructorNullClause) ((SqlLiteral) e).getValue();
     } else {
@@ -7863,24 +8149,22 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     jj_consume_token(JSON_ARRAY);
                    span = span();
     jj_consume_token(LPAREN);
-    if (jj_2_807(2)) {
-      e = Expression(ExprContext.ACCEPT_NON_QUERY);
-            elements.add(e);
-      label_57:
+    if (jj_2_826(2)) {
+      AddExpression(elements, ExprContext.ACCEPT_NON_QUERY);
+      label_63:
       while (true) {
-        if (jj_2_806(2)) {
+        if (jj_2_825(2)) {
           ;
         } else {
-          break label_57;
+          break label_63;
         }
         jj_consume_token(COMMA);
-        e = Expression(ExprContext.ACCEPT_NON_QUERY);
-                elements.add(e);
+        AddExpression(elements, ExprContext.ACCEPT_NON_QUERY);
       }
     } else {
       ;
     }
-    if (jj_2_808(2)) {
+    if (jj_2_827(2)) {
       e = JsonConstructorNullClause();
             otherArgs[0] = e;
     } else {
@@ -7896,40 +8180,38 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
   final public SqlNodeList JsonArrayAggOrderByClause() throws ParseException {
     final SqlNodeList orderList;
-    if (jj_2_809(2)) {
-      orderList = OrderBy(true);
-    } else {
-          orderList = null;
-    }
-        {if (true) return orderList;}
+    orderList = OrderBy(true);
+      {if (true) return orderList;}
     throw new Error("Missing return statement in function");
   }
 
   final public SqlCall JsonArrayAggFunctionCall() throws ParseException {
     final SqlNode valueExpr;
     final SqlNodeList orderList;
-    List<SqlNode> list;
     final Span span;
-    SqlJsonConstructorNullClause nullClause =
-        SqlJsonConstructorNullClause.ABSENT_ON_NULL;
-    SqlNode e = null;
+    final SqlJsonConstructorNullClause nullClause;
+    SqlNode e;
     final SqlNode aggCall;
     jj_consume_token(JSON_ARRAYAGG);
                       span = span();
     jj_consume_token(LPAREN);
     e = Expression(ExprContext.ACCEPT_NON_QUERY);
         valueExpr = e;
-    orderList = JsonArrayAggOrderByClause();
-    if (jj_2_810(2)) {
+    if (jj_2_828(2)) {
+      orderList = JsonArrayAggOrderByClause();
+    } else {
+                                                  orderList = null;
+    }
+    if (jj_2_829(2)) {
       e = JsonConstructorNullClause();
             nullClause = (SqlJsonConstructorNullClause) ((SqlLiteral) e).getValue();
     } else {
-      ;
+          nullClause = SqlJsonConstructorNullClause.ABSENT_ON_NULL;
     }
     jj_consume_token(RPAREN);
         aggCall = SqlStdOperatorTable.JSON_ARRAYAGG.with(nullClause)
             .createCall(span.end(this), valueExpr, orderList);
-    if (jj_2_811(2)) {
+    if (jj_2_830(2)) {
       e = withinGroup(aggCall);
             if (orderList != null) {
                 {if (true) throw SqlUtil.newContextException(span.pos().plus(e.getParserPosition()),
@@ -7952,22 +8234,18 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses a call to TIMESTAMPADD.
  */
   final public SqlCall TimestampAddFunctionCall() throws ParseException {
-    List<SqlNode> args;
-    SqlNode e;
+    final List<SqlNode> args = new ArrayList<SqlNode>();
     final Span s;
-    TimeUnit interval;
-    SqlNode node;
+    final TimeUnit interval;
     jj_consume_token(TIMESTAMPADD);
                      s = span();
     jj_consume_token(LPAREN);
     interval = TimestampInterval();
-        args = startList(SqlLiteral.createSymbol(interval, getPos()));
+        args.add(SqlLiteral.createSymbol(interval, getPos()));
     jj_consume_token(COMMA);
-    e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-                                                   args.add(e);
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
     jj_consume_token(COMMA);
-    e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-                                                   args.add(e);
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
     jj_consume_token(RPAREN);
         {if (true) return SqlStdOperatorTable.TIMESTAMP_ADD.createCall(
             s.end(this), args);}
@@ -7978,22 +8256,18 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses a call to TIMESTAMPDIFF.
  */
   final public SqlCall TimestampDiffFunctionCall() throws ParseException {
-    List<SqlNode> args;
-    SqlNode e;
+    final List<SqlNode> args = new ArrayList<SqlNode>();
     final Span s;
-    TimeUnit interval;
-    SqlNode node;
+    final TimeUnit interval;
     jj_consume_token(TIMESTAMPDIFF);
                       s = span();
     jj_consume_token(LPAREN);
     interval = TimestampInterval();
-        args = startList(SqlLiteral.createSymbol(interval, getPos()));
+        args.add(SqlLiteral.createSymbol(interval, getPos()));
     jj_consume_token(COMMA);
-    e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-                                                   args.add(e);
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
     jj_consume_token(COMMA);
-    e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-                                                   args.add(e);
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
     jj_consume_token(RPAREN);
         {if (true) return SqlStdOperatorTable.TIMESTAMP_DIFF.createCall(
             s.end(this), args);}
@@ -8008,20 +8282,20 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final Span s;
     final List<SqlNode> args;
     final SqlOperator op;
-    if (jj_2_812(2)) {
+    if (jj_2_831(2)) {
       jj_consume_token(TUMBLE);
-            op = SqlStdOperatorTable.TUMBLE_OLD;
-    } else if (jj_2_813(2)) {
+                   op = SqlStdOperatorTable.TUMBLE_OLD;
+    } else if (jj_2_832(2)) {
       jj_consume_token(HOP);
-            op = SqlStdOperatorTable.HOP_OLD;
-    } else if (jj_2_814(2)) {
+                op = SqlStdOperatorTable.HOP_OLD;
+    } else if (jj_2_833(2)) {
       jj_consume_token(SESSION);
-            op = SqlStdOperatorTable.SESSION_OLD;
+                    op = SqlStdOperatorTable.SESSION_OLD;
     } else {
       jj_consume_token(-1);
       throw new ParseException();
     }
-        s = span();
+      s = span();
     args = UnquantifiedFunctionParameterList(ExprContext.ACCEPT_SUB_QUERY);
         {if (true) return op.createCall(s.end(this), args);}
     throw new Error("Missing return statement in function");
@@ -8030,23 +8304,23 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   final public SqlCall MatchRecognizeFunctionCall() throws ParseException {
     final SqlCall func;
     final Span s;
-    if (jj_2_815(2)) {
+    if (jj_2_834(2)) {
       jj_consume_token(CLASSIFIER);
                        s = span();
       jj_consume_token(LPAREN);
       jj_consume_token(RPAREN);
             func = SqlStdOperatorTable.CLASSIFIER.createCall(s.end(this));
-    } else if (jj_2_816(2)) {
+    } else if (jj_2_835(2)) {
       jj_consume_token(MATCH_NUMBER);
                          s = span();
       jj_consume_token(LPAREN);
       jj_consume_token(RPAREN);
             func = SqlStdOperatorTable.MATCH_NUMBER.createCall(s.end(this));
-    } else if (jj_2_817(3)) {
+    } else if (jj_2_836(3)) {
       func = MatchRecognizeNavigationLogical();
-    } else if (jj_2_818(2)) {
+    } else if (jj_2_837(2)) {
       func = MatchRecognizeNavigationPhysical();
-    } else if (jj_2_819(2)) {
+    } else if (jj_2_838(2)) {
       func = MatchRecognizeCallWithModifier();
     } else {
       jj_consume_token(-1);
@@ -8060,10 +8334,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final Span s;
     final SqlOperator runningOp;
     final SqlNode func;
-    if (jj_2_820(2)) {
+    if (jj_2_839(2)) {
       jj_consume_token(RUNNING);
                     runningOp = SqlStdOperatorTable.RUNNING;
-    } else if (jj_2_821(2)) {
+    } else if (jj_2_840(2)) {
       jj_consume_token(FINAL);
                   runningOp = SqlStdOperatorTable.FINAL;
     } else {
@@ -8081,21 +8355,21 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     SqlCall func;
     final SqlOperator funcOp;
     final SqlOperator runningOp;
-    SqlNode arg0;
-    SqlNode arg1 = SqlLiteral.createExactNumeric("0", SqlParserPos.ZERO);
-    if (jj_2_822(2)) {
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    SqlNode e;
+    if (jj_2_841(2)) {
       jj_consume_token(RUNNING);
                     runningOp = SqlStdOperatorTable.RUNNING; s.add(this);
-    } else if (jj_2_823(2)) {
+    } else if (jj_2_842(2)) {
       jj_consume_token(FINAL);
                   runningOp = SqlStdOperatorTable.FINAL; s.add(this);
     } else {
           runningOp = null;
     }
-    if (jj_2_824(2)) {
+    if (jj_2_843(2)) {
       jj_consume_token(FIRST);
                   funcOp = SqlStdOperatorTable.FIRST;
-    } else if (jj_2_825(2)) {
+    } else if (jj_2_844(2)) {
       jj_consume_token(LAST);
                  funcOp = SqlStdOperatorTable.LAST;
     } else {
@@ -8104,15 +8378,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     }
       s.add(this);
     jj_consume_token(LPAREN);
-    arg0 = Expression(ExprContext.ACCEPT_SUB_QUERY);
-    if (jj_2_826(2)) {
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
+    if (jj_2_845(2)) {
       jj_consume_token(COMMA);
-      arg1 = NumericLiteral();
+      e = NumericLiteral();
+                                       args.add(e);
     } else {
-      ;
+          args.add(LITERAL_ZERO);
     }
     jj_consume_token(RPAREN);
-        func = funcOp.createCall(s.end(this), arg0, arg1);
+        func = funcOp.createCall(s.end(this), args);
         if (runningOp != null) {
             {if (true) return runningOp.createCall(s.end(this), func);}
         } else {
@@ -8123,14 +8398,13 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
   final public SqlCall MatchRecognizeNavigationPhysical() throws ParseException {
     final Span s;
-    SqlCall func;
-    SqlOperator funcOp;
-    SqlNode arg0;
-    SqlNode arg1 = SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO);
-    if (jj_2_827(2)) {
+    final SqlOperator funcOp;
+    final List<SqlNode> args = new ArrayList<SqlNode>();
+    SqlNode e;
+    if (jj_2_846(2)) {
       jj_consume_token(PREV);
                  funcOp = SqlStdOperatorTable.PREV;
-    } else if (jj_2_828(2)) {
+    } else if (jj_2_847(2)) {
       jj_consume_token(NEXT);
                  funcOp = SqlStdOperatorTable.NEXT;
     } else {
@@ -8139,15 +8413,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     }
       s = span();
     jj_consume_token(LPAREN);
-    arg0 = Expression(ExprContext.ACCEPT_SUB_QUERY);
-    if (jj_2_829(2)) {
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
+    if (jj_2_848(2)) {
       jj_consume_token(COMMA);
-      arg1 = NumericLiteral();
+      e = NumericLiteral();
+                                       args.add(e);
     } else {
-      ;
+          args.add(LITERAL_ONE);
     }
     jj_consume_token(RPAREN);
-        {if (true) return funcOp.createCall(s.end(this), arg0, arg1);}
+        {if (true) return funcOp.createCall(s.end(this), args);}
     throw new Error("Missing return statement in function");
   }
 
@@ -8181,12 +8456,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
   final public Pair<SqlParserPos, SqlOperator> NullTreatment() throws ParseException {
     final Span span;
-    if (jj_2_830(2)) {
+    if (jj_2_849(2)) {
       jj_consume_token(IGNORE);
                span = span();
       jj_consume_token(NULLS);
         {if (true) return Pair.of(span.end(this), SqlStdOperatorTable.IGNORE_NULLS);}
-    } else if (jj_2_831(2)) {
+    } else if (jj_2_850(2)) {
       jj_consume_token(RESPECT);
                 span = span();
       jj_consume_token(NULLS);
@@ -8226,32 +8501,31 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final SqlNode filter;
     final Span overSpan;
     final SqlNode over;
-    final Span withinGroupSpan;
-    if (jj_2_832(2)) {
+    if (jj_2_851(2)) {
       call = StringAggFunctionCall();
-    } else if (jj_2_833(2)) {
+    } else if (jj_2_852(2)) {
       call = NamedCall();
     } else {
       jj_consume_token(-1);
       throw new ParseException();
     }
-    if (jj_2_834(2)) {
+    if (jj_2_853(2)) {
       call = nullTreatment(call);
     } else {
       ;
     }
-    if (jj_2_835(2)) {
+    if (jj_2_854(2)) {
       // decide between WITHIN DISTINCT and WITHIN GROUP
               call = withinDistinct(call);
     } else {
       ;
     }
-    if (jj_2_836(2)) {
+    if (jj_2_855(2)) {
       call = withinGroup(call);
     } else {
       ;
     }
-    if (jj_2_837(2)) {
+    if (jj_2_856(2)) {
       jj_consume_token(FILTER);
                    filterSpan = span();
       jj_consume_token(LPAREN);
@@ -8263,12 +8537,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     } else {
       ;
     }
-    if (jj_2_840(2)) {
+    if (jj_2_859(2)) {
       jj_consume_token(OVER);
                  overSpan = span();
-      if (jj_2_838(2)) {
+      if (jj_2_857(2)) {
         over = SimpleIdentifier();
-      } else if (jj_2_839(2)) {
+      } else if (jj_2_858(2)) {
         over = WindowSpecification();
       } else {
         jj_consume_token(-1);
@@ -8288,7 +8562,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     final Span s;
     final List<SqlNode> args;
     SqlLiteral quantifier = null;
-    if (jj_2_841(2)) {
+    if (jj_2_860(2)) {
       jj_consume_token(SPECIFIC);
             funcType = SqlFunctionCategory.USER_DEFINED_SPECIFIC_FUNCTION;
     } else {
@@ -8296,16 +8570,16 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
     }
     qualifiedName = FunctionName();
         s = span();
-    if (jj_2_842(2)) {
+    if (jj_2_861(2)) {
       jj_consume_token(LPAREN);
       jj_consume_token(STAR);
-            args = startList(SqlIdentifier.star(getPos()));
+            args = ImmutableList.of(SqlIdentifier.star(getPos()));
       jj_consume_token(RPAREN);
-    } else if (jj_2_843(2)) {
+    } else if (jj_2_862(2)) {
       jj_consume_token(LPAREN);
       jj_consume_token(RPAREN);
-            args = Collections.emptyList();
-    } else if (jj_2_844(2)) {
+            args = ImmutableList.of();
+    } else if (jj_2_863(2)) {
       args = FunctionParameterList(ExprContext.ACCEPT_SUB_QUERY);
             quantifier = (SqlLiteral) args.get(0);
             args.remove(0);
@@ -8322,14 +8596,13 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 */
   final public SqlNode StandardFloorCeilOptions(Span s, boolean floorFlag) throws ParseException {
     SqlNode e;
-    final List<SqlNode> args;
+    final List<SqlNode> args = new ArrayList<SqlNode>();
     TimeUnit unit;
     SqlCall function;
     final Span s1;
     jj_consume_token(LPAREN);
-    e = Expression(ExprContext.ACCEPT_SUB_QUERY);
-        args = startList(e);
-    if (jj_2_845(2)) {
+    AddExpression(args, ExprContext.ACCEPT_SUB_QUERY);
+    if (jj_2_864(2)) {
       jj_consume_token(TO);
       unit = TimeUnit();
             args.add(new SqlIntervalQualifier(unit, null, getPos()));
@@ -8341,12 +8614,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             ? SqlStdOperatorTable.FLOOR
             : SqlStdOperatorTable.CEIL;
         function =  op.createCall(s.end(this), args);
-    if (jj_2_848(2)) {
+    if (jj_2_867(2)) {
       jj_consume_token(OVER);
                  s1 = span();
-      if (jj_2_846(2)) {
+      if (jj_2_865(2)) {
         e = SimpleIdentifier();
-      } else if (jj_2_847(2)) {
+      } else if (jj_2_866(2)) {
         e = WindowSpecification();
       } else {
         jj_consume_token(-1);
@@ -8374,9 +8647,9 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlIdentifier FunctionName() throws ParseException {
     SqlIdentifier qualifiedName;
-    if (jj_2_849(2)) {
+    if (jj_2_868(2)) {
       qualifiedName = CompoundIdentifier();
-    } else if (jj_2_850(2)) {
+    } else if (jj_2_869(2)) {
       qualifiedName = ReservedFunctionName();
     } else {
       jj_consume_token(-1);
@@ -8390,133 +8663,135 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses a reserved word which is used as the name of a function.
  */
   final public SqlIdentifier ReservedFunctionName() throws ParseException {
-    if (jj_2_851(2)) {
+    if (jj_2_870(2)) {
       jj_consume_token(ABS);
-    } else if (jj_2_852(2)) {
+    } else if (jj_2_871(2)) {
       jj_consume_token(AVG);
-    } else if (jj_2_853(2)) {
+    } else if (jj_2_872(2)) {
       jj_consume_token(CARDINALITY);
-    } else if (jj_2_854(2)) {
+    } else if (jj_2_873(2)) {
       jj_consume_token(CEILING);
-    } else if (jj_2_855(2)) {
+    } else if (jj_2_874(2)) {
+      jj_consume_token(CHAR);
+    } else if (jj_2_875(2)) {
       jj_consume_token(CHAR_LENGTH);
-    } else if (jj_2_856(2)) {
+    } else if (jj_2_876(2)) {
       jj_consume_token(CHARACTER_LENGTH);
-    } else if (jj_2_857(2)) {
+    } else if (jj_2_877(2)) {
       jj_consume_token(COALESCE);
-    } else if (jj_2_858(2)) {
+    } else if (jj_2_878(2)) {
       jj_consume_token(COLLECT);
-    } else if (jj_2_859(2)) {
+    } else if (jj_2_879(2)) {
       jj_consume_token(COVAR_POP);
-    } else if (jj_2_860(2)) {
+    } else if (jj_2_880(2)) {
       jj_consume_token(COVAR_SAMP);
-    } else if (jj_2_861(2)) {
+    } else if (jj_2_881(2)) {
       jj_consume_token(CUME_DIST);
-    } else if (jj_2_862(2)) {
+    } else if (jj_2_882(2)) {
       jj_consume_token(COUNT);
-    } else if (jj_2_863(2)) {
+    } else if (jj_2_883(2)) {
       jj_consume_token(CURRENT_DATE);
-    } else if (jj_2_864(2)) {
+    } else if (jj_2_884(2)) {
       jj_consume_token(CURRENT_TIME);
-    } else if (jj_2_865(2)) {
+    } else if (jj_2_885(2)) {
       jj_consume_token(CURRENT_TIMESTAMP);
-    } else if (jj_2_866(2)) {
+    } else if (jj_2_886(2)) {
       jj_consume_token(DENSE_RANK);
-    } else if (jj_2_867(2)) {
+    } else if (jj_2_887(2)) {
       jj_consume_token(ELEMENT);
-    } else if (jj_2_868(2)) {
+    } else if (jj_2_888(2)) {
       jj_consume_token(EVERY);
-    } else if (jj_2_869(2)) {
+    } else if (jj_2_889(2)) {
       jj_consume_token(EXP);
-    } else if (jj_2_870(2)) {
+    } else if (jj_2_890(2)) {
       jj_consume_token(FIRST_VALUE);
-    } else if (jj_2_871(2)) {
+    } else if (jj_2_891(2)) {
       jj_consume_token(FLOOR);
-    } else if (jj_2_872(2)) {
+    } else if (jj_2_892(2)) {
       jj_consume_token(FUSION);
-    } else if (jj_2_873(2)) {
+    } else if (jj_2_893(2)) {
       jj_consume_token(INTERSECTION);
-    } else if (jj_2_874(2)) {
+    } else if (jj_2_894(2)) {
       jj_consume_token(GROUPING);
-    } else if (jj_2_875(2)) {
+    } else if (jj_2_895(2)) {
       jj_consume_token(HOUR);
-    } else if (jj_2_876(2)) {
+    } else if (jj_2_896(2)) {
       jj_consume_token(LAG);
-    } else if (jj_2_877(2)) {
+    } else if (jj_2_897(2)) {
       jj_consume_token(LEAD);
-    } else if (jj_2_878(2)) {
+    } else if (jj_2_898(2)) {
       jj_consume_token(LEFT);
-    } else if (jj_2_879(2)) {
+    } else if (jj_2_899(2)) {
       jj_consume_token(LAST_VALUE);
-    } else if (jj_2_880(2)) {
+    } else if (jj_2_900(2)) {
       jj_consume_token(LN);
-    } else if (jj_2_881(2)) {
+    } else if (jj_2_901(2)) {
       jj_consume_token(LOCALTIME);
-    } else if (jj_2_882(2)) {
+    } else if (jj_2_902(2)) {
       jj_consume_token(LOCALTIMESTAMP);
-    } else if (jj_2_883(2)) {
+    } else if (jj_2_903(2)) {
       jj_consume_token(LOWER);
-    } else if (jj_2_884(2)) {
+    } else if (jj_2_904(2)) {
       jj_consume_token(MAX);
-    } else if (jj_2_885(2)) {
+    } else if (jj_2_905(2)) {
       jj_consume_token(MIN);
-    } else if (jj_2_886(2)) {
+    } else if (jj_2_906(2)) {
       jj_consume_token(MINUTE);
-    } else if (jj_2_887(2)) {
+    } else if (jj_2_907(2)) {
       jj_consume_token(MOD);
-    } else if (jj_2_888(2)) {
+    } else if (jj_2_908(2)) {
       jj_consume_token(MONTH);
-    } else if (jj_2_889(2)) {
+    } else if (jj_2_909(2)) {
       jj_consume_token(NTH_VALUE);
-    } else if (jj_2_890(2)) {
+    } else if (jj_2_910(2)) {
       jj_consume_token(NTILE);
-    } else if (jj_2_891(2)) {
+    } else if (jj_2_911(2)) {
       jj_consume_token(NULLIF);
-    } else if (jj_2_892(2)) {
+    } else if (jj_2_912(2)) {
       jj_consume_token(OCTET_LENGTH);
-    } else if (jj_2_893(2)) {
+    } else if (jj_2_913(2)) {
       jj_consume_token(PERCENT_RANK);
-    } else if (jj_2_894(2)) {
+    } else if (jj_2_914(2)) {
       jj_consume_token(PERCENTILE_CONT);
-    } else if (jj_2_895(2)) {
+    } else if (jj_2_915(2)) {
       jj_consume_token(PERCENTILE_DISC);
-    } else if (jj_2_896(2)) {
+    } else if (jj_2_916(2)) {
       jj_consume_token(POWER);
-    } else if (jj_2_897(2)) {
+    } else if (jj_2_917(2)) {
       jj_consume_token(RANK);
-    } else if (jj_2_898(2)) {
+    } else if (jj_2_918(2)) {
       jj_consume_token(REGR_COUNT);
-    } else if (jj_2_899(2)) {
+    } else if (jj_2_919(2)) {
       jj_consume_token(REGR_SXX);
-    } else if (jj_2_900(2)) {
+    } else if (jj_2_920(2)) {
       jj_consume_token(REGR_SYY);
-    } else if (jj_2_901(2)) {
+    } else if (jj_2_921(2)) {
       jj_consume_token(RIGHT);
-    } else if (jj_2_902(2)) {
+    } else if (jj_2_922(2)) {
       jj_consume_token(ROW_NUMBER);
-    } else if (jj_2_903(2)) {
+    } else if (jj_2_923(2)) {
       jj_consume_token(SECOND);
-    } else if (jj_2_904(2)) {
+    } else if (jj_2_924(2)) {
       jj_consume_token(SOME);
-    } else if (jj_2_905(2)) {
+    } else if (jj_2_925(2)) {
       jj_consume_token(SQRT);
-    } else if (jj_2_906(2)) {
+    } else if (jj_2_926(2)) {
       jj_consume_token(STDDEV_POP);
-    } else if (jj_2_907(2)) {
+    } else if (jj_2_927(2)) {
       jj_consume_token(STDDEV_SAMP);
-    } else if (jj_2_908(2)) {
+    } else if (jj_2_928(2)) {
       jj_consume_token(SUM);
-    } else if (jj_2_909(2)) {
+    } else if (jj_2_929(2)) {
       jj_consume_token(UPPER);
-    } else if (jj_2_910(2)) {
+    } else if (jj_2_930(2)) {
       jj_consume_token(TRUNCATE);
-    } else if (jj_2_911(2)) {
+    } else if (jj_2_931(2)) {
       jj_consume_token(USER);
-    } else if (jj_2_912(2)) {
+    } else if (jj_2_932(2)) {
       jj_consume_token(VAR_POP);
-    } else if (jj_2_913(2)) {
+    } else if (jj_2_933(2)) {
       jj_consume_token(VAR_SAMP);
-    } else if (jj_2_914(2)) {
+    } else if (jj_2_934(2)) {
       jj_consume_token(YEAR);
     } else {
       jj_consume_token(-1);
@@ -8527,33 +8802,33 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
   }
 
   final public SqlIdentifier ContextVariable() throws ParseException {
-    if (jj_2_915(2)) {
+    if (jj_2_935(2)) {
       jj_consume_token(CURRENT_CATALOG);
-    } else if (jj_2_916(2)) {
+    } else if (jj_2_936(2)) {
       jj_consume_token(CURRENT_DATE);
-    } else if (jj_2_917(2)) {
+    } else if (jj_2_937(2)) {
       jj_consume_token(CURRENT_DEFAULT_TRANSFORM_GROUP);
-    } else if (jj_2_918(2)) {
+    } else if (jj_2_938(2)) {
       jj_consume_token(CURRENT_PATH);
-    } else if (jj_2_919(2)) {
+    } else if (jj_2_939(2)) {
       jj_consume_token(CURRENT_ROLE);
-    } else if (jj_2_920(2)) {
+    } else if (jj_2_940(2)) {
       jj_consume_token(CURRENT_SCHEMA);
-    } else if (jj_2_921(2)) {
+    } else if (jj_2_941(2)) {
       jj_consume_token(CURRENT_TIME);
-    } else if (jj_2_922(2)) {
+    } else if (jj_2_942(2)) {
       jj_consume_token(CURRENT_TIMESTAMP);
-    } else if (jj_2_923(2)) {
+    } else if (jj_2_943(2)) {
       jj_consume_token(CURRENT_USER);
-    } else if (jj_2_924(2)) {
+    } else if (jj_2_944(2)) {
       jj_consume_token(LOCALTIME);
-    } else if (jj_2_925(2)) {
+    } else if (jj_2_945(2)) {
       jj_consume_token(LOCALTIMESTAMP);
-    } else if (jj_2_926(2)) {
+    } else if (jj_2_946(2)) {
       jj_consume_token(SESSION_USER);
-    } else if (jj_2_927(2)) {
+    } else if (jj_2_947(2)) {
       jj_consume_token(SYSTEM_USER);
-    } else if (jj_2_928(2)) {
+    } else if (jj_2_948(2)) {
       jj_consume_token(USER);
     } else {
       jj_consume_token(-1);
@@ -8583,12 +8858,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
             args = new SqlNodeList(call.getOperandList(), getPos());
       break;
     default:
-      jj_la1[9] = jj_gen;
-      if (jj_2_939(3)) {
+      jj_la1[12] = jj_gen;
+      if (jj_2_959(3)) {
         call = TimestampDiffFunctionCall();
             name = call.getOperator().getName();
             args = new SqlNodeList(call.getOperandList(), getPos());
-      } else if (jj_2_940(2)) {
+      } else if (jj_2_960(2)) {
         jj_consume_token(CONVERT);
                     name = unquotedIdentifier();
         jj_consume_token(LPAREN);
@@ -8599,19 +8874,19 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         tl = JdbcOdbcDataType();
                                   args.add(tl);
         jj_consume_token(RPAREN);
-      } else if (jj_2_941(2)) {
+      } else if (jj_2_961(2)) {
         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
         case INSERT:
         case LEFT:
         case RIGHT:
         case TRUNCATE:
-          if (jj_2_929(2)) {
+          if (jj_2_949(2)) {
             jj_consume_token(INSERT);
-          } else if (jj_2_930(2)) {
+          } else if (jj_2_950(2)) {
             jj_consume_token(LEFT);
-          } else if (jj_2_931(2)) {
+          } else if (jj_2_951(2)) {
             jj_consume_token(RIGHT);
-          } else if (jj_2_932(2)) {
+          } else if (jj_2_952(2)) {
             jj_consume_token(TRUNCATE);
           } else {
             jj_consume_token(-1);
@@ -8620,33 +8895,33 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
                                                            name = unquotedIdentifier();
           break;
         default:
-          jj_la1[8] = jj_gen;
-          if (jj_2_933(2)) {
+          jj_la1[11] = jj_gen;
+          if (jj_2_953(2)) {
             // For cases like {fn power(1,2)} and {fn lower('a')}
                         id = ReservedFunctionName();
                                           name = id.getSimple();
-          } else if (jj_2_934(2)) {
+          } else if (jj_2_954(2)) {
             // For cases like {fn substring('foo', 1,2)}
                         name = NonReservedJdbcFunctionName();
-          } else if (jj_2_935(2)) {
+          } else if (jj_2_955(2)) {
             name = Identifier();
           } else {
             jj_consume_token(-1);
             throw new ParseException();
           }
         }
-        if (jj_2_936(2)) {
+        if (jj_2_956(2)) {
           jj_consume_token(LPAREN);
           jj_consume_token(STAR);
                                            s1 = span();
           jj_consume_token(RPAREN);
                 args = new SqlNodeList(s1.pos());
                 args.add(SqlIdentifier.star(s1.pos()));
-        } else if (jj_2_937(2)) {
+        } else if (jj_2_957(2)) {
           jj_consume_token(LPAREN);
           jj_consume_token(RPAREN);
                                              args = SqlNodeList.EMPTY;
-        } else if (jj_2_938(2)) {
+        } else if (jj_2_958(2)) {
           args = ParenthesizedQueryOrCommaList(ExprContext.ACCEPT_SUB_QUERY);
         } else {
           jj_consume_token(-1);
@@ -8667,32 +8942,32 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses a binary query operator like UNION.
  */
   final public SqlBinaryOperator BinaryQueryOperator() throws ParseException {
-    if (jj_2_950(2)) {
+    if (jj_2_970(2)) {
       jj_consume_token(UNION);
-      if (jj_2_942(2)) {
+      if (jj_2_962(2)) {
         jj_consume_token(ALL);
                     {if (true) return SqlStdOperatorTable.UNION_ALL;}
-      } else if (jj_2_943(2)) {
+      } else if (jj_2_963(2)) {
         jj_consume_token(DISTINCT);
                          {if (true) return SqlStdOperatorTable.UNION;}
       } else {
               {if (true) return SqlStdOperatorTable.UNION;}
       }
-    } else if (jj_2_951(2)) {
+    } else if (jj_2_971(2)) {
       jj_consume_token(INTERSECT);
-      if (jj_2_944(2)) {
+      if (jj_2_964(2)) {
         jj_consume_token(ALL);
                     {if (true) return SqlStdOperatorTable.INTERSECT_ALL;}
-      } else if (jj_2_945(2)) {
+      } else if (jj_2_965(2)) {
         jj_consume_token(DISTINCT);
                          {if (true) return SqlStdOperatorTable.INTERSECT;}
       } else {
               {if (true) return SqlStdOperatorTable.INTERSECT;}
       }
-    } else if (jj_2_952(2)) {
-      if (jj_2_946(2)) {
+    } else if (jj_2_972(2)) {
+      if (jj_2_966(2)) {
         jj_consume_token(EXCEPT);
-      } else if (jj_2_947(2)) {
+      } else if (jj_2_967(2)) {
         jj_consume_token(SET_MINUS);
                 if (!this.conformance.isMinusAllowed()) {
                     {if (true) throw SqlUtil.newContextException(getPos(), RESOURCE.minusNotAllowed());}
@@ -8701,10 +8976,10 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         jj_consume_token(-1);
         throw new ParseException();
       }
-      if (jj_2_948(2)) {
+      if (jj_2_968(2)) {
         jj_consume_token(ALL);
                     {if (true) return SqlStdOperatorTable.EXCEPT_ALL;}
-      } else if (jj_2_949(2)) {
+      } else if (jj_2_969(2)) {
         jj_consume_token(DISTINCT);
                          {if (true) return SqlStdOperatorTable.EXCEPT;}
       } else {
@@ -8722,12 +8997,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlBinaryOperator BinaryMultisetOperator() throws ParseException {
     jj_consume_token(MULTISET);
-    if (jj_2_962(2)) {
+    if (jj_2_982(2)) {
       jj_consume_token(UNION);
-      if (jj_2_955(2)) {
-        if (jj_2_953(2)) {
+      if (jj_2_975(2)) {
+        if (jj_2_973(2)) {
           jj_consume_token(ALL);
-        } else if (jj_2_954(2)) {
+        } else if (jj_2_974(2)) {
           jj_consume_token(DISTINCT);
                          {if (true) return SqlStdOperatorTable.MULTISET_UNION_DISTINCT;}
         } else {
@@ -8738,12 +9013,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         ;
       }
           {if (true) return SqlStdOperatorTable.MULTISET_UNION;}
-    } else if (jj_2_963(2)) {
+    } else if (jj_2_983(2)) {
       jj_consume_token(INTERSECT);
-      if (jj_2_958(2)) {
-        if (jj_2_956(2)) {
+      if (jj_2_978(2)) {
+        if (jj_2_976(2)) {
           jj_consume_token(ALL);
-        } else if (jj_2_957(2)) {
+        } else if (jj_2_977(2)) {
           jj_consume_token(DISTINCT);
                          {if (true) return SqlStdOperatorTable.MULTISET_INTERSECT_DISTINCT;}
         } else {
@@ -8754,12 +9029,12 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         ;
       }
           {if (true) return SqlStdOperatorTable.MULTISET_INTERSECT;}
-    } else if (jj_2_964(2)) {
+    } else if (jj_2_984(2)) {
       jj_consume_token(EXCEPT);
-      if (jj_2_961(2)) {
-        if (jj_2_959(2)) {
+      if (jj_2_981(2)) {
+        if (jj_2_979(2)) {
           jj_consume_token(ALL);
-        } else if (jj_2_960(2)) {
+        } else if (jj_2_980(2)) {
           jj_consume_token(DISTINCT);
                          {if (true) return SqlStdOperatorTable.MULTISET_EXCEPT_DISTINCT;}
         } else {
@@ -8782,105 +9057,105 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  */
   final public SqlBinaryOperator BinaryRowOperator() throws ParseException {
     SqlBinaryOperator op;
-    if (jj_2_965(2)) {
+    if (jj_2_985(2)) {
       jj_consume_token(EQ);
            {if (true) return SqlStdOperatorTable.EQUALS;}
-    } else if (jj_2_966(2)) {
+    } else if (jj_2_986(2)) {
       jj_consume_token(GT);
            {if (true) return SqlStdOperatorTable.GREATER_THAN;}
-    } else if (jj_2_967(2)) {
+    } else if (jj_2_987(2)) {
       jj_consume_token(LT);
            {if (true) return SqlStdOperatorTable.LESS_THAN;}
-    } else if (jj_2_968(2)) {
+    } else if (jj_2_988(2)) {
       jj_consume_token(LE);
            {if (true) return SqlStdOperatorTable.LESS_THAN_OR_EQUAL;}
-    } else if (jj_2_969(2)) {
+    } else if (jj_2_989(2)) {
       jj_consume_token(GE);
            {if (true) return SqlStdOperatorTable.GREATER_THAN_OR_EQUAL;}
-    } else if (jj_2_970(2)) {
+    } else if (jj_2_990(2)) {
       jj_consume_token(NE);
            {if (true) return SqlStdOperatorTable.NOT_EQUALS;}
-    } else if (jj_2_971(2)) {
+    } else if (jj_2_991(2)) {
       jj_consume_token(NE2);
         if (!this.conformance.isBangEqualAllowed()) {
             {if (true) throw SqlUtil.newContextException(getPos(), RESOURCE.bangEqualNotAllowed());}
         }
         {if (true) return SqlStdOperatorTable.NOT_EQUALS;}
-    } else if (jj_2_972(2)) {
+    } else if (jj_2_992(2)) {
       jj_consume_token(PLUS);
              {if (true) return SqlStdOperatorTable.PLUS;}
-    } else if (jj_2_973(2)) {
+    } else if (jj_2_993(2)) {
       jj_consume_token(MINUS);
               {if (true) return SqlStdOperatorTable.MINUS;}
-    } else if (jj_2_974(2)) {
+    } else if (jj_2_994(2)) {
       jj_consume_token(STAR);
              {if (true) return SqlStdOperatorTable.MULTIPLY;}
-    } else if (jj_2_975(2)) {
+    } else if (jj_2_995(2)) {
       jj_consume_token(SLASH);
               {if (true) return SqlStdOperatorTable.DIVIDE;}
-    } else if (jj_2_976(2)) {
+    } else if (jj_2_996(2)) {
       jj_consume_token(PERCENT_REMAINDER);
         if (!this.conformance.isPercentRemainderAllowed()) {
             {if (true) throw SqlUtil.newContextException(getPos(), RESOURCE.percentRemainderNotAllowed());}
         }
         {if (true) return SqlStdOperatorTable.PERCENT_REMAINDER;}
-    } else if (jj_2_977(2)) {
+    } else if (jj_2_997(2)) {
       jj_consume_token(CONCAT);
                {if (true) return SqlStdOperatorTable.CONCAT;}
-    } else if (jj_2_978(2)) {
+    } else if (jj_2_998(2)) {
       jj_consume_token(AND);
             {if (true) return SqlStdOperatorTable.AND;}
-    } else if (jj_2_979(2)) {
+    } else if (jj_2_999(2)) {
       jj_consume_token(OR);
            {if (true) return SqlStdOperatorTable.OR;}
-    } else if (jj_2_980(2)) {
+    } else if (jj_2_1000(2)) {
       jj_consume_token(IS);
       jj_consume_token(DISTINCT);
       jj_consume_token(FROM);
                                           {if (true) return SqlStdOperatorTable.IS_DISTINCT_FROM;}
-    } else if (jj_2_981(2)) {
+    } else if (jj_2_1001(2)) {
       jj_consume_token(IS);
       jj_consume_token(NOT);
       jj_consume_token(DISTINCT);
       jj_consume_token(FROM);
                                    {if (true) return SqlStdOperatorTable.IS_NOT_DISTINCT_FROM;}
-    } else if (jj_2_982(2)) {
+    } else if (jj_2_1002(2)) {
       jj_consume_token(MEMBER);
       jj_consume_token(OF);
                     {if (true) return SqlStdOperatorTable.MEMBER_OF;}
-    } else if (jj_2_983(2)) {
+    } else if (jj_2_1003(2)) {
       jj_consume_token(SUBMULTISET);
       jj_consume_token(OF);
                                       {if (true) return SqlStdOperatorTable.SUBMULTISET_OF;}
-    } else if (jj_2_984(2)) {
+    } else if (jj_2_1004(2)) {
       jj_consume_token(NOT);
       jj_consume_token(SUBMULTISET);
       jj_consume_token(OF);
                                {if (true) return SqlStdOperatorTable.NOT_SUBMULTISET_OF;}
-    } else if (jj_2_985(2)) {
+    } else if (jj_2_1005(2)) {
       jj_consume_token(CONTAINS);
                  {if (true) return SqlStdOperatorTable.CONTAINS;}
-    } else if (jj_2_986(2)) {
+    } else if (jj_2_1006(2)) {
       jj_consume_token(OVERLAPS);
                  {if (true) return SqlStdOperatorTable.OVERLAPS;}
-    } else if (jj_2_987(2)) {
+    } else if (jj_2_1007(2)) {
       jj_consume_token(EQUALS);
                {if (true) return SqlStdOperatorTable.PERIOD_EQUALS;}
-    } else if (jj_2_988(2)) {
+    } else if (jj_2_1008(2)) {
       jj_consume_token(PRECEDES);
                  {if (true) return SqlStdOperatorTable.PRECEDES;}
-    } else if (jj_2_989(2)) {
+    } else if (jj_2_1009(2)) {
       jj_consume_token(SUCCEEDS);
                  {if (true) return SqlStdOperatorTable.SUCCEEDS;}
-    } else if (jj_2_990(2)) {
+    } else if (jj_2_1010(2)) {
       jj_consume_token(IMMEDIATELY);
       jj_consume_token(PRECEDES);
                                             {if (true) return SqlStdOperatorTable.IMMEDIATELY_PRECEDES;}
-    } else if (jj_2_991(2)) {
+    } else if (jj_2_1011(2)) {
       jj_consume_token(IMMEDIATELY);
       jj_consume_token(SUCCEEDS);
                                {if (true) return SqlStdOperatorTable.IMMEDIATELY_SUCCEEDS;}
-    } else if (jj_2_992(2)) {
+    } else if (jj_2_1012(2)) {
       op = BinaryMultisetOperator();
                                     {if (true) return op;}
     } else {
@@ -8894,19 +9169,19 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses a prefix row operator like NOT.
  */
   final public SqlPrefixOperator PrefixRowOperator() throws ParseException {
-    if (jj_2_993(2)) {
+    if (jj_2_1013(2)) {
       jj_consume_token(PLUS);
              {if (true) return SqlStdOperatorTable.UNARY_PLUS;}
-    } else if (jj_2_994(2)) {
+    } else if (jj_2_1014(2)) {
       jj_consume_token(MINUS);
               {if (true) return SqlStdOperatorTable.UNARY_MINUS;}
-    } else if (jj_2_995(2)) {
+    } else if (jj_2_1015(2)) {
       jj_consume_token(NOT);
             {if (true) return SqlStdOperatorTable.NOT;}
-    } else if (jj_2_996(2)) {
+    } else if (jj_2_1016(2)) {
       jj_consume_token(EXISTS);
                {if (true) return SqlStdOperatorTable.EXISTS;}
-    } else if (jj_2_997(2)) {
+    } else if (jj_2_1017(2)) {
       jj_consume_token(UNIQUE);
                {if (true) return SqlStdOperatorTable.UNIQUE;}
     } else {
@@ -8920,89 +9195,89 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * Parses a postfix row operator like IS NOT NULL.
  */
   final public SqlPostfixOperator PostfixRowOperator() throws ParseException {
-    if (jj_2_1022(2)) {
+    if (jj_2_1042(2)) {
       jj_consume_token(IS);
-      if (jj_2_1019(2)) {
+      if (jj_2_1039(2)) {
         jj_consume_token(A);
         jj_consume_token(SET);
                     {if (true) return SqlStdOperatorTable.IS_A_SET;}
-      } else if (jj_2_1020(2)) {
+      } else if (jj_2_1040(2)) {
         jj_consume_token(NOT);
-        if (jj_2_998(2)) {
+        if (jj_2_1018(2)) {
           jj_consume_token(NULL);
                      {if (true) return SqlStdOperatorTable.IS_NOT_NULL;}
-        } else if (jj_2_999(2)) {
+        } else if (jj_2_1019(2)) {
           jj_consume_token(TRUE);
                      {if (true) return SqlStdOperatorTable.IS_NOT_TRUE;}
-        } else if (jj_2_1000(2)) {
+        } else if (jj_2_1020(2)) {
           jj_consume_token(FALSE);
                       {if (true) return SqlStdOperatorTable.IS_NOT_FALSE;}
-        } else if (jj_2_1001(2)) {
+        } else if (jj_2_1021(2)) {
           jj_consume_token(UNKNOWN);
                         {if (true) return SqlStdOperatorTable.IS_NOT_UNKNOWN;}
-        } else if (jj_2_1002(2)) {
+        } else if (jj_2_1022(2)) {
           jj_consume_token(A);
           jj_consume_token(SET);
                         {if (true) return SqlStdOperatorTable.IS_NOT_A_SET;}
-        } else if (jj_2_1003(2)) {
+        } else if (jj_2_1023(2)) {
           jj_consume_token(EMPTY);
                       {if (true) return SqlStdOperatorTable.IS_NOT_EMPTY;}
-        } else if (jj_2_1004(2)) {
+        } else if (jj_2_1024(2)) {
           jj_consume_token(JSON);
           jj_consume_token(VALUE);
                                           {if (true) return SqlStdOperatorTable.IS_NOT_JSON_VALUE;}
-        } else if (jj_2_1005(2)) {
+        } else if (jj_2_1025(2)) {
           jj_consume_token(JSON);
           jj_consume_token(OBJECT);
                                            {if (true) return SqlStdOperatorTable.IS_NOT_JSON_OBJECT;}
-        } else if (jj_2_1006(2)) {
+        } else if (jj_2_1026(2)) {
           jj_consume_token(JSON);
           jj_consume_token(ARRAY);
                                           {if (true) return SqlStdOperatorTable.IS_NOT_JSON_ARRAY;}
-        } else if (jj_2_1007(2)) {
+        } else if (jj_2_1027(2)) {
           jj_consume_token(JSON);
           jj_consume_token(SCALAR);
                                            {if (true) return SqlStdOperatorTable.IS_NOT_JSON_SCALAR;}
-        } else if (jj_2_1008(2)) {
+        } else if (jj_2_1028(2)) {
           jj_consume_token(JSON);
                      {if (true) return SqlStdOperatorTable.IS_NOT_JSON_VALUE;}
         } else {
           jj_consume_token(-1);
           throw new ParseException();
         }
-      } else if (jj_2_1021(2)) {
-        if (jj_2_1009(2)) {
+      } else if (jj_2_1041(2)) {
+        if (jj_2_1029(2)) {
           jj_consume_token(NULL);
                      {if (true) return SqlStdOperatorTable.IS_NULL;}
-        } else if (jj_2_1010(2)) {
+        } else if (jj_2_1030(2)) {
           jj_consume_token(TRUE);
                      {if (true) return SqlStdOperatorTable.IS_TRUE;}
-        } else if (jj_2_1011(2)) {
+        } else if (jj_2_1031(2)) {
           jj_consume_token(FALSE);
                       {if (true) return SqlStdOperatorTable.IS_FALSE;}
-        } else if (jj_2_1012(2)) {
+        } else if (jj_2_1032(2)) {
           jj_consume_token(UNKNOWN);
                         {if (true) return SqlStdOperatorTable.IS_UNKNOWN;}
-        } else if (jj_2_1013(2)) {
+        } else if (jj_2_1033(2)) {
           jj_consume_token(EMPTY);
                       {if (true) return SqlStdOperatorTable.IS_EMPTY;}
-        } else if (jj_2_1014(2)) {
+        } else if (jj_2_1034(2)) {
           jj_consume_token(JSON);
           jj_consume_token(VALUE);
                                           {if (true) return SqlStdOperatorTable.IS_JSON_VALUE;}
-        } else if (jj_2_1015(2)) {
+        } else if (jj_2_1035(2)) {
           jj_consume_token(JSON);
           jj_consume_token(OBJECT);
                                            {if (true) return SqlStdOperatorTable.IS_JSON_OBJECT;}
-        } else if (jj_2_1016(2)) {
+        } else if (jj_2_1036(2)) {
           jj_consume_token(JSON);
           jj_consume_token(ARRAY);
                                           {if (true) return SqlStdOperatorTable.IS_JSON_ARRAY;}
-        } else if (jj_2_1017(2)) {
+        } else if (jj_2_1037(2)) {
           jj_consume_token(JSON);
           jj_consume_token(SCALAR);
                                            {if (true) return SqlStdOperatorTable.IS_JSON_SCALAR;}
-        } else if (jj_2_1018(2)) {
+        } else if (jj_2_1038(2)) {
           jj_consume_token(JSON);
                      {if (true) return SqlStdOperatorTable.IS_JSON_VALUE;}
         } else {
@@ -9013,7 +9288,7 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
         jj_consume_token(-1);
         throw new ParseException();
       }
-    } else if (jj_2_1023(2)) {
+    } else if (jj_2_1043(2)) {
       jj_consume_token(FORMAT);
       JsonRepresentation();
             {if (true) return SqlStdOperatorTable.JSON_VALUE_EXPRESSION;}
@@ -9039,11 +9314,11 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
  * @see Glossary#SQL2003 SQL:2003 Part 2 Section 5.2
  */
   final public String NonReservedKeyWord() throws ParseException {
-    if (jj_2_1024(2)) {
+    if (jj_2_1044(2)) {
       NonReservedKeyWord0of3();
-    } else if (jj_2_1025(2)) {
+    } else if (jj_2_1045(2)) {
       NonReservedKeyWord1of3();
-    } else if (jj_2_1026(2)) {
+    } else if (jj_2_1046(2)) {
       NonReservedKeyWord2of3();
     } else {
       jj_consume_token(-1);
@@ -9055,273 +9330,273 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
 /** @see #NonReservedKeyWord */
   final public void NonReservedKeyWord0of3() throws ParseException {
-    if (jj_2_1027(2)) {
+    if (jj_2_1047(2)) {
       jj_consume_token(SEMI);
-    } else if (jj_2_1028(2)) {
+    } else if (jj_2_1048(2)) {
       jj_consume_token(AFFINITY_KEY);
-    } else if (jj_2_1029(2)) {
+    } else if (jj_2_1049(2)) {
       jj_consume_token(CACHE_GROUP);
-    } else if (jj_2_1030(2)) {
+    } else if (jj_2_1050(2)) {
       jj_consume_token(VALUE_TYPE);
-    } else if (jj_2_1031(2)) {
+    } else if (jj_2_1051(2)) {
       jj_consume_token(INLINE_SIZE);
-    } else if (jj_2_1032(2)) {
+    } else if (jj_2_1052(2)) {
       jj_consume_token(PASSWORD);
-    } else if (jj_2_1033(2)) {
+    } else if (jj_2_1053(2)) {
       jj_consume_token(CONTINUOUS);
-    } else if (jj_2_1034(2)) {
+    } else if (jj_2_1054(2)) {
       jj_consume_token(ASYNC);
-    } else if (jj_2_1035(2)) {
+    } else if (jj_2_1055(2)) {
       jj_consume_token(REFRESH);
-    } else if (jj_2_1036(2)) {
+    } else if (jj_2_1056(2)) {
       jj_consume_token(TOTAL);
-    } else if (jj_2_1037(2)) {
+    } else if (jj_2_1057(2)) {
       jj_consume_token(ABSOLUTE);
-    } else if (jj_2_1038(2)) {
+    } else if (jj_2_1058(2)) {
       jj_consume_token(AFTER);
-    } else if (jj_2_1039(2)) {
+    } else if (jj_2_1059(2)) {
       jj_consume_token(ALTER);
-    } else if (jj_2_1040(2)) {
+    } else if (jj_2_1060(2)) {
       jj_consume_token(ARRAY);
-    } else if (jj_2_1041(2)) {
+    } else if (jj_2_1061(2)) {
       jj_consume_token(ARRAY_MAX_CARDINALITY);
-    } else if (jj_2_1042(2)) {
+    } else if (jj_2_1062(2)) {
       jj_consume_token(ASENSITIVE);
-    } else if (jj_2_1043(2)) {
+    } else if (jj_2_1063(2)) {
       jj_consume_token(AT);
-    } else if (jj_2_1044(2)) {
+    } else if (jj_2_1064(2)) {
       jj_consume_token(AVG);
-    } else if (jj_2_1045(2)) {
+    } else if (jj_2_1065(2)) {
       jj_consume_token(BEGIN_FRAME);
-    } else if (jj_2_1046(2)) {
+    } else if (jj_2_1066(2)) {
       jj_consume_token(BIGINT);
-    } else if (jj_2_1047(2)) {
+    } else if (jj_2_1067(2)) {
       jj_consume_token(BLOB);
-    } else if (jj_2_1048(2)) {
+    } else if (jj_2_1068(2)) {
       jj_consume_token(BREADTH);
-    } else if (jj_2_1049(2)) {
+    } else if (jj_2_1069(2)) {
       jj_consume_token(CALLED);
-    } else if (jj_2_1050(2)) {
+    } else if (jj_2_1070(2)) {
       jj_consume_token(CASCADED);
-    } else if (jj_2_1051(2)) {
+    } else if (jj_2_1071(2)) {
       jj_consume_token(CEIL);
-    } else if (jj_2_1052(2)) {
+    } else if (jj_2_1072(2)) {
       jj_consume_token(CHARACTER);
-    } else if (jj_2_1053(2)) {
+    } else if (jj_2_1073(2)) {
       jj_consume_token(CHECK);
-    } else if (jj_2_1054(2)) {
+    } else if (jj_2_1074(2)) {
       jj_consume_token(CLOSE);
-    } else if (jj_2_1055(2)) {
+    } else if (jj_2_1075(2)) {
       jj_consume_token(COLLATION);
-    } else if (jj_2_1056(2)) {
+    } else if (jj_2_1076(2)) {
       jj_consume_token(COMMIT);
-    } else if (jj_2_1057(2)) {
+    } else if (jj_2_1077(2)) {
       jj_consume_token(CONNECTION);
-    } else if (jj_2_1058(2)) {
+    } else if (jj_2_1078(2)) {
       jj_consume_token(CONTAINS);
-    } else if (jj_2_1059(2)) {
+    } else if (jj_2_1079(2)) {
       jj_consume_token(CORR);
-    } else if (jj_2_1060(2)) {
+    } else if (jj_2_1080(2)) {
       jj_consume_token(COVAR_POP);
-    } else if (jj_2_1061(2)) {
+    } else if (jj_2_1081(2)) {
       jj_consume_token(CUME_DIST);
-    } else if (jj_2_1062(2)) {
+    } else if (jj_2_1082(2)) {
       jj_consume_token(CURRENT_DEFAULT_TRANSFORM_GROUP);
-    } else if (jj_2_1063(2)) {
+    } else if (jj_2_1083(2)) {
       jj_consume_token(CURRENT_ROW);
-    } else if (jj_2_1064(2)) {
+    } else if (jj_2_1084(2)) {
       jj_consume_token(CURRENT_TIMESTAMP);
-    } else if (jj_2_1065(2)) {
+    } else if (jj_2_1085(2)) {
       jj_consume_token(CYCLE);
-    } else if (jj_2_1066(2)) {
+    } else if (jj_2_1086(2)) {
       jj_consume_token(DAY);
-    } else if (jj_2_1067(2)) {
+    } else if (jj_2_1087(2)) {
       jj_consume_token(DECIMAL);
-    } else if (jj_2_1068(2)) {
+    } else if (jj_2_1088(2)) {
       jj_consume_token(DEFERRED);
-    } else if (jj_2_1069(2)) {
+    } else if (jj_2_1089(2)) {
       jj_consume_token(DEREF);
-    } else if (jj_2_1070(2)) {
+    } else if (jj_2_1090(2)) {
       jj_consume_token(DETERMINISTIC);
-    } else if (jj_2_1071(2)) {
+    } else if (jj_2_1091(2)) {
       jj_consume_token(DISCONNECT);
-    } else if (jj_2_1072(2)) {
+    } else if (jj_2_1092(2)) {
       jj_consume_token(DYNAMIC);
-    } else if (jj_2_1073(2)) {
+    } else if (jj_2_1093(2)) {
       jj_consume_token(ELSE);
-    } else if (jj_2_1074(2)) {
+    } else if (jj_2_1094(2)) {
       jj_consume_token(END_FRAME);
-    } else if (jj_2_1075(2)) {
+    } else if (jj_2_1095(2)) {
       jj_consume_token(ESCAPE);
-    } else if (jj_2_1076(2)) {
+    } else if (jj_2_1096(2)) {
       jj_consume_token(EXEC);
-    } else if (jj_2_1077(2)) {
+    } else if (jj_2_1097(2)) {
       jj_consume_token(EXP);
-    } else if (jj_2_1078(2)) {
+    } else if (jj_2_1098(2)) {
       jj_consume_token(EXTRACT);
-    } else if (jj_2_1079(2)) {
+    } else if (jj_2_1099(2)) {
       jj_consume_token(FIRST);
-    } else if (jj_2_1080(2)) {
+    } else if (jj_2_1100(2)) {
       jj_consume_token(FLOOR);
-    } else if (jj_2_1081(2)) {
+    } else if (jj_2_1101(2)) {
       jj_consume_token(FOUND);
-    } else if (jj_2_1082(2)) {
+    } else if (jj_2_1102(2)) {
       jj_consume_token(FUNCTION);
-    } else if (jj_2_1083(2)) {
+    } else if (jj_2_1103(2)) {
       jj_consume_token(GENERAL);
-    } else if (jj_2_1084(2)) {
+    } else if (jj_2_1104(2)) {
       jj_consume_token(GO);
-    } else if (jj_2_1085(2)) {
+    } else if (jj_2_1105(2)) {
       jj_consume_token(HOLD);
-    } else if (jj_2_1086(2)) {
+    } else if (jj_2_1106(2)) {
       jj_consume_token(IMMEDIATE);
-    } else if (jj_2_1087(2)) {
+    } else if (jj_2_1107(2)) {
       jj_consume_token(INDICATOR);
-    } else if (jj_2_1088(2)) {
+    } else if (jj_2_1108(2)) {
       jj_consume_token(INOUT);
-    } else if (jj_2_1089(2)) {
+    } else if (jj_2_1109(2)) {
       jj_consume_token(INT);
-    } else if (jj_2_1090(2)) {
+    } else if (jj_2_1110(2)) {
       jj_consume_token(IS);
-    } else if (jj_2_1091(2)) {
+    } else if (jj_2_1111(2)) {
       jj_consume_token(JSON_ARRAYAGG);
-    } else if (jj_2_1092(2)) {
+    } else if (jj_2_1112(2)) {
       jj_consume_token(JSON_OBJECTAGG);
-    } else if (jj_2_1093(2)) {
+    } else if (jj_2_1113(2)) {
       jj_consume_token(K);
-    } else if (jj_2_1094(2)) {
+    } else if (jj_2_1114(2)) {
       jj_consume_token(LANGUAGE);
-    } else if (jj_2_1095(2)) {
+    } else if (jj_2_1115(2)) {
       jj_consume_token(LAST_VALUE);
-    } else if (jj_2_1096(2)) {
+    } else if (jj_2_1116(2)) {
       jj_consume_token(LENGTH);
-    } else if (jj_2_1097(2)) {
+    } else if (jj_2_1117(2)) {
       jj_consume_token(LIKE_REGEX);
-    } else if (jj_2_1098(2)) {
+    } else if (jj_2_1118(2)) {
       jj_consume_token(LOCALTIME);
-    } else if (jj_2_1099(2)) {
+    } else if (jj_2_1119(2)) {
       jj_consume_token(LOWER);
-    } else if (jj_2_1100(2)) {
+    } else if (jj_2_1120(2)) {
       jj_consume_token(MATCH);
-    } else if (jj_2_1101(2)) {
+    } else if (jj_2_1121(2)) {
       jj_consume_token(MAX);
-    } else if (jj_2_1102(2)) {
+    } else if (jj_2_1122(2)) {
       jj_consume_token(METHOD);
-    } else if (jj_2_1103(2)) {
+    } else if (jj_2_1123(2)) {
       jj_consume_token(MOD);
-    } else if (jj_2_1104(2)) {
+    } else if (jj_2_1124(2)) {
       jj_consume_token(MONTH);
-    } else if (jj_2_1105(2)) {
+    } else if (jj_2_1125(2)) {
       jj_consume_token(NAMES);
-    } else if (jj_2_1106(2)) {
+    } else if (jj_2_1126(2)) {
       jj_consume_token(NCLOB);
-    } else if (jj_2_1107(2)) {
+    } else if (jj_2_1127(2)) {
       jj_consume_token(NORMALIZE);
-    } else if (jj_2_1108(2)) {
+    } else if (jj_2_1128(2)) {
       jj_consume_token(NTILE);
-    } else if (jj_2_1109(2)) {
+    } else if (jj_2_1129(2)) {
       jj_consume_token(OBJECT);
-    } else if (jj_2_1110(2)) {
+    } else if (jj_2_1130(2)) {
       jj_consume_token(OF);
-    } else if (jj_2_1111(2)) {
+    } else if (jj_2_1131(2)) {
       jj_consume_token(ONE);
-    } else if (jj_2_1112(2)) {
+    } else if (jj_2_1132(2)) {
       jj_consume_token(OPTION);
-    } else if (jj_2_1113(2)) {
+    } else if (jj_2_1133(2)) {
       jj_consume_token(OUT);
-    } else if (jj_2_1114(2)) {
+    } else if (jj_2_1134(2)) {
       jj_consume_token(OVERLAY);
-    } else if (jj_2_1115(2)) {
+    } else if (jj_2_1135(2)) {
       jj_consume_token(PARTIAL);
-    } else if (jj_2_1116(2)) {
+    } else if (jj_2_1136(2)) {
       jj_consume_token(PERCENT);
-    } else if (jj_2_1117(2)) {
+    } else if (jj_2_1137(2)) {
       jj_consume_token(PERCENT_RANK);
-    } else if (jj_2_1118(2)) {
+    } else if (jj_2_1138(2)) {
       jj_consume_token(PORTION);
-    } else if (jj_2_1119(2)) {
+    } else if (jj_2_1139(2)) {
       jj_consume_token(POWER);
-    } else if (jj_2_1120(2)) {
+    } else if (jj_2_1140(2)) {
       jj_consume_token(PREPARE);
-    } else if (jj_2_1121(2)) {
+    } else if (jj_2_1141(2)) {
       jj_consume_token(PRIOR);
-    } else if (jj_2_1122(2)) {
+    } else if (jj_2_1142(2)) {
       jj_consume_token(PUBLIC);
-    } else if (jj_2_1123(2)) {
+    } else if (jj_2_1143(2)) {
       jj_consume_token(READ);
-    } else if (jj_2_1124(2)) {
+    } else if (jj_2_1144(2)) {
       jj_consume_token(RECURSIVE);
-    } else if (jj_2_1125(2)) {
+    } else if (jj_2_1145(2)) {
       jj_consume_token(REFERENCING);
-    } else if (jj_2_1126(2)) {
+    } else if (jj_2_1146(2)) {
       jj_consume_token(REGR_COUNT);
-    } else if (jj_2_1127(2)) {
+    } else if (jj_2_1147(2)) {
       jj_consume_token(REGR_SLOPE);
-    } else if (jj_2_1128(2)) {
+    } else if (jj_2_1148(2)) {
       jj_consume_token(REGR_SYY);
-    } else if (jj_2_1129(2)) {
+    } else if (jj_2_1149(2)) {
       jj_consume_token(REPLACE);
-    } else if (jj_2_1130(2)) {
+    } else if (jj_2_1150(2)) {
       jj_consume_token(RESULT);
-    } else if (jj_2_1131(2)) {
+    } else if (jj_2_1151(2)) {
       jj_consume_token(REVOKE);
-    } else if (jj_2_1132(2)) {
+    } else if (jj_2_1152(2)) {
       jj_consume_token(ROUTINE);
-    } else if (jj_2_1133(2)) {
+    } else if (jj_2_1153(2)) {
       jj_consume_token(SAVEPOINT);
-    } else if (jj_2_1134(2)) {
+    } else if (jj_2_1154(2)) {
       jj_consume_token(SCROLL);
-    } else if (jj_2_1135(2)) {
+    } else if (jj_2_1155(2)) {
       jj_consume_token(SECTION);
-    } else if (jj_2_1136(2)) {
+    } else if (jj_2_1156(2)) {
       jj_consume_token(SESSION);
-    } else if (jj_2_1137(2)) {
+    } else if (jj_2_1157(2)) {
       jj_consume_token(SIMILAR);
-    } else if (jj_2_1138(2)) {
+    } else if (jj_2_1158(2)) {
       jj_consume_token(SPACE);
-    } else if (jj_2_1139(2)) {
+    } else if (jj_2_1159(2)) {
       jj_consume_token(SQL);
-    } else if (jj_2_1140(2)) {
+    } else if (jj_2_1160(2)) {
       jj_consume_token(SQLWARNING);
-    } else if (jj_2_1141(2)) {
+    } else if (jj_2_1161(2)) {
       jj_consume_token(STATE);
-    } else if (jj_2_1142(2)) {
+    } else if (jj_2_1162(2)) {
       jj_consume_token(STDDEV_SAMP);
-    } else if (jj_2_1143(2)) {
+    } else if (jj_2_1163(2)) {
       jj_consume_token(SUBSTRING);
-    } else if (jj_2_1144(2)) {
+    } else if (jj_2_1164(2)) {
       jj_consume_token(SUM);
-    } else if (jj_2_1145(2)) {
+    } else if (jj_2_1165(2)) {
       jj_consume_token(SYSTEM_TIME);
-    } else if (jj_2_1146(2)) {
+    } else if (jj_2_1166(2)) {
       jj_consume_token(GROUP_CONCAT);
-    } else if (jj_2_1147(2)) {
+    } else if (jj_2_1167(2)) {
       jj_consume_token(TIMEZONE_MINUTE);
-    } else if (jj_2_1148(2)) {
+    } else if (jj_2_1168(2)) {
       jj_consume_token(TRAILING);
-    } else if (jj_2_1149(2)) {
+    } else if (jj_2_1169(2)) {
       jj_consume_token(TRANSLATE_REGEX);
-    } else if (jj_2_1150(2)) {
+    } else if (jj_2_1170(2)) {
       jj_consume_token(TRIGGER);
-    } else if (jj_2_1151(2)) {
+    } else if (jj_2_1171(2)) {
       jj_consume_token(TRUE);
-    } else if (jj_2_1152(2)) {
+    } else if (jj_2_1172(2)) {
       jj_consume_token(UNDER);
-    } else if (jj_2_1153(2)) {
+    } else if (jj_2_1173(2)) {
       jj_consume_token(UPPER);
-    } else if (jj_2_1154(2)) {
+    } else if (jj_2_1174(2)) {
       jj_consume_token(USER);
-    } else if (jj_2_1155(2)) {
+    } else if (jj_2_1175(2)) {
       jj_consume_token(VARBINARY);
-    } else if (jj_2_1156(2)) {
+    } else if (jj_2_1176(2)) {
       jj_consume_token(VAR_POP);
-    } else if (jj_2_1157(2)) {
+    } else if (jj_2_1177(2)) {
       jj_consume_token(VERSIONING);
-    } else if (jj_2_1158(2)) {
+    } else if (jj_2_1178(2)) {
       jj_consume_token(WHENEVER);
-    } else if (jj_2_1159(2)) {
+    } else if (jj_2_1179(2)) {
       jj_consume_token(WITHOUT);
-    } else if (jj_2_1160(2)) {
+    } else if (jj_2_1180(2)) {
       jj_consume_token(YEAR);
     } else {
       jj_consume_token(-1);
@@ -9331,273 +9606,273 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
 /** @see #NonReservedKeyWord */
   final public void NonReservedKeyWord1of3() throws ParseException {
-    if (jj_2_1161(2)) {
+    if (jj_2_1181(2)) {
       jj_consume_token(TEMPLATE);
-    } else if (jj_2_1162(2)) {
+    } else if (jj_2_1182(2)) {
       jj_consume_token(ATOMICITY);
-    } else if (jj_2_1163(2)) {
+    } else if (jj_2_1183(2)) {
       jj_consume_token(CACHE_NAME);
-    } else if (jj_2_1164(2)) {
+    } else if (jj_2_1184(2)) {
       jj_consume_token(ENCRYPTED);
-    } else if (jj_2_1165(2)) {
+    } else if (jj_2_1185(2)) {
       jj_consume_token(LOGGING);
-    } else if (jj_2_1166(2)) {
+    } else if (jj_2_1186(2)) {
       jj_consume_token(KILL);
-    } else if (jj_2_1167(2)) {
+    } else if (jj_2_1187(2)) {
       jj_consume_token(SERVICE);
-    } else if (jj_2_1168(2)) {
+    } else if (jj_2_1188(2)) {
       jj_consume_token(QUERY);
-    } else if (jj_2_1169(2)) {
+    } else if (jj_2_1189(2)) {
       jj_consume_token(ANALYZE);
-    } else if (jj_2_1170(2)) {
+    } else if (jj_2_1190(2)) {
       jj_consume_token(A);
-    } else if (jj_2_1171(2)) {
+    } else if (jj_2_1191(2)) {
       jj_consume_token(ACTION);
-    } else if (jj_2_1172(2)) {
+    } else if (jj_2_1192(2)) {
       jj_consume_token(ALLOCATE);
-    } else if (jj_2_1173(2)) {
+    } else if (jj_2_1193(2)) {
       jj_consume_token(AND);
-    } else if (jj_2_1174(2)) {
+    } else if (jj_2_1194(2)) {
       jj_consume_token(ARRAY_AGG);
-    } else if (jj_2_1175(2)) {
+    } else if (jj_2_1195(2)) {
       jj_consume_token(AS);
-    } else if (jj_2_1176(2)) {
+    } else if (jj_2_1196(2)) {
       jj_consume_token(ASSERTION);
-    } else if (jj_2_1177(2)) {
+    } else if (jj_2_1197(2)) {
       jj_consume_token(ATOMIC);
-    } else if (jj_2_1178(2)) {
+    } else if (jj_2_1198(2)) {
       jj_consume_token(BEFORE);
-    } else if (jj_2_1179(2)) {
+    } else if (jj_2_1199(2)) {
       jj_consume_token(BEGIN_PARTITION);
-    } else if (jj_2_1180(2)) {
+    } else if (jj_2_1200(2)) {
       jj_consume_token(BINARY);
-    } else if (jj_2_1181(2)) {
+    } else if (jj_2_1201(2)) {
       jj_consume_token(BOOLEAN);
-    } else if (jj_2_1182(2)) {
+    } else if (jj_2_1202(2)) {
       jj_consume_token(BY);
-    } else if (jj_2_1183(2)) {
+    } else if (jj_2_1203(2)) {
       jj_consume_token(CARDINALITY);
-    } else if (jj_2_1184(2)) {
+    } else if (jj_2_1204(2)) {
       jj_consume_token(CAST);
-    } else if (jj_2_1185(2)) {
+    } else if (jj_2_1205(2)) {
       jj_consume_token(CEILING);
-    } else if (jj_2_1186(2)) {
+    } else if (jj_2_1206(2)) {
       jj_consume_token(CHARACTER_LENGTH);
-    } else if (jj_2_1187(2)) {
+    } else if (jj_2_1207(2)) {
       jj_consume_token(CLASSIFIER);
-    } else if (jj_2_1188(2)) {
+    } else if (jj_2_1208(2)) {
       jj_consume_token(COALESCE);
-    } else if (jj_2_1189(2)) {
+    } else if (jj_2_1209(2)) {
       jj_consume_token(COLLECT);
-    } else if (jj_2_1190(2)) {
+    } else if (jj_2_1210(2)) {
       jj_consume_token(CONDITION);
-    } else if (jj_2_1191(2)) {
+    } else if (jj_2_1211(2)) {
       jj_consume_token(CONSTRAINTS);
-    } else if (jj_2_1192(2)) {
+    } else if (jj_2_1212(2)) {
       jj_consume_token(CONTINUE);
-    } else if (jj_2_1193(2)) {
+    } else if (jj_2_1213(2)) {
       jj_consume_token(CORRESPONDING);
-    } else if (jj_2_1194(2)) {
+    } else if (jj_2_1214(2)) {
       jj_consume_token(COVAR_SAMP);
-    } else if (jj_2_1195(2)) {
+    } else if (jj_2_1215(2)) {
       jj_consume_token(CURRENT_CATALOG);
-    } else if (jj_2_1196(2)) {
+    } else if (jj_2_1216(2)) {
       jj_consume_token(CURRENT_PATH);
-    } else if (jj_2_1197(2)) {
+    } else if (jj_2_1217(2)) {
       jj_consume_token(CURRENT_SCHEMA);
-    } else if (jj_2_1198(2)) {
+    } else if (jj_2_1218(2)) {
       jj_consume_token(CURRENT_TRANSFORM_GROUP_FOR_TYPE);
-    } else if (jj_2_1199(2)) {
+    } else if (jj_2_1219(2)) {
       jj_consume_token(DATA);
-    } else if (jj_2_1200(2)) {
+    } else if (jj_2_1220(2)) {
       jj_consume_token(DEALLOCATE);
-    } else if (jj_2_1201(2)) {
+    } else if (jj_2_1221(2)) {
       jj_consume_token(DECLARE);
-    } else if (jj_2_1202(2)) {
+    } else if (jj_2_1222(2)) {
       jj_consume_token(DENSE_RANK);
-    } else if (jj_2_1203(2)) {
+    } else if (jj_2_1223(2)) {
       jj_consume_token(DESC);
-    } else if (jj_2_1204(2)) {
+    } else if (jj_2_1224(2)) {
       jj_consume_token(DIAGNOSTICS);
-    } else if (jj_2_1205(2)) {
+    } else if (jj_2_1225(2)) {
       jj_consume_token(DOMAIN);
-    } else if (jj_2_1206(2)) {
+    } else if (jj_2_1226(2)) {
       jj_consume_token(EACH);
-    } else if (jj_2_1207(2)) {
+    } else if (jj_2_1227(2)) {
       jj_consume_token(EMPTY);
-    } else if (jj_2_1208(2)) {
+    } else if (jj_2_1228(2)) {
       jj_consume_token(END_PARTITION);
-    } else if (jj_2_1209(2)) {
+    } else if (jj_2_1229(2)) {
       jj_consume_token(EVERY);
-    } else if (jj_2_1210(2)) {
+    } else if (jj_2_1230(2)) {
       jj_consume_token(EXECUTE);
-    } else if (jj_2_1211(2)) {
+    } else if (jj_2_1231(2)) {
       jj_consume_token(EXTEND);
-    } else if (jj_2_1212(2)) {
+    } else if (jj_2_1232(2)) {
       jj_consume_token(FALSE);
-    } else if (jj_2_1213(2)) {
+    } else if (jj_2_1233(2)) {
       jj_consume_token(FIRST_VALUE);
-    } else if (jj_2_1214(2)) {
+    } else if (jj_2_1234(2)) {
       jj_consume_token(FOR);
-    } else if (jj_2_1215(2)) {
+    } else if (jj_2_1235(2)) {
       jj_consume_token(FRAME_ROW);
-    } else if (jj_2_1216(2)) {
+    } else if (jj_2_1236(2)) {
       jj_consume_token(FUSION);
-    } else if (jj_2_1217(2)) {
+    } else if (jj_2_1237(2)) {
       jj_consume_token(GET);
-    } else if (jj_2_1218(2)) {
+    } else if (jj_2_1238(2)) {
       jj_consume_token(GOTO);
-    } else if (jj_2_1219(2)) {
+    } else if (jj_2_1239(2)) {
       jj_consume_token(HOUR);
-    } else if (jj_2_1220(2)) {
+    } else if (jj_2_1240(2)) {
       jj_consume_token(IMMEDIATELY);
-    } else if (jj_2_1221(2)) {
+    } else if (jj_2_1241(2)) {
       jj_consume_token(INITIAL);
-    } else if (jj_2_1222(2)) {
+    } else if (jj_2_1242(2)) {
       jj_consume_token(INPUT);
-    } else if (jj_2_1223(2)) {
+    } else if (jj_2_1243(2)) {
       jj_consume_token(INTEGER);
-    } else if (jj_2_1224(2)) {
+    } else if (jj_2_1244(2)) {
       jj_consume_token(ISOLATION);
-    } else if (jj_2_1225(2)) {
+    } else if (jj_2_1245(2)) {
       jj_consume_token(JSON_EXISTS);
-    } else if (jj_2_1226(2)) {
+    } else if (jj_2_1246(2)) {
       jj_consume_token(JSON_QUERY);
-    } else if (jj_2_1227(2)) {
+    } else if (jj_2_1247(2)) {
       jj_consume_token(KEY);
-    } else if (jj_2_1228(2)) {
+    } else if (jj_2_1248(2)) {
       jj_consume_token(LARGE);
-    } else if (jj_2_1229(2)) {
+    } else if (jj_2_1249(2)) {
       jj_consume_token(LEAD);
-    } else if (jj_2_1230(2)) {
+    } else if (jj_2_1250(2)) {
       jj_consume_token(LEVEL);
-    } else if (jj_2_1231(2)) {
+    } else if (jj_2_1251(2)) {
       jj_consume_token(LN);
-    } else if (jj_2_1232(2)) {
+    } else if (jj_2_1252(2)) {
       jj_consume_token(LOCALTIMESTAMP);
-    } else if (jj_2_1233(2)) {
+    } else if (jj_2_1253(2)) {
       jj_consume_token(M);
-    } else if (jj_2_1234(2)) {
+    } else if (jj_2_1254(2)) {
       jj_consume_token(MATCHES);
-    } else if (jj_2_1235(2)) {
+    } else if (jj_2_1255(2)) {
       jj_consume_token(MEASURES);
-    } else if (jj_2_1236(2)) {
+    } else if (jj_2_1256(2)) {
       jj_consume_token(MIN);
-    } else if (jj_2_1237(2)) {
+    } else if (jj_2_1257(2)) {
       jj_consume_token(MODIFIES);
-    } else if (jj_2_1238(2)) {
+    } else if (jj_2_1258(2)) {
       jj_consume_token(MULTISET);
-    } else if (jj_2_1239(2)) {
+    } else if (jj_2_1259(2)) {
       jj_consume_token(NATIONAL);
-    } else if (jj_2_1240(2)) {
+    } else if (jj_2_1260(2)) {
       jj_consume_token(NO);
-    } else if (jj_2_1241(2)) {
+    } else if (jj_2_1261(2)) {
       jj_consume_token(NOT);
-    } else if (jj_2_1242(2)) {
+    } else if (jj_2_1262(2)) {
       jj_consume_token(NULLIF);
-    } else if (jj_2_1243(2)) {
+    } else if (jj_2_1263(2)) {
       jj_consume_token(OCCURRENCES_REGEX);
-    } else if (jj_2_1244(2)) {
+    } else if (jj_2_1264(2)) {
       jj_consume_token(OLD);
-    } else if (jj_2_1245(2)) {
+    } else if (jj_2_1265(2)) {
       jj_consume_token(ONLY);
-    } else if (jj_2_1246(2)) {
+    } else if (jj_2_1266(2)) {
       jj_consume_token(OR);
-    } else if (jj_2_1247(2)) {
+    } else if (jj_2_1267(2)) {
       jj_consume_token(OUTPUT);
-    } else if (jj_2_1248(2)) {
+    } else if (jj_2_1268(2)) {
       jj_consume_token(PAD);
-    } else if (jj_2_1249(2)) {
+    } else if (jj_2_1269(2)) {
       jj_consume_token(PATH);
-    } else if (jj_2_1250(2)) {
+    } else if (jj_2_1270(2)) {
       jj_consume_token(PERCENTILE_CONT);
-    } else if (jj_2_1251(2)) {
+    } else if (jj_2_1271(2)) {
       jj_consume_token(PERIOD);
-    } else if (jj_2_1252(2)) {
+    } else if (jj_2_1272(2)) {
       jj_consume_token(POSITION);
-    } else if (jj_2_1253(2)) {
+    } else if (jj_2_1273(2)) {
       jj_consume_token(PRECEDES);
-    } else if (jj_2_1254(2)) {
+    } else if (jj_2_1274(2)) {
       jj_consume_token(PRESERVE);
-    } else if (jj_2_1255(2)) {
+    } else if (jj_2_1275(2)) {
       jj_consume_token(PRIVILEGES);
-    } else if (jj_2_1256(2)) {
+    } else if (jj_2_1276(2)) {
       jj_consume_token(QUARTER);
-    } else if (jj_2_1257(2)) {
+    } else if (jj_2_1277(2)) {
       jj_consume_token(READS);
-    } else if (jj_2_1258(2)) {
+    } else if (jj_2_1278(2)) {
       jj_consume_token(REF);
-    } else if (jj_2_1259(2)) {
+    } else if (jj_2_1279(2)) {
       jj_consume_token(REGR_AVGX);
-    } else if (jj_2_1260(2)) {
+    } else if (jj_2_1280(2)) {
       jj_consume_token(REGR_INTERCEPT);
-    } else if (jj_2_1261(2)) {
+    } else if (jj_2_1281(2)) {
       jj_consume_token(REGR_SXX);
-    } else if (jj_2_1262(2)) {
+    } else if (jj_2_1282(2)) {
       jj_consume_token(RELATIVE);
-    } else if (jj_2_1263(2)) {
+    } else if (jj_2_1283(2)) {
       jj_consume_token(RESET);
-    } else if (jj_2_1264(2)) {
+    } else if (jj_2_1284(2)) {
       jj_consume_token(RETURN);
-    } else if (jj_2_1265(2)) {
+    } else if (jj_2_1285(2)) {
       jj_consume_token(ROLE);
-    } else if (jj_2_1266(2)) {
+    } else if (jj_2_1286(2)) {
       jj_consume_token(ROW_NUMBER);
-    } else if (jj_2_1267(2)) {
+    } else if (jj_2_1287(2)) {
       jj_consume_token(SCHEMA);
-    } else if (jj_2_1268(2)) {
+    } else if (jj_2_1288(2)) {
       jj_consume_token(SEARCH);
-    } else if (jj_2_1269(2)) {
+    } else if (jj_2_1289(2)) {
       jj_consume_token(SEEK);
-    } else if (jj_2_1270(2)) {
+    } else if (jj_2_1290(2)) {
       jj_consume_token(SESSION_USER);
-    } else if (jj_2_1271(2)) {
+    } else if (jj_2_1291(2)) {
       jj_consume_token(SIZE);
-    } else if (jj_2_1272(2)) {
+    } else if (jj_2_1292(2)) {
       jj_consume_token(SPECIFIC);
-    } else if (jj_2_1273(2)) {
+    } else if (jj_2_1293(2)) {
       jj_consume_token(SQLEXCEPTION);
-    } else if (jj_2_1274(2)) {
+    } else if (jj_2_1294(2)) {
       jj_consume_token(SQRT);
-    } else if (jj_2_1275(2)) {
+    } else if (jj_2_1295(2)) {
       jj_consume_token(STATIC);
-    } else if (jj_2_1276(2)) {
+    } else if (jj_2_1296(2)) {
       jj_consume_token(SUBMULTISET);
-    } else if (jj_2_1277(2)) {
+    } else if (jj_2_1297(2)) {
       jj_consume_token(SUBSTRING_REGEX);
-    } else if (jj_2_1278(2)) {
+    } else if (jj_2_1298(2)) {
       jj_consume_token(SYMMETRIC);
-    } else if (jj_2_1279(2)) {
+    } else if (jj_2_1299(2)) {
       jj_consume_token(SYSTEM_USER);
-    } else if (jj_2_1280(2)) {
+    } else if (jj_2_1300(2)) {
       jj_consume_token(TEMPORARY);
-    } else if (jj_2_1281(2)) {
+    } else if (jj_2_1301(2)) {
       jj_consume_token(TINYINT);
-    } else if (jj_2_1282(2)) {
+    } else if (jj_2_1302(2)) {
       jj_consume_token(TRANSACTION);
-    } else if (jj_2_1283(2)) {
+    } else if (jj_2_1303(2)) {
       jj_consume_token(TRANSLATION);
-    } else if (jj_2_1284(2)) {
+    } else if (jj_2_1304(2)) {
       jj_consume_token(TRIM);
-    } else if (jj_2_1285(2)) {
+    } else if (jj_2_1305(2)) {
       jj_consume_token(TRUNCATE);
-    } else if (jj_2_1286(2)) {
+    } else if (jj_2_1306(2)) {
       jj_consume_token(UNIQUE);
-    } else if (jj_2_1287(2)) {
+    } else if (jj_2_1307(2)) {
       jj_consume_token(UPSERT);
-    } else if (jj_2_1288(2)) {
+    } else if (jj_2_1308(2)) {
       jj_consume_token(VALUE);
-    } else if (jj_2_1289(2)) {
+    } else if (jj_2_1309(2)) {
       jj_consume_token(VARCHAR);
-    } else if (jj_2_1290(2)) {
+    } else if (jj_2_1310(2)) {
       jj_consume_token(VAR_SAMP);
-    } else if (jj_2_1291(2)) {
+    } else if (jj_2_1311(2)) {
       jj_consume_token(VIEW);
-    } else if (jj_2_1292(2)) {
+    } else if (jj_2_1312(2)) {
       jj_consume_token(WIDTH_BUCKET);
-    } else if (jj_2_1293(2)) {
+    } else if (jj_2_1313(2)) {
       jj_consume_token(WORK);
-    } else if (jj_2_1294(2)) {
+    } else if (jj_2_1314(2)) {
       jj_consume_token(ZONE);
     } else {
       jj_consume_token(-1);
@@ -9607,271 +9882,271 @@ public class IgniteSqlParserImpl extends SqlAbstractParserImpl implements Ignite
 
 /** @see #NonReservedKeyWord */
   final public void NonReservedKeyWord2of3() throws ParseException {
-    if (jj_2_1295(2)) {
+    if (jj_2_1315(2)) {
       jj_consume_token(BACKUPS);
-    } else if (jj_2_1296(2)) {
+    } else if (jj_2_1316(2)) {
       jj_consume_token(WRITE_SYNCHRONIZATION_MODE);
-    } else if (jj_2_1297(2)) {
+    } else if (jj_2_1317(2)) {
       jj_consume_token(DATA_REGION);
-    } else if (jj_2_1298(2)) {
+    } else if (jj_2_1318(2)) {
       jj_consume_token(PARALLEL);
-    } else if (jj_2_1299(2)) {
+    } else if (jj_2_1319(2)) {
       jj_consume_token(NOLOGGING);
-    } else if (jj_2_1300(2)) {
+    } else if (jj_2_1320(2)) {
       jj_consume_token(SCAN);
-    } else if (jj_2_1301(2)) {
+    } else if (jj_2_1321(2)) {
       jj_consume_token(COMPUTE);
-    } else if (jj_2_1302(2)) {
+    } else if (jj_2_1322(2)) {
       jj_consume_token(STATISTICS);
-    } else if (jj_2_1303(2)) {
+    } else if (jj_2_1323(2)) {
       jj_consume_token(MAX_CHANGED_PARTITION_ROWS_PERCENT);
-    } else if (jj_2_1304(2)) {
+    } else if (jj_2_1324(2)) {
       jj_consume_token(ABS);
-    } else if (jj_2_1305(2)) {
+    } else if (jj_2_1325(2)) {
       jj_consume_token(ADD);
-    } else if (jj_2_1306(2)) {
+    } else if (jj_2_1326(2)) {
       jj_consume_token(ALLOW);
-    } else if (jj_2_1307(2)) {
+    } else if (jj_2_1327(2)) {
       jj_consume_token(ARE);
-    } else if (jj_2_1308(2)) {
+    } else if (jj_2_1328(2)) {
       jj_consume_token(ARRAY_CONCAT_AGG);
-    } else if (jj_2_1309(2)) {
+    } else if (jj_2_1329(2)) {
       jj_consume_token(ASC);
-    } else if (jj_2_1310(2)) {
+    } else if (jj_2_1330(2)) {
       jj_consume_token(ASYMMETRIC);
-    } else if (jj_2_1311(2)) {
+    } else if (jj_2_1331(2)) {
       jj_consume_token(AUTHORIZATION);
-    } else if (jj_2_1312(2)) {
+    } else if (jj_2_1332(2)) {
       jj_consume_token(BEGIN);
-    } else if (jj_2_1313(2)) {
+    } else if (jj_2_1333(2)) {
       jj_consume_token(BETWEEN);
-    } else if (jj_2_1314(2)) {
+    } else if (jj_2_1334(2)) {
       jj_consume_token(BIT);
-    } else if (jj_2_1315(2)) {
+    } else if (jj_2_1335(2)) {
       jj_consume_token(BOTH);
... 17406 lines suppressed ...