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]