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

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


The following commit(s) were added to refs/heads/master by this push:
     new 35e9e436a7f feat: Update to Calcite 1.42.0. (#19976)
35e9e436a7f is described below

commit 35e9e436a7f0dcd410d4320d892e020007329cf0
Author: Gian Merlino <[email protected]>
AuthorDate: Wed Sep 9 10:51:44 2026 -0700

    feat: Update to Calcite 1.42.0. (#19976)
    
    Main changes:
    
    1) Sync of Parser.jj (using dev/upgrade-calcite-parser) and
       CalcitePlanner.
    
    2) Add DruidTypeFactory to work around undesirable behavior introduced
       by CALCITE-7358.
    
    3) Add validation to prevent aliases in CLUSTERED BY, which have been
       added to the parser since CALCITE-5347. (The change is done at the
       validator instead of the parser to minimize parser diffs.)
    
    4) Adjust test expectations for slightly different plans.
---
 dev/upgrade-calcite-parser                         |   4 +-
 licenses.yaml                                      |   4 +-
 pom.xml                                            |  10 +-
 .../qaWin/sql_explain.dart.iq                      |  16 +-
 sql/src/main/codegen/default_config.fmpp           |   1 +
 sql/src/main/codegen/templates/Parser.jj           | 364 +++++++++++++++++++--
 .../sql/calcite/parser/DruidSqlParserUtils.java    |   8 +
 .../druid/sql/calcite/planner/CalcitePlanner.java  |  63 ++--
 .../sql/calcite/planner/DruidTypeFactory.java      |  61 ++++
 .../druid/sql/calcite/CalciteJoinQueryTest.java    |  34 +-
 .../sql/calcite/CalciteNestedDataQueryTest.java    |   3 +-
 .../apache/druid/sql/calcite/CalciteQueryTest.java |   5 +-
 .../calcite/parser/DruidSqlParserUtilsTest.java    |  22 ++
 .../sql/calcite/planner/DruidTypeFactoryTest.java  |  75 +++++
 .../testJoinWithInputRefCondition.iq               |  14 +-
 ...ultaneouslyUsingWhereInSubquery@all_disabled.iq |  14 +-
 ...multaneouslyUsingWhereInSubquery@all_enabled.iq |  14 +-
 [email protected] |  14 +-
 ...reInSubquery@filter-on-value-column_disabled.iq |  14 +-
 [email protected] |  14 +-
 [email protected] |  14 +-
 [email protected] |  14 +-
 22 files changed, 648 insertions(+), 134 deletions(-)

diff --git a/dev/upgrade-calcite-parser b/dev/upgrade-calcite-parser
index f311d3ea738..8afd6100a15 100755
--- a/dev/upgrade-calcite-parser
+++ b/dev/upgrade-calcite-parser
@@ -35,7 +35,7 @@ CALCITE_NEW=$2
 set -e
 set -x
 
-BRANCH=`git name-rev --name-only HEAD`
+BRANCH=`git rev-parse --abbrev-ref HEAD`
 
 REPO=.git/calcite-upgrade
 rm -rf "$REPO"
@@ -52,7 +52,7 @@ git revert --no-edit HEAD
 
 git branch base-changes curr-changes^
 git checkout base-changes
-git show|patch -p0 -R # undo temproarily to ensure maven runs
+git show|patch -p1 -R # undo temporarily to ensure maven runs
 
 mvn -q generate-sources -pl sql -Dcalcite.version=$CALCITE_NEW 
-Pskip-static-checks
 cp -r sql/target/calcite-base-parser/codegen/./  sql/src/main/codegen/./
diff --git a/licenses.yaml b/licenses.yaml
index bd7bd7c74f4..01fc4a05585 100644
--- a/licenses.yaml
+++ b/licenses.yaml
@@ -1242,7 +1242,7 @@ name: org.jooq joou-java-6
 license_category: binary
 module: java-core
 license_name: Apache License version 2.0
-version: 0.9.4
+version: 0.9.5
 libraries:
   - org.jooq: joou-java-6
 
@@ -1928,7 +1928,7 @@ name: Apache Calcite
 license_category: binary
 module: java-core
 license_name: Apache License version 2.0
-version: 1.41.0
+version: 1.42.0
 libraries:
   - org.apache.calcite: calcite-core
   - org.apache.calcite: calcite-linq4j
diff --git a/pom.xml b/pom.xml
index c80f1e6a0d5..0ebed327af8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -89,7 +89,7 @@
         <!--
             The base calcite parser was copied into the project; when updating 
Calcite run dev/upgrade-calcite-parser to adopt upstream changes
           -->
-        <calcite.version>1.41.0</calcite.version>
+        <calcite.version>1.42.0</calcite.version>
         <confluent.version>8.3.1</confluent.version>
         <cronutils.version>9.2.1</cronutils.version>
         <datasketches.version>4.2.0</datasketches.version>
@@ -430,6 +430,14 @@
                 <version>3.8.7</version>
             </dependency>
 
+            <!-- transitive dependency of calcite-core and avatica-core, which 
require different
+            versions; pinned to the higher of the two -->
+            <dependency>
+                <groupId>org.jooq</groupId>
+                <artifactId>joou-java-6</artifactId>
+                <version>0.9.5</version>
+            </dependency>
+
             <!-- transitive dependency of kafka-clients and kubernetes client
             this should get resolved with the update of above depdendencies -->
             <dependency>
diff --git 
a/quidem-ut/src/test/quidem/org.apache.druid.quidem.QTest/qaWin/sql_explain.dart.iq
 
b/quidem-ut/src/test/quidem/org.apache.druid.quidem.QTest/qaWin/sql_explain.dart.iq
index c2efa567878..decba0fcb6f 100644
--- 
a/quidem-ut/src/test/quidem/org.apache.druid.quidem.QTest/qaWin/sql_explain.dart.iq
+++ 
b/quidem-ut/src/test/quidem/org.apache.druid.quidem.QTest/qaWin/sql_explain.dart.iq
@@ -59,9 +59,9 @@ WHERE client_ip IN ('107.13.54.103',
 
 !ok
 
-LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], $3=[$4], 
$4=[$7], $5=[$8], $6=[$9])
+LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], t=[$4], 
FIRST=[$7], LAST=[$8], cnt=[$9])
   LogicalWindow(window#0=[window(partition {1} order by [0, 5, 6, 2, 3] aggs 
[FIRST_VALUE($2), LAG($2, $7), COUNT($2)])], constants=[[0:BIGINT]])
-    LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], 
$3=[TIME_FLOOR($3, 'PT12H')], $4=[CAST(TIME_FLOOR($3, 'PT12H')):CHAR(1) NOT 
NULL], $5=[LENGTH($0)], $6=[+(CAST(LENGTH($0)):DOUBLE, 0.123:DECIMAL(4, 3))])
+    LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], 
$3=[TIME_FLOOR($3, 'PT12H')], t=[CAST(TIME_FLOOR($3, 'PT12H')):CHAR(1) NOT 
NULL], $5=[LENGTH($0)], $6=[+(CAST(LENGTH($0)):DOUBLE, 0.123:DECIMAL(4, 3))])
       LogicalFilter(condition=[SEARCH($1, Sarg['107.13.54.103':VARCHAR, 
'99.9.55.22':VARCHAR]:VARCHAR)])
         LogicalAggregate(group=[{0, 1, 2, 3}])
           LogicalProject(server_ip=[$14], client_ip=[$5], timezone=[$18], 
__time=[TIME_FLOOR($0, 'PT12H')])
@@ -112,9 +112,9 @@ WHERE client_ip IN ('107.13.54.103',
 
 !ok
 
-LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], $3=[$4], 
$4=[$7], $5=[$8], $6=[$9])
+LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], t=[$4], 
FIRST=[$7], LAST=[$8], cnt=[$9])
   LogicalWindow(window#0=[window(partition {1} order by [0, 5, 6, 2, 3] aggs 
[FIRST_VALUE($2), LAG($2, $7), COUNT($2)])], constants=[[0:BIGINT]])
-    LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], 
$3=[TIME_FLOOR($3, 'PT12H')], $4=[CAST(TIME_FLOOR($3, 'PT12H')):CHAR(1) NOT 
NULL], $5=[LENGTH($0)], $6=[+(CAST(LENGTH($0)):DOUBLE, 0.123:DECIMAL(4, 3))])
+    LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], 
$3=[TIME_FLOOR($3, 'PT12H')], t=[CAST(TIME_FLOOR($3, 'PT12H')):CHAR(1) NOT 
NULL], $5=[LENGTH($0)], $6=[+(CAST(LENGTH($0)):DOUBLE, 0.123:DECIMAL(4, 3))])
       LogicalFilter(condition=[SEARCH($1, Sarg['107.13.54.103':VARCHAR, 
'99.9.55.22':VARCHAR]:VARCHAR)])
         LogicalAggregate(group=[{0, 1, 2, 3}])
           LogicalProject(server_ip=[$14], client_ip=[$5], timezone=[$18], 
__time=[TIME_FLOOR($0, 'PT12H')])
@@ -159,9 +159,9 @@ GROUP BY server_ip,
 
 !ok
 
-LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], $3=[$4], 
$4=[$7], $5=[$8], $6=[$9])
+LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], t=[$4], 
FIRST=[$7], LAST=[$8], cnt=[$9])
   LogicalWindow(window#0=[window(partition {1} order by [0, 5, 6, 2, 3] aggs 
[FIRST_VALUE($2), LAG($2, $7), COUNT($2)])], constants=[[0:BIGINT]])
-    LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], $3=[$3], 
$4=[CAST($3):CHAR(1) NOT NULL], $5=[LENGTH($0)], $6=[+(CAST(LENGTH($0)):DOUBLE, 
0.123:DECIMAL(4, 3))])
+    LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], $3=[$3], 
t=[CAST($3):CHAR(1) NOT NULL], $5=[LENGTH($0)], $6=[+(CAST(LENGTH($0)):DOUBLE, 
0.123:DECIMAL(4, 3))])
       LogicalAggregate(group=[{0, 1, 2, 3}])
         LogicalProject(server_ip=[$2], client_ip=[$1], timezone=[$3], 
$f3=[TIME_FLOOR($0, 'PT12H')])
           LogicalFilter(condition=[SEARCH($1, Sarg['107.13.54.103':VARCHAR, 
'99.9.55.22':VARCHAR]:VARCHAR)])
@@ -208,9 +208,9 @@ GROUP BY server_ip,
 
 !ok
 
-LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], $3=[$4], 
$4=[$7], $5=[$8], $6=[$9])
+LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], t=[$4], 
FIRST=[$7], LAST=[$8], cnt=[$9])
   LogicalWindow(window#0=[window(partition {1} order by [0, 5, 6, 2, 3] aggs 
[FIRST_VALUE($2), LAG($2, $7), COUNT($2)])], constants=[[0:BIGINT]])
-    LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], $3=[$3], 
$4=[CAST($3):CHAR(1) NOT NULL], $5=[LENGTH($0)], $6=[+(CAST(LENGTH($0)):DOUBLE, 
0.123:DECIMAL(4, 3))])
+    LogicalProject(server_ip=[$0], client_ip=[$1], timezone=[$2], $3=[$3], 
t=[CAST($3):CHAR(1) NOT NULL], $5=[LENGTH($0)], $6=[+(CAST(LENGTH($0)):DOUBLE, 
0.123:DECIMAL(4, 3))])
       LogicalAggregate(group=[{0, 1, 2, 3}])
         LogicalProject(server_ip=[$2], client_ip=[$1], timezone=[$3], 
$f3=[TIME_FLOOR($0, 'PT12H')])
           LogicalFilter(condition=[SEARCH($1, Sarg['107.13.54.103':VARCHAR, 
'99.9.55.22':VARCHAR]:VARCHAR)])
diff --git a/sql/src/main/codegen/default_config.fmpp 
b/sql/src/main/codegen/default_config.fmpp
index a2547273cb1..56d17b82798 100644
--- a/sql/src/main/codegen/default_config.fmpp
+++ b/sql/src/main/codegen/default_config.fmpp
@@ -460,4 +460,5 @@ parser: {
   includeAdditionalDeclarations: false
   includeParsingStringLiteralAsArrayLiteral: false
   includeIntervalWithoutQualifier: false
+  includeStarExclude: false
 }
diff --git a/sql/src/main/codegen/templates/Parser.jj 
b/sql/src/main/codegen/templates/Parser.jj
index 5d68325134a..100b955f264 100644
--- a/sql/src/main/codegen/templates/Parser.jj
+++ b/sql/src/main/codegen/templates/Parser.jj
@@ -91,7 +91,10 @@ import org.apache.calcite.sql.SqlPrefixOperator;
 import org.apache.calcite.sql.SqlRowTypeNameSpec;
 import org.apache.calcite.sql.SqlSampleSpec;
 import org.apache.calcite.sql.SqlSelect;
+import org.apache.calcite.sql.SqlByRewriter;
 import org.apache.calcite.sql.SqlSelectKeyword;
+import org.apache.calcite.sql.SqlStarExclude;
+import org.apache.calcite.sql.SqlStarReplace;
 import org.apache.calcite.sql.SqlSetOption;
 import org.apache.calcite.sql.SqlSnapshot;
 import org.apache.calcite.sql.SqlTableRef;
@@ -169,6 +172,20 @@ public class ${parser.class} extends SqlAbstractParserImpl
     private Casing quotedCasing;
     private int identifierMaxLength;
     private SqlConformance conformance;
+    private int rowValueStarCount;
+
+    private void pushRowValueStar() {
+        rowValueStarCount++;
+    }
+
+    private void popRowValueStar() {
+        assert rowValueStarCount > 0;
+        rowValueStarCount--;
+    }
+
+    private boolean allowRowValueStar() {
+        return rowValueStarCount > 0;
+    }
 
     /**
      * {@link SqlParserImplFactory} implementation for creating parser.
@@ -728,6 +745,12 @@ SqlNode OrderByLimitOpt(SqlNode e) :
     ]
     {
         if (orderBy != null || offsetFetch[0] != null || offsetFetch[1] != 
null) {
+            if (orderBy != null
+                && e instanceof SqlSelect
+                && ((SqlSelect) e).hasByClause()) {
+              throw SqlUtil.newContextException(orderBy.getParserPosition(),
+                  RESOURCE.selectByCannotWithOrderBy());
+            }
             return new SqlOrderBy(getPos(), e,
                 Util.first(orderBy, SqlNodeList.EMPTY),
                 offsetFetch[0], offsetFetch[1]);
@@ -1250,9 +1273,14 @@ void AddKeyValueOption(List<SqlNode> list) :
         key = StringLiteral()
     )
     <EQ>
-    value = StringLiteral() {
-        list.add(key);
-        list.add(value);
+    (
+        value = StringLiteral()
+    |
+        value = SimpleIdentifier()
+    )
+    {
+         list.add(key);
+         list.add(value);
     }
 }
 
@@ -1288,11 +1316,13 @@ SqlNodeList ParenthesizedLiteralOptionCommaList() :
 
 void AddHint(List<SqlNode> hints) :
 {
+    final Span s;
     final SqlIdentifier hintName;
     final SqlNodeList hintOptions;
     final SqlHint.HintOptionFormat optionFormat;
 }
 {
+    { s = span(); }
     hintName = SimpleIdentifier()
     (
        LOOKAHEAD(5)
@@ -1319,7 +1349,7 @@ void AddHint(List<SqlNode> hints) :
     )
     {
         hints.add(
-           new SqlHint(Span.of(hintOptions).end(this), hintName, hintOptions,
+           new SqlHint(s.end(this), hintName, hintOptions,
                optionFormat));
     }
 }
@@ -1353,6 +1383,7 @@ SqlSelect SqlSelect() :
     final SqlNode having;
     final SqlNodeList windowDecls;
     final SqlNode qualify;
+    final SqlNodeList by;
     final List<SqlNode> hints = new ArrayList<SqlNode>();
     final Span s;
 }
@@ -1373,6 +1404,11 @@ SqlSelect SqlSelect() :
     }
     AddSelectItem(selectList)
     ( <COMMA> AddSelectItem(selectList) )*
+<#if parser.includeSelectBy!false>
+    ( by = SqlSelectBy() | { by = null; } )
+<#else>
+    { by = null; }
+</#if>
     (
         <FROM> fromClause = FromClause()
         ( where = Where() | { where = null; } )
@@ -1391,10 +1427,12 @@ SqlSelect SqlSelect() :
         }
     )
     {
-        return new SqlSelect(s.end(this), keywordList,
+        final SqlSelect select = new SqlSelect(s.end(this), keywordList,
             new SqlNodeList(selectList, Span.of(selectList).pos()),
             fromClause, where, groupBy, having, windowDecls, qualify,
             null, null, null, new SqlNodeList(hints, getPos()));
+        SqlByRewriter.rewrite(select, by);
+        return select;
     }
 }
 
@@ -2031,6 +2069,116 @@ void AddSelectItem(List<SqlNode> list) :
     )
 }
 
+<#if (parser.includeStarExclude!default.parser.includeStarExclude)>
+/**
+ * Parses one unaliased expression in a select list.
+ */
+SqlNode SelectExpression() :
+{
+    SqlNode e;
+    SqlNodeList excludeList;
+    SqlNodeList replaceList;
+}
+{
+    (
+        <STAR> {
+            e = SqlIdentifier.star(getPos());
+        }
+    |
+        e = Expression(ExprContext.ACCEPT_SUB_QUERY)
+    )
+    (
+<#if (parser.includeStarExclude!default.parser.includeStarExclude)>
+        excludeList = StarExcludeList() {
+            if (!(e instanceof SqlIdentifier)) {
+                throw 
SqlUtil.newContextException(excludeList.getParserPosition(),
+                    RESOURCE.selectExcludeRequiresStar());
+            }
+            final SqlIdentifier sqlIdentifier = (SqlIdentifier) e;
+            if (!sqlIdentifier.isStar()) {
+                throw 
SqlUtil.newContextException(excludeList.getParserPosition(),
+                    RESOURCE.selectExcludeRequiresStar());
+            }
+            final SqlParserPos pos = SqlParserPos.sum(
+                ImmutableList.of(sqlIdentifier.getParserPosition(),
+                    excludeList.getParserPosition()));
+            return new SqlStarExclude(pos, sqlIdentifier, excludeList);
+        }
+    |
+</#if>
+<#if (parser.includeStarExclude!default.parser.includeStarExclude)>
+        replaceList = StarReplaceList() {
+            if (!(e instanceof SqlIdentifier)) {
+                throw 
SqlUtil.newContextException(replaceList.getParserPosition(),
+                    RESOURCE.selectReplaceRequiresStar());
+            }
+            final SqlIdentifier sqlIdentifier = (SqlIdentifier) e;
+            if (!sqlIdentifier.isStar()) {
+                throw 
SqlUtil.newContextException(replaceList.getParserPosition(),
+                    RESOURCE.selectReplaceRequiresStar());
+            }
+            final SqlParserPos pos = SqlParserPos.sum(
+                ImmutableList.of(sqlIdentifier.getParserPosition(),
+                    replaceList.getParserPosition()));
+            return new SqlStarReplace(pos, sqlIdentifier, replaceList);
+        }
+    |
+</#if>
+        { return e; }
+    )
+}
+
+<#if (parser.includeStarExclude!default.parser.includeStarExclude)>
+SqlNodeList StarExcludeList() :
+{
+    final Span s;
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    SqlIdentifier id;
+}
+{
+    ( <EXCLUDE> | <EXCEPT> ) <LPAREN> { s = span(); }
+    id = CompoundIdentifier() {
+        list.add(id);
+    }
+    (
+        <COMMA> id = CompoundIdentifier() {
+            list.add(id);
+        }
+    )*
+    <RPAREN> {
+        return new SqlNodeList(list, s.end(this));
+    }
+}
+</#if>
+
+<#if (parser.includeStarExclude!default.parser.includeStarExclude)>
+SqlNodeList StarReplaceList() :
+{
+    final Span s;
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    SqlNode expr;
+    SqlIdentifier id;
+}
+{
+    <REPLACE> <LPAREN> { s = span(); }
+    expr = Expression(ExprContext.ACCEPT_SUB_QUERY) <AS> id = 
CompoundIdentifier() {
+        list.add(SqlStdOperatorTable.AS.createCall(
+            SqlParserPos.sum(ImmutableList.of(expr.getParserPosition(),
+                id.getParserPosition())), expr, id));
+    }
+    (
+        <COMMA> expr = Expression(ExprContext.ACCEPT_SUB_QUERY) <AS> id = 
CompoundIdentifier() {
+            list.add(SqlStdOperatorTable.AS.createCall(
+                SqlParserPos.sum(ImmutableList.of(expr.getParserPosition(),
+                    id.getParserPosition())), expr, id));
+        }
+    )*
+    <RPAREN> {
+        return new SqlNodeList(list, s.end(this));
+    }
+}
+</#if>
+<#else>
 /**
  * Parses one unaliased expression in a select list.
  */
@@ -2047,6 +2195,7 @@ SqlNode SelectExpression() :
         return e;
     }
 }
+</#if>
 
 SqlLiteral Natural() :
 {
@@ -2318,7 +2467,10 @@ SqlNode TableRef3(ExprContext exprContext, boolean 
lateral) :
         // END: Druid-specific code
             tableRef = Over(tableRef)
             [ tableRef = Snapshot(tableRef) ]
-            [ tableRef = MatchRecognize(tableRef) ]
+            [
+              LOOKAHEAD(3)
+              tableRef = MatchRecognize(tableRef)
+            ]
         )
     |
         LOOKAHEAD(2)
@@ -2326,7 +2478,10 @@ SqlNode TableRef3(ExprContext exprContext, boolean 
lateral) :
         tableRef = ParenthesizedExpression(exprContext)
         tableRef = Over(tableRef)
         tableRef = addLateral(tableRef, lateral)
-        [ tableRef = MatchRecognize(tableRef) ]
+        [
+          LOOKAHEAD(3)
+          tableRef = MatchRecognize(tableRef)
+        ]
     |
         LOOKAHEAD(2)
         [ <LATERAL> ] // "LATERAL" is implicit with "UNNEST", so ignore
@@ -2995,26 +3150,65 @@ SqlNodeList OrderBy(boolean accept) :
             throw SqlUtil.newContextException(s.pos(), 
RESOURCE.illegalOrderBy());
         }
     }
-    <BY> AddOrderItem(list)
-    (
-        // NOTE jvs 6-Feb-2004:  See comments at top of file for why
-        // hint is necessary here.
-        LOOKAHEAD(2) <COMMA> AddOrderItem(list)
-    )*
+    <BY> OrderItemList(list)
     {
         return new SqlNodeList(list, s.addAll(list).pos());
     }
 }
 
+<#if parser.includeSelectBy!false>
+/**
+ * Parses a BY clause for SELECT (syntactic sugar for GROUP BY ... ORDER BY).
+ */
+SqlNodeList SqlSelectBy() :
+{
+    final List<SqlNode> list = new ArrayList<SqlNode>();
+    final Span s;
+}
+{
+    <BY> { s = span(); }
+    OrderItemList(list)
+    {
+        return new SqlNodeList(list, s.addAll(list).pos());
+    }
+}
+</#if>
+
+
+/**
+ * Parses a list of ORDER BY items.
+ */
+void OrderItemList(List<SqlNode> list) :
+{
+}
+{
+    AddOrderItem(list)
+    (
+        LOOKAHEAD(2) <COMMA> AddOrderItem(list)
+    )*
+}
+
 /**
  * Parses one item in an ORDER BY clause, and adds it to a list.
  */
 void AddOrderItem(List<SqlNode> list) :
 {
     SqlNode e;
+    final SqlIdentifier id;
 }
 {
     e = Expression(ExprContext.ACCEPT_SUB_QUERY)
+    (
+        [ <AS>
+            (
+                id = SimpleIdentifier()
+            |
+                LOOKAHEAD(1)
+                id = SimpleIdentifierFromStringLiteral()
+            )
+            { e = SqlStdOperatorTable.AS.createCall(span().end(e), e, id); }
+        ]
+    )
     (
         <ASC>
     |   <DESC> {
@@ -3209,6 +3403,7 @@ void AddUnpivotValue(List<SqlNode> list) :
 SqlMatchRecognize MatchRecognize(SqlNode tableRef) :
 {
     final Span s, s0, s1, s2;
+    final SqlIdentifier aliasBeforeMatch;
     final SqlNodeList measureList;
     final SqlNodeList partitionList;
     final SqlNodeList orderList;
@@ -3223,6 +3418,12 @@ SqlMatchRecognize MatchRecognize(SqlNode tableRef) :
     final SqlLiteral isStrictEnds;
 }
 {
+    [
+      <AS> aliasBeforeMatch = SimpleIdentifier() {
+          tableRef = SqlStdOperatorTable.AS.createCall(
+              Span.of(tableRef).end(this), tableRef, aliasBeforeMatch);
+      }
+    ]
     <MATCH_RECOGNIZE> { s = span(); checkNotJoin(tableRef); } <LPAREN>
     (
         <PARTITION> { s2 = span(); } <BY>
@@ -3601,8 +3802,12 @@ SqlNode Query(ExprContext exprContext) :
     final List<Object> list = new ArrayList<Object>();
 }
 {
-    [ withList = WithList() ]
-    e = LeafQuery(exprContext) { list.add(e); }
+    (
+        withList = WithList()
+        e = LeafQueryOrExpr(exprContext) { list.add(e); }
+    |
+        e = LeafQuery(exprContext) { list.add(e); }
+    )
     ( AddSetOpQuery(list, exprContext) )*
     { return addWith(withList, SqlParserUtil.toTree(list)); }
 }
@@ -3732,6 +3937,83 @@ SqlNode Expression(ExprContext exprContext) :
     list = Expression2(exprContext) { return SqlParserUtil.toTree(list); }
 }
 
+/** Adds an optional trailing colon path to the expression under
+ * construction, for example {@code :field.nested}, {@code :['field']} or
+ * {@code :item[1].price}. Dot-separated path segments are parsed as simple
+ * identifiers, but unquoted segment spelling is preserved for case-sensitive
+ * variant key lookup. Bracketed segments are literals (string for exact key
+ * access, integer for array index); arbitrary expressions are not allowed. */
+void AddOptionalColonPath(List<Object> list) :
+{
+    SqlParserPos colonPos;
+    List<SqlNode> segments;
+    Span s;
+    SqlIdentifier p;
+}
+{
+    [
+        LOOKAHEAD(2, <COLON> ( SimpleIdentifier() | <LBRACKET> ),
+            { this.conformance.isColonFieldAccessAllowed() })
+        <COLON> {
+            colonPos = getPos();
+            segments = new ArrayList<SqlNode>();
+            s = span();
+        }
+        (
+            p = SimpleIdentifier() {
+                segments.add(p.getParserPosition().isQuoted()
+                    ? p
+                    : new SqlIdentifier(getToken(0).image, 
p.getParserPosition()));
+            }
+        |
+            ColonBracketSegment(segments)
+        )
+        (
+            LOOKAHEAD(2) <DOT>
+            p = SimpleIdentifier() {
+                segments.add(p.getParserPosition().isQuoted()
+                    ? p
+                    : new SqlIdentifier(getToken(0).image, 
p.getParserPosition()));
+            }
+        |
+            ColonBracketSegment(segments)
+        )*
+        {
+            list.add(
+                new SqlParserUtil.ToTreeListItem(
+                    SqlStdOperatorTable.COLON, colonPos));
+            list.add(new SqlNodeList(segments, s.end(this)));
+        }
+    ]
+}
+
+/** Parses one bracketed segment of a colon path: {@code ['field']} for key
+ * access, or {@code [n]} for array index. */
+void ColonBracketSegment(List<SqlNode> segments) :
+{
+    SqlNode lit;
+    SqlIdentifier id;
+}
+{
+    <LBRACKET>
+    (
+        lit = StringLiteral() { segments.add(lit); }
+    |
+        <UNSIGNED_INTEGER_LITERAL> {
+            segments.add(SqlLiteral.createExactNumeric(token.image, getPos()));
+        }
+    |
+        LOOKAHEAD(SimpleIdentifier() <RBRACKET>)
+        id = SimpleIdentifier() {
+            throw SqlUtil.newContextException(id.getParserPosition(),
+                RESOURCE.unknownIdentifier(id.toString()));
+        }
+    )
+    <RBRACKET>
+}
+
+/** Parses an expression atom with its dot-access chain and at most one
+ * trailing colon path. */
 void AddExpression2b(List<Object> list, ExprContext exprContext) :
 {
     SqlNode e;
@@ -3758,6 +4040,7 @@ void AddExpression2b(List<Object> list, ExprContext 
exprContext) :
             list.add(ext);
         }
     )*
+    AddOptionalColonPath(list)
 }
 
 /**
@@ -3943,6 +4226,7 @@ List<Object> Expression2(ExprContext exprContext) :
                         list.add(p);
                     }
                 )*
+                AddOptionalColonPath(list)
             |
                 {
                     checkNonQueryExpression(exprContext);
@@ -4012,27 +4296,38 @@ SqlNode Expression3(ExprContext exprContext) :
     LOOKAHEAD(3)
     <ROW> {
         s = span();
+        pushRowValueStar();
     }
     list = ParenthesizedQueryOrCommaList(exprContext) {
-        if (exprContext != ExprContext.ACCEPT_ALL
-            && exprContext != ExprContext.ACCEPT_CURSOR
-            && !this.conformance.allowExplicitRowValueConstructor())
-        {
-            throw SqlUtil.newContextException(s.end(list),
-                RESOURCE.illegalRowExpression());
+        try {
+            if (exprContext != ExprContext.ACCEPT_ALL
+                && exprContext != ExprContext.ACCEPT_CURSOR
+                && !this.conformance.allowExplicitRowValueConstructor())
+            {
+                throw SqlUtil.newContextException(s.end(list),
+                    RESOURCE.illegalRowExpression());
+            }
+            return SqlStdOperatorTable.ROW.createCall(list);
+        } finally {
+            popRowValueStar();
         }
-        return SqlStdOperatorTable.ROW.createCall(list);
     }
 |
     (
-        <ROW> { rowSpan = span(); }
+        <ROW> { rowSpan = span(); pushRowValueStar(); }
     |   { rowSpan = null; }
     )
     list1 = ParenthesizedQueryOrCommaList(exprContext) {
-        if (rowSpan != null) {
-            // interpret as row constructor
-            return SqlStdOperatorTable.ROW.createCall(rowSpan.end(list1),
-                (List<SqlNode>) list1);
+        try {
+            if (rowSpan != null) {
+                // interpret as row constructor
+                return SqlStdOperatorTable.ROW.createCall(rowSpan.end(list1),
+                    (List<SqlNode>) list1);
+            }
+        } finally {
+            if (rowSpan != null) {
+                popRowValueStar();
+            }
         }
     }
     [
@@ -4363,6 +4658,9 @@ SqlNode AtomicRowExpression() :
         e = ContextVariable()
     |
         e = CompoundIdentifier()
+    |
+        LOOKAHEAD({ allowRowValueStar() })
+        <STAR> { return SqlIdentifier.star(getPos()); }
     |
         e = NewSpecification()
     |
@@ -4527,6 +4825,8 @@ SqlCreate SqlCreate() :
 {
     <CREATE> { s = span(); }
     [
+        // Allow downstream projects implement different syntax, for instance 
CREATE OR REPLACE
+        LOOKAHEAD(2)
         <OR> <REPLACE> {
             replace = true;
         }
@@ -6956,13 +7256,13 @@ List<SqlNode> JsonNameAndValue() :
         <VALUE>
     |
         <COMMA> {
-            if (kvMode) {
+            if (kvMode || this.conformance.isColonFieldAccessAllowed()) {
                 throw SqlUtil.newContextException(getPos(), 
RESOURCE.illegalComma());
             }
         }
     |
         <COLON> {
-            if (kvMode) {
+            if (kvMode || this.conformance.isColonFieldAccessAllowed()) {
                 throw SqlUtil.newContextException(getPos(), 
RESOURCE.illegalColon());
             }
         }
@@ -7436,7 +7736,7 @@ SqlCall MatchRecognizeCallWithModifier() :
 {
     final Span s;
     final SqlOperator runningOp;
-    final SqlNode func;
+    final SqlNode e;
 }
 {
     (
@@ -7445,8 +7745,8 @@ SqlCall MatchRecognizeCallWithModifier() :
         <FINAL> { runningOp = SqlStdOperatorTable.FINAL; }
     )
     { s = span(); }
-    func = NamedFunctionCall() {
-        return runningOp.createCall(s.end(func), func);
+    e = Expression3(ExprContext.ACCEPT_NON_QUERY) {
+        return runningOp.createCall(s.end(e), e);
     }
 }
 
diff --git 
a/sql/src/main/java/org/apache/druid/sql/calcite/parser/DruidSqlParserUtils.java
 
b/sql/src/main/java/org/apache/druid/sql/calcite/parser/DruidSqlParserUtils.java
index cf5cfdfd588..ae9f0018ba4 100644
--- 
a/sql/src/main/java/org/apache/druid/sql/calcite/parser/DruidSqlParserUtils.java
+++ 
b/sql/src/main/java/org/apache/druid/sql/calcite/parser/DruidSqlParserUtils.java
@@ -475,6 +475,14 @@ public class DruidSqlParserUtils
         );
       }
 
+      // Aliases like "CLUSTERED BY col AS alias" are not allowed.
+      if (clusteredByNode.isA(ImmutableSet.of(SqlKind.AS))) {
+        throw InvalidSqlInput.exception(
+            "Invalid CLUSTERED BY clause [%s]: cannot use an alias.",
+            clusteredByNode
+        );
+      }
+
       // Calcite already throws Ordinal out of range exception for positive 
non-existent ordinals. This negative ordinal check
       // is for completeness and is fixed in later Calcite versions.
       if (clusteredByNode instanceof SqlNumericLiteral) {
diff --git 
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/CalcitePlanner.java 
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/CalcitePlanner.java
index fa8f10ff776..cb4758cda09 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/CalcitePlanner.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/CalcitePlanner.java
@@ -24,7 +24,6 @@ import org.apache.calcite.adapter.java.JavaTypeFactory;
 import org.apache.calcite.config.CalciteConnectionConfig;
 import org.apache.calcite.config.CalciteSystemProperty;
 import org.apache.calcite.jdbc.CalciteSchema;
-import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
 import org.apache.calcite.plan.Context;
 import org.apache.calcite.plan.ConventionTraitDef;
 import org.apache.calcite.plan.RelOptCluster;
@@ -35,6 +34,7 @@ import org.apache.calcite.plan.RelTraitDef;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.plan.volcano.VolcanoPlanner;
 import org.apache.calcite.prepare.CalciteCatalogReader;
+import org.apache.calcite.prepare.PlannerImpl;
 import org.apache.calcite.rel.RelCollationTraitDef;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelRoot;
@@ -54,6 +54,7 @@ import org.apache.calcite.sql.validate.SqlValidator;
 import org.apache.calcite.sql2rel.RelDecorrelator;
 import org.apache.calcite.sql2rel.SqlRexConvertletTable;
 import org.apache.calcite.sql2rel.SqlToRelConverter;
+import org.apache.calcite.sql2rel.TopDownGeneralDecorrelator;
 import org.apache.calcite.tools.FrameworkConfig;
 import org.apache.calcite.tools.Planner;
 import org.apache.calcite.tools.Program;
@@ -69,17 +70,28 @@ import java.util.Objects;
 import java.util.Properties;
 
 /**
- * Calcite planner. Clone of Calcite's
- * {@link  org.apache.calcite.prepare.PlannerImpl}, as of version 1.35,
- * but with the validator made accessible, and with the minimum of formatting
- * changes needed to pass Druid's static checks. Note that the resulting code
- * is more Calcite-like than Druid-like. There seemed no value in restructuring
- * the code just to be more Druid-like.
+ * Calcite planner. Clone of Calcite's {@link PlannerImpl}, as of version 
1.42, with the following adjustments:
  *
- * Changes in 1.35:
- *
- * Allowing user-defined config and appending default values to the config
- * frameworkConfig is now replaced by costFactory
+ * <ul>
+ * <li>The validator is retained in a field and exposed through {@link 
#getValidator()}.</li>
+ * <li>{@link #skipParse()} exists so that {@link DruidSqlParser} can parse 
ahead of the planner.</li>
+ * <li>{@link #connConfig(Context)} takes no {@link SqlParser.Config}, and 
therefore does not derive
+ *     any connection-config defaults from the parser config the way upstream 
does.</li>
+ * <li>{@link #ready()} does not call {@code RelOptUtil#registerDefaultRules}; 
Druid registers its
+ *     own rules through {@link CalciteRulesManager}. It also creates a {@link 
DruidTypeFactory}
+ *     rather than a plain {@code JavaTypeFactoryImpl}.</li>
+ * <li>{@link #parse(Reader)} calls {@code parseStmtList} rather than {@code 
parseStmt}.</li>
+ * <li>{@link #validate(SqlNode)} additionally runs {@link 
Hook#PARSE_TREE}.</li>
+ * <li>{@link #createSqlValidator(CalciteCatalogReader)} builds a {@link 
DruidSqlValidator} with
+ *     {@link DruidTypeCoercion}. It starts from {@link 
SqlValidator.Config#DEFAULT} rather than
+ *     {@link FrameworkConfig#getSqlValidatorConfig()}, and does not apply
+ *     {@code withDefaultNullCollation}. Both are inert today, since Druid 
never sets a validator
+ *     config and both defaults are {@code NullCollation.HIGH}, but a 
validator config set on the
+ *     {@link FrameworkConfig} would be silently ignored.</li>
+ * <li>{@link #rel(SqlNode)} builds a {@link DruidSqlToRelConverter} and 
registers
+ *     {@link DruidHint#HINT_STRATEGY_TABLE}. It also converts its {@code sql} 
argument, whereas
+ *     upstream converts the stored {@link #validatedSqlNode}.</li>
+ * </ul>
  */
 public class CalcitePlanner implements Planner, ViewExpander
 {
@@ -106,10 +118,10 @@ public class CalcitePlanner implements Planner, 
ViewExpander
   private boolean open;
 
   // set in STATE_2_READY
-  private @Nullable SchemaPlus defaultSchema;
+  private final @Nullable SchemaPlus defaultSchema;
   private @Nullable JavaTypeFactory typeFactory;
   private @Nullable RelOptPlanner planner;
-  private @Nullable RexExecutor executor;
+  private final @Nullable RexExecutor executor;
 
   // set in STATE_4_VALIDATE
   private @Nullable SqlValidator validator;
@@ -195,7 +207,7 @@ public class CalcitePlanner implements Planner, ViewExpander
     }
     ensure(CalcitePlanner.State.STATE_1_RESET);
 
-    typeFactory = new JavaTypeFactoryImpl(typeSystem);
+    typeFactory = new DruidTypeFactory(typeSystem);
     RelOptPlanner planner = this.planner = new VolcanoPlanner(costFactory, 
context);
     planner.setExecutor(executor);
 
@@ -316,7 +328,9 @@ public class CalcitePlanner implements Planner, ViewExpander
     );
     final SqlToRelConverter.Config config =
         sqlToRelConverterConfig.withTrimUnusedFields(false)
-                               
.withHintStrategyTable(DruidHint.HINT_STRATEGY_TABLE);
+                               
.withHintStrategyTable(DruidHint.HINT_STRATEGY_TABLE)
+                               .withTopDownGeneralDecorrelationEnabled(
+                                   
connectionConfig.topDownGeneralDecorrelationEnabled());
     final SqlToRelConverter sqlToRelConverter =
         new DruidSqlToRelConverter(this, validator,
                                    createCatalogReader(), cluster, 
convertletTable, config
@@ -326,8 +340,9 @@ public class CalcitePlanner implements Planner, ViewExpander
     root = root.withRel(sqlToRelConverter.flattenTypes(root.rel, true));
     final RelBuilder relBuilder =
         config.getRelBuilderFactory().create(cluster, null);
-    root = root.withRel(
-        RelDecorrelator.decorrelateQuery(root.rel, relBuilder));
+    root = config.isTopDownGeneralDecorrelationEnabled()
+           ? 
root.withRel(TopDownGeneralDecorrelator.decorrelateQuery(root.rel, relBuilder))
+           : root.withRel(RelDecorrelator.decorrelateQuery(root.rel, 
relBuilder));
     state = CalcitePlanner.State.STATE_5_CONVERTED;
     return root;
   }
@@ -392,20 +407,22 @@ public class CalcitePlanner implements Planner, 
ViewExpander
     final RexBuilder rexBuilder = createRexBuilder();
     final RelOptCluster cluster = RelOptCluster.create(planner, rexBuilder);
     final SqlToRelConverter.Config config =
-        sqlToRelConverterConfig.withTrimUnusedFields(false);
+        sqlToRelConverterConfig.withTrimUnusedFields(false)
+                               .withTopDownGeneralDecorrelationEnabled(
+                                   
connectionConfig.topDownGeneralDecorrelationEnabled());
     final SqlToRelConverter sqlToRelConverter =
         new SqlToRelConverter(this, validator,
                               catalogReader, cluster, convertletTable, config
         );
 
-    final RelRoot root =
+    RelRoot root =
         sqlToRelConverter.convertQuery(sqlNode, true, false);
-    final RelRoot root2 =
-        root.withRel(sqlToRelConverter.flattenTypes(root.rel, true));
+    root = root.withRel(sqlToRelConverter.flattenTypes(root.rel, true));
     final RelBuilder relBuilder =
         config.getRelBuilderFactory().create(cluster, null);
-    return root2.withRel(
-        RelDecorrelator.decorrelateQuery(root.rel, relBuilder));
+    return config.isTopDownGeneralDecorrelationEnabled()
+           ? 
root.withRel(TopDownGeneralDecorrelator.decorrelateQuery(root.rel, relBuilder))
+           : root.withRel(RelDecorrelator.decorrelateQuery(root.rel, 
relBuilder));
   }
 
   // CalciteCatalogReader is stateless; no need to store one
diff --git 
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidTypeFactory.java 
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidTypeFactory.java
new file mode 100644
index 00000000000..65a6c6bccf0
--- /dev/null
+++ 
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidTypeFactory.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.sql.calcite.planner;
+
+import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeSystem;
+import org.apache.calcite.sql.type.SqlTypeMappingRule;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.sql.type.SqlTypeUtil;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.List;
+
+/**
+ * Druid's type factory.
+ */
+public class DruidTypeFactory extends JavaTypeFactoryImpl
+{
+  public DruidTypeFactory(final RelDataTypeSystem typeSystem)
+  {
+    super(typeSystem);
+  }
+
+  @Nullable
+  @Override
+  public RelDataType leastRestrictive(final List<RelDataType> types, final 
SqlTypeMappingRule mappingRule)
+  {
+    final RelDataType leastRestrictive = super.leastRestrictive(types, 
mappingRule);
+
+    if (leastRestrictive != null
+        && (SqlTypeUtil.isCollection(leastRestrictive) || 
leastRestrictive.getSqlTypeName() == SqlTypeName.MAP)
+        && types.stream().anyMatch(SqlTypeUtil::isCharacter)) {
+      // Return null, indicating that character types cannot be implicitly 
cast to arrays/maps. Such implicit casts
+      // became allowed in Calcite 1.42 (see 
https://issues.apache.org/jira/browse/CALCITE-7358). Allowing them
+      // causes execution failures for e.g. COALESCE(multiValueString, 
ARRAY['fallback']). See the test
+      // 
CalciteMultiValueStringQueryTest#testMultiValueStringOverlapFilterInconsistentUsage
+      return null;
+    }
+
+    // Otherwise return what JavaTypeFactoryImpl would have returned.
+    return leastRestrictive;
+  }
+}
diff --git 
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteJoinQueryTest.java 
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteJoinQueryTest.java
index b1980846207..f7819cf9d81 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteJoinQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteJoinQueryTest.java
@@ -2742,8 +2742,8 @@ public class CalciteJoinQueryTest extends 
BaseCalciteQueryTest
                         .setGranularity(Granularities.ALL)
                         .setDimFilter(
                             or(
-                                equality("j0._a0", 0L, ColumnType.LONG),
-                                and(isNull("_j0.p0"), 
expressionFilter("(\"j0._a1\" >= \"j0._a0\")"))
+                                and(isNull("_j0.p0"), 
expressionFilter("(\"j0._a1\" >= \"j0._a0\")")),
+                                equality("j0._a0", 0L, ColumnType.LONG)
                             )
                         )
                         .setDimensions(dimensions(new 
DefaultDimensionSpec("__time", "d0", ColumnType.LONG)))
@@ -2760,6 +2760,27 @@ public class CalciteJoinQueryTest extends 
BaseCalciteQueryTest
     );
   }
 
+  @Test
+  public void testNotInSubqueryWithNonNullKeys()
+  {
+    testBuilder()
+        .sql(
+            "SELECT __time FROM druid.foo\n"
+            + "WHERE __time NOT IN (SELECT __time FROM druid.foo WHERE dim1 = 
'abc')"
+        )
+        .expectedResults(
+            // Only the 2001-01-03 row has dim1 = 'abc', so every other row 
survives.
+            ImmutableList.of(
+                new Object[]{timestamp("2000-01-01")},
+                new Object[]{timestamp("2000-01-02")},
+                new Object[]{timestamp("2000-01-03")},
+                new Object[]{timestamp("2001-01-01")},
+                new Object[]{timestamp("2001-01-02")}
+            )
+        )
+        .run();
+  }
+
   @DecoupledTestConfig(quidemReason = 
QuidemTestCaseReason.JOIN_FILTER_LOCATIONS)
   @MethodSource("provideQueryContexts")
   @ParameterizedTest(name = "{0}")
@@ -4115,11 +4136,11 @@ public class CalciteJoinQueryTest extends 
BaseCalciteQueryTest
                             and(
                                 in("dim1", ImmutableList.of("abc", "def")),
                                 or(
-                                    equality("_j0._a0", 0L, ColumnType.LONG),
                                     and(
                                         isNull("__j0.p0"),
                                         expressionFilter("(\"_j0._a1\" >= 
\"_j0._a0\")")
-                                    )
+                                    ),
+                                    equality("_j0._a0", 0L, ColumnType.LONG)
                                 )
                             )
                         )
@@ -6031,12 +6052,11 @@ public class CalciteJoinQueryTest extends 
BaseCalciteQueryTest
                                        new FilteredAggregatorFactory(
                                            new CountAggregatorFactory("a0"),
                                            or(
-                                               equality("j0.a0", 0L, 
ColumnType.LONG),
                                                and(
                                                    isNull("_j0.a0"),
                                                    
expressionFilter("(\"j0.a1\" >= \"j0.a0\")")
-                                               )
-
+                                               ),
+                                               equality("j0.a0", 0L, 
ColumnType.LONG)
                                            )
                                        )
                                    ))
diff --git 
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteNestedDataQueryTest.java
 
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteNestedDataQueryTest.java
index 0758656c81f..72fe7f3993c 100644
--- 
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteNestedDataQueryTest.java
+++ 
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteNestedDataQueryTest.java
@@ -2401,7 +2401,8 @@ public abstract class CalciteNestedDataQueryTest extends 
BaseCalciteQueryTest
                                 )
                             )
                             .setVirtualColumns(
-                                new NestedFieldVirtualColumn("arrayLongNulls", 
"$[1]", "v0", ColumnType.LONG)
+                                expressionVirtualColumn("v0", "(\"v1\" != 0)", 
ColumnType.LONG),
+                                new NestedFieldVirtualColumn("arrayLongNulls", 
"$[1]", "v1", ColumnType.LONG)
                             )
                             .setDimFilter(isNull("v0"))
                             .setAggregatorSpecs(aggregators(new 
LongSumAggregatorFactory("a0", "cnt")))
diff --git 
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java 
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
index 66cf266a4eb..7ab2628271d 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
@@ -7557,7 +7557,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                             )))
                                             .setSubtotalsSpec(ImmutableList.of(
                                                 ImmutableList.of("d0", "d1"),
-                                                ImmutableList.of("d0", "d2")
+                                                ImmutableList.of("d0", "d2"),
+                                                ImmutableList.of("d0")
                                             ))
                                             
.setContext(withTimestampResultContext(
                                                 QUERY_CONTEXT_DEFAULT,
@@ -15672,7 +15673,7 @@ public class CalciteQueryTest extends 
BaseCalciteQueryTest
   public void testUnSupportedAggInSelectWindow()
   {
     assertEquals(
-        "1.41.0",
+        "1.42.0",
         RelNode.class.getPackage().getImplementationVersion(),
         "Calcite version changed; check if CALCITE-6500 is fixed and update:\n 
* method DruidSqlValidator#validateWindowClause"
     );
diff --git 
a/sql/src/test/java/org/apache/druid/sql/calcite/parser/DruidSqlParserUtilsTest.java
 
b/sql/src/test/java/org/apache/druid/sql/calcite/parser/DruidSqlParserUtilsTest.java
index d110f1065d2..7d4eba1fd63 100644
--- 
a/sql/src/test/java/org/apache/druid/sql/calcite/parser/DruidSqlParserUtilsTest.java
+++ 
b/sql/src/test/java/org/apache/druid/sql/calcite/parser/DruidSqlParserUtilsTest.java
@@ -326,6 +326,28 @@ public class DruidSqlParserUtilsTest
           .assertThrowsAndMatches(() -> 
DruidSqlParserUtils.validateClusteredByColumns(clusteredByArgs));
     }
 
+    /**
+     * Tests clause "CLUSTERED BY DIM1, DIM2 AS ALIAS2"
+     */
+    @Test
+    public void testClusteredByColumnsWithAliasThrowsException()
+    {
+      final SqlNodeList clusteredByArgs = new SqlNodeList(SqlParserPos.ZERO);
+      clusteredByArgs.add(new SqlIdentifier("DIM1", SqlParserPos.ZERO));
+      clusteredByArgs.add(
+          SqlStdOperatorTable.AS.createCall(
+              SqlParserPos.ZERO,
+              new SqlIdentifier("DIM2", SqlParserPos.ZERO),
+              new SqlIdentifier("ALIAS2", SqlParserPos.ZERO)
+          )
+      );
+
+      DruidExceptionMatcher
+          .invalidSqlInput()
+          .expectMessageIs("Invalid CLUSTERED BY clause [`DIM2` AS `ALIAS2`]: 
cannot use an alias.")
+          .assertThrowsAndMatches(() -> 
DruidSqlParserUtils.validateClusteredByColumns(clusteredByArgs));
+    }
+
     /**
      * Tests clause "CLUSTERED BY DIM1, DIM2, 3, -10"
      */
diff --git 
a/sql/src/test/java/org/apache/druid/sql/calcite/planner/DruidTypeFactoryTest.java
 
b/sql/src/test/java/org/apache/druid/sql/calcite/planner/DruidTypeFactoryTest.java
new file mode 100644
index 00000000000..a0b81056061
--- /dev/null
+++ 
b/sql/src/test/java/org/apache/druid/sql/calcite/planner/DruidTypeFactoryTest.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.sql.calcite.planner;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class DruidTypeFactoryTest
+{
+  private final DruidTypeFactory typeFactory = new 
DruidTypeFactory(DruidTypeSystem.INSTANCE);
+
+  private final RelDataType varcharType = 
typeFactory.createSqlType(SqlTypeName.VARCHAR);
+  private final RelDataType charType = 
typeFactory.createSqlType(SqlTypeName.CHAR, 5);
+  private final RelDataType arrayType = 
typeFactory.createArrayType(varcharType, -1);
+  private final RelDataType multisetType = 
typeFactory.createMultisetType(varcharType, -1);
+  private final RelDataType mapType = typeFactory.createMapType(varcharType, 
varcharType);
+
+  @Test
+  public void testLeastRestrictiveArrayAndCharacter()
+  {
+    
Assertions.assertNull(typeFactory.leastRestrictive(ImmutableList.of(arrayType, 
varcharType)));
+  }
+
+  @Test
+  public void testLeastRestrictiveMultisetAndCharacter()
+  {
+    
Assertions.assertNull(typeFactory.leastRestrictive(ImmutableList.of(multisetType,
 varcharType)));
+  }
+
+  @Test
+  public void testLeastRestrictiveMapAndCharacter()
+  {
+    
Assertions.assertNull(typeFactory.leastRestrictive(ImmutableList.of(mapType, 
varcharType)));
+  }
+
+  @Test
+  public void testLeastRestrictiveArrayAndArray()
+  {
+    Assertions.assertEquals(arrayType, 
typeFactory.leastRestrictive(ImmutableList.of(arrayType, arrayType)));
+  }
+
+  @Test
+  public void testLeastRestrictiveMapAndMap()
+  {
+    Assertions.assertEquals(mapType, 
typeFactory.leastRestrictive(ImmutableList.of(mapType, mapType)));
+  }
+
+  @Test
+  public void testLeastRestrictiveCharacters()
+  {
+    final RelDataType leastRestrictive = 
typeFactory.leastRestrictive(ImmutableList.of(charType, varcharType));
+    Assertions.assertNotNull(leastRestrictive);
+    Assertions.assertEquals(SqlTypeName.VARCHAR, 
leastRestrictive.getSqlTypeName());
+  }
+}
diff --git 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testJoinWithInputRefCondition.iq
 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testJoinWithInputRefCondition.iq
index 4e32b7d3d68..69c2354aba8 100644
--- 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testJoinWithInputRefCondition.iq
+++ 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testJoinWithInputRefCondition.iq
@@ -18,7 +18,7 @@ SELECT COUNT(*) FILTER (WHERE FLOOR(100) NOT IN (SELECT m1 
FROM foo)) FROM foo;
 
 !ok
 LogicalAggregate(group=[{}], EXPR$0=[COUNT() FILTER $0])
-  LogicalProject($f0=[OR(=($8, 0), AND(IS NULL($11), >=($9, $8)))])
+  LogicalProject($f0=[OR(AND(IS NULL($11), >=($9, $8)), =($8, 0))])
     LogicalJoin(condition=[=(CAST(FLOOR(100)):FLOAT NOT NULL, $10)], 
joinType=[left])
       LogicalJoin(condition=[true], joinType=[inner])
         LogicalTableScan(table=[[druid, foo]])
@@ -29,7 +29,7 @@ LogicalAggregate(group=[{}], EXPR$0=[COUNT() FILTER $0])
 
 !logicalPlan
 DruidAggregate(group=[{}], EXPR$0=[COUNT() FILTER $0], druid=[logical])
-  DruidProject($f0=[OR(=($8, 0), AND(IS NULL($11), >=($9, $8)))], 
druid=[logical])
+  DruidProject($f0=[OR(AND(IS NULL($11), >=($9, $8)), =($8, 0))], 
druid=[logical])
     DruidJoin(condition=[=(CAST(FLOOR(100)):FLOAT NOT NULL, $10)], 
joinType=[left])
       DruidJoin(condition=[true], joinType=[inner])
         DruidTableScan(table=[[druid, foo]], druid=[logical])
@@ -140,11 +140,6 @@ DruidAggregate(group=[{}], EXPR$0=[COUNT() FILTER $0], 
druid=[logical])
     "filter" : {
       "type" : "or",
       "fields" : [ {
-        "type" : "equals",
-        "column" : "j0.a0",
-        "matchValueType" : "LONG",
-        "matchValue" : 0
-      }, {
         "type" : "and",
         "fields" : [ {
           "type" : "null",
@@ -153,6 +148,11 @@ DruidAggregate(group=[{}], EXPR$0=[COUNT() FILTER $0], 
druid=[logical])
           "type" : "expression",
           "expression" : "(\"j0.a1\" >= \"j0.a0\")"
         } ]
+      }, {
+        "type" : "equals",
+        "column" : "j0.a0",
+        "matchValueType" : "LONG",
+        "matchValue" : 0
       } ]
     },
     "name" : "a0"
diff --git 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testSemiAndAntiJoinSimultaneouslyUsingWhereInSubquery@all_disabled.iq
 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testSemiAndAntiJoinSimultaneouslyUsingWhereInSubquery@all_disabled.iq
index c99186580e9..f44ae484032 100644
--- 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testSemiAndAntiJoinSimultaneouslyUsingWhereInSubquery@all_disabled.iq
+++ 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testSemiAndAntiJoinSimultaneouslyUsingWhereInSubquery@all_disabled.iq
@@ -26,7 +26,7 @@ GROUP BY 1;
 
 !ok
 LogicalAggregate(group=[{1}], EXPR$1=[COUNT()])
-  LogicalFilter(condition=[OR(=($3, 0), AND(IS NULL($6), >=($4, $3)))])
+  LogicalFilter(condition=[OR(AND(IS NULL($6), >=($4, $3)), =($3, 0))])
     LogicalJoin(condition=[=($0, $5)], joinType=[left])
       LogicalJoin(condition=[true], joinType=[inner])
         LogicalJoin(condition=[=($0, $2)], joinType=[inner])
@@ -44,7 +44,7 @@ LogicalAggregate(group=[{1}], EXPR$1=[COUNT()])
 
 !logicalPlan
 DruidAggregate(group=[{1}], EXPR$1=[COUNT()], druid=[logical])
-  DruidFilter(condition=[OR(=($3, 0), AND(IS NULL($6), >=($4, $3)))])
+  DruidFilter(condition=[OR(AND(IS NULL($6), >=($4, $3)), =($3, 0))])
     DruidJoin(condition=[=($0, $5)], joinType=[left])
       DruidJoin(condition=[true], joinType=[inner])
         DruidJoin(condition=[=($0, $2)], joinType=[inner])
@@ -214,11 +214,6 @@ DruidAggregate(group=[{1}], EXPR$1=[COUNT()], 
druid=[logical])
   "filter" : {
     "type" : "or",
     "fields" : [ {
-      "type" : "equals",
-      "column" : "_j0._a0",
-      "matchValueType" : "LONG",
-      "matchValue" : 0
-    }, {
       "type" : "and",
       "fields" : [ {
         "type" : "null",
@@ -227,6 +222,11 @@ DruidAggregate(group=[{1}], EXPR$1=[COUNT()], 
druid=[logical])
         "type" : "expression",
         "expression" : "(\"_j0._a1\" >= \"_j0._a0\")"
       } ]
+    }, {
+      "type" : "equals",
+      "column" : "_j0._a0",
+      "matchValueType" : "LONG",
+      "matchValue" : 0
     } ]
   },
   "granularity" : {
diff --git 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testSemiAndAntiJoinSimultaneouslyUsingWhereInSubquery@all_enabled.iq
 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testSemiAndAntiJoinSimultaneouslyUsingWhereInSubquery@all_enabled.iq
index 4ccfa907234..206e3950a0e 100644
--- 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testSemiAndAntiJoinSimultaneouslyUsingWhereInSubquery@all_enabled.iq
+++ 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testSemiAndAntiJoinSimultaneouslyUsingWhereInSubquery@all_enabled.iq
@@ -26,7 +26,7 @@ GROUP BY 1;
 
 !ok
 LogicalAggregate(group=[{1}], EXPR$1=[COUNT()])
-  LogicalFilter(condition=[OR(=($3, 0), AND(IS NULL($6), >=($4, $3)))])
+  LogicalFilter(condition=[OR(AND(IS NULL($6), >=($4, $3)), =($3, 0))])
     LogicalJoin(condition=[=($0, $5)], joinType=[left])
       LogicalJoin(condition=[true], joinType=[inner])
         LogicalJoin(condition=[=($0, $2)], joinType=[inner])
@@ -44,7 +44,7 @@ LogicalAggregate(group=[{1}], EXPR$1=[COUNT()])
 
 !logicalPlan
 DruidAggregate(group=[{1}], EXPR$1=[COUNT()], druid=[logical])
-  DruidFilter(condition=[OR(=($3, 0), AND(IS NULL($6), >=($4, $3)))])
+  DruidFilter(condition=[OR(AND(IS NULL($6), >=($4, $3)), =($3, 0))])
     DruidJoin(condition=[=($0, $5)], joinType=[left])
       DruidJoin(condition=[true], joinType=[inner])
         DruidJoin(condition=[=($0, $2)], joinType=[inner])
@@ -214,11 +214,6 @@ DruidAggregate(group=[{1}], EXPR$1=[COUNT()], 
druid=[logical])
   "filter" : {
     "type" : "or",
     "fields" : [ {
-      "type" : "equals",
-      "column" : "_j0._a0",
-      "matchValueType" : "LONG",
-      "matchValue" : 0
-    }, {
       "type" : "and",
       "fields" : [ {
         "type" : "null",
@@ -227,6 +222,11 @@ DruidAggregate(group=[{1}], EXPR$1=[COUNT()], 
druid=[logical])
         "type" : "expression",
         "expression" : "(\"_j0._a1\" >= \"_j0._a0\")"
       } ]
+    }, {
+      "type" : "equals",
+      "column" : "_j0._a0",
+      "matchValueType" : "LONG",
+      "matchValue" : 0
     } ]
   },
   "granularity" : {
diff --git 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/[email protected]
 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/[email protected]
index e37795e1962..aa18de637c6 100644
--- 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/[email protected]
+++ 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/[email protected]
@@ -23,7 +23,7 @@ GROUP BY 1;
 
 !ok
 LogicalAggregate(group=[{1}], EXPR$1=[COUNT()])
-  LogicalFilter(condition=[OR(=($3, 0), AND(IS NULL($6), >=($4, $3)))])
+  LogicalFilter(condition=[OR(AND(IS NULL($6), >=($4, $3)), =($3, 0))])
     LogicalJoin(condition=[=($0, $5)], joinType=[left])
       LogicalJoin(condition=[true], joinType=[inner])
         LogicalJoin(condition=[=($0, $2)], joinType=[inner])
@@ -41,7 +41,7 @@ LogicalAggregate(group=[{1}], EXPR$1=[COUNT()])
 
 !logicalPlan
 DruidAggregate(group=[{1}], EXPR$1=[COUNT()], druid=[logical])
-  DruidFilter(condition=[OR(=($3, 0), AND(IS NULL($6), >=($4, $3)))])
+  DruidFilter(condition=[OR(AND(IS NULL($6), >=($4, $3)), =($3, 0))])
     DruidJoin(condition=[=($0, $5)], joinType=[left])
       DruidJoin(condition=[true], joinType=[inner])
         DruidJoin(condition=[=($0, $2)], joinType=[inner])
@@ -211,11 +211,6 @@ DruidAggregate(group=[{1}], EXPR$1=[COUNT()], 
druid=[logical])
   "filter" : {
     "type" : "or",
     "fields" : [ {
-      "type" : "equals",
-      "column" : "_j0._a0",
-      "matchValueType" : "LONG",
-      "matchValue" : 0
-    }, {
       "type" : "and",
       "fields" : [ {
         "type" : "null",
@@ -224,6 +219,11 @@ DruidAggregate(group=[{1}], EXPR$1=[COUNT()], 
druid=[logical])
         "type" : "expression",
         "expression" : "(\"_j0._a1\" >= \"_j0._a0\")"
       } ]
+    }, {
+      "type" : "equals",
+      "column" : "_j0._a0",
+      "matchValueType" : "LONG",
+      "matchValue" : 0
     } ]
   },
   "granularity" : {
diff --git 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testSemiAndAntiJoinSimultaneouslyUsingWhereInSubquery@filter-on-value-column_disabled.iq
 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testSemiAndAntiJoinSimultaneouslyUsingWhereInSubquery@filter-on-value-column_disabled.iq
index 6988f152a14..893cdcfef39 100644
--- 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testSemiAndAntiJoinSimultaneouslyUsingWhereInSubquery@filter-on-value-column_disabled.iq
+++ 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testSemiAndAntiJoinSimultaneouslyUsingWhereInSubquery@filter-on-value-column_disabled.iq
@@ -26,7 +26,7 @@ GROUP BY 1;
 
 !ok
 LogicalAggregate(group=[{1}], EXPR$1=[COUNT()])
-  LogicalFilter(condition=[OR(=($3, 0), AND(IS NULL($6), >=($4, $3)))])
+  LogicalFilter(condition=[OR(AND(IS NULL($6), >=($4, $3)), =($3, 0))])
     LogicalJoin(condition=[=($0, $5)], joinType=[left])
       LogicalJoin(condition=[true], joinType=[inner])
         LogicalJoin(condition=[=($0, $2)], joinType=[inner])
@@ -44,7 +44,7 @@ LogicalAggregate(group=[{1}], EXPR$1=[COUNT()])
 
 !logicalPlan
 DruidAggregate(group=[{1}], EXPR$1=[COUNT()], druid=[logical])
-  DruidFilter(condition=[OR(=($3, 0), AND(IS NULL($6), >=($4, $3)))])
+  DruidFilter(condition=[OR(AND(IS NULL($6), >=($4, $3)), =($3, 0))])
     DruidJoin(condition=[=($0, $5)], joinType=[left])
       DruidJoin(condition=[true], joinType=[inner])
         DruidJoin(condition=[=($0, $2)], joinType=[inner])
@@ -214,11 +214,6 @@ DruidAggregate(group=[{1}], EXPR$1=[COUNT()], 
druid=[logical])
   "filter" : {
     "type" : "or",
     "fields" : [ {
-      "type" : "equals",
-      "column" : "_j0._a0",
-      "matchValueType" : "LONG",
-      "matchValue" : 0
-    }, {
       "type" : "and",
       "fields" : [ {
         "type" : "null",
@@ -227,6 +222,11 @@ DruidAggregate(group=[{1}], EXPR$1=[COUNT()], 
druid=[logical])
         "type" : "expression",
         "expression" : "(\"_j0._a1\" >= \"_j0._a0\")"
       } ]
+    }, {
+      "type" : "equals",
+      "column" : "_j0._a0",
+      "matchValueType" : "LONG",
+      "matchValue" : 0
     } ]
   },
   "granularity" : {
diff --git 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testsemiandantijoinsimultaneouslyusingwhereinsubqu...@filter-rewrites-disabled.iq
 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testsemiandantijoinsimultaneouslyusingwhereinsubqu...@filter-rewrites-disabled.iq
index 6c75ab1af71..ee539eb1ca4 100644
--- 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testsemiandantijoinsimultaneouslyusingwhereinsubqu...@filter-rewrites-disabled.iq
+++ 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testsemiandantijoinsimultaneouslyusingwhereinsubqu...@filter-rewrites-disabled.iq
@@ -26,7 +26,7 @@ GROUP BY 1;
 
 !ok
 LogicalAggregate(group=[{1}], EXPR$1=[COUNT()])
-  LogicalFilter(condition=[OR(=($3, 0), AND(IS NULL($6), >=($4, $3)))])
+  LogicalFilter(condition=[OR(AND(IS NULL($6), >=($4, $3)), =($3, 0))])
     LogicalJoin(condition=[=($0, $5)], joinType=[left])
       LogicalJoin(condition=[true], joinType=[inner])
         LogicalJoin(condition=[=($0, $2)], joinType=[inner])
@@ -44,7 +44,7 @@ LogicalAggregate(group=[{1}], EXPR$1=[COUNT()])
 
 !logicalPlan
 DruidAggregate(group=[{1}], EXPR$1=[COUNT()], druid=[logical])
-  DruidFilter(condition=[OR(=($3, 0), AND(IS NULL($6), >=($4, $3)))])
+  DruidFilter(condition=[OR(AND(IS NULL($6), >=($4, $3)), =($3, 0))])
     DruidJoin(condition=[=($0, $5)], joinType=[left])
       DruidJoin(condition=[true], joinType=[inner])
         DruidJoin(condition=[=($0, $2)], joinType=[inner])
@@ -214,11 +214,6 @@ DruidAggregate(group=[{1}], EXPR$1=[COUNT()], 
druid=[logical])
   "filter" : {
     "type" : "or",
     "fields" : [ {
-      "type" : "equals",
-      "column" : "_j0._a0",
-      "matchValueType" : "LONG",
-      "matchValue" : 0
-    }, {
       "type" : "and",
       "fields" : [ {
         "type" : "null",
@@ -227,6 +222,11 @@ DruidAggregate(group=[{1}], EXPR$1=[COUNT()], 
druid=[logical])
         "type" : "expression",
         "expression" : "(\"_j0._a1\" >= \"_j0._a0\")"
       } ]
+    }, {
+      "type" : "equals",
+      "column" : "_j0._a0",
+      "matchValueType" : "LONG",
+      "matchValue" : 0
     } ]
   },
   "granularity" : {
diff --git 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testsemiandantijoinsimultaneouslyusingwhereinsubqu...@filter-rewrites.iq
 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testsemiandantijoinsimultaneouslyusingwhereinsubqu...@filter-rewrites.iq
index 5a8578aaad8..f8531a2434a 100644
--- 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testsemiandantijoinsimultaneouslyusingwhereinsubqu...@filter-rewrites.iq
+++ 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testsemiandantijoinsimultaneouslyusingwhereinsubqu...@filter-rewrites.iq
@@ -26,7 +26,7 @@ GROUP BY 1;
 
 !ok
 LogicalAggregate(group=[{1}], EXPR$1=[COUNT()])
-  LogicalFilter(condition=[OR(=($3, 0), AND(IS NULL($6), >=($4, $3)))])
+  LogicalFilter(condition=[OR(AND(IS NULL($6), >=($4, $3)), =($3, 0))])
     LogicalJoin(condition=[=($0, $5)], joinType=[left])
       LogicalJoin(condition=[true], joinType=[inner])
         LogicalJoin(condition=[=($0, $2)], joinType=[inner])
@@ -44,7 +44,7 @@ LogicalAggregate(group=[{1}], EXPR$1=[COUNT()])
 
 !logicalPlan
 DruidAggregate(group=[{1}], EXPR$1=[COUNT()], druid=[logical])
-  DruidFilter(condition=[OR(=($3, 0), AND(IS NULL($6), >=($4, $3)))])
+  DruidFilter(condition=[OR(AND(IS NULL($6), >=($4, $3)), =($3, 0))])
     DruidJoin(condition=[=($0, $5)], joinType=[left])
       DruidJoin(condition=[true], joinType=[inner])
         DruidJoin(condition=[=($0, $2)], joinType=[inner])
@@ -214,11 +214,6 @@ DruidAggregate(group=[{1}], EXPR$1=[COUNT()], 
druid=[logical])
   "filter" : {
     "type" : "or",
     "fields" : [ {
-      "type" : "equals",
-      "column" : "_j0._a0",
-      "matchValueType" : "LONG",
-      "matchValue" : 0
-    }, {
       "type" : "and",
       "fields" : [ {
         "type" : "null",
@@ -227,6 +222,11 @@ DruidAggregate(group=[{1}], EXPR$1=[COUNT()], 
druid=[logical])
         "type" : "expression",
         "expression" : "(\"_j0._a1\" >= \"_j0._a0\")"
       } ]
+    }, {
+      "type" : "equals",
+      "column" : "_j0._a0",
+      "matchValueType" : "LONG",
+      "matchValue" : 0
     } ]
   },
   "granularity" : {
diff --git 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testsemiandantijoinsimultaneouslyusingwhereinsubqu...@join-to-filter.iq
 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testsemiandantijoinsimultaneouslyusingwhereinsubqu...@join-to-filter.iq
index e6cede5cb4b..9898d88f4ec 100644
--- 
a/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testsemiandantijoinsimultaneouslyusingwhereinsubqu...@join-to-filter.iq
+++ 
b/sql/src/test/quidem/org.apache.druid.sql.calcite.DecoupledPlanningCalciteJoinQueryTest/testsemiandantijoinsimultaneouslyusingwhereinsubqu...@join-to-filter.iq
@@ -26,7 +26,7 @@ GROUP BY 1;
 
 !ok
 LogicalAggregate(group=[{1}], EXPR$1=[COUNT()])
-  LogicalFilter(condition=[OR(=($3, 0), AND(IS NULL($6), >=($4, $3)))])
+  LogicalFilter(condition=[OR(AND(IS NULL($6), >=($4, $3)), =($3, 0))])
     LogicalJoin(condition=[=($0, $5)], joinType=[left])
       LogicalJoin(condition=[true], joinType=[inner])
         LogicalJoin(condition=[=($0, $2)], joinType=[inner])
@@ -44,7 +44,7 @@ LogicalAggregate(group=[{1}], EXPR$1=[COUNT()])
 
 !logicalPlan
 DruidAggregate(group=[{1}], EXPR$1=[COUNT()], druid=[logical])
-  DruidFilter(condition=[OR(=($3, 0), AND(IS NULL($6), >=($4, $3)))])
+  DruidFilter(condition=[OR(AND(IS NULL($6), >=($4, $3)), =($3, 0))])
     DruidJoin(condition=[=($0, $5)], joinType=[left])
       DruidJoin(condition=[true], joinType=[inner])
         DruidJoin(condition=[=($0, $2)], joinType=[inner])
@@ -214,11 +214,6 @@ DruidAggregate(group=[{1}], EXPR$1=[COUNT()], 
druid=[logical])
   "filter" : {
     "type" : "or",
     "fields" : [ {
-      "type" : "equals",
-      "column" : "_j0._a0",
-      "matchValueType" : "LONG",
-      "matchValue" : 0
-    }, {
       "type" : "and",
       "fields" : [ {
         "type" : "null",
@@ -227,6 +222,11 @@ DruidAggregate(group=[{1}], EXPR$1=[COUNT()], 
druid=[logical])
         "type" : "expression",
         "expression" : "(\"_j0._a1\" >= \"_j0._a0\")"
       } ]
+    }, {
+      "type" : "equals",
+      "column" : "_j0._a0",
+      "matchValueType" : "LONG",
+      "matchValue" : 0
     } ]
   },
   "granularity" : {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to