def put_path_var( rel: pgast.BaseRelation, path_id: irast.PathId, var: pgast.BaseExpr, *, aspect: str, force: bool=False, env: context.Environment) -> None: if (path_id, aspect) in rel.path_namespace and not force: raise KeyError( f'{aspect} of {path_id} is already present in {rel}') rel.path_namespace[path_id, aspect] = var
def ensure_transient_identity_for_set(ir_set: irast.Set, stmt: pgast.BaseRelation, *, ctx: context.CompilerContextLevel, type: str = 'int') -> None: if type == 'uuid': id_expr = pgast.FuncCall( name=( 'edgedbext', 'uuid_generate_v1mc', ), args=[], ) else: id_expr = pgast.FuncCall(name=('row_number', ), args=[], over=pgast.WindowDef()) pathctx.put_path_identity_var(stmt, ir_set.path_id, id_expr, force=True, env=ctx.env) pathctx.put_path_bond(stmt, ir_set.path_id) if (ctx.volatility_ref is not None and ctx.volatility_ref is not context.NO_VOLATILITY and isinstance(stmt, pgast.SelectStmt)): # Apply the volatility reference. # See the comment in process_set_as_subquery(). stmt.where_clause = astutils.extend_binop( stmt.where_clause, pgast.NullTest( arg=ctx.volatility_ref, negated=True, ))
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 ref: pgast.BaseExpr alias = None rptr = path_id.rptr() if rptr is not None and irtyputils.is_id_ptrref(rptr): # A value reference to Object.id is the same as a value # reference to the Object itself. src_path_id = path_id.src_path() id_output = rel.path_outputs.get((src_path_id, 'value')) if id_output is not None: _put_path_output_var(rel, path_id, aspect, id_output, env=env) return id_output if is_terminal_relation(rel): return _get_rel_path_output(rel, path_id, aspect=aspect, ptr_info=ptr_info, env=env) assert isinstance(rel, pgast.Query) if is_values_relation(rel): # The VALUES() construct seems to always expose its # value as "column1". alias = 'column1' ref = pgast.ColumnRef(name=[alias]) 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: _put_path_output_var(rel, path_id, aspect, other_output, env=env) return other_output if isinstance(ref, pgast.TupleVarBase): 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.TupleElementBase(path_id=el_path_id, name=element)) result = pgast.TupleVarBase(elements=elements, named=ref.named) else: if astutils.is_set_op_query(rel): assert isinstance(ref, pgast.OutputVar) result = astutils.strip_output_var(ref) else: assert isinstance(rel, pgast.ReturningQuery), \ "expected ReturningQuery" if alias is None: alias = get_path_output_alias(path_id, aspect, env=env) restarget = pgast.ResTarget(name=alias, val=ref, ser_safe=getattr( ref, 'ser_safe', False)) rel.target_list.append(restarget) nullable = is_nullable(ref, env=env) optional = None if isinstance(ref, pgast.ColumnRef): optional = ref.optional 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) _put_path_output_var(rel, path_id, aspect, result, env=env) if (path_id.is_objtype_path() and not isinstance(result, pgast.TupleVarBase)): equiv_aspect = None if aspect == 'identity': equiv_aspect = 'value' elif aspect == 'value': equiv_aspect = 'identity' if (equiv_aspect is not None and (path_id, equiv_aspect) not in rel.path_outputs): _put_path_output_var(rel, path_id, equiv_aspect, result, env=env) return result
def _put_path_output_var(rel: pgast.BaseRelation, path_id: irast.PathId, aspect: str, var: pgast.OutputVar, *, env: context.Environment) -> None: rel.path_outputs[path_id, aspect] = var