def range_for_typeref( typeref: irast.TypeRef, path_id: irast.PathId, *, for_mutation: bool = False, include_descendants: bool = True, dml_source: Optional[irast.MutatingStmt] = None, common_parent: bool = False, ctx: context.CompilerContextLevel, ) -> pgast.PathRangeVar: if typeref.common_parent is not None and common_parent: rvar = range_for_material_objtype( typeref.common_parent, path_id, include_descendants=include_descendants, for_mutation=for_mutation, dml_source=dml_source, ctx=ctx, ) elif typeref.union: # Union object types are represented as a UNION of selects # from their children, which is, for most purposes, equivalent # to SELECTing from a parent table. set_ops = [] for child in typeref.union: c_rvar = range_for_typeref( child, path_id=path_id, include_descendants=not typeref.union_is_concrete, for_mutation=for_mutation, dml_source=dml_source, ctx=ctx, ) qry = pgast.SelectStmt(from_clause=[c_rvar], ) pathctx.put_path_value_rvar(qry, path_id, c_rvar, env=ctx.env) if path_id.is_objtype_path(): pathctx.put_path_source_rvar(qry, path_id, c_rvar, env=ctx.env) pathctx.put_path_bond(qry, path_id) set_ops.append(('union', qry)) rvar = range_from_queryset(set_ops, typeref.name_hint, ctx=ctx) elif typeref.intersection: wrapper = pgast.SelectStmt() component_rvars = [] for component in typeref.intersection: component_rvar = range_for_typeref( component, path_id=path_id, for_mutation=for_mutation, dml_source=dml_source, ctx=ctx, ) pathctx.put_rvar_path_bond(component_rvar, path_id) component_rvars.append(component_rvar) include_rvar(wrapper, component_rvar, path_id, ctx=ctx) int_rvar = pgast.IntersectionRangeVar(component_rvars=component_rvars) for aspect in ('source', 'value'): pathctx.put_path_rvar(wrapper, path_id, int_rvar, aspect=aspect, env=ctx.env) pathctx.put_path_bond(wrapper, path_id) rvar = rvar_for_rel(wrapper, ctx=ctx) else: rvar = range_for_material_objtype( typeref, path_id, include_descendants=include_descendants, for_mutation=for_mutation, dml_source=dml_source, ctx=ctx, ) rvar.query.path_id = path_id return rvar
def new_root_rvar(ir_set: irast.Set, *, typeref: Optional[irast.TypeRef] = None, as_intersection_el: bool = False, ctx: context.CompilerContextLevel) -> pgast.PathRangeVar: if not ir_set.path_id.is_objtype_path(): raise ValueError('cannot create root rvar for non-object path') if typeref is None: typeref = ir_set.typeref if typeref.intersection: wrapper = pgast.SelectStmt() component_rvars = [] for component in typeref.intersection: component_rvar = new_root_rvar( ir_set, typeref=component, as_intersection_el=True, ctx=ctx, ) component_rvars.append(component_rvar) include_rvar(wrapper, component_rvar, ir_set.path_id, ctx=ctx) int_rvar = pgast.IntersectionRangeVar(component_rvars=component_rvars) for aspect in ('source', 'value'): pathctx.put_path_rvar(wrapper, ir_set.path_id, int_rvar, aspect=aspect, env=ctx.env) result_rvar = rvar_for_rel(wrapper, ctx=ctx) pathctx.put_rvar_path_bond(result_rvar, ir_set.path_id) return result_rvar dml_source = irutils.get_nearest_dml_stmt(ir_set) set_rvar = range_for_typeref(typeref, ir_set.path_id, dml_source=dml_source, ctx=ctx) pathctx.put_rvar_path_bond(set_rvar, ir_set.path_id) set_rvar.query.value_scope.add(ir_set.path_id) if ir_set.rptr and ir_set.rptr.is_inbound: ptrref = ir_set.rptr.ptrref ptr_info = pg_types.get_ptrref_storage_info(ptrref, resolve_type=False, link_bias=False) if (ptr_info.table_type == 'ObjectType' and (not as_intersection_el or typeref == ptrref.dir_target)): # Inline link prefix_path_id = ir_set.path_id.src_path() assert prefix_path_id is not None, 'expected a path' rref = pgast.ColumnRef(name=[ptr_info.column_name], nullable=not ptrref.required) pathctx.put_rvar_path_bond(set_rvar, prefix_path_id) pathctx.put_rvar_path_output(set_rvar, prefix_path_id, aspect='identity', var=rref, env=ctx.env) if astutils.is_set_op_query(set_rvar.query): assert isinstance(set_rvar.query, pgast.SelectStmt) astutils.for_each_query_in_set( set_rvar.query, lambda qry: qry.target_list.append( pgast.ResTarget( val=rref, name=ptr_info.column_name, ))) return set_rvar