@@ -292,15 +292,38 @@ public Expression visitIn(In node, AnalysisContext context) {
292292
293293 private Expression visitIn (
294294 UnresolvedExpression field , List <UnresolvedExpression > valueList , AnalysisContext context ) {
295- if (valueList .size () == 1 ) {
296- return visitCompare (new Compare ("=" , field , valueList .get (0 )), context );
297- } else if (valueList .size () > 1 ) {
298- return DSL .or (
299- visitCompare (new Compare ("=" , field , valueList .get (0 )), context ),
300- visitIn (field , valueList .subList (1 , valueList .size ()), context ));
301- } else {
295+ if (valueList .isEmpty ()) {
302296 throw new SemanticCheckException ("Values in In clause should not be empty" );
303297 }
298+
299+ Expression [] expressions = new Expression [valueList .size ()];
300+
301+ for (int i = 0 ; i < expressions .length ; i ++) {
302+ expressions [i ] = visitCompare (new Compare ("=" , field , valueList .get (i )), context );
303+ }
304+
305+ return buildOrTree (expressions , 0 , expressions .length );
306+ }
307+
308+ /**
309+ * `DSL.or` can only take two arguments. To represent large lists without massive recursion, we
310+ * want to represent the expression as a balanced tree. This builds that tree from a node list.
311+ *
312+ * @param children The list of expressions to merge.
313+ * @param start The starting position (inclusive) for the current combination step.
314+ * @param end The ending position (exclusive) for the current combination step. If <= start,
315+ * children[start] is returned.
316+ * @return The final `DSL.or` expression.
317+ */
318+ private Expression buildOrTree (Expression [] children , int start , int end ) {
319+ if (end - start <= 1 ) {
320+ return children [start ];
321+ }
322+ if (end - start == 2 ) {
323+ return DSL .or (children [start ], children [end - 1 ]);
324+ }
325+ int split = start + (end - start ) / 2 ;
326+ return DSL .or (buildOrTree (children , start , split ), buildOrTree (children , split , end ));
304327 }
305328
306329 @ Override
0 commit comments