def compile_TypeCast(expr: irast.TypeCast, *, ctx: context.CompilerContextLevel) -> pgast.BaseExpr: pg_expr = dispatch.compile(expr.expr, ctx=ctx) if expr.sql_cast: # Use explicit SQL cast. pg_type = pg_types.pg_type_from_ir_typeref(expr.to_type) return pgast.TypeCast(arg=pg_expr, type_name=pgast.TypeName(name=pg_type)) elif expr.sql_function or expr.sql_expr: # Cast implemented as a function. if expr.sql_expr: func_name = common.get_cast_backend_name(expr.cast_name, expr.cast_module_id, aspect='function') else: func_name = tuple(expr.sql_function.split('.')) return pgast.FuncCall( name=func_name, args=[pg_expr], ) else: raise RuntimeError('cast not supported')
def compile_TypeCast( expr: irast.TypeCast, *, ctx: context.CompilerContextLevel) -> pgast.BaseExpr: pg_expr = dispatch.compile(expr.expr, ctx=ctx) if expr.sql_cast: # Use explicit SQL cast. pg_type = pg_types.pg_type_from_ir_typeref(expr.to_type) res: pgast.BaseExpr = pgast.TypeCast( arg=pg_expr, type_name=pgast.TypeName( name=pg_type ) ) elif expr.sql_function or expr.sql_expr: # Cast implemented as a function. if expr.sql_expr: func_name = common.get_cast_backend_name( expr.cast_name, expr.cast_module_id, aspect='function') else: func_name = tuple(expr.sql_function.split('.')) res = pgast.FuncCall( name=func_name, args=[pg_expr], ) else: raise RuntimeError('cast not supported') if expr.cardinality_mod is qlast.CardinalityModifier.Required: res = pgast.FuncCall( name=('edgedb', '_raise_exception_on_null'), args=[ res, pgast.StringConstant( val='invalid_parameter_value', ), pgast.StringConstant( val='invalid null value in cast', ), pgast.StringConstant(val=''), ] ) return res
def serialize_expr_to_json(expr: pgast.BaseExpr, *, styperef: irast.TypeRef, nested: bool = False, env: context.Environment) -> pgast.BaseExpr: val: pgast.BaseExpr if isinstance(expr, pgast.TupleVar): val = tuple_var_as_json_object(expr, styperef=styperef, env=env) elif isinstance(expr, (pgast.RowExpr, pgast.ImplicitRowExpr)): val = _build_json( 'build_array', args=expr.args, null_safe=True, ser_safe=True, env=env, ) elif irtyputils.is_collection(styperef) and not expr.ser_safe: val = coll_as_json_object(expr, styperef=styperef, env=env) # TODO: We'll probably want to generalize this to other custom JSON # casts once they exist. elif (irtyputils.is_bytes(styperef) and not expr.ser_safe): cast_name = s_casts.get_cast_fullname_from_names( 'std', 'std::bytes', 'std::json') val = pgast.FuncCall(name=common.get_cast_backend_name( cast_name, aspect='function'), args=[expr], null_safe=True, ser_safe=True) elif not nested: val = pgast.FuncCall(name=_get_json_func('to', env=env), args=[expr], null_safe=True, ser_safe=True) else: val = expr return val
def _compile_config_value( op: irast.ConfigSet, *, ctx: context.CompilerContextLevel, ) -> pgast.BaseExpr: val: pgast.BaseExpr if op.backend_setting: assert op.backend_expr is not None expr = op.backend_expr else: expr = op.expr with ctx.new() as subctx: if op.backend_setting or op.scope == qltypes.ConfigScope.GLOBAL: output_format = context.OutputFormat.NATIVE else: output_format = context.OutputFormat.JSONB with context.output_format(ctx, output_format): if isinstance(expr, irast.EmptySet): # Special handling for empty sets, because we want a # singleton representation of the value and not an empty rel # in this context. if op.cardinality is qltypes.SchemaCardinality.One: val = pgast.NullConstant() elif subctx.env.output_format is context.OutputFormat.JSONB: val = pgast.TypeCast( arg=pgast.StringConstant(val='[]'), type_name=pgast.TypeName(name=('jsonb', ), ), ) else: val = pgast.TypeCast( arg=pgast.ArrayExpr(elements=[]), type_name=pgast.TypeName(name=('text[]', ), ), ) else: val = dispatch.compile(expr, ctx=subctx) assert isinstance(val, pgast.SelectStmt), "expected SelectStmt" pathctx.get_path_serialized_output(val, expr.path_id, env=ctx.env) if op.cardinality is qltypes.SchemaCardinality.Many: val = output.aggregate_json_output(val, expr, env=ctx.env) # For globals, we need to output the binary encoding so that we # can just hand it back to the server. We abuse `record_send` to # act as a generic `_send` function if op.scope is qltypes.ConfigScope.GLOBAL: val = pgast.FuncCall( name=('substring', ), args=[ pgast.FuncCall( name=('record_send', ), args=[pgast.RowExpr(args=[val])], ), # The first twelve bytes are header, the rest is the # encoding of the actual element pgast.NumericConstant(val="13"), ], ) cast_name = s_casts.get_cast_fullname_from_names( 'std', 'std::bytes', 'std::json') val = pgast.FuncCall( name=common.get_cast_backend_name(cast_name, aspect='function'), args=[val], ) if op.backend_setting and op.scope is qltypes.ConfigScope.INSTANCE: assert isinstance(val, pgast.SelectStmt) and len(val.target_list) == 1 val = val.target_list[0].val if isinstance(val, pgast.TypeCast): val = val.arg if not isinstance(val, pgast.BaseConstant): raise AssertionError('value is not a constant in ConfigSet') return val