gianm commented on code in PR #16388:
URL: https://github.com/apache/druid/pull/16388#discussion_r1597101353
##########
sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidSqlValidator.java:
##########
@@ -774,6 +776,59 @@ public void validateCall(SqlCall call, SqlValidatorScope
scope)
super.validateCall(call, scope);
}
+ @Override
+ protected SqlNode performUnconditionalRewrites(SqlNode node, final boolean
underFrom)
+ {
+ if (node != null && (node.getKind() == SqlKind.IN || node.getKind() ==
SqlKind.NOT_IN)) {
+ final SqlNode rewritten = rewriteInToScalarInArrayIfNeeded((SqlCall)
node, underFrom);
+ //noinspection ObjectEquality
+ if (rewritten != node) {
+ return rewritten;
+ }
+ }
+
+ return super.performUnconditionalRewrites(node, underFrom);
+ }
+
+ /**
+ * Rewrites "x IN (values)" to "SCALAR_IN_ARRAY(x, values)", if appropriate.
Checks the form of the IN and checks
+ * the value of {@link QueryContext#getInFunctionThreshold()}.
+ *
+ * @param call call to {@link SqlKind#IN} or {@link SqlKind#NOT_IN}
+ * @param underFrom underFrom arg from {@link
#performUnconditionalRewrites(SqlNode, boolean)}, used for
+ * recursive calls
+ *
+ * @return rewritten call, or the original call if no rewrite was appropriate
+ */
+ private SqlNode rewriteInToScalarInArrayIfNeeded(final SqlCall call, final
boolean underFrom)
+ {
+ if (call.getOperandList().size() == 2 && call.getOperandList().get(1)
instanceof SqlNodeList) {
+ // expr IN (values)
+ final SqlNode exprNode = call.getOperandList().get(0);
+ final SqlNodeList valuesNode = (SqlNodeList)
call.getOperandList().get(1);
+
+ // Confirm valuesNode is big enough to convert to SCALAR_IN_ARRAY, and
references only nonnull literals.
+ // (Can't include NULL literals in the conversion, because
SCALAR_IN_ARRAY matches NULLs as if they were regular
+ // values, whereas IN does not.)
+ if (valuesNode.size() >
plannerContext.queryContext().getInFunctionThreshold()
+ && valuesNode.stream().allMatch(node -> node.getKind() ==
SqlKind.LITERAL && !SqlUtil.isNull(node))) {
Review Comment:
Extending this to split the call up into multiple calls would add
complexity, and I was trying to keep the logic simple. I figured it would not
be common to include `NULL` or nonliterals in the `IN`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]