def semi_join(stmt: pgast.Query, ir_set: irast.Set, src_rvar: pgast.BaseRangeVar, *, ctx: context.CompilerContextLevel) -> pgast.BaseRangeVar: """Join an IR Set using semi-join.""" rptr = ir_set.rptr # Target set range. typeref = ctx.join_target_type_filter.get(ir_set, ir_set.typeref) set_rvar = new_root_rvar(ir_set, typeref=typeref, ctx=ctx) ptrref = rptr.ptrref ptr_info = pg_types.get_ptrref_storage_info(ptrref, resolve_type=False) if ptr_info.table_type == 'ObjectType': if irtyputils.is_inbound_ptrref(ptrref): far_pid = ir_set.path_id.src_path() else: far_pid = ir_set.path_id else: far_pid = ir_set.path_id # Link range. map_rvar = new_pointer_rvar(rptr, src_rvar=src_rvar, ctx=ctx) include_rvar(ctx.rel, map_rvar, path_id=ir_set.path_id.ptr_path(), ctx=ctx) tgt_ref = pathctx.get_rvar_path_identity_var(set_rvar, far_pid, env=ctx.env) pathctx.get_path_identity_output(ctx.rel, far_pid, env=ctx.env) cond = astutils.new_binop(tgt_ref, ctx.rel, 'IN') stmt.where_clause = astutils.extend_binop(stmt.where_clause, cond) return set_rvar
def rel_join(query: pgast.Query, right_rvar: pgast.BaseRangeVar, *, ctx: context.CompilerContextLevel) -> None: condition = None for path_id in right_rvar.path_scope: lref = maybe_get_path_var(query, path_id, aspect='identity', ctx=ctx) if lref is None: lref = maybe_get_path_var(query, path_id, aspect='value', ctx=ctx) if lref is None: continue rref = pathctx.get_rvar_path_identity_var(right_rvar, path_id, env=ctx.env) path_cond = astutils.join_condition(lref, rref) condition = astutils.extend_binop(condition, path_cond) if condition is None: join_type = 'cross' else: join_type = 'inner' if not query.from_clause: query.from_clause.append(right_rvar) if condition is not None: query.where_clause = astutils.extend_binop(query.where_clause, condition) else: larg = query.from_clause[0] rarg = right_rvar query.from_clause[0] = pgast.JoinExpr(type=join_type, larg=larg, rarg=rarg, quals=condition)