You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2018/12/06 01:18:47 UTC

[1/4] calcite git commit: [CALCITE-2726] ReduceExpressionRule oversimplifies filter conditions containing nulls [Forced Update!]

Repository: calcite
Updated Branches:
  refs/heads/branch-1.18 5f07b88df -> b3d144bdf (forced update)


[CALCITE-2726] ReduceExpressionRule oversimplifies filter conditions containing nulls

ReduceExpressionsRule might have simplified "(empno=null and mgr=1) is
null" to "false".

Add test case based on [HIVE-20617];
deprecate ExprSimplifier (Julian Hyde)

Close apache/calcite#956


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/4da9c0d9
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/4da9c0d9
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/4da9c0d9

Branch: refs/heads/branch-1.18
Commit: 4da9c0d94ee0e2a2f4d03845730ffc63a83a7cbd
Parents: efec74d
Author: Zoltan Haindrich <ki...@rxd.hu>
Authored: Wed Dec 5 16:32:50 2018 +0100
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Dec 5 16:18:19 2018 -0800

----------------------------------------------------------------------
 .../rel/rules/ReduceExpressionsRule.java        |  9 ++--
 .../org/apache/calcite/rex/RexSimplify.java     |  7 +--
 .../java/org/apache/calcite/rex/RexUtil.java    |  8 ++--
 .../apache/calcite/test/RelOptRulesTest.java    | 15 ++++++
 .../calcite/test/RexImplicationCheckerTest.java | 50 ++++++++++++--------
 .../org/apache/calcite/test/RelOptRulesTest.xml | 23 ++++++++-
 core/src/test/resources/sql/conditions.iq       | 13 +++++
 7 files changed, 93 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/4da9c0d9/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
index 50823f4..48ed3cd 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
@@ -54,7 +54,6 @@ import org.apache.calcite.rex.RexSimplify;
 import org.apache.calcite.rex.RexSubQuery;
 import org.apache.calcite.rex.RexUnknownAs;
 import org.apache.calcite.rex.RexUtil;
-import org.apache.calcite.rex.RexUtil.ExprSimplifier;
 import org.apache.calcite.rex.RexVisitorImpl;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlOperator;
@@ -539,14 +538,14 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
 
     // Simplify predicates in place
     final RexUnknownAs unknownAs = RexUnknownAs.falseIf(unknownAsFalse);
-    boolean reduced = reduceExpressionsInternal(rel, simplify, unknownAs,
+    final boolean reduced = reduceExpressionsInternal(rel, simplify, unknownAs,
         expList, predicates);
 
-    final ExprSimplifier simplifier =
-        new ExprSimplifier(simplify, unknownAs, matchNullability);
     boolean simplified = false;
     for (int i = 0; i < expList.size(); i++) {
-      RexNode expr2 = simplifier.apply(expList.get(i));
+      final RexNode expr2 =
+          simplify.simplifyPreservingType(expList.get(i), unknownAs,
+              matchNullability);
       if (!expr2.equals(expList.get(i))) {
         expList.set(i, expr2);
         simplified = true;

http://git-wip-us.apache.org/repos/asf/calcite/blob/4da9c0d9/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
index f78a90c..c7b6dac 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
@@ -164,15 +164,16 @@ public class RexSimplify {
    * <p>This is useful if you are simplifying expressions in a
    * {@link Project}. */
   public RexNode simplifyPreservingType(RexNode e) {
-    return simplifyPreservingType(e, defaultUnknownAs);
+    return simplifyPreservingType(e, defaultUnknownAs, true);
   }
 
-  private RexNode simplifyPreservingType(RexNode e, RexUnknownAs unknownAs) {
+  public RexNode simplifyPreservingType(RexNode e, RexUnknownAs unknownAs,
+      boolean matchNullability) {
     final RexNode e2 = simplifyUnknownAs(e, unknownAs);
     if (e2.getType() == e.getType()) {
       return e2;
     }
-    final RexNode e3 = rexBuilder.makeCast(e.getType(), e2, true);
+    final RexNode e3 = rexBuilder.makeCast(e.getType(), e2, matchNullability);
     if (e3.equals(e)) {
       return e;
     }

http://git-wip-us.apache.org/repos/asf/calcite/blob/4da9c0d9/core/src/main/java/org/apache/calcite/rex/RexUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexUtil.java b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
index 56eabb6..053d950 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
@@ -2607,7 +2607,11 @@ public class RexUtil {
     }
   }
 
-  /** Deep expressions simplifier. */
+  /** Deep expressions simplifier.
+   *
+   * <p>This class is broken because it does not change the value of
+   * {@link RexUnknownAs} as it recurses into an expression. Do not use. */
+  @Deprecated // to be removed before 2.0
   public static class ExprSimplifier extends RexShuttle {
     private final RexSimplify simplify;
     private final Map<RexNode, RexUnknownAs> unknownAsMap =
@@ -2615,12 +2619,10 @@ public class RexUtil {
     private final RexUnknownAs unknownAs;
     private final boolean matchNullability;
 
-    @Deprecated // to be removed before 2.0
     public ExprSimplifier(RexSimplify simplify) {
       this(simplify, RexUnknownAs.UNKNOWN, true);
     }
 
-    @Deprecated // to be removed before 2.0
     public ExprSimplifier(RexSimplify simplify, boolean matchNullability) {
       this(simplify, RexUnknownAs.UNKNOWN, matchNullability);
     }

http://git-wip-us.apache.org/repos/asf/calcite/blob/4da9c0d9/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
index 3db0ccc..ae82438 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -4208,6 +4208,21 @@ public class RelOptRulesTest extends RelOptTestBase {
         + "case when MGR > 0 then deptno / MGR else null end > 1";
     checkPlanning(program, sql);
   }
+
+  /** Test case for
+  * <a href="https://issues.apache.org/jira/browse/CALCITE-2726">[CALCITE-2726]
+  * ReduceExpressionRule may oversimplify filter conditions containing nulls</a>.
+  */
+  @Test public void testNoOversimplificationBelowIsNull() {
+    HepProgram program = new HepProgramBuilder()
+        .addRuleInstance(ReduceExpressionsRule.FILTER_INSTANCE)
+        .build();
+
+    String sql =
+        "select * from emp where ( (empno=1 and mgr=1) or (empno=null and mgr=1) ) is null";
+    checkPlanning(program, sql);
+  }
+
 }
 
 // End RelOptRulesTest.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/4da9c0d9/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java b/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java
index 207a819..2b9b57f 100644
--- a/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RexImplicationCheckerTest.java
@@ -34,7 +34,6 @@ import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexSimplify;
 import org.apache.calcite.rex.RexUnknownAs;
-import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.schema.SchemaPlus;
 import org.apache.calcite.schema.Schemas;
 import org.apache.calcite.server.CalciteServerStatement;
@@ -345,14 +344,11 @@ public class RexImplicationCheckerTest {
   /** Test case for
    * <a href="https://issues.apache.org/jira/browse/CALCITE-2041">[CALCITE-2041]
    * When simplifying a nullable expression, allow the result to change type to
-   * NOT NULL</a> and
-   * {@link org.apache.calcite.rex.RexUtil.ExprSimplifier#matchNullability}. */
+   * NOT NULL</a> and match nullability.
+   *
+   * @see RexSimplify#simplifyPreservingType(RexNode, RexUnknownAs, boolean) */
   @Test public void testSimplifyCastMatchNullability() {
     final Fixture f = new Fixture();
-    final RexUtil.ExprSimplifier defaultSimplifier =
-        new RexUtil.ExprSimplifier(f.simplify, RexUnknownAs.UNKNOWN, true);
-    final RexUtil.ExprSimplifier nonMatchingNullabilitySimplifier =
-        new RexUtil.ExprSimplifier(f.simplify, RexUnknownAs.UNKNOWN, false);
 
     // The cast is nullable, while the literal is not nullable. When we simplify
     // it, we end up with the literal. If defaultSimplifier is used, a CAST is
@@ -361,9 +357,13 @@ public class RexImplicationCheckerTest {
     // nonMatchingNullabilitySimplifier is used, the CAST is not added and the
     // simplified expression only consists of the literal.
     final RexNode e = f.cast(f.intRelDataType, f.literal(2014));
-    assertThat(defaultSimplifier.apply(e).toString(),
+    assertThat(
+        f.simplify.simplifyPreservingType(e, RexUnknownAs.UNKNOWN, true)
+            .toString(),
         is("CAST(2014):JavaType(class java.lang.Integer)"));
-    assertThat(nonMatchingNullabilitySimplifier.apply(e).toString(),
+    assertThat(
+        f.simplify.simplifyPreservingType(e, RexUnknownAs.UNKNOWN, false)
+            .toString(),
         is("2014"));
 
     // In this case, the cast is not nullable. Thus, in both cases, the
@@ -371,9 +371,13 @@ public class RexImplicationCheckerTest {
     RelDataType notNullIntRelDataType = f.typeFactory.createJavaType(int.class);
     final RexNode e2 = f.cast(notNullIntRelDataType,
         f.cast(notNullIntRelDataType, f.literal(2014)));
-    assertThat(defaultSimplifier.apply(e2).toString(),
+    assertThat(
+        f.simplify.simplifyPreservingType(e2, RexUnknownAs.UNKNOWN, true)
+            .toString(),
         is("2014"));
-    assertThat(nonMatchingNullabilitySimplifier.apply(e2).toString(),
+    assertThat(
+        f.simplify.simplifyPreservingType(e2, RexUnknownAs.UNKNOWN, false)
+            .toString(),
         is("2014"));
   }
 
@@ -385,8 +389,6 @@ public class RexImplicationCheckerTest {
     final ImmutableList<TimeUnitRange> timeUnitRanges =
         ImmutableList.of(TimeUnitRange.YEAR, TimeUnitRange.MONTH);
     final Fixture f = new Fixture();
-    final RexUtil.ExprSimplifier defaultSimplifier =
-        new RexUtil.ExprSimplifier(f.simplify, RexUnknownAs.UNKNOWN, true);
 
     final RexNode literalTs =
         f.timestampLiteral(new TimestampString("2010-10-10 00:00:00"));
@@ -404,12 +406,18 @@ public class RexImplicationCheckerTest {
         final RexNode outerCeilCall = f.rexBuilder.makeCall(
             SqlStdOperatorTable.CEIL, innerCeilCall,
             f.rexBuilder.makeFlag(timeUnitRanges.get(j)));
-        final RexCall floorSimplifiedExpr = (RexCall) defaultSimplifier.apply(outerFloorCall);
+        final RexCall floorSimplifiedExpr =
+            (RexCall) f.simplify.simplifyPreservingType(outerFloorCall,
+                RexUnknownAs.UNKNOWN, true);
         assertThat(floorSimplifiedExpr.getKind(), is(SqlKind.FLOOR));
-        assertThat(((RexLiteral) floorSimplifiedExpr.getOperands().get(1)).getValue().toString(),
+        assertThat(((RexLiteral) floorSimplifiedExpr.getOperands().get(1))
+                .getValue().toString(),
             is(timeUnitRanges.get(j).toString()));
-        assertThat(floorSimplifiedExpr.getOperands().get(0).toString(), is(literalTs.toString()));
-        final RexCall ceilSimplifiedExpr = (RexCall) defaultSimplifier.apply(outerCeilCall);
+        assertThat(floorSimplifiedExpr.getOperands().get(0).toString(),
+            is(literalTs.toString()));
+        final RexCall ceilSimplifiedExpr =
+            (RexCall) f.simplify.simplifyPreservingType(outerCeilCall,
+                RexUnknownAs.UNKNOWN, true);
         assertThat(ceilSimplifiedExpr.getKind(), is(SqlKind.CEIL));
         assertThat(((RexLiteral) ceilSimplifiedExpr.getOperands().get(1)).getValue().toString(),
             is(timeUnitRanges.get(j).toString()));
@@ -432,9 +440,13 @@ public class RexImplicationCheckerTest {
         final RexNode outerCeilCall = f.rexBuilder.makeCall(
             SqlStdOperatorTable.CEIL, innerCeilCall,
             f.rexBuilder.makeFlag(timeUnitRanges.get(j)));
-        final RexCall floorSimplifiedExpr = (RexCall) defaultSimplifier.apply(outerFloorCall);
+        final RexCall floorSimplifiedExpr =
+            (RexCall) f.simplify.simplifyPreservingType(outerFloorCall,
+                RexUnknownAs.UNKNOWN, true);
         assertThat(floorSimplifiedExpr.toString(), is(outerFloorCall.toString()));
-        final RexCall ceilSimplifiedExpr = (RexCall) defaultSimplifier.apply(outerCeilCall);
+        final RexCall ceilSimplifiedExpr =
+            (RexCall) f.simplify.simplifyPreservingType(outerCeilCall,
+                RexUnknownAs.UNKNOWN, true);
         assertThat(ceilSimplifiedExpr.toString(), is(outerCeilCall.toString()));
       }
     }

http://git-wip-us.apache.org/repos/asf/calcite/blob/4da9c0d9/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
index dd775ff..192e573 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -3114,6 +3114,25 @@ LogicalProject(EXPR$0=[CAST(/($2, $3)):INTEGER NOT NULL])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testNoOversimplificationBelowIsNull">
+        <Resource name="sql">
+            <![CDATA[select * from emp where ( (empno=1 and mgr=1) or (empno=null and mgr=1) ) is null]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
+  LogicalFilter(condition=[IS NULL(OR(AND(=($0, 1), =($3, 1)), AND(=($0, null), =($3, 1))))])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
+  LogicalFilter(condition=[IS NULL(OR(AND(=($0, 1), =($3, 1)), AND(null, =($3, 1))))])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testOrAlwaysTrue">
         <Resource name="sql">
             <![CDATA[select * from EMPNULLABLES_20
@@ -6855,7 +6874,7 @@ LogicalProject(NEWCOL=[+($0, CASE(=('a', 'a'), 1, null))])
         </Resource>
         <Resource name="planAfter">
             <![CDATA[
-LogicalProject(NEWCOL=[+($0, 1)])
+LogicalProject(NEWCOL=[+($0, CAST(1):INTEGER)])
   LogicalTableScan(table=[[CATALOG, SALES, EMP]])
 ]]>
         </Resource>
@@ -8705,7 +8724,7 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$
         <Resource name="planAfter">
             <![CDATA[
 LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
-  LogicalFilter(condition=[AND(>($3, 0), CASE(>($3, 0), >(/($7, $3), 1), false))])
+  LogicalFilter(condition=[AND(>($3, 0), CASE(>($3, 0), >(/($7, $3), 1), null))])
     LogicalTableScan(table=[[CATALOG, SALES, EMP]])
 ]]>
         </Resource>

http://git-wip-us.apache.org/repos/asf/calcite/blob/4da9c0d9/core/src/test/resources/sql/conditions.iq
----------------------------------------------------------------------
diff --git a/core/src/test/resources/sql/conditions.iq b/core/src/test/resources/sql/conditions.iq
index bc565af..70f7b76 100644
--- a/core/src/test/resources/sql/conditions.iq
+++ b/core/src/test/resources/sql/conditions.iq
@@ -258,4 +258,17 @@ select "value" from "nullables" a
 
 !ok
 
+# Test case for [CALCITE-2726] based on [HIVE-20617]
+with ax(s, t) as (values ('a','a'),('a','a '),('b','bb'))
+select 'expected 1' as e,count(*) as c
+from ax where ((s,t) in (('a','a'),(null, 'bb'))) is null;
++------------+---+
+| E          | C |
++------------+---+
+| expected 1 | 1 |
++------------+---+
+(1 row)
+
+!ok
+
 # End conditions.iq


[3/4] calcite git commit: [CALCITE-2670] Combine similar JSON aggregate functions in operator table

Posted by jh...@apache.org.
[CALCITE-2670] Combine similar JSON aggregate functions in operator table

Convert parameters from Enum to more specific types;
include varying flag values in JSON aggregate functions.

Some cosmetic stuff.

Close apache/calcite#916


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/f3655e15
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/f3655e15
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/f3655e15

Branch: refs/heads/branch-1.18
Commit: f3655e15a11a9fb266af290cb390e690d4301c09
Parents: 40d12b7
Author: hongzezhang <ho...@tencent.com>
Authored: Wed Nov 14 19:48:49 2018 +0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Dec 5 16:59:02 2018 -0800

----------------------------------------------------------------------
 core/src/main/codegen/templates/Parser.jj       |  26 ++---
 .../calcite/adapter/enumerable/RexImpTable.java |  34 +++---
 .../calcite/jdbc/JavaTypeFactoryImpl.java       |   2 +
 .../apache/calcite/rel/core/AggregateCall.java  |   2 +-
 .../apache/calcite/runtime/SqlFunctions.java    |  18 +---
 .../sql/SqlJsonConstructorNullClause.java       |   9 +-
 .../apache/calcite/sql/SqlJsonEmptyOrError.java |   5 +-
 .../calcite/sql/SqlJsonExistsErrorBehavior.java |   5 +-
 .../sql/SqlJsonQueryEmptyOrErrorBehavior.java   |   2 +-
 .../sql/SqlJsonValueEmptyOrErrorBehavior.java   |   2 +-
 .../calcite/sql/dialect/MssqlSqlDialect.java    |   4 +-
 .../sql/fun/SqlJsonArrayAggAggFunction.java     |  51 ++++++---
 .../calcite/sql/fun/SqlJsonArrayFunction.java   |   2 +-
 .../sql/fun/SqlJsonObjectAggAggFunction.java    |  47 +++++---
 .../calcite/sql/fun/SqlJsonObjectFunction.java  |   2 +-
 .../calcite/sql/fun/SqlStdOperatorTable.java    |  16 +--
 .../org/apache/calcite/util/BuiltInMethod.java  |  21 ++--
 .../calcite/test/SqlToRelConverterTest.java     |  58 ++++++++++
 .../calcite/test/SqlToRelConverterTest.xml      | 108 +++++++++++++++++++
 core/src/test/resources/sql/misc.iq             |   6 ++
 .../java/org/apache/calcite/test/CsvTest.java   |   8 +-
 21 files changed, 304 insertions(+), 124 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/codegen/templates/Parser.jj
----------------------------------------------------------------------
diff --git a/core/src/main/codegen/templates/Parser.jj b/core/src/main/codegen/templates/Parser.jj
index cf6b3f2..6cecc56 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -5267,14 +5267,8 @@ SqlCall JsonObjectAggFunctionCall() :
         }
     ]
     <RPAREN> {
-        switch (nullClause) {
-        case ABSENT_ON_NULL:
-          return SqlStdOperatorTable.JSON_OBJECTAGG_ABSENT_ON_NULL.createCall(span.end(this), args);
-        case NULL_ON_NULL:
-          return SqlStdOperatorTable.JSON_OBJECTAGG_NULL_ON_NULL.createCall(span.end(this), args);
-        default:
-          return SqlStdOperatorTable.JSON_OBJECTAGG_NULL_ON_NULL.createCall(span.end(this), args);
-        }
+        return SqlStdOperatorTable.JSON_OBJECTAGG.with(nullClause)
+            .createCall(span.end(this), args);
     }
 }
 
@@ -5313,7 +5307,7 @@ SqlCall JsonArrayFunctionCall() :
 
 SqlCall JsonArrayAggFunctionCall() :
 {
-    final SqlNode arg;
+    final SqlNode[] args = new SqlNode[1];
     List<SqlNode> list;
     final Span span;
     SqlJsonConstructorNullClause nullClause =
@@ -5322,21 +5316,17 @@ SqlCall JsonArrayAggFunctionCall() :
 }
 {
     <JSON_ARRAYAGG> { span = span(); }
-    <LPAREN> arg = JsonValueExpression(false)
+    <LPAREN> e = JsonValueExpression(false) {
+        args[0] = e;
+    }
     [
         e = JsonConstructorNullClause() {
             nullClause = (SqlJsonConstructorNullClause) ((SqlLiteral) e).getValue();
         }
     ]
     <RPAREN> {
-        switch (nullClause) {
-        case ABSENT_ON_NULL:
-          return SqlStdOperatorTable.JSON_ARRAYAGG_ABSENT_ON_NULL.createCall(span.end(this), arg);
-        case NULL_ON_NULL:
-          return SqlStdOperatorTable.JSON_ARRAYAGG_NULL_ON_NULL.createCall(span.end(this), arg);
-        default:
-          return SqlStdOperatorTable.JSON_ARRAYAGG_ABSENT_ON_NULL.createCall(span.end(this), arg);
-        }
+        return SqlStdOperatorTable.JSON_ARRAYAGG.with(nullClause)
+            .createCall(span.end(this), args);
     }
 }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index 7776ac9..dd117ee 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -45,6 +45,8 @@ import org.apache.calcite.schema.impl.AggregateFunctionImpl;
 import org.apache.calcite.sql.SqlAggFunction;
 import org.apache.calcite.sql.SqlBinaryOperator;
 import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.fun.SqlJsonArrayAggAggFunction;
+import org.apache.calcite.sql.fun.SqlJsonObjectAggAggFunction;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.fun.SqlTrimFunction;
 import org.apache.calcite.sql.type.SqlTypeName;
@@ -157,12 +159,10 @@ import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_TRUE;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.ITEM;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_API_COMMON_SYNTAX;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_ARRAY;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_ARRAYAGG_ABSENT_ON_NULL;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_ARRAYAGG_NULL_ON_NULL;
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_ARRAYAGG;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_EXISTS;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_OBJECT;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_OBJECTAGG_ABSENT_ON_NULL;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_OBJECTAGG_NULL_ON_NULL;
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_OBJECTAGG;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_QUERY;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_STRUCTURED_VALUE_EXPRESSION;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_VALUE_ANY;
@@ -448,19 +448,13 @@ public class RexImpTable {
     defineMethod(JSON_VALUE_ANY, BuiltInMethod.JSON_VALUE_ANY.method, NullPolicy.NONE);
     defineMethod(JSON_QUERY, BuiltInMethod.JSON_QUERY.method, NullPolicy.NONE);
     defineMethod(JSON_OBJECT, BuiltInMethod.JSON_OBJECT.method, NullPolicy.NONE);
-    aggMap.put(JSON_OBJECTAGG_NULL_ON_NULL,
+    aggMap.put(JSON_OBJECTAGG,
         JsonObjectAggImplementor
-            .supplierFor(BuiltInMethod.JSON_OBJECTAGG_ADD_NULL_ON_NULL.method));
-    aggMap.put(JSON_OBJECTAGG_ABSENT_ON_NULL,
-        JsonObjectAggImplementor
-            .supplierFor(BuiltInMethod.JSON_OBJECTAGG_ADD_ABSENT_ON_NULL.method));
+            .supplierFor(BuiltInMethod.JSON_OBJECTAGG_ADD.method));
     defineMethod(JSON_ARRAY, BuiltInMethod.JSON_ARRAY.method, NullPolicy.NONE);
-    aggMap.put(JSON_ARRAYAGG_NULL_ON_NULL,
-        JsonArrayAggImplementor
-            .supplierFor(BuiltInMethod.JSON_ARRAYAGG_ADD_NULL_ON_NULL.method));
-    aggMap.put(JSON_ARRAYAGG_ABSENT_ON_NULL,
+    aggMap.put(JSON_ARRAYAGG,
         JsonArrayAggImplementor
-            .supplierFor(BuiltInMethod.JSON_ARRAYAGG_ADD_ABSENT_ON_NULL.method));
+            .supplierFor(BuiltInMethod.JSON_ARRAYAGG_ADD.method));
     defineImplementor(IS_JSON_VALUE, NullPolicy.NONE,
             new MethodImplementor(BuiltInMethod.IS_JSON_VALUE.method), false);
     defineImplementor(IS_JSON_OBJECT, NullPolicy.NONE,
@@ -1813,12 +1807,16 @@ public class RexImpTable {
     }
 
     @Override public void implementAdd(AggContext info, AggAddContext add) {
+      final SqlJsonObjectAggAggFunction function =
+          (SqlJsonObjectAggAggFunction) info.aggregation();
       add.currentBlock().add(
           Expressions.statement(
               Expressions.call(m,
                   Iterables.concat(
                       Collections.singletonList(add.accumulator().get(0)),
-                      add.arguments()))));
+                      add.arguments(),
+                      Collections.singletonList(
+                          Expressions.constant(function.getNullClause()))))));
     }
 
     @Override public Expression implementResult(AggContext info,
@@ -1854,12 +1852,16 @@ public class RexImpTable {
 
     @Override public void implementAdd(AggContext info,
         AggAddContext add) {
+      final SqlJsonArrayAggAggFunction function =
+          (SqlJsonArrayAggAggFunction) info.aggregation();
       add.currentBlock().add(
           Expressions.statement(
               Expressions.call(m,
                   Iterables.concat(
                       Collections.singletonList(add.accumulator().get(0)),
-                      add.arguments()))));
+                      add.arguments(),
+                      Collections.singletonList(
+                          Expressions.constant(function.getNullClause()))))));
     }
 
     @Override public Expression implementResult(AggContext info,

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java b/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java
index 59805fe..08a7aa8 100644
--- a/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java
+++ b/core/src/main/java/org/apache/calcite/jdbc/JavaTypeFactoryImpl.java
@@ -213,6 +213,8 @@ public class JavaTypeFactoryImpl
         return ByteString.class;
       case GEOMETRY:
         return GeoFunctions.Geom.class;
+      case SYMBOL:
+        return Enum.class;
       case ANY:
         return Object.class;
       }

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java b/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java
index fb32cbc..d612ea4 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/AggregateCall.java
@@ -254,7 +254,7 @@ public class AggregateCall {
   }
 
   public String toString() {
-    StringBuilder buf = new StringBuilder(aggFunction.getName());
+    StringBuilder buf = new StringBuilder(aggFunction.toString());
     buf.append("(");
     if (distinct) {
       buf.append((argList.size() == 0) ? "DISTINCT" : "DISTINCT ");

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
index af008fb..7644d0a 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -2409,7 +2409,7 @@ public class SqlFunctions {
       if (!matcher.matches()) {
         throw RESOURCE.illegalJsonPathSpec(pathSpec).ex();
       }
-      PathMode mode = PathMode.valueOf(matcher.group(1).toUpperCase(Locale.ENGLISH));
+      PathMode mode = PathMode.valueOf(matcher.group(1).toUpperCase(Locale.ROOT));
       String pathWff = matcher.group(2);
       DocumentContext ctx;
       switch (mode) {
@@ -2636,14 +2636,6 @@ public class SqlFunctions {
     }
   }
 
-  public static void jsonObjectAggAddNullOnNull(Map map, String k, Object v) {
-    jsonObjectAggAdd(map, k, v, SqlJsonConstructorNullClause.NULL_ON_NULL);
-  }
-
-  public static void jsonObjectAggAddAbsentOnNull(Map map, String k, Object v) {
-    jsonObjectAggAdd(map, k, v, SqlJsonConstructorNullClause.ABSENT_ON_NULL);
-  }
-
   public static String jsonArray(SqlJsonConstructorNullClause nullClause,
       Object... elements) {
     List<Object> list = new ArrayList<>();
@@ -2670,14 +2662,6 @@ public class SqlFunctions {
     }
   }
 
-  public static void jsonArrayAggAddNullOnNull(List list, Object element) {
-    jsonArrayAggAdd(list, element, SqlJsonConstructorNullClause.NULL_ON_NULL);
-  }
-
-  public static void jsonArrayAggAddAbsentOnNull(List list, Object element) {
-    jsonArrayAggAdd(list, element, SqlJsonConstructorNullClause.ABSENT_ON_NULL);
-  }
-
   public static boolean isJsonValue(String input) {
     try {
       dejsonize(input);

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/sql/SqlJsonConstructorNullClause.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlJsonConstructorNullClause.java b/core/src/main/java/org/apache/calcite/sql/SqlJsonConstructorNullClause.java
index a4a94b8..ef660fa 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlJsonConstructorNullClause.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlJsonConstructorNullClause.java
@@ -20,7 +20,14 @@ package org.apache.calcite.sql;
  * Indicating that how do Json constructors handle null
  */
 public enum SqlJsonConstructorNullClause {
-  NULL_ON_NULL, ABSENT_ON_NULL
+  NULL_ON_NULL("NULL ON NULL"),
+  ABSENT_ON_NULL("ABSENT ON NULL");
+
+  public final String sql;
+
+  SqlJsonConstructorNullClause(String sql) {
+    this.sql = sql;
+  }
 }
 
 // End SqlJsonConstructorNullClause.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/sql/SqlJsonEmptyOrError.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlJsonEmptyOrError.java b/core/src/main/java/org/apache/calcite/sql/SqlJsonEmptyOrError.java
index 82491cd..07d847a 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlJsonEmptyOrError.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlJsonEmptyOrError.java
@@ -23,10 +23,11 @@ import java.util.Locale;
  * EmptyOrErrorBehavior is invoked.
  */
 public enum SqlJsonEmptyOrError {
-  EMPTY, ERROR;
+  EMPTY,
+  ERROR;
 
   @Override public String toString() {
-    return String.format(Locale.ENGLISH, "SqlJsonEmptyOrError[%s]", name());
+    return String.format(Locale.ROOT, "SqlJsonEmptyOrError[%s]", name());
   }
 }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/sql/SqlJsonExistsErrorBehavior.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlJsonExistsErrorBehavior.java b/core/src/main/java/org/apache/calcite/sql/SqlJsonExistsErrorBehavior.java
index 4da8a4f..1f9e9d8 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlJsonExistsErrorBehavior.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlJsonExistsErrorBehavior.java
@@ -20,7 +20,10 @@ package org.apache.calcite.sql;
  * Categorizing Json exists error behaviors.
  */
 public enum SqlJsonExistsErrorBehavior {
-  TRUE, FALSE, UNKNOWN, ERROR
+  TRUE,
+  FALSE,
+  UNKNOWN,
+  ERROR
 }
 
 // End SqlJsonExistsErrorBehavior.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/sql/SqlJsonQueryEmptyOrErrorBehavior.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlJsonQueryEmptyOrErrorBehavior.java b/core/src/main/java/org/apache/calcite/sql/SqlJsonQueryEmptyOrErrorBehavior.java
index 2dd2e34..1893552 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlJsonQueryEmptyOrErrorBehavior.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlJsonQueryEmptyOrErrorBehavior.java
@@ -28,7 +28,7 @@ public enum SqlJsonQueryEmptyOrErrorBehavior {
   EMPTY_OBJECT;
 
   @Override public String toString() {
-    return String.format(Locale.ENGLISH,
+    return String.format(Locale.ROOT,
         "SqlJsonQueryEmptyOrErrorBehavior[%s]", name());
   }
 }

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/sql/SqlJsonValueEmptyOrErrorBehavior.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlJsonValueEmptyOrErrorBehavior.java b/core/src/main/java/org/apache/calcite/sql/SqlJsonValueEmptyOrErrorBehavior.java
index cb39279..0650fb7 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlJsonValueEmptyOrErrorBehavior.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlJsonValueEmptyOrErrorBehavior.java
@@ -27,7 +27,7 @@ public enum SqlJsonValueEmptyOrErrorBehavior {
   DEFAULT;
 
   @Override public String toString() {
-    return String.format(Locale.ENGLISH,
+    return String.format(Locale.ROOT,
         "SqlJsonValueEmptyOrErrorBehavior[%s]", name());
   }
 }

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java
index 644a39b..89de617 100644
--- a/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java
@@ -180,8 +180,8 @@ public class MssqlSqlDialect extends SqlDialect {
 
   private void unparseSqlIntervalLiteralMssql(
       SqlWriter writer, SqlIntervalLiteral literal, int sign) {
-    SqlIntervalLiteral.IntervalValue interval
-        = (SqlIntervalLiteral.IntervalValue) literal.getValue();
+    final SqlIntervalLiteral.IntervalValue interval =
+        (SqlIntervalLiteral.IntervalValue) literal.getValue();
     unparseSqlIntervalQualifier(writer, interval.getIntervalQualifier(),
         RelDataTypeSystem.DEFAULT);
     writer.sep(",", true);

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonArrayAggAggFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonArrayAggAggFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonArrayAggAggFunction.java
index 4791e67..a5d1520 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonArrayAggAggFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonArrayAggAggFunction.java
@@ -16,20 +16,27 @@
  */
 package org.apache.calcite.sql.fun;
 
+import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.sql.SqlAggFunction;
 import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlFunctionCategory;
 import org.apache.calcite.sql.SqlJsonConstructorNullClause;
 import org.apache.calcite.sql.SqlKind;
-import org.apache.calcite.sql.SqlLiteral;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlWriter;
 import org.apache.calcite.sql.type.OperandTypes;
 import org.apache.calcite.sql.type.ReturnTypes;
+import org.apache.calcite.sql.type.SqlTypeFamily;
+import org.apache.calcite.sql.validate.SqlValidator;
+import org.apache.calcite.sql.validate.SqlValidatorImpl;
+import org.apache.calcite.sql.validate.SqlValidatorScope;
 import org.apache.calcite.util.Optionality;
 
+import java.util.Locale;
+import java.util.Objects;
+
 /**
- * The <code>JSON_OBJECTAGG</code> aggregation function.
+ * The <code>JSON_OBJECTAGG</code> aggregate function.
  */
 public class SqlJsonArrayAggAggFunction extends SqlAggFunction {
   private final SqlJsonConstructorNullClause nullClause;
@@ -37,9 +44,9 @@ public class SqlJsonArrayAggAggFunction extends SqlAggFunction {
   public SqlJsonArrayAggAggFunction(String name,
       SqlJsonConstructorNullClause nullClause) {
     super(name, null, SqlKind.JSON_ARRAYAGG, ReturnTypes.VARCHAR_2000, null,
-        OperandTypes.ANY, SqlFunctionCategory.SYSTEM, false, false,
-        Optionality.FORBIDDEN);
-    this.nullClause = nullClause;
+        OperandTypes.family(SqlTypeFamily.ANY), SqlFunctionCategory.SYSTEM,
+        false, false, Optionality.FORBIDDEN);
+    this.nullClause = Objects.requireNonNull(nullClause);
   }
 
   @Override public void unparse(SqlWriter writer, SqlCall call, int leftPrec,
@@ -47,21 +54,31 @@ public class SqlJsonArrayAggAggFunction extends SqlAggFunction {
     assert call.operandCount() == 1;
     final SqlWriter.Frame frame = writer.startFunCall("JSON_ARRAYAGG");
     call.operand(0).unparse(writer, leftPrec, rightPrec);
-    switch (nullClause) {
-    case ABSENT_ON_NULL:
-      writer.keyword("ABSENT ON NULL");
-      break;
-    case NULL_ON_NULL:
-      writer.keyword("NULL ON NULL");
-      break;
-    default:
-      throw new IllegalStateException("unreachable code");
-    }
+    writer.keyword(nullClause.sql);
     writer.endFunCall(frame);
   }
 
-  private <E extends Enum<E>> E getEnumValue(SqlNode operand) {
-    return (E) ((SqlLiteral) operand).getValue();
+  @Override public RelDataType deriveType(SqlValidator validator,
+      SqlValidatorScope scope, SqlCall call) {
+    // To prevent operator rewriting by SqlFunction#deriveType.
+    for (SqlNode operand : call.getOperandList()) {
+      RelDataType nodeType = validator.deriveType(scope, operand);
+      ((SqlValidatorImpl) validator).setValidatedNodeType(operand, nodeType);
+    }
+    return validateOperands(validator, scope, call);
+  }
+
+  @Override public String toString() {
+    return getName() + String.format(Locale.ROOT, "<%s>", nullClause);
+  }
+
+  public SqlJsonArrayAggAggFunction with(SqlJsonConstructorNullClause nullClause) {
+    return this.nullClause == nullClause ? this
+        : new SqlJsonArrayAggAggFunction(getName(), nullClause);
+  }
+
+  public SqlJsonConstructorNullClause getNullClause() {
+    return nullClause;
   }
 }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonArrayFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonArrayFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonArrayFunction.java
index 0306654..29ae0f8 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonArrayFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonArrayFunction.java
@@ -67,7 +67,7 @@ public class SqlJsonArrayFunction extends SqlFunction {
     final StringBuilder sb = new StringBuilder();
     sb.append("{0}(");
     for (int i = 1; i < operandsCount; i++) {
-      sb.append(String.format(Locale.ENGLISH, "{%d} ", i + 1));
+      sb.append(String.format(Locale.ROOT, "{%d} ", i + 1));
     }
     sb.append("{1})");
     return sb.toString();

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonObjectAggAggFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonObjectAggAggFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonObjectAggAggFunction.java
index 4b50c5c..d8b85c7 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonObjectAggAggFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonObjectAggAggFunction.java
@@ -16,31 +16,38 @@
  */
 package org.apache.calcite.sql.fun;
 
+import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.sql.SqlAggFunction;
 import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlFunctionCategory;
 import org.apache.calcite.sql.SqlJsonConstructorNullClause;
 import org.apache.calcite.sql.SqlKind;
-import org.apache.calcite.sql.SqlLiteral;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlWriter;
 import org.apache.calcite.sql.type.OperandTypes;
 import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.sql.type.SqlTypeFamily;
+import org.apache.calcite.sql.validate.SqlValidator;
+import org.apache.calcite.sql.validate.SqlValidatorImpl;
+import org.apache.calcite.sql.validate.SqlValidatorScope;
 import org.apache.calcite.util.Optionality;
 
+import java.util.Locale;
+import java.util.Objects;
+
 /**
- * The <code>JSON_OBJECTAGG</code> aggregation function.
+ * The <code>JSON_OBJECTAGG</code> aggregate function.
  */
 public class SqlJsonObjectAggAggFunction extends SqlAggFunction {
   private final SqlJsonConstructorNullClause nullClause;
 
+  /** Creates a SqlJsonObjectAggAggFunction. */
   public SqlJsonObjectAggAggFunction(String name,
       SqlJsonConstructorNullClause nullClause) {
     super(name, null, SqlKind.JSON_OBJECTAGG, ReturnTypes.VARCHAR_2000, null,
         OperandTypes.family(SqlTypeFamily.CHARACTER, SqlTypeFamily.ANY),
         SqlFunctionCategory.SYSTEM, false, false, Optionality.FORBIDDEN);
-    this.nullClause = nullClause;
+    this.nullClause = Objects.requireNonNull(nullClause);
   }
 
   @Override public void unparse(SqlWriter writer, SqlCall call, int leftPrec,
@@ -51,21 +58,31 @@ public class SqlJsonObjectAggAggFunction extends SqlAggFunction {
     call.operand(0).unparse(writer, leftPrec, rightPrec);
     writer.keyword("VALUE");
     call.operand(1).unparse(writer, leftPrec, rightPrec);
-    switch (nullClause) {
-    case ABSENT_ON_NULL:
-      writer.keyword("ABSENT ON NULL");
-      break;
-    case NULL_ON_NULL:
-      writer.keyword("NULL ON NULL");
-      break;
-    default:
-      throw new IllegalStateException("unreachable code");
-    }
+    writer.keyword(nullClause.sql);
     writer.endFunCall(frame);
   }
 
-  private <E extends Enum<E>> E getEnumValue(SqlNode operand) {
-    return (E) ((SqlLiteral) operand).getValue();
+  @Override public RelDataType deriveType(SqlValidator validator,
+      SqlValidatorScope scope, SqlCall call) {
+    // To prevent operator rewriting by SqlFunction#deriveType.
+    for (SqlNode operand : call.getOperandList()) {
+      RelDataType nodeType = validator.deriveType(scope, operand);
+      ((SqlValidatorImpl) validator).setValidatedNodeType(operand, nodeType);
+    }
+    return validateOperands(validator, scope, call);
+  }
+
+  @Override public String toString() {
+    return getName() + String.format(Locale.ROOT, "<%s>", nullClause);
+  }
+
+  public SqlJsonObjectAggAggFunction with(SqlJsonConstructorNullClause nullClause) {
+    return this.nullClause == nullClause ? this
+        : new SqlJsonObjectAggAggFunction(getName(), nullClause);
+  }
+
+  public SqlJsonConstructorNullClause getNullClause() {
+    return nullClause;
   }
 }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonObjectFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonObjectFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonObjectFunction.java
index 771c823..0240532 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonObjectFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonObjectFunction.java
@@ -93,7 +93,7 @@ public class SqlJsonObjectFunction extends SqlFunction {
     StringBuilder sb = new StringBuilder();
     sb.append("{0}(");
     for (int i = 1; i < operandsCount; i++) {
-      sb.append(String.format(Locale.ENGLISH, "{%d} ", i + 1));
+      sb.append(String.format(Locale.ROOT, "{%d} ", i + 1));
     }
     sb.append("{1})");
     return sb.toString();

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
index 03d4336..6c3c596 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
@@ -1291,24 +1291,16 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
 
   public static final SqlFunction JSON_OBJECT = new SqlJsonObjectFunction();
 
-  public static final SqlAggFunction JSON_OBJECTAGG_NULL_ON_NULL =
-      new SqlJsonObjectAggAggFunction("JSON_OBJECTAGG_NULL_ON_NULL",
+  public static final SqlJsonObjectAggAggFunction JSON_OBJECTAGG =
+      new SqlJsonObjectAggAggFunction("JSON_OBJECTAGG",
           SqlJsonConstructorNullClause.NULL_ON_NULL);
 
-  public static final SqlAggFunction JSON_OBJECTAGG_ABSENT_ON_NULL =
-      new SqlJsonObjectAggAggFunction("JSON_OBJECTAGG_ABSENT_ON_NULL",
-          SqlJsonConstructorNullClause.ABSENT_ON_NULL);
-
   public static final SqlFunction JSON_ARRAY = new SqlJsonArrayFunction();
 
-  public static final SqlAggFunction JSON_ARRAYAGG_NULL_ON_NULL =
-      new SqlJsonArrayAggAggFunction("JSON_ARRAYAGG_NULL_ON_NULL",
+  public static final SqlJsonArrayAggAggFunction JSON_ARRAYAGG =
+      new SqlJsonArrayAggAggFunction("JSON_ARRAYAGG",
           SqlJsonConstructorNullClause.NULL_ON_NULL);
 
-  public static final SqlAggFunction JSON_ARRAYAGG_ABSENT_ON_NULL =
-      new SqlJsonArrayAggAggFunction("JSON_ARRAYAGG_ABSENT_ON_NULL",
-          SqlJsonConstructorNullClause.ABSENT_ON_NULL);
-
   public static final SqlBetweenOperator BETWEEN =
       new SqlBetweenOperator(
           SqlBetweenOperator.Flag.ASYMMETRIC,

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
index 8160ead..f23a931 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -272,27 +272,20 @@ public enum BuiltInMethod {
       Object.class, String.class),
   JSON_EXISTS(SqlFunctions.class, "jsonExists", Object.class),
   JSON_VALUE_ANY(SqlFunctions.class, "jsonValueAny", Object.class,
-      SqlJsonValueEmptyOrErrorBehavior.class,
-      Object.class,
-      SqlJsonValueEmptyOrErrorBehavior.class,
-      Object.class),
-  JSON_QUERY(SqlFunctions.class, "jsonQuery",
-      Object.class,
+      SqlJsonValueEmptyOrErrorBehavior.class, Object.class,
+      SqlJsonValueEmptyOrErrorBehavior.class, Object.class),
+  JSON_QUERY(SqlFunctions.class, "jsonQuery", Object.class,
       SqlJsonQueryWrapperBehavior.class,
       SqlJsonQueryEmptyOrErrorBehavior.class,
       SqlJsonQueryEmptyOrErrorBehavior.class),
   JSON_OBJECT(SqlFunctions.class, "jsonObject",
       SqlJsonConstructorNullClause.class),
-  JSON_OBJECTAGG_ADD_NULL_ON_NULL(SqlFunctions.class,
-      "jsonObjectAggAddNullOnNull", Map.class, String.class, Object.class),
-  JSON_OBJECTAGG_ADD_ABSENT_ON_NULL(SqlFunctions.class,
-      "jsonObjectAggAddAbsentOnNull", Map.class, String.class, Object.class),
+  JSON_OBJECTAGG_ADD(SqlFunctions.class, "jsonObjectAggAdd", Map.class,
+      String.class, Object.class, SqlJsonConstructorNullClause.class),
   JSON_ARRAY(SqlFunctions.class, "jsonArray",
       SqlJsonConstructorNullClause.class),
-  JSON_ARRAYAGG_ADD_NULL_ON_NULL(SqlFunctions.class,
-      "jsonArrayAggAddNullOnNull", List.class, Object.class),
-  JSON_ARRAYAGG_ADD_ABSENT_ON_NULL(SqlFunctions.class,
-      "jsonArrayAggAddAbsentOnNull", List.class, Object.class),
+  JSON_ARRAYAGG_ADD(SqlFunctions.class, "jsonArrayAggAdd",
+      List.class, Object.class, SqlJsonConstructorNullClause.class),
   IS_JSON_VALUE(SqlFunctions.class, "isJsonValue", String.class),
   IS_JSON_OBJECT(SqlFunctions.class, "isJsonObject", String.class),
   IS_JSON_ARRAY(SqlFunctions.class, "isJsonArray", String.class),

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
index 1207020..f13894c 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
@@ -2882,6 +2882,64 @@ public class SqlToRelConverterTest extends SqlToRelTestBase {
     sql(sql).with(tester).ok();
   }
 
+  @Test public void testJsonExists() {
+    final String sql = "select json_exists(ename, 'lax $')\n"
+        + "from emp";
+    sql(sql).ok();
+  }
+
+  @Test public void testJsonValue() {
+    final String sql = "select json_value(ename, 'lax $')\n"
+        + "from emp";
+    sql(sql).ok();
+  }
+
+  @Test public void testJsonQuery() {
+    final String sql = "select json_query(ename, 'lax $')\n"
+        + "from emp";
+    sql(sql).ok();
+  }
+
+  @Test public void testJsonArray() {
+    final String sql = "select json_array(ename, ename)\n"
+        + "from emp";
+    sql(sql).ok();
+  }
+
+  @Test public void testJsonArrayAgg() {
+    final String sql = "select json_arrayagg(ename)\n"
+        + "from emp";
+    sql(sql).ok();
+  }
+
+  @Test public void testJsonObject() {
+    final String sql = "select json_object(ename: deptno, ename: deptno)\n"
+        + "from emp";
+    sql(sql).ok();
+  }
+
+  @Test public void testJsonObjectAgg() {
+    final String sql = "select json_objectagg(ename: deptno)\n"
+        + "from emp";
+    sql(sql).ok();
+  }
+
+  @Test public void testJsonPredicate() {
+    final String sql = "select\n"
+        + "ename is json,\n"
+        + "ename is json value,\n"
+        + "ename is json object,\n"
+        + "ename is json array,\n"
+        + "ename is json scalar,\n"
+        + "ename is not json,\n"
+        + "ename is not json value,\n"
+        + "ename is not json object,\n"
+        + "ename is not json array,\n"
+        + "ename is not json scalar\n"
+        + "from emp";
+    sql(sql).ok();
+  }
+
   @Test public void testWithinGroup1() {
     final String sql = "select deptno,\n"
         + " collect(empno) within group (order by deptno, hiredate desc)\n"

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
index 28d2e3f..d8539c7 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -5316,6 +5316,114 @@ LogicalProject(ANYEMPNO=[$1])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testJsonExists">
+        <Resource name="sql">
+            <![CDATA[select json_exists(ename, 'lax $')
+from emp]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalProject(EXPR$0=[JSON_EXISTS(JSON_API_COMMON_SYNTAX(JSON_VALUE_EXPRESSION($1), 'lax $'))])
+  LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testJsonValue">
+        <Resource name="sql">
+            <![CDATA[select json_value(ename, 'lax $')
+from emp]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalProject(EXPR$0=[CAST(JSON_VALUE_ANY(JSON_API_COMMON_SYNTAX(JSON_VALUE_EXPRESSION($1), 'lax $'), FLAG(SqlJsonValueEmptyOrErrorBehavior[NULL]), null, FLAG(SqlJsonValueEmptyOrErrorBehavior[NULL]), null)):VARCHAR(2000) CHARACTER SET "ISO-8859-1" COLLATE "ISO-8859-1$en_US$primary"])
+  LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testJsonQuery">
+        <Resource name="sql">
+            <![CDATA[select json_query(ename, 'lax $')
+from emp]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalProject(EXPR$0=[JSON_QUERY(JSON_API_COMMON_SYNTAX(JSON_VALUE_EXPRESSION($1), 'lax $'), FLAG(WITHOUT_ARRAY), FLAG(SqlJsonQueryEmptyOrErrorBehavior[NULL]), FLAG(SqlJsonQueryEmptyOrErrorBehavior[NULL]))])
+  LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testJsonArray">
+        <Resource name="sql">
+            <![CDATA[select json_array(ename, ename)
+from emp]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalProject(EXPR$0=[JSON_ARRAY(FLAG(ABSENT_ON_NULL), JSON_STRUCTURED_VALUE_EXPRESSION($1), JSON_STRUCTURED_VALUE_EXPRESSION($1))])
+  LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testJsonArrayAgg">
+        <Resource name="sql">
+            <![CDATA[select json_arrayagg(ename)
+from emp]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalAggregate(group=[{}], EXPR$0=[JSON_ARRAYAGG<ABSENT_ON_NULL>($0)])
+  LogicalProject($f0=[JSON_STRUCTURED_VALUE_EXPRESSION($1)])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testJsonObject">
+        <Resource name="sql">
+            <![CDATA[select select json_object(ename: deptno, ename: deptno)
+from emp]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalProject(EXPR$0=[JSON_OBJECT(FLAG(NULL_ON_NULL), $1, JSON_STRUCTURED_VALUE_EXPRESSION($7), $1, JSON_STRUCTURED_VALUE_EXPRESSION($7))])
+  LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testJsonObjectAgg">
+        <Resource name="sql">
+            <![CDATA[select json_objectagg(ename: deptno)
+from emp]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalAggregate(group=[{}], EXPR$0=[JSON_OBJECTAGG<NULL_ON_NULL>($0, $1)])
+  LogicalProject(ENAME=[$1], $f1=[JSON_STRUCTURED_VALUE_EXPRESSION($7)])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testJsonPredicate">
+        <Resource name="sql">
+            <![CDATA[select
+ename is json,
+ename is json value,
+ename is json object,
+ename is json array,
+ename is json scalar,
+ename is not json,
+ename is not json value,
+ename is not json object,
+ename is not json array,
+ename is not json scalar
+from emp]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalProject(EXPR$0=[IS JSON VALUE($1)], EXPR$1=[IS JSON VALUE($1)], EXPR$2=[IS JSON OBJECT($1)], EXPR$3=[IS JSON ARRAY($1)], EXPR$4=[IS JSON SCALAR($1)], EXPR$5=[IS NOT JSON VALUE($1)], EXPR$6=[IS NOT JSON VALUE($1)], EXPR$7=[IS NOT JSON OBJECT($1)], EXPR$8=[IS NOT JSON ARRAY($1)], EXPR$9=[IS NOT JSON SCALAR($1)])
+  LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testWithinGroup1">
         <Resource name="sql">
             <![CDATA[select deptno,

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/core/src/test/resources/sql/misc.iq
----------------------------------------------------------------------
diff --git a/core/src/test/resources/sql/misc.iq b/core/src/test/resources/sql/misc.iq
index 0862a54..8b771ff 100644
--- a/core/src/test/resources/sql/misc.iq
+++ b/core/src/test/resources/sql/misc.iq
@@ -2213,4 +2213,10 @@ X
 true
 !ok
 
+# JSON
+values json_exists('{"foo":"bar"}', 'strict $.foo' false on error);
+EXPR$0
+true
+!ok
+
 # End misc.iq

http://git-wip-us.apache.org/repos/asf/calcite/blob/f3655e15/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java
----------------------------------------------------------------------
diff --git a/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java b/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java
index 703e813..5789d41 100644
--- a/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java
+++ b/example/csv/src/test/java/org/apache/calcite/test/CsvTest.java
@@ -512,8 +512,8 @@ public class CsvTest {
     Properties info = new Properties();
     info.put("model", jsonPath("bug"));
 
-    try (Connection connection
-        = DriverManager.getConnection("jdbc:calcite:", info)) {
+    try (Connection connection =
+        DriverManager.getConnection("jdbc:calcite:", info)) {
       ResultSet res = connection.getMetaData().getColumns(null, null,
           "DATE", "JOINEDAT");
       res.next();
@@ -560,8 +560,8 @@ public class CsvTest {
     Properties info = new Properties();
     info.put("model", jsonPath("bug"));
 
-    try (Connection connection
-        = DriverManager.getConnection("jdbc:calcite:", info)) {
+    try (Connection connection =
+        DriverManager.getConnection("jdbc:calcite:", info)) {
       Statement statement = connection.createStatement();
       final String sql = "select * from \"DATE\"\n"
           + "where EMPNO >= 140 and EMPNO < 200";


[4/4] calcite git commit: [CALCITE-2575] Release Calcite 1.18.0

Posted by jh...@apache.org.
[CALCITE-2575] Release Calcite 1.18.0

Release notes; change version numbers.

Update release instructions in HOWTO.


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/b3d144bd
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/b3d144bd
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/b3d144bd

Branch: refs/heads/branch-1.18
Commit: b3d144bdf465b81bc2d303ba6ac3948b867102cb
Parents: f3655e1
Author: Julian Hyde <jh...@apache.org>
Authored: Sun Dec 2 19:58:56 2018 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Dec 5 16:59:02 2018 -0800

----------------------------------------------------------------------
 README                |   2 +-
 pom.xml               |   7 +-
 site/_docs/history.md | 462 ++++++++++++++++++++++++++++++++++++++++++++-
 site/_docs/howto.md   |  44 ++---
 4 files changed, 487 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/b3d144bd/README
----------------------------------------------------------------------
diff --git a/README b/README
index 3c34a49..71181c0 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Apache Calcite release 1.17.0
+Apache Calcite release 1.18.0
 
 This is a source or binary distribution of Apache Calcite.
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/b3d144bd/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 727ed35..36b55ae 100644
--- a/pom.xml
+++ b/pom.xml
@@ -58,7 +58,7 @@ limitations under the License.
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <top.dir>${project.basedir}</top.dir>
     <version.major>1</version.major>
-    <version.minor>17</version.minor>
+    <version.minor>18</version.minor>
 
     <!-- Don't fail the build for vulnerabilities below this threshold. -->
     <failBuildOnCVSS>8</failBuildOnCVSS>
@@ -795,6 +795,11 @@ limitations under the License.
         <dependencies>
           <dependency>
             <groupId>org.apache.maven.scm</groupId>
+            <artifactId>maven-scm-api</artifactId>
+            <version>${maven-scm-provider.version}</version>
+          </dependency>
+          <dependency>
+            <groupId>org.apache.maven.scm</groupId>
             <artifactId>maven-scm-provider-gitexe</artifactId>
             <version>${maven-scm-provider.version}</version>
           </dependency>

http://git-wip-us.apache.org/repos/asf/calcite/blob/b3d144bd/site/_docs/history.md
----------------------------------------------------------------------
diff --git a/site/_docs/history.md b/site/_docs/history.md
index 1f63f78..ed46431 100644
--- a/site/_docs/history.md
+++ b/site/_docs/history.md
@@ -28,16 +28,469 @@ For a full list of releases, see
 Downloads are available on the
 [downloads page]({{ site.baseurl }}/downloads/).
 
-## <a href="https://github.com/apache/calcite/releases/tag/calcite-1.18.0">1.18.0</a> / under development
+## <a href="https://github.com/apache/calcite/releases/tag/calcite-1.18.0">1.18.0</a> / 2018-12-11
 {: #v1-18-0}
 
+With over 200 commits from 36 contributors, this is the largest
+Calcite release ever. To the SQL dialect, we added
+<a href="https://issues.apache.org/jira/browse/CALCITE-2266">JSON
+functions</a> and
+<a href="https://issues.apache.org/jira/browse/CALCITE-2402">linear
+regression functions</a>, the
+<a href="https://issues.apache.org/jira/browse/CALCITE-2224">WITHIN
+GROUP</a> clause for aggregate functions; there is a new
+<a href="https://issues.apache.org/jira/browse/CALCITE-1870">utility
+to recommend lattices based on past queries</a>,
+and improvements to expression simplification, the SQL advisor,
+and the Elasticsearch and Apache Geode adapters.
+
 Compatibility: This release is tested
 on Linux, macOS, Microsoft Windows;
-using Oracle JDK 8, 9, 10;
-Guava versions 19.0 to 23.0;
+using Oracle JDK 8, 9, 10, 11 and OpenJDK 10, 11;
+Guava versions 19.0 to 27.0.1-jre;
 Druid version 0.11.0;
 other software versions as specified in `pom.xml`.
 
+#### New features
+
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2662">CALCITE-2662</a>]
+  In `Planner`, allow parsing a stream (`Reader`) instead of a `String`
+  (Enrico Olivelli)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2699">CALCITE-2699</a>]
+  `TIMESTAMPADD` function now applies to `DATE` and `TIME` as well as `TIMESTAMP`
+  (xuqianjin)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-563">CALCITE-563</a>]
+  In JDBC adapter, push bindable parameters down to the underlying JDBC data
+  source (Vladimir Sitnikov, Piotr Bojko)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2663">CALCITE-2663</a>]
+  In DDL parser, add `CREATE` and `DROP FUNCTION` (ambition119)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2266">CALCITE-2266</a>]
+  Implement SQL:2016 JSON functions: `JSON_EXISTS`, `JSON_VALUE`, `JSON_QUERY`,
+  `JSON_OBJECT`, `JSON_OBJECTAGG`, `JSON_ARRAY`, `JSON_ARRAYAGG`, `x IS JSON`
+  predicate (Hongze Zhang)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2224">CALCITE-2224</a>]
+  Support `WITHIN GROUP` clause for aggregate functions (Hongze Zhang)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2405">CALCITE-2405</a>]
+  In Babel parser, make 400 reserved keywords including `YEAR`, `SECOND`, `DESC`
+  non-reserved
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-1870">CALCITE-1870</a>]
+  Lattice suggester
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2571">CALCITE-2571</a>]
+  `TRIM` function now trims more than one character (Andrew Pilloud)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2112">CALCITE-2112</a>]
+  Add Maven wrapper for Calcite (Ratandeep S. Ratti)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-1026">CALCITE-1026</a>]
+  Allow models in YAML format
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2402">CALCITE-2402</a>]
+  Implement regression functions: `COVAR_POP`, `COVAR_SAMP`, `REGR_COUNT`,
+  `REGR_SXX`, `REGR_SYY`
+* SQL advisor (`SqlAdvisor`):
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2479">CALCITE-2479</a>]
+    Automatically quote identifiers that look like SQL keywords
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2478">CALCITE-2478</a>]
+    Purge `from_clause` when `_suggest_` token is located in one of the
+    `FROM` sub-queries
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2477">CALCITE-2477</a>]
+    Scalar sub-queries
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2476">CALCITE-2476</a>]
+    Produce hints when sub-query with `*` is present in query
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2475">CALCITE-2475</a>]
+    Support `MINUS`
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2473">CALCITE-2473</a>]
+    Support `--` comments
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2434">CALCITE-2434</a>]
+    Hints for nested tables and schemas
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2433">CALCITE-2433</a>]
+    Configurable quoting characters
+* Relational algebra builder (`RelBuilder`):
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2661">CALCITE-2661</a>]
+    Add methods for creating `Exchange` and `SortExchange`
+    relational expressions (Chunwei Lei)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2654">CALCITE-2654</a>]
+    Add a fluent API for building complex aggregate calls
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2441">CALCITE-2441</a>]
+    `RelBuilder.scan` should expand `TranslatableTable` and views
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2647">CALCITE-2647</a>]
+    Add a `groupKey` method that assumes only one grouping set
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2470">CALCITE-2470</a>]
+    `project` method should combine expressions if the underlying
+    node is a `Project`
+* Elasticsearch adapter:
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2679">CALCITE-2679</a>]
+    Implement `DISTINCT` and `GROUP BY` without aggregate functions (Siyuan Liu)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2689">CALCITE-2689</a>]
+    Allow grouping on non-textual fields like `DATE` and `NUMBER`
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2651">CALCITE-2651</a>]
+    Enable scrolling for basic search queries
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2585">CALCITE-2585</a>]
+    Support `NOT` operator
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2578">CALCITE-2578</a>]
+    Support `ANY_VALUE` aggregate function
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2528">CALCITE-2528</a>]
+    Support `Aggregate` (Andrei Sereda)
+* Apache Geode adapter:
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2709">CALCITE-2709</a>]
+    Allow filtering on `DATE`, `TIME`, `TIMESTAMP` fields (Sandeep Chada)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2671">CALCITE-2671</a>]
+    `GeodeFilter` now converts multiple `OR` predicates (on same attribute) into
+    a single `IN SET` (Sandeep Chada)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2498">CALCITE-2498</a>]
+    Geode adapter wrongly quotes `BOOLEAN` values as strings (Andrei Sereda)
+
+#### Bug-fixes, API changes and minor enhancements
+
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2596">CALCITE-2596</a>]
+  When translating correlated variables in enumerable convention, convert
+  not-null boxed primitive values to primitive (Stamatis Zampetakis)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2684">CALCITE-2684</a>]
+  `RexBuilder` gives `AssertionError` when creating integer literal larger than
+  2<sup>63</sup> (Ruben Quesada Lopez)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2719">CALCITE-2719</a>]
+  In JDBC adapter for MySQL, fix cast to `INTEGER` and `BIGINT` (Piotr Bojko)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2713">CALCITE-2713</a>]
+  JDBC adapter may generate casts on PostgreSQL for `VARCHAR` type exceeding max
+  length
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2529">CALCITE-2529</a>]
+  All numbers are in the same type family (Andrew Pilloud)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2701">CALCITE-2701</a>]
+  Make generated `Baz` classes immutable (Stamatis Zampetakis)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2619">CALCITE-2619</a>]
+  Reduce string literal creation cost by deferring and caching charset
+  conversion (Ted Xu)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2720">CALCITE-2720</a>]
+  `RelMetadataQuery.getTableOrigin` throws `IndexOutOfBoundsException` if
+  `RelNode` has no columns (Zoltan Haindrich)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2717">CALCITE-2717</a>]
+  Use `Interner` instead of `LoadingCache` to cache traits, and so allow traits
+  to be garbage-collected (Haisheng Yuan)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2542">CALCITE-2542</a>]
+  In SQL parser, allow `.field` to follow any expression, not just tables and
+  columns (Rong Rong)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2637">CALCITE-2637</a>]
+  In SQL parser, allow prefix '-' between `BETWEEN` and `AND` (Qi Yu)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2632">CALCITE-2632</a>]
+  Ensure that `RexNode` and its sub-classes implement `hashCode` and `equals`
+  methods (Zoltan Haindrich)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2494">CALCITE-2494</a>]
+  `RexFieldAccess` should implement `equals` and `hashCode` methods
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2715">CALCITE-2715</a>]
+  In JDBC adapter, do not generate character set in data types for MS SQL Server
+  (Piotr Bojko)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2714">CALCITE-2714</a>]
+  Make `BasicSqlType` immutable, and now `SqlTypeFactory.createWithNullability`
+  can reuse existing type if possible (Ruben Quesada Lopez)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2687">CALCITE-2687</a>]
+  `IS DISTINCT FROM` could lead to exceptions in `ReduceExpressionsRule`
+  (Zoltan Haindrich)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2673">CALCITE-2673</a>]
+  `SqlDialect` supports pushing of all functions by default
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2675">CALCITE-2675</a>]
+  Type validation error as `ReduceExpressionsRule` fails to preserve type
+  nullability (Zoltan Haindrich)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2669">CALCITE-2669</a>]
+  `RelMdTableReferences` should check whether references inferred from input are
+  null for `Union`/`Join` operators
+* Following
+  [<a href="https://issues.apache.org/jira/browse/CALCITE-2031">CALCITE-2031</a>]
+  remove incorrect "Not implemented" message
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2668">CALCITE-2668</a>]
+  Support for left/right outer join in `RelMdExpressionLineage`
+* Fix invocation of deprecated constructor of `SqlAggFunction` (Hongze Zhang)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2652">CALCITE-2652</a>]
+  `SqlNode` to SQL conversion fails if the join condition references a `BOOLEAN`
+  column (Zoltan Haindrich)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2657">CALCITE-2657</a>]
+  In `RexShuttle`, use `RexCall.clone` instead of `new RexCall` (Chunwei Lei)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2605">CALCITE-2605</a>]
+  Support semi-join via `EnumerableCorrelate` (Ruben Quesada Lopez)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2605">CALCITE-2605</a>]
+  Support left outer join via `EnumerableCorrelate`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-1174">CALCITE-1174</a>]
+  When generating SQL, translate `SUM0(x)` to `COALESCE(SUM(x), 0)`
+* `RelBuilder.toString()`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2617">CALCITE-2617</a>]
+  Add a variant of `FilterProjectTransposeRule` that can push down a `Filter`
+  that contains correlated variables (Stamatis Zampetakis)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2638">CALCITE-2638</a>]
+  Constant reducer should not treat as constant an `RexInputRef` that points to a
+  call to a dynamic or non-deterministic function (Danny Chan)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2628">CALCITE-2628</a>]
+  JDBC adapter throws `NullPointerException` while generating `GROUP BY` query
+  for MySQL
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2404">CALCITE-2404</a>]
+  Implement access to structured-types in enumerable runtime
+  (Stamatis Zampetakis)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2622">CALCITE-2622</a>]
+  `RexFieldCollation.toString()` method is not deterministic
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2611">CALCITE-2611</a>]
+  Linq4j code generation failure if one side of an `OR` contains `UNKNOWN`
+  (Zoltan Haindrich)
+* Canonize simple cases for composite traits in trait factory
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2591">CALCITE-2591</a>]
+  `EnumerableDefaults#mergeJoin` should throw error and not return incorrect
+  results when inputs are not ordered (Enrico Olivelli)
+* Test case for
+  [<a href="https://issues.apache.org/jira/browse/CALCITE-2592">CALCITE-2592</a>]
+  `EnumerableMergeJoin` is never taken
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2526">CALCITE-2526</a>]
+  Add test for `OR` with nullable comparisons (pengzhiwei)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2413">CALCITE-2413</a>]
+  Use raw signatures for classes with generics when producing Java code
+* In Elasticsearch adapter, remove redundant null check in
+  `CompoundQueryExpression`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2562">CALCITE-2562</a>]
+  Remove dead code in `StandardConvertletTable#convertDatetimeMinus`
+* Avoid `NullPointerException` when `FlatList` contains null elements
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2561">CALCITE-2561</a>]
+  Remove dead code in `Lattice` constructor
+* Apply small refactorings to Calcite codebase (Java 5, Java 7, Java 8)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2572">CALCITE-2572</a>]
+  SQL standard semantics for `SUBSTRING` function (Andrew Pilloud)
+* Remove dead code: `Compatible`, `CompatibleGuava11`
+* Remove "Now, do something with table" from standard output when implementing
+  sequences
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2444">CALCITE-2444</a>]
+  Handle `IN` expressions when converting `SqlNode` to SQL (Zoltan Haindrich)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2537">CALCITE-2537</a>]
+  Use litmus for `VolcanoPlanner#validate`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2546">CALCITE-2546</a>]
+  Reduce precision of `Profiler`'s `surprise` and `cardinality` attributes to
+  avoid floating point discrepancies (Alisha Prabhu)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2563">CALCITE-2563</a>]
+  Materialized view rewriting may swap columns in equivalent classes incorrectly
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2551">CALCITE-2551</a>]
+  `SqlToRelConverter` gives `ClassCastException` while handling `IN` inside
+  `WHERE NOT CASE` (pengzhiwei)
+* Remove redundant `new` expression in constant array creation
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2474">CALCITE-2474</a>]
+  SqlAdvisor: avoid NPE in lookupFromHints where FROM is empty
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2418">CALCITE-2418</a>]
+  Remove `matchRecognize` field of `SqlSelect`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2514">CALCITE-2514</a>]
+  Add `SqlIdentifier` conversion to `ITEM` operator for dynamic tables in
+  `ExtendedExpander` (Arina Ielchiieva)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2491">CALCITE-2491</a>]
+  Refactor `NameSet`, `NameMap`, and `NameMultimap`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2520">CALCITE-2520</a>]
+  Make `SparkHandlerImpl#compile` silent by default, print code in
+  `calcite.debug=true` mode only
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-1026">CALCITE-1026</a>]
+  Remove unused import
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2483">CALCITE-2483</a>]
+  Druid adapter, when querying Druid segment metadata, throws when row number is
+  larger than `Integer.MAX_VALUE` (Hongze Zhang)
+* Support `AND`, `OR`, `COALESCE`, `IS [NOT] DISTINCT` in `RexUtil#op`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2495">CALCITE-2495</a>]
+  Support encoded URLs in `org.apache.calcite.util.Source`, and use it for URL
+  &rarr; File conversion in tests
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2271">CALCITE-2271</a>]
+  Join of two views with window aggregates produces incorrect results or throws
+  `NullPointerException`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2481">CALCITE-2481</a>]
+  `NameSet` assumes lower-case characters have greater codes, which does not hold
+  for certain characters
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2480">CALCITE-2480</a>]
+  `NameSet.contains` wrongly returns `false` when element in set is upper-case
+  and `seek` is lower-case
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2465">CALCITE-2465</a>]
+  Enable use of materialized views for any planner
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2446">CALCITE-2446</a>]
+  Lateral joins do not work when saved as custom views (Piotr Bojko)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2447">CALCITE-2447</a>]
+  `POWER`, `ATAN2` functions fail with `NoSuchMethodException`
+* Typo in `HepPlanner` trace message (Dylan)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2416">CALCITE-2416</a>]
+  `AssertionError` when determining monotonicity (Alina Ipatina)
+* Java 8: use `Map.computeIfAbsent` when possible
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2431">CALCITE-2431</a>]
+  `SqlUtil.getAncestry` throws `AssertionError` when providing completion hints
+  for sub-schema
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2430">CALCITE-2430</a>]
+  `RelDataTypeImpl.getFieldList` throws `AssertionError` when SQL Advisor inspects
+  non-struct field
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2429">CALCITE-2429</a>]
+  `SqlValidatorImpl.lookupFieldNamespace` throws `NullPointerException` when SQL
+  Advisor observes non-existing field
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2422">CALCITE-2422</a>]
+  Query with unnest of column from nested sub-query fails when dynamic table is
+  used
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2417">CALCITE-2417</a>]
+  `RelToSqlConverter` throws `ClassCastException` with structs (Benoit Hanotte)
+* Upgrades:
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2716">CALCITE-2716</a>]
+    Upgrade to Avatica 1.13.0
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2711">CALCITE-2711</a>]
+    Upgrade SQLLine to 1.6.0
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2570">CALCITE-2570</a>]
+    Upgrade `forbiddenapis` to 2.6 for JDK 11 support
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2486">CALCITE-2486</a>]
+    Upgrade Apache parent POM to version 21
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2467">CALCITE-2467</a>]
+    Upgrade `owasp-dependency-check` maven plugin to 3.3.1
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2559">CALCITE-2559</a>]
+    Update Checkstyle to 7.8.2
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2497">CALCITE-2497</a>]
+    Update Janino version to 3.0.9
+* Expression simplification (`RexSimplify`):
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2726">CALCITE-2726</a>]
+    `ReduceExpressionRule` may oversimplify filter conditions containing `NULL`
+    values
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2695">CALCITE-2695</a>]
+    Simplify casts that are only widening nullability (Zoltan Haindrich)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2631">CALCITE-2631</a>]
+    General improvements in simplifying `CASE`
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2639">CALCITE-2639</a>]
+    `FilterReduceExpressionsRule` causes `ArithmeticException` at execution time
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2620">CALCITE-2620</a>]
+    Simplify `COALESCE(NULL, x)` &rarr; `x` (pengzhiwei)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-1413">CALCITE-1413</a>]
+    Enhance boolean case statement simplifications (Zoltan Haindrich)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2615">CALCITE-2615</a>]
+    When simplifying `NOT-AND-OR`, `RexSimplify` incorrectly applies predicates
+    deduced for operands to the same operands (Zoltan Haindrich)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2604">CALCITE-2604</a>]
+    When simplifying an expression, say whether an `UNKNOWN` value will be
+    interpreted as is, or as `TRUE` or `FALSE`
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2438">CALCITE-2438</a>]
+    Fix wrong results for `IS NOT FALSE(FALSE)` (zhiwei.pzw) (Zoltan Haindrich)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2506">CALCITE-2506</a>]
+    Simplifying `COALESCE(+ nullInt, +vInt())` results in
+    `AssertionError: result mismatch` (pengzhiwei)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2580">CALCITE-2580</a>]
+    Simplifying `COALESCE(NULL > NULL, TRUE)` produces wrong result filter
+    expressions (pengzhiwei)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2586">CALCITE-2586</a>]
+    `CASE` with repeated branches gives `AssertionError`
+    (pengzhiwei)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2590">CALCITE-2590</a>]
+    Remove redundant `CAST` when operand has exactly the same type as it is casted to
+  * Implement fuzzy generator for `CASE` expressions
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2556">CALCITE-2556</a>]
+    Simplify `NOT TRUE` &rarr; `FALSE`, and `NOT FALSE` &rarr; `TRUE` (pengzhiwei)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2581">CALCITE-2581</a>]
+    Avoid errors in simplifying `UNKNOWN AND NOT (UNKNOWN OR ...)` (pengzhiwei)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2527">CALCITE-2527</a>]
+    Simplify `(c IS NULL) OR (c IS ...)` might result in AssertionError: result
+    mismatch (pengzhiwei)
+  * Display random failure of Rex fuzzer in build logs to inspire further fixes
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2567">CALCITE-2567</a>]
+    Simplify `IS NULL(NULL)` to `TRUE` (pengzhiwei)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2555">CALCITE-2555</a>]
+    RexSimplify: Simplify `x >= NULL` to `UNKNOWN` (pengzhiwei)
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2504">CALCITE-2504</a>]
+    Add randomized test for better code coverage of rex node create and
+    simplification
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2469">CALCITE-2469</a>]
+    Simplify `(NOT x) IS NULL` &rarr; `x IS NULL` (pengzhiwei);
+    also, simplify `f(x, y) IS NULL` &rarr; `x IS NULL OR y IS NULL` if `f` is a
+    strong operator
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2327">CALCITE-2327</a>]
+    Simplify `AND(x, y, NOT(y))` &rarr; `AND(x, null, IS NULL(y))`
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2327">CALCITE-2327</a>]
+    Avoid simplification of `x AND NOT(x)` to `FALSE` for nullable `x`
+  * [<a href="https://issues.apache.org/jira/browse/CALCITE-2505">CALCITE-2505</a>]
+    `AssertionError` when simplifying `IS [NOT] DISTINCT` expressions
+    (Haisheng Yuan)
+
+#### Build and test suite
+
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2678">CALCITE-2678</a>]
+  `RelBuilderTest#testRelBuilderToString` fails on Windows (Stamatis Zampetakis)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2660">CALCITE-2660</a>]
+  `OsAdapterTest` now checks whether required commands are available
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2655">CALCITE-2655</a>]
+  Enable Travis to test against JDK 12
+* Ensure that tests are not calling `checkSimplify3` with `expected`,
+  `expectedFalse`, `expectedTrue` all the same
+* Geode adapter tests: Removed unnecessary `try/final` block in `RefCountPolicy`
+* Add license to `TestKtTest` and add `apache-rat:check` to Travis CI
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2112">CALCITE-2112</a>]
+  Add Apache license header to `maven-wrapper.properties`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2588">CALCITE-2588</a>]
+  Run Geode adapter tests with an embedded instance
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2594">CALCITE-2594</a>]
+  Ensure `forbiddenapis` and `maven-compiler` use the correct JDK version
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2642">CALCITE-2642</a>]
+  Checkstyle complains that `maven-wrapper.properties` is missing a header
+* `commons:commons-pool2` is used in tests only, so use `scope=test` for it
+* Make `findbugs:jsr305` dependency optional
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2458">CALCITE-2458</a>]
+  Add Kotlin as a test dependency
+* Make build scripts Maven 3.3 compatible
+* Fix JavaDoc warnings for Java 9+, and check JavaDoc in Travis CI
+* Unwrap invocation target exception from QuidemTest#test
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2518">CALCITE-2518</a>]
+  Add `failOnWarnings` to `maven-javadoc-plugin` configuration
+* Silence Pig, Spark, and Elasticsearch logs in tests
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-1894">CALCITE-1894</a>]
+  `CsvTest.testCsvStream` failing often: add `@Ignore` since the test is known to
+  fail
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2535">CALCITE-2535</a>]
+  Enable `SqlTester.checkFails` (previously it was a no-op) (Hongze Zhang)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2558">CALCITE-2558</a>]
+  Improve re-compilation times by skipping `parser.java` update on each build
+* Increase timeout for Cassandra daemon startup for `CassandraAdapterTest`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2412">CALCITE-2412</a>]
+  Add Windows CI via AppVeyor (Sergey Nuyanzin)
+* Reduce `HepPlannerTest#testRuleApplyCount` complexity
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2523">CALCITE-2523</a>]
+  Guard `PartiallyOrderedSetTest#testPosetBitsLarge` with
+  `CalciteAssert.ENABLE_SLOW`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2521">CALCITE-2521</a>]
+  Guard `RelMetadataTest#testMetadataHandlerCacheLimit` with
+  `CalciteAssert.ENABLE_SLOW`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2484">CALCITE-2484</a>]
+  Add `SqlValidatorDynamicTest` to `CalciteSuite`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2484">CALCITE-2484</a>]
+  Move dynamic tests to a separate class like `SqlValidatorDynamicTest`, and
+  avoid reuse of `MockCatalogReaderDynamic`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2522">CALCITE-2522</a>]
+  Remove `e.printStackTrace()` from `CalciteAssert#returns`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2512">CALCITE-2512</a>]
+  Move `StreamTest#ROW_GENERATOR` to `Table.scan().iterator` to make it not
+  shared between threads (Sergey Nuyanzin)
+* Skip second Checkstyle execution during Travis CI build
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2519">CALCITE-2519</a>]
+  Silence ERROR logs from `CalciteException`, `SqlValidatorException` during
+  tests
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-1026">CALCITE-1026</a>]
+  Fix `ModelTest#testYamlFileDetection` when source folder has spaces
+* `MockCatalogReader` is used in testing, so cache should be disabled there to
+  avoid thread conflicts and/or stale results
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-311">CALCITE-311</a>]
+  Add a test-case for Filter after Window aggregate
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2462">CALCITE-2462</a>]
+  `RexProgramTest`: replace `nullLiteral` &rarr; `nullInt`,
+  `unknownLiteral` &rarr; `nullBool` for brevity
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2462">CALCITE-2462</a>]
+  `RexProgramTest`: move "rex building" methods to base class
+* `SqlTestFactory`: use lazy initialization of objects
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2435">CALCITE-2435</a>]
+  Refactor `SqlTestFactory`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2428">CALCITE-2428</a>]
+  Cassandra unit test fails to parse JDK version string (Andrei Sereda)
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2419">CALCITE-2419</a>]
+  Use embedded Cassandra for tests
+
+#### Web site and documentation
+
+* Add geospatial category to DOAP file
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2577">CALCITE-2577</a>]
+  Update links on download page to HTTPS
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2574">CALCITE-2574</a>]
+  Update download page to include instructions for verifying a downloaded
+  artifact
+* Update build status badges in `README.md`
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-2705">CALCITE-2705</a>]
+  Site: Remove duplicate "selectivity" in list of metadata types (Alan Jin)
+* Site: Add Andrei Sereda as committer
+* Site: Update Julian Hyde's affiliation
+* Update Michael Mior's affiliation
+* Site: Add instructions for updating PRs based on the discussion in the dev
+  list (Stamatis Zampetakis)
+* Site: Add committer Sergey Nuyanzin
+* Site: News item for release 1.17.0
+
 ## <a href="https://github.com/apache/calcite/releases/tag/calcite-1.17.0">1.17.0</a> / 2018-07-16
 {: #v1-17-0}
 
@@ -255,7 +708,8 @@ Calcite has been upgraded to use <a href='https://issues.apache.org/jira/browse/
 * [<a href='https://issues.apache.org/jira/browse/CALCITE-2403'>CALCITE-2403</a>]
   Upgrade quidem to 0.9
 * [<a href='https://issues.apache.org/jira/browse/CALCITE-2409'>CALCITE-2409</a>]
-  SparkAdapterTest fails on Windows when '/tmp' directory does not exist (Sergey Nuyanzin)
+  `SparkAdapterTest` fails on Windows when '/tmp' directory does not exist
+  (Sergey Nuyanzin)
 
 ## <a href="https://github.com/apache/calcite/releases/tag/calcite-1.16.0">1.16.0</a> / 2018-03-14
 {: #v1-16-0}

http://git-wip-us.apache.org/repos/asf/calcite/blob/b3d144bd/site/_docs/howto.md
----------------------------------------------------------------------
diff --git a/site/_docs/howto.md b/site/_docs/howto.md
index f52abb3..6a04052 100644
--- a/site/_docs/howto.md
+++ b/site/_docs/howto.md
@@ -31,15 +31,15 @@ adapters.
 
 ## Building from a source distribution
 
-Prerequisite is Java (JDK 8, 9 or 10) on your path.
+Prerequisite is Java (JDK 8, 9, 10 or 11) on your path.
 
 Unpack the source distribution `.tar.gz` file,
 `cd` to the root directory of the unpacked source,
 then build using the included maven wrapper:
 
 {% highlight bash %}
-$ tar xvfz calcite-1.17.0-source.tar.gz
-$ cd calcite-1.17.0
+$ tar xvfz calcite-1.18.0-source.tar.gz
+$ cd calcite-1.18.0
 $ ./mvnw install
 {% endhighlight %}
 
@@ -49,7 +49,7 @@ tests.
 ## Building from git
 
 Prerequisites are git
-and Java (JDK 8, 9 or 10) on your path.
+and Java (JDK 8, 9, 10 or 11) on your path.
 
 Create a local copy of the github repository,
 `cd` to its root directory,
@@ -486,18 +486,18 @@ Follow the instructions [here](http://www.apache.org/dev/publishing-maven-artifa
 Before you start:
 
 * Set up signing keys as described above.
-* Make sure you are using JDK 8 (not 9 or 10).
+* Make sure you are using JDK 11.
 * Make sure build and tests succeed with `-Dcalcite.test.db=hsqldb` (the default)
 
 {% highlight bash %}
-# Set passphrase variable without putting it into shell history
-read -s GPG_PASSPHRASE
+# Tell GPG how to read a password from your terminal
+export GPG_TTY=$(tty)
 
 # Make sure that there are no junk files in the sandbox
 git clean -xn
 ./mvnw clean
 
-./mvnw -Papache-release -Dgpg.passphrase=${GPG_PASSPHRASE} install
+./mvnw -Papache-release install
 {% endhighlight %}
 
 When the dry-run has succeeded, change `install` to `deploy`.
@@ -581,31 +581,31 @@ If any of the steps fail, clean up (see below), fix the problem, and
 start again from the top.
 
 {% highlight bash %}
-# Set passphrase variable without putting it into shell history
-read -s GPG_PASSPHRASE
+# Tell GPG how to read a password from your terminal
+export GPG_TTY=$(tty)
 
 # Make sure that there are no junk files in the sandbox
 git clean -xn
 ./mvnw clean
 
 # Do a dry run of the release:prepare step, which sets version numbers
-# (accept the default tag name of calcite-X.Y.Z)
-# Note X.Y.Z is the current version we're trying to release, and X.Y+1.Z is the next development version.
-# For example, if I am currently building a release for 1.16.0, X.Y.Z would be 1.16.0 and X.Y+1.Z would be 1.17.0.
-./mvnw -DdryRun=true -DskipTests -DreleaseVersion=X.Y.Z -DdevelopmentVersion=X.Y+1.Z-SNAPSHOT -Papache-release -Darguments="-Dgpg.passphrase=${GPG_PASSPHRASE}" release:prepare 2>&1 | tee /tmp/prepare-dry.log
+# (accept the default tag name of calcite-X.Y.Z).
+# Note X.Y.Z is the current version we're trying to release (e.g. 1.8.0),
+# and X.(Y+1).Z is the next development version (e.g. 1.9.0).
+./mvnw -DdryRun=true -DskipTests -DreleaseVersion=X.Y.Z -DdevelopmentVersion=X.(Y+1).Z-SNAPSHOT -Papache-release release:prepare 2>&1 | tee /tmp/prepare-dry.log
 
 # If you have multiple GPG keys, you can select the key used to sign the release by adding `-Dgpg.keyname=${GPG_KEY_ID}` to `-Darguments`:
-./mvnw -DdryRun=true -DskipTests -DreleaseVersion=X.Y.Z -DdevelopmentVersion=X.Y+1.Z-SNAPSHOT -Papache-release -Darguments="-Dgpg.passphrase=${GPG_PASSPHRASE} -Dgpg.keyname=${GPG_KEY_ID}" release:prepare 2>&1 | tee /tmp/prepare-dry.log
+./mvnw -DdryRun=true -DskipTests -DreleaseVersion=X.Y.Z -DdevelopmentVersion=X.(Y+1).Z-SNAPSHOT -Papache-release -Darguments="-Dgpg.keyname=${GPG_KEY_ID}" release:prepare 2>&1 | tee /tmp/prepare-dry.log
 {% endhighlight %}
 
 Check the artifacts.
 Note that when performing the dry run `SNAPSHOT` will appear in any file or directory names given below.
 The version will be automatically changed when performing the release for real.
 
-* In the `target` directory should be these 6 files, among others:
-  * apache-calcite-X.Y.Z-src.tar.gz
-  * apache-calcite-X.Y.Z-src.tar.gz.asc
-  * apache-calcite-X.Y.Z-src.tar.gz.sha256
+* In the `target` directory should be these 3 files, among others:
+  * `apache-calcite-X.Y.Z-src.tar.gz`
+  * `apache-calcite-X.Y.Z-src.tar.gz.asc`
+  * `apache-calcite-X.Y.Z-src.tar.gz.sha256`
 * Note that the file names start `apache-calcite-`.
 * In the source distro `.tar.gz` (currently there is
   no binary distro), check that all files belong to a directory called
@@ -632,13 +632,13 @@ For this step you'll have to add the [Apache servers](https://maven.apache.org/d
 # Prepare sets the version numbers, creates a tag, and pushes it to git
 # Note X.Y.Z is the current version we're trying to release, and X.Y+1.Z is the next development version.
 # For example, if I am currently building a release for 1.16.0, X.Y.Z would be 1.16.0 and X.Y+1.Z would be 1.17.0.
-./mvnw -DdryRun=false -DskipTests -DreleaseVersion=X.Y.Z -DdevelopmentVersion=X.Y+1.Z-SNAPSHOT -Papache-release -Darguments="-Dgpg.passphrase=${GPG_PASSPHRASE}" release:prepare 2>&1 | tee /tmp/prepare.log
+./mvnw -DdryRun=false -DskipTests -DreleaseVersion=X.Y.Z -DdevelopmentVersion=X.Y+1.Z-SNAPSHOT -Papache-release release:prepare 2>&1 | tee /tmp/prepare.log
 
 # If you have multiple GPG keys, you can select the key used to sign the release by adding `-Dgpg.keyname=${GPG_KEY_ID}` to `-Darguments`:
-./mvnw -DdryRun=false -DskipTests -DreleaseVersion=X.Y.Z -DdevelopmentVersion=X.Y+1.Z-SNAPSHOT -Papache-release -Darguments="-Dgpg.passphrase=${GPG_PASSPHRASE} -Dgpg.keyname=${GPG_KEY_ID}" release:prepare 2>&1 | tee /tmp/prepare-dry.log
+./mvnw -DdryRun=false -DskipTests -DreleaseVersion=X.Y.Z -DdevelopmentVersion=X.Y+1.Z-SNAPSHOT -Papache-release -Darguments="-Dgpg.keyname=${GPG_KEY_ID}" release:prepare 2>&1 | tee /tmp/prepare.log
 
 # Perform checks out the tagged version, builds, and deploys to the staging repository
-./mvnw -DskipTests -Papache-release -Darguments="-Dgpg.passphrase=${GPG_PASSPHRASE}" release:perform 2>&1 | tee /tmp/perform.log
+./mvnw -DskipTests -Papache-release release:perform 2>&1 | tee /tmp/perform.log
 {% endhighlight %}
 
 Verify the staged artifacts in the Nexus repository:


[2/4] calcite git commit: [CALCITE-2468] Validator throws IndexOutOfBoundsException when trying to infer operand type from STRUCT return type (Rong Rong)

Posted by jh...@apache.org.
[CALCITE-2468] Validator throws IndexOutOfBoundsException when trying to infer operand type from STRUCT return type (Rong Rong)

Add example in server module's type.iq test.
Fix type inference when operator is AS with a complex row of just 1 element.

Close apache/calcite#932


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/40d12b74
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/40d12b74
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/40d12b74

Branch: refs/heads/branch-1.18
Commit: 40d12b7419bd544bd829011a18ac37f6bc529ce7
Parents: 4da9c0d
Author: Rong Rong <wa...@hotmail.com>
Authored: Mon Aug 20 17:16:19 2018 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Dec 5 16:19:32 2018 -0800

----------------------------------------------------------------------
 .../calcite/sql/validate/SqlValidatorImpl.java  | 31 +++++++++++++-------
 .../calcite/test/SqlToRelConverterTest.java     | 10 +++++++
 .../calcite/test/SqlToRelConverterTest.xml      | 12 ++++++++
 server/src/test/resources/sql/type.iq           | 22 ++++++++++++++
 4 files changed, 65 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/40d12b74/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
index 626399f..41fdab5 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
@@ -131,6 +131,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.function.Supplier;
+import javax.annotation.Nonnull;
 
 import static org.apache.calcite.sql.SqlUtil.stripAs;
 import static org.apache.calcite.util.Static.RESOURCE;
@@ -454,7 +455,9 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
     selectItems.add(expanded);
     aliases.add(alias);
 
-    inferUnknownTypes(targetType, scope, expanded);
+    if (expanded != null) {
+      inferUnknownTypes(targetType, scope, expanded);
+    }
     final RelDataType type = deriveType(selectScope, expanded);
     setValidatedNodeType(expanded, type);
     fields.add(Pair.of(alias, type));
@@ -1720,9 +1723,12 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
   }
 
   protected void inferUnknownTypes(
-      RelDataType inferredType,
-      SqlValidatorScope scope,
-      SqlNode node) {
+      @Nonnull RelDataType inferredType,
+      @Nonnull SqlValidatorScope scope,
+      @Nonnull SqlNode node) {
+    Objects.requireNonNull(inferredType);
+    Objects.requireNonNull(scope);
+    Objects.requireNonNull(node);
     final SqlValidatorScope newScope = scopes.get(node);
     if (newScope != null) {
       scope = newScope;
@@ -1790,6 +1796,9 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
       } else {
         setValidatedNodeType(caseCall.getElseOperand(), returnType);
       }
+    } else if (node.getKind()  == SqlKind.AS) {
+      // For AS operator, only infer the operand not the alias
+      inferUnknownTypes(inferredType, scope, ((SqlCall) node).operand(0));
     } else if (node instanceof SqlCall) {
       final SqlCall call = (SqlCall) node;
       final SqlOperandTypeInference operandTypeInference =
@@ -1797,18 +1806,20 @@ public class SqlValidatorImpl implements SqlValidatorWithHints {
       final SqlCallBinding callBinding = new SqlCallBinding(this, scope, call);
       final List<SqlNode> operands = callBinding.operands();
       final RelDataType[] operandTypes = new RelDataType[operands.size()];
-      if (operandTypeInference == null) {
-        // TODO:  eventually should assert(operandTypeInference != null)
-        // instead; for now just eat it
-        Arrays.fill(operandTypes, unknownType);
-      } else {
+      Arrays.fill(operandTypes, unknownType);
+      // TODO:  eventually should assert(operandTypeInference != null)
+      // instead; for now just eat it
+      if (operandTypeInference != null) {
         operandTypeInference.inferOperandTypes(
             callBinding,
             inferredType,
             operandTypes);
       }
       for (int i = 0; i < operands.size(); ++i) {
-        inferUnknownTypes(operandTypes[i], scope, operands.get(i));
+        final SqlNode operand = operands.get(i);
+        if (operand != null) {
+          inferUnknownTypes(operandTypes[i], scope, operand);
+        }
       }
     }
   }

http://git-wip-us.apache.org/repos/asf/calcite/blob/40d12b74/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
index 77fa01c..1207020 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
@@ -123,6 +123,16 @@ public class SqlToRelConverterTest extends SqlToRelTestBase {
     sql(sql).ok();
   }
 
+  /** Test case for:
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-2468">[CALCITE-2468]
+   * struct type alias should not cause IOOBE.</a>.
+   */
+  @Test public void testStructTypeAlias() {
+    final String sql = "select t.r AS myRow \n"
+        + "from (select row(row(1)) r from dept) t";
+    sql(sql).ok();
+  }
+
   @Test
   public void testJoinUsingDynamicTable() {
     final String sql = "select * from SALES.NATION t1\n"

http://git-wip-us.apache.org/repos/asf/calcite/blob/40d12b74/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
index 9128946..28d2e3f 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -1459,6 +1459,18 @@ LogicalProject(A=[$0], B=[$1], C=[$2], DEPTNO=[$3], NAME=[$4])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testStructTypeAlias">
+        <Resource name="sql">
+            <![CDATA[select t.r AS myRow
+from (select row(row(1)) r from dept) t]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalProject(MYROW$$0$$0=[1])
+  LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testJoinWithUnion">
         <Resource name="sql">
             <![CDATA[select grade

http://git-wip-us.apache.org/repos/asf/calcite/blob/40d12b74/server/src/test/resources/sql/type.iq
----------------------------------------------------------------------
diff --git a/server/src/test/resources/sql/type.iq b/server/src/test/resources/sql/type.iq
index 64314e9..7103be4 100644
--- a/server/src/test/resources/sql/type.iq
+++ b/server/src/test/resources/sql/type.iq
@@ -49,7 +49,29 @@ select * from t;
 
 !ok
 
+
+# Create a table with complex structure type
+# This is to test struct type inference in
+# <a href="https://issues.apache.org/jira/browse/CALCITE-1222">[CALCITE-2468]
+
+create type mytype1 as (ii int not null);
+(0 rows modified)
+
+!update
+
+# Create a complex table
+create table v (i int not null, j mytype1 not null);
+(0 rows modified)
+
+!update
+
+select i AS myInt, j AS myStruct from v;
+MYINT INTEGER(10) NOT NULL
+MYSTRUCT STRUCT NOT NULL
+!type
+
 drop table t;
+drop table v;
 (0 rows modified)
 
 !update