def _compile_shape(ir_set: irast.Set, shape: typing.List[irast.Set], *, ctx: context.CompilerContextLevel) -> pgast.TupleVar: result = shapecomp.compile_shape(ir_set, shape, ctx=ctx) for element in result.elements: # The ref might have already been added by the nested shape # processing, so add it conditionally. pathctx.put_path_var_if_not_exists(ctx.rel, element.path_id, element.val, aspect='serialized', env=ctx.env) ser_elements = [] for el in result.elements: ser_val = pathctx.get_path_serialized_or_value_var(ctx.rel, el.path_id, env=ctx.env) ser_elements.append( pgast.TupleElement(path_id=el.path_id, name=el.name, val=ser_val)) ser_result = pgast.TupleVar(elements=ser_elements, named=True) sval = output.serialize_expr(ser_result, path_id=ir_set.path_id, env=ctx.env) pathctx.put_path_serialized_var(ctx.rel, ir_set.path_id, sval, force=True, env=ctx.env) return result
def strip_output_var( var: pgast.OutputVar, *, optional: typing.Optional[bool] = None, nullable: typing.Optional[bool] = None) -> pgast.OutputVar: if isinstance(var, pgast.TupleVar): elements = [] for el in var.elements: if isinstance(el.name, str): val = pgast.ColumnRef(name=[el.name]) else: val = strip_output_var(el.name) elements.append( pgast.TupleElement(path_id=el.path_id, name=el.name, val=val)) result = pgast.TupleVar(elements, named=var.named) else: result = pgast.ColumnRef( name=[var.name[-1]], optional=optional if optional is not None else var.optional, nullable=nullable if nullable is not None else var.nullable, ) return result
def get_rvar_var(rvar: pgast.BaseRangeVar, var: pgast.OutputVar) -> pgast.OutputVar: assert isinstance(var, pgast.OutputVar) if isinstance(var, pgast.TupleVar): elements = [] for el in var.elements: val = get_rvar_var(rvar, el.name) elements.append( pgast.TupleElement(path_id=el.path_id, name=el.name, val=val)) fieldref = pgast.TupleVar(elements, named=var.named) else: fieldref = get_column(rvar, var) return fieldref
def tuple_element_for_shape_el(shape_el, value): if shape_el.path_id.is_type_indirection_path(): rptr = shape_el.rptr.source.rptr else: rptr = shape_el.rptr ptrcls = rptr.ptrcls ptrdir = rptr.direction or s_pointers.PointerDirection.Outbound ptrname = ptrcls.shortname attr_name = s_pointers.PointerVector( name=ptrname.name, module=ptrname.module, direction=ptrdir, target=ptrcls.get_far_endpoint(ptrdir), is_linkprop=ptrcls.is_link_property()) return pgast.TupleElement( path_id=shape_el.path_id, name=attr_name, val=value, )
def compile_Tuple(expr: irast.Base, *, ctx: context.CompilerContextLevel) -> pgast.Base: ttype = _infer_type(expr, ctx=ctx) ttypes = ttype.element_types telems = list(ttypes) path_id = irast.PathId(ttype) elements = [] for i, e in enumerate(expr.elements): telem = telems[i] ttype = ttypes[telem] el_path_id = irutils.tuple_indirection_path_id(path_id, telem, ttype) val = dispatch.compile(e.val, ctx=ctx) elements.append(pgast.TupleElement(path_id=el_path_id, val=val)) result = pgast.TupleVar(elements=elements) return output.output_as_value(result, env=ctx.env)
def get_rvar_var( rvar: typing.Optional[pgast.BaseRangeVar], var: pgast.OutputVar, *, optional: bool=False, nullable: bool=None) \ -> typing.Union[pgast.ColumnRef, pgast.TupleVar]: assert isinstance(var, pgast.OutputVar) if isinstance(var, pgast.TupleVar): elements = [] for el in var.elements: val = get_rvar_var(rvar, el.name) elements.append( pgast.TupleElement(path_id=el.path_id, name=el.name, val=val)) fieldref = pgast.TupleVar(elements, named=var.named) else: fieldref = get_column(rvar, var, optional=optional, nullable=nullable) return fieldref
def get_rvar_fieldref( rvar: typing.Optional[pgast.BaseRangeVar], colname: typing.Union[str, pgast.TupleVar], *, optional: bool=False, nullable: bool=None) \ -> typing.Union[pgast.ColumnRef, pgast.TupleVar]: if isinstance(colname, pgast.TupleVar): elements = [] for el in colname.elements: val = get_rvar_fieldref(rvar, el.name) elements.append( pgast.TupleElement(path_id=el.path_id, name=el.name, val=val)) fieldref = pgast.TupleVar(elements, named=colname.named) else: fieldref = get_column(rvar, colname, optional=optional, nullable=nullable) return fieldref
def _get_path_output(rel: pgast.BaseRelation, path_id: irast.PathId, *, aspect: str, allow_nullable: bool = True, ptr_info: typing.Optional[ pg_types.PointerStorageInfo] = None, env: context.Environment) -> pgast.OutputVar: result = rel.path_outputs.get((path_id, aspect)) if result is not None: return result if is_terminal_relation(rel): return _get_rel_path_output(rel, path_id, aspect=aspect, ptr_info=ptr_info, env=env) else: ref = get_path_var(rel, path_id, aspect=aspect, env=env) other_output = find_path_output(rel, path_id, ref, env=env) if other_output is not None: rel.path_outputs[path_id, aspect] = other_output return other_output if isinstance(ref, pgast.TupleVar): elements = [] for el in ref.elements: el_path_id = reverse_map_path_id(el.path_id, rel.view_path_id_map) try: # Similarly to get_path_var(), check for outer path_id # first for tuple serialized var disambiguation. element = _get_path_output(rel, el_path_id, aspect=aspect, allow_nullable=False, env=env) except LookupError: element = get_path_output(rel, el_path_id, aspect=aspect, allow_nullable=False, env=env) elements.append( pgast.TupleElement(path_id=el_path_id, name=element)) result = pgast.TupleVar(elements=elements, named=ref.named) else: if astutils.is_set_op_query(rel): assert isinstance(ref, pgast.ColumnRef) result = dbobj.get_column(None, ref) else: alias = get_path_output_alias(path_id, aspect, env=env) restarget = pgast.ResTarget(name=alias, val=ref) if hasattr(rel, 'returning_list'): rel.returning_list.append(restarget) else: rel.target_list.append(restarget) nullable = is_nullable(ref, env=env) if isinstance(ref, pgast.ColumnRef): optional = ref.optional else: optional = None if nullable and not allow_nullable: var = get_path_var(rel, path_id, aspect=aspect, env=env) rel.where_clause = astutils.extend_binop( rel.where_clause, pgast.NullTest(arg=var, negated=True)) nullable = False result = pgast.ColumnRef(name=[alias], nullable=nullable, optional=optional) rel.path_outputs[path_id, aspect] = result return result
def _compile_shape(ir_set: irast.Set, shape: typing.List[irast.Set], *, ctx: context.CompilerContextLevel) -> pgast.TupleVar: elements = [] with ctx.newscope() as shapectx: shapectx.disable_semi_join.add(ir_set.path_id) shapectx.unique_paths.add(ir_set.path_id) for el in shape: rptr = el.rptr ptrcls = rptr.ptrcls ptrdir = rptr.direction or s_pointers.PointerDirection.Outbound is_singleton = ptrcls.singular(ptrdir) if (irutils.is_subquery_set(el) or isinstance(el.scls, s_objtypes.ObjectType) or not is_singleton or not ptrcls.required): wrapper = relgen.set_as_subquery(el, as_value=True, ctx=shapectx) if not is_singleton: value = relgen.set_to_array(ir_set=el, query=wrapper, ctx=shapectx) else: value = wrapper else: value = dispatch.compile(el, ctx=shapectx) elements.append(astutils.tuple_element_for_shape_el(el, value)) result = pgast.TupleVar(elements=elements, named=True) pathctx.put_path_value_var(ctx.rel, ir_set.path_id, result, force=True, env=ctx.env) for element in elements: # The ref might have already been added by the nested shape # processing, so add it conditionally. pathctx.put_path_value_var_if_not_exists(ctx.rel, element.path_id, element.val, env=ctx.env) if output.in_serialization_ctx(ctx): ser_elements = [] for el in elements: ser_val = pathctx.get_path_serialized_or_value_var(ctx.rel, el.path_id, env=ctx.env) ser_elements.append( pgast.TupleElement(path_id=el.path_id, name=el.name, val=ser_val)) ser_result = pgast.TupleVar(elements=ser_elements, named=True) sval = output.serialize_expr(ser_result, env=ctx.env) pathctx.put_path_serialized_var(ctx.rel, ir_set.path_id, sval, force=True, env=ctx.env) return result
def get_path_output(rel: pgast.BaseRelation, path_id: irast.PathId, *, aspect: str, ptr_info: typing.Optional[ pg_types.PointerStorageInfo] = None, env: context.Environment) -> pgast.OutputVar: view_path_id_map = getattr(rel, 'view_path_id_map', None) if view_path_id_map: path_id = map_path_id(path_id, view_path_id_map) result = rel.path_outputs.get((path_id, aspect)) if result is not None: return result if isinstance(rel, pgast.Relation): return _get_rel_path_output(rel, path_id, aspect=aspect, ptr_info=ptr_info, env=env) else: ref = get_path_var(rel, path_id, aspect=aspect, env=env) other_output = find_path_output(rel, path_id, ref, env=env) if other_output is not None: rel.path_outputs[path_id, aspect] = other_output return other_output if isinstance(ref, pgast.TupleVar): elements = [] for el in ref.elements: el_path_id = reverse_map_path_id(el.path_id, rel.view_path_id_map) element = get_path_output(rel, el_path_id, aspect=aspect, env=env) elements.append( pgast.TupleElement(path_id=el_path_id, name=element)) result = pgast.TupleVar(elements=elements, named=ref.named) else: if astutils.is_set_op_query(rel): assert isinstance(ref, pgast.ColumnRef) result = dbobj.get_column(None, ref) else: alias = get_path_output_alias(path_id, aspect, env=env) restarget = pgast.ResTarget(name=alias, val=ref) if hasattr(rel, 'returning_list'): rel.returning_list.append(restarget) else: rel.target_list.append(restarget) if isinstance(ref, pgast.ColumnRef): nullable = ref.nullable optional = ref.optional else: nullable = rel.nullable optional = None result = pgast.ColumnRef(name=[alias], nullable=nullable, optional=optional) rel.path_outputs[path_id, aspect] = result return result