@@ -336,6 +336,68 @@ def join(
336336
337337 return SQLGlotIR (expr = new_expr , uid_gen = self .uid_gen )
338338
339+ def isin_join (
340+ self ,
341+ right : SQLGlotIR ,
342+ indicator_col : str ,
343+ conditions : tuple [typed_expr .TypedExpr , typed_expr .TypedExpr ],
344+ joins_nulls : bool = True ,
345+ ) -> SQLGlotIR :
346+ """Joins the current query with another SQLGlotIR instance."""
347+ left_cte_name = sge .to_identifier (
348+ next (self .uid_gen .get_uid_stream ("bfcte_" )), quoted = self .quoted
349+ )
350+
351+ left_select = _select_to_cte (self .expr , left_cte_name )
352+ # Prefer subquery over CTE for the IN clause's right side to improve SQL readability.
353+ right_select = right .expr
354+
355+ left_ctes = left_select .args .pop ("with" , [])
356+ right_ctes = right_select .args .pop ("with" , [])
357+ merged_ctes = [* left_ctes , * right_ctes ]
358+
359+ left_condition = typed_expr .TypedExpr (
360+ sge .Column (this = conditions [0 ].expr , table = left_cte_name ),
361+ conditions [0 ].dtype ,
362+ )
363+
364+ new_column : sge .Expression
365+ if joins_nulls :
366+ right_table_name = sge .to_identifier (
367+ next (self .uid_gen .get_uid_stream ("bft_" )), quoted = self .quoted
368+ )
369+ right_condition = typed_expr .TypedExpr (
370+ sge .Column (this = conditions [1 ].expr , table = right_table_name ),
371+ conditions [1 ].dtype ,
372+ )
373+ new_column = sge .Exists (
374+ this = sge .Select ()
375+ .select (sge .convert (1 ))
376+ .from_ (sge .Alias (this = right_select .subquery (), alias = right_table_name ))
377+ .where (
378+ _join_condition (left_condition , right_condition , joins_nulls = True )
379+ )
380+ )
381+ else :
382+ new_column = sge .In (
383+ this = left_condition .expr ,
384+ expressions = [right_select .subquery ()],
385+ )
386+
387+ new_column = sge .Alias (
388+ this = new_column ,
389+ alias = sge .to_identifier (indicator_col , quoted = self .quoted ),
390+ )
391+
392+ new_expr = (
393+ sge .Select ()
394+ .select (sge .Column (this = sge .Star (), table = left_cte_name ), new_column )
395+ .from_ (sge .Table (this = left_cte_name ))
396+ )
397+ new_expr .set ("with" , sge .With (expressions = merged_ctes ))
398+
399+ return SQLGlotIR (expr = new_expr , uid_gen = self .uid_gen )
400+
339401 def explode (
340402 self ,
341403 column_names : tuple [str , ...],
0 commit comments