From 519f3575bca99434e784562938d209dfa9e673da Mon Sep 17 00:00:00 2001 From: Ruben Quesada Lopez Date: Mon, 18 May 2026 10:52:50 +0100 Subject: [PATCH 1/6] HIVE-28931: Convert IN to SEARCH in RexNodeConverter --- .../calcite/translator/RexNodeConverter.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java index ab9eb330b3a5..98f2329df1b0 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java @@ -265,13 +265,14 @@ private RexNode convert(ExprNodeGenericFuncDesc func) throws SemanticException { // except complex types calciteOp = SqlStdOperatorTable.EQUALS; } else if (RexUtil.isReferenceOrAccess(childRexNodeLst.get(0), true)){ - // if it is more than an single item in an IN clause, - // transform from IN [A,B,C] => OR [EQUALS [A,B], EQUALS [A,C]] + // if it is more than a single item in an IN clause, + // transform from IN [A,B,C] => SEARCH(A, SARG([B..B], [C..C])) // except complex types - // Rewrite to OR is done only if number of operands are less than - // the threshold configured - childRexNodeLst = rewriteInClauseChildren(calciteOp, childRexNodeLst, rexBuilder); - calciteOp = SqlStdOperatorTable.OR; + RexNode rewritten = rewriteInClause(calciteOp, childRexNodeLst, rexBuilder); + assert rewritten instanceof RexCall; + RexCall call = (RexCall) rewritten; + calciteOp = call.op; + childRexNodeLst = call.operands; } } else if (calciteOp.getKind() == SqlKind.COALESCE && childRexNodeLst.size() > 1) { @@ -577,6 +578,14 @@ public static List transformInToOrOperands(List operands, RexB return disjuncts; } + public static RexNode rewriteInClause(SqlOperator op, List childRexNodeLst, + RexBuilder rexBuilder) { + assert op == HiveIn.INSTANCE; + RexNode firstPred = childRexNodeLst.get(0); + List ranges = childRexNodeLst.subList(1, childRexNodeLst.size()); + return rexBuilder.makeIn(firstPred, ranges); + } + public static List rewriteInClauseChildren(SqlOperator op, List childRexNodeLst, RexBuilder rexBuilder) throws SemanticException { assert op == HiveIn.INSTANCE; From 393009d95521bc2bc8caa93565609c14d357d887 Mon Sep 17 00:00:00 2001 From: Ruben Quesada Lopez Date: Mon, 18 May 2026 13:07:56 +0100 Subject: [PATCH 2/6] Improve RexNodeConverter#rewriteInClause, apply changes on HiveFunctionHelper --- .../calcite/translator/RexNodeConverter.java | 43 +++++++++++++------ .../ql/parse/type/HiveFunctionHelper.java | 32 ++++++-------- 2 files changed, 41 insertions(+), 34 deletions(-) diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java index 98f2329df1b0..3ad4c78b990c 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java @@ -259,16 +259,8 @@ private RexNode convert(ExprNodeGenericFuncDesc func) throws SemanticException { // If it is a floor operator, we need to rewrite it childRexNodeLst = rewriteFloorDateChildren(calciteOp, childRexNodeLst, rexBuilder); } else if (HiveIn.INSTANCE.equals(calciteOp) && isAllPrimitive) { - if (childRexNodeLst.size() == 2) { - // if it is a single item in an IN clause, transform A IN (B) to A = B - // from IN [A,B] => EQUALS [A,B] - // except complex types - calciteOp = SqlStdOperatorTable.EQUALS; - } else if (RexUtil.isReferenceOrAccess(childRexNodeLst.get(0), true)){ - // if it is more than a single item in an IN clause, - // transform from IN [A,B,C] => SEARCH(A, SARG([B..B], [C..C])) - // except complex types - RexNode rewritten = rewriteInClause(calciteOp, childRexNodeLst, rexBuilder); + if (childRexNodeLst.size() == 2 || RexUtil.isReferenceOrAccess(childRexNodeLst.get(0), true)) { + RexNode rewritten = rewriteInClause(childRexNodeLst, rexBuilder); assert rewritten instanceof RexCall; RexCall call = (RexCall) rewritten; calciteOp = call.op; @@ -578,14 +570,37 @@ public static List transformInToOrOperands(List operands, RexB return disjuncts; } - public static RexNode rewriteInClause(SqlOperator op, List childRexNodeLst, - RexBuilder rexBuilder) { - assert op == HiveIn.INSTANCE; + /** + * This method tries to rewrite IN expression arguments into an equivalent call. + * If there are only two elements, generates an EQUALS: + * IN [A,B] => EQUALS [A,B] + * Otherwise, tries to generate a SEARCH: + * IN [A,B,C] => SEARCH(A, SARG([B..B], [C..C])) + * If this is not possible (e.g., argument types not sufficiently compatible to generate a Calcite SEARCH expression), + * tries to generate an OR expression: + * IN [A,B,C] => OR [EQUALS [A,B], EQUALS [A,C]] + * If this is not possible (e.g., non-deterministic calls are found in the expressions), returns null + */ + public static RexNode rewriteInClause(List childRexNodeLst, RexBuilder rexBuilder) { + if (childRexNodeLst.size() == 2) { + return rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, childRexNodeLst); + } + RexNode firstPred = childRexNodeLst.get(0); List ranges = childRexNodeLst.subList(1, childRexNodeLst.size()); - return rexBuilder.makeIn(firstPred, ranges); + RexNode res = rexBuilder.makeIn(firstPred, ranges); + if (res.getKind() == SqlKind.SEARCH) { + return res; + } + // Calcite SEARCH conversion was not possible: generate our own OR expression + List newInputs = RexNodeConverter.transformInToOrOperands(childRexNodeLst, rexBuilder); + if (newInputs == null) { + return null; + } + return newInputs.size() == 1 ? newInputs.get(0) : rexBuilder.makeCall(SqlStdOperatorTable.OR, newInputs); } + // TODO remove? public static List rewriteInClauseChildren(SqlOperator op, List childRexNodeLst, RexBuilder rexBuilder) throws SemanticException { assert op == HiveIn.INSTANCE; diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/type/HiveFunctionHelper.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/type/HiveFunctionHelper.java index 556388c71914..ab0473f0b90b 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/type/HiveFunctionHelper.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/type/HiveFunctionHelper.java @@ -267,27 +267,19 @@ public RexNode getExpression(String functionText, FunctionInfo fi, // If it is a floor operator, we need to rewrite it inputs = RexNodeConverter.rewriteFloorDateChildren(calciteOp, inputs, rexBuilder); } else if (HiveIn.INSTANCE.equals(calciteOp)) { - // if it is a single item in an IN clause, transform A IN (B) to A = B - // from IN [A,B] => EQUALS [A,B] - // if it is more than an single item in an IN clause, - // transform from IN [A,B,C] => OR [EQUALS [A,B], EQUALS [A,C]] - // Rewrite to OR is done only if number of operands are less than - // the threshold configured - boolean rewriteToOr = true; - if(maxNodesForInToOrTransformation != 0) { - if(inputs.size() > maxNodesForInToOrTransformation) { - rewriteToOr = false; - } - } - if(rewriteToOr) { - // If there are non-deterministic functions, we cannot perform this rewriting - List newInputs = RexNodeConverter.transformInToOrOperands(inputs, rexBuilder); - if (newInputs != null) { - inputs = newInputs; - if (inputs.size() == 1) { - inputs.add(rexBuilder.makeLiteral(false)); + RexNode rewritten = RexNodeConverter.rewriteInClause(inputs, rexBuilder); + if (rewritten != null) { + assert rewritten instanceof RexCall; + RexCall call = (RexCall) rewritten; + if (call.getKind() == SqlKind.OR && maxNodesForInToOrTransformation != 0) { + // Rewrite to OR is done only if number of operands are less than the threshold configured + if (call.getOperands().size() <= maxNodesForInToOrTransformation) { + calciteOp = call.op; + inputs = call.operands; } - calciteOp = SqlStdOperatorTable.OR; + } else { + calciteOp = call.op; + inputs = call.operands; } } } else if (calciteOp.getKind() == SqlKind.COALESCE && From ff031f6fc2fac6909790186ab0ac5b83a20d536c Mon Sep 17 00:00:00 2001 From: Ruben Quesada Lopez Date: Tue, 19 May 2026 16:04:19 +0100 Subject: [PATCH 3/6] Refactoring --- .../calcite/translator/RexNodeConverter.java | 51 ++++++++++--------- .../ql/parse/type/HiveFunctionHelper.java | 22 +------- 2 files changed, 30 insertions(+), 43 deletions(-) diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java index 3ad4c78b990c..4b2b56120ccd 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java @@ -54,7 +54,10 @@ import org.apache.hadoop.hive.common.type.HiveVarchar; import org.apache.hadoop.hive.common.type.Timestamp; import org.apache.hadoop.hive.common.type.TimestampTZ; +import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.ql.exec.FunctionRegistry; +import org.apache.hadoop.hive.ql.metadata.Hive; +import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.hive.ql.optimizer.calcite.CalciteSemanticException; import org.apache.hadoop.hive.ql.optimizer.calcite.CalciteSemanticException.UnsupportedFeature; import org.apache.hadoop.hive.ql.optimizer.calcite.HiveCalciteUtil; @@ -117,6 +120,16 @@ public class RexNodeConverter { private final RexBuilder rexBuilder; private final RelDataTypeFactory typeFactory; + private static final int MAX_NODES_FOR_IN_TO_OR_TRANSFORMATION; + + static { + try { + MAX_NODES_FOR_IN_TO_OR_TRANSFORMATION = HiveConf.getIntVar( + Hive.get().getConf(), HiveConf.ConfVars.HIVEOPT_TRANSFORM_IN_MAXNODES); + } catch (HiveException e) { + throw new IllegalStateException(e); + } + } /** * Constructor used by HiveRexExecutorImpl. @@ -579,39 +592,31 @@ public static List transformInToOrOperands(List operands, RexB * If this is not possible (e.g., argument types not sufficiently compatible to generate a Calcite SEARCH expression), * tries to generate an OR expression: * IN [A,B,C] => OR [EQUALS [A,B], EQUALS [A,C]] - * If this is not possible (e.g., non-deterministic calls are found in the expressions), returns null + * If this is not possible (e.g., non-deterministic calls are found in the expressions), returns null. */ public static RexNode rewriteInClause(List childRexNodeLst, RexBuilder rexBuilder) { if (childRexNodeLst.size() == 2) { return rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, childRexNodeLst); } - RexNode firstPred = childRexNodeLst.get(0); + RexNode arg = childRexNodeLst.get(0); List ranges = childRexNodeLst.subList(1, childRexNodeLst.size()); - RexNode res = rexBuilder.makeIn(firstPred, ranges); - if (res.getKind() == SqlKind.SEARCH) { - return res; - } - // Calcite SEARCH conversion was not possible: generate our own OR expression - List newInputs = RexNodeConverter.transformInToOrOperands(childRexNodeLst, rexBuilder); - if (newInputs == null) { - return null; + // Avoid SEARCH on rows for the moment (it can lead to issues in Calcite), and check all types are SEARCH-compatible + if (arg.getKind() != SqlKind.ROW + && ranges.stream().allMatch(range -> SqlTypeUtil.inSameFamily(arg.getType(), range.getType()))) { + RexNode search = rexBuilder.makeIn(arg, ranges); + assert search.getKind() == SqlKind.SEARCH; + return search; } - return newInputs.size() == 1 ? newInputs.get(0) : rexBuilder.makeCall(SqlStdOperatorTable.OR, newInputs); - } - // TODO remove? - public static List rewriteInClauseChildren(SqlOperator op, List childRexNodeLst, - RexBuilder rexBuilder) throws SemanticException { - assert op == HiveIn.INSTANCE; - RexNode firstPred = childRexNodeLst.get(0); - List newChildRexNodeLst = new ArrayList(); - for (int i = 1; i < childRexNodeLst.size(); i++) { - newChildRexNodeLst.add( - rexBuilder.makeCall( - SqlStdOperatorTable.EQUALS, firstPred, childRexNodeLst.get(i))); + // Calcite SEARCH conversion was not possible: generate our own OR expression + if (MAX_NODES_FOR_IN_TO_OR_TRANSFORMATION == 0 || childRexNodeLst.size() <= MAX_NODES_FOR_IN_TO_OR_TRANSFORMATION) { + List newInputs = RexNodeConverter.transformInToOrOperands(childRexNodeLst, rexBuilder); + if (newInputs != null) { + return newInputs.size() == 1 ? newInputs.get(0) : rexBuilder.makeCall(SqlStdOperatorTable.OR, newInputs); + } } - return newChildRexNodeLst; + return null; } public static List rewriteCoalesceChildren( diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/type/HiveFunctionHelper.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/type/HiveFunctionHelper.java index ab0473f0b90b..affc07032afb 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/type/HiveFunctionHelper.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/type/HiveFunctionHelper.java @@ -38,12 +38,9 @@ import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.util.Util; -import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.ql.exec.FunctionInfo; import org.apache.hadoop.hive.ql.exec.FunctionRegistry; import org.apache.hadoop.hive.ql.exec.HiveFunctionInfo; -import org.apache.hadoop.hive.ql.metadata.Hive; -import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.hive.ql.optimizer.calcite.HiveRexExecutorImpl; import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveExtractDate; import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveFloorDate; @@ -102,16 +99,9 @@ public class HiveFunctionHelper implements FunctionHelper { private static final Logger LOG = LoggerFactory.getLogger(HiveFunctionHelper.class); private final RexBuilder rexBuilder; - private final int maxNodesForInToOrTransformation; public HiveFunctionHelper(RexBuilder rexBuilder) { this.rexBuilder = rexBuilder; - try { - this.maxNodesForInToOrTransformation = HiveConf.getIntVar( - Hive.get().getConf(), HiveConf.ConfVars.HIVEOPT_TRANSFORM_IN_MAXNODES); - } catch (HiveException e) { - throw new IllegalStateException(e); - } } /** @@ -271,16 +261,8 @@ public RexNode getExpression(String functionText, FunctionInfo fi, if (rewritten != null) { assert rewritten instanceof RexCall; RexCall call = (RexCall) rewritten; - if (call.getKind() == SqlKind.OR && maxNodesForInToOrTransformation != 0) { - // Rewrite to OR is done only if number of operands are less than the threshold configured - if (call.getOperands().size() <= maxNodesForInToOrTransformation) { - calciteOp = call.op; - inputs = call.operands; - } - } else { - calciteOp = call.op; - inputs = call.operands; - } + calciteOp = call.op; + inputs = call.operands; } } else if (calciteOp.getKind() == SqlKind.COALESCE && inputs.size() > 1) { From 6fc1566b6b7a96b135164cbc518bf253dee82bc4 Mon Sep 17 00:00:00 2001 From: Ruben Quesada Lopez Date: Tue, 19 May 2026 18:44:42 +0100 Subject: [PATCH 4/6] Fix condition --- .../hive/ql/optimizer/calcite/translator/RexNodeConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java index 4b2b56120ccd..0ee9cf6d0ccb 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java @@ -602,7 +602,7 @@ public static RexNode rewriteInClause(List childRexNodeLst, RexBuilder RexNode arg = childRexNodeLst.get(0); List ranges = childRexNodeLst.subList(1, childRexNodeLst.size()); // Avoid SEARCH on rows for the moment (it can lead to issues in Calcite), and check all types are SEARCH-compatible - if (arg.getKind() != SqlKind.ROW + if (!arg.getType().isStruct() && ranges.stream().allMatch(range -> SqlTypeUtil.inSameFamily(arg.getType(), range.getType()))) { RexNode search = rexBuilder.makeIn(arg, ranges); assert search.getKind() == SqlKind.SEARCH; From 36a0eeea4ccc1a9b3afccf68b941f0b0fa9dfee8 Mon Sep 17 00:00:00 2001 From: Ruben Quesada Lopez Date: Wed, 20 May 2026 09:51:47 +0100 Subject: [PATCH 5/6] Search can only be created on Literal arguments --- .../ql/optimizer/calcite/translator/RexNodeConverter.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java index 0ee9cf6d0ccb..53324cba1b8d 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java @@ -602,10 +602,12 @@ public static RexNode rewriteInClause(List childRexNodeLst, RexBuilder RexNode arg = childRexNodeLst.get(0); List ranges = childRexNodeLst.subList(1, childRexNodeLst.size()); // Avoid SEARCH on rows for the moment (it can lead to issues in Calcite), and check all types are SEARCH-compatible - if (!arg.getType().isStruct() - && ranges.stream().allMatch(range -> SqlTypeUtil.inSameFamily(arg.getType(), range.getType()))) { + if (!arg.getType().isStruct() && ranges.stream().allMatch(range -> range.getKind() == SqlKind.LITERAL + && SqlTypeUtil.inSameFamily(arg.getType(), range.getType()))) { RexNode search = rexBuilder.makeIn(arg, ranges); - assert search.getKind() == SqlKind.SEARCH; + if (search.getKind() != SqlKind.SEARCH) { + throw new AssertionError("SEARCH creation failed: " + search); + } return search; } From a569e2366b2770c67679e9d407011fe12477275a Mon Sep 17 00:00:00 2001 From: Ruben Quesada Lopez Date: Wed, 20 May 2026 16:09:28 +0100 Subject: [PATCH 6/6] Fix search handling in HiveReduceExpressionsWithStatsRule, and null handling in RexNodeConverter#rewriteInClause --- .../HiveReduceExpressionsWithStatsRule.java | 20 ++++++++++++++++--- .../calcite/translator/RexNodeConverter.java | 1 + 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveReduceExpressionsWithStatsRule.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveReduceExpressionsWithStatsRule.java index 74de4c58660c..19198a52424b 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveReduceExpressionsWithStatsRule.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveReduceExpressionsWithStatsRule.java @@ -39,8 +39,10 @@ import org.apache.calcite.rex.RexUnknownAs; import org.apache.calcite.rex.RexUtil; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.util.Pair; import org.apache.hadoop.hive.ql.optimizer.calcite.RelOptHiveTable; +import org.apache.hadoop.hive.ql.optimizer.calcite.SearchTransformer; import org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveIn; import org.apache.hadoop.hive.ql.plan.ColStatistics; import org.apache.hadoop.hive.ql.stats.StatsUtils; @@ -189,10 +191,14 @@ public RexNode visitCall(RexCall call) { newOperands.add(operand); } } - if (newOperands.size() == 1) { - return rexBuilder.makeLiteral(false); + switch (newOperands.size()) { + case 1: + return rexBuilder.makeLiteral(false); + case 2: + return rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, newOperands); + default: + return rexBuilder.makeCall(HiveIn.INSTANCE, newOperands); } - return rexBuilder.makeCall(HiveIn.INSTANCE, newOperands); } } else if (call.getOperands().get(0).getKind() == SqlKind.ROW) { // Struct @@ -269,6 +275,14 @@ public RexNode visitCall(RexCall call) { } } } + } else if (call.getKind() == SqlKind.SEARCH) { + // TODO process SEARCH as is? + RexNode expanded = new SearchTransformer<> (rexBuilder, call, RexUnknownAs.UNKNOWN).transform(); + RexNode processed = expanded.accept(this); + if (expanded != processed) { + return processed; + } + return call; } // If we did not reduce, check the children nodes diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java index 53324cba1b8d..f315cb62aed2 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java @@ -603,6 +603,7 @@ public static RexNode rewriteInClause(List childRexNodeLst, RexBuilder List ranges = childRexNodeLst.subList(1, childRexNodeLst.size()); // Avoid SEARCH on rows for the moment (it can lead to issues in Calcite), and check all types are SEARCH-compatible if (!arg.getType().isStruct() && ranges.stream().allMatch(range -> range.getKind() == SqlKind.LITERAL + && !RexLiteral.isNullLiteral(range) && SqlTypeUtil.inSameFamily(arg.getType(), range.getType()))) { RexNode search = rexBuilder.makeIn(arg, ranges); if (search.getKind() != SqlKind.SEARCH) {