def compile_ConfigSet( op: irast.ConfigSet, *, ctx: context.CompilerContextLevel, ) -> pgast.BaseExpr: val: pgast.BaseExpr with ctx.new() as subctx: if op.backend_setting: output_format = context.OutputFormat.NATIVE else: output_format = context.OutputFormat.JSONB with context.output_format(ctx, output_format): if isinstance(op.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(), type_name=pgast.TypeName( name=('text[]',), ), ) else: val = dispatch.compile(op.expr, ctx=subctx) assert isinstance(val, pgast.SelectStmt), "expected SelectStmt" pathctx.get_path_serialized_output( val, op.expr.path_id, env=ctx.env) if op.cardinality is qltypes.SchemaCardinality.Many: val = output.aggregate_json_output( val, op.expr, env=ctx.env) result: pgast.BaseExpr if op.scope is qltypes.ConfigScope.SYSTEM and op.backend_setting: assert isinstance(val, pgast.SelectStmt) and len(val.target_list) == 1 valval = val.target_list[0].val if isinstance(valval, pgast.TypeCast): valval = valval.arg if not isinstance(valval, pgast.BaseConstant): raise AssertionError('value is not a constant in ConfigSet') result = pgast.AlterSystem( name=op.backend_setting, value=valval, ) elif op.scope is qltypes.ConfigScope.DATABASE and op.backend_setting: fcall = pgast.FuncCall( name=('edgedb', '_alter_current_database_set'), args=[pgast.StringConstant(val=op.backend_setting), val], ) result = output.wrap_script_stmt( pgast.SelectStmt(target_list=[pgast.ResTarget(val=fcall)]), suppress_all_output=True, env=ctx.env, ) elif op.scope is qltypes.ConfigScope.SESSION and op.backend_setting: fcall = pgast.FuncCall( name=('pg_catalog', 'set_config'), args=[ pgast.StringConstant(val=op.backend_setting), pgast.TypeCast( arg=val, type_name=pgast.TypeName(name=('text',)), ), pgast.BooleanConstant(val='false'), ], ) result = output.wrap_script_stmt( pgast.SelectStmt(target_list=[pgast.ResTarget(val=fcall)]), suppress_all_output=True, env=ctx.env, ) elif op.scope is qltypes.ConfigScope.SYSTEM: result_row = pgast.RowExpr( args=[ pgast.StringConstant(val='SET'), pgast.StringConstant(val=str(op.scope)), pgast.StringConstant(val=op.name), val, ] ) result = pgast.FuncCall( name=('jsonb_build_array',), args=result_row.args, null_safe=True, ser_safe=True, ) result = pgast.SelectStmt( target_list=[ pgast.ResTarget( val=result, ), ], ) elif op.scope is qltypes.ConfigScope.SESSION: result = pgast.InsertStmt( relation=pgast.RelRangeVar( relation=pgast.Relation( name='_edgecon_state', ), ), select_stmt=pgast.SelectStmt( values=[ pgast.ImplicitRowExpr( args=[ pgast.StringConstant( val=op.name, ), val, pgast.StringConstant( val='C', ), ] ) ] ), cols=[ pgast.ColumnRef(name=['name']), pgast.ColumnRef(name=['value']), pgast.ColumnRef(name=['type']), ], on_conflict=pgast.OnConflictClause( action='update', infer=pgast.InferClause( index_elems=[ pgast.ColumnRef(name=['name']), pgast.ColumnRef(name=['type']), ], ), target_list=[ pgast.MultiAssignRef( columns=[pgast.ColumnRef(name=['value'])], source=pgast.RowExpr( args=[ val, ], ), ), ], ), ) elif op.scope is qltypes.ConfigScope.DATABASE: result = pgast.InsertStmt( relation=pgast.RelRangeVar( relation=pgast.Relation( name='_db_config', schemaname='edgedb', ), ), select_stmt=pgast.SelectStmt( values=[ pgast.ImplicitRowExpr( args=[ pgast.StringConstant( val=op.name, ), val, ] ) ] ), cols=[ pgast.ColumnRef(name=['name']), pgast.ColumnRef(name=['value']), ], on_conflict=pgast.OnConflictClause( action='update', infer=pgast.InferClause( index_elems=[ pgast.ColumnRef(name=['name']), ], ), target_list=[ pgast.MultiAssignRef( columns=[pgast.ColumnRef(name=['value'])], source=pgast.RowExpr( args=[ val, ], ), ), ], ), ) else: raise AssertionError(f'unexpected configuration scope: {op.scope}') return result
def _compile_ql_config_op(self, ctx: CompileContext, ql: qlast.Base): current_tx = ctx.state.current_tx() schema = current_tx.get_schema() modaliases = ctx.state.current_tx().get_modaliases() session_config = ctx.state.current_tx().get_session_config() if ql.system and not current_tx.is_implicit(): raise errors.QueryError('CONFIGURE SYSTEM cannot be executed in a ' 'transaction block') ir = ql_compiler.compile_ast_to_ir( ql, schema=schema, modaliases=modaliases, ) is_backend_setting = bool(getattr(ir, 'backend_setting', None)) requires_restart = bool(getattr(ir, 'requires_restart', False)) if is_backend_setting: if isinstance(ql, qlast.ConfigReset): val = None else: # Postgres is fine with all setting types to be passed # as strings. value = ireval.evaluate_to_python_val(ir.expr, schema=schema) val = pg_ast.StringConstant(val=str(value)) if ir.system: sql_ast = pg_ast.AlterSystem( name=ir.backend_setting, value=val, ) else: sql_ast = pg_ast.Set( name=ir.backend_setting, value=val, ) sql_text = pg_codegen.generate_source(sql_ast) + ';' sql = (sql_text.encode(), ) else: sql_text, _ = pg_compiler.compile_ir_to_sql( ir, pretty=debug.flags.edgeql_compile, output_format=pg_compiler.OutputFormat.JSONB) sql = (sql_text.encode(), ) if not ql.system: config_op = ireval.evaluate_to_config_op(ir, schema=schema) session_config = config_op.apply(config.get_settings(), session_config) ctx.state.current_tx().update_session_config(session_config) else: config_op = None return dbstate.SessionStateQuery( sql=sql, is_backend_setting=is_backend_setting, is_system_setting=ql.system, requires_restart=requires_restart, config_op=config_op, )
def compile_ConfigReset( op: irast.ConfigReset, *, ctx: context.CompilerContextLevel, ) -> pgast.BaseExpr: stmt: pgast.BaseExpr if op.scope is qltypes.ConfigScope.SYSTEM and op.backend_setting: stmt = pgast.AlterSystem( name=op.backend_setting, value=None, ) elif op.scope is qltypes.ConfigScope.DATABASE and op.backend_setting: fcall = pgast.FuncCall( name=('edgedb', '_alter_current_database_set'), args=[ pgast.StringConstant(val=op.backend_setting), pgast.NullConstant(), ], ) stmt = output.wrap_script_stmt( pgast.SelectStmt(target_list=[pgast.ResTarget(val=fcall)]), suppress_all_output=True, env=ctx.env, ) elif op.scope is qltypes.ConfigScope.SESSION and op.backend_setting: fcall = pgast.FuncCall( name=('pg_catalog', 'set_config'), args=[ pgast.StringConstant(val=op.backend_setting), pgast.NullConstant(), pgast.BooleanConstant(val='false'), ], ) stmt = output.wrap_script_stmt( pgast.SelectStmt(target_list=[pgast.ResTarget(val=fcall)]), suppress_all_output=True, env=ctx.env, ) elif op.scope is qltypes.ConfigScope.SYSTEM: if op.selector is None: # Scalar reset result_row = pgast.RowExpr( args=[ pgast.StringConstant(val='RESET'), pgast.StringConstant(val=str(op.scope)), pgast.StringConstant(val=op.name), pgast.NullConstant(), ] ) rvar = None else: with context.output_format(ctx, context.OutputFormat.JSONB): selector = dispatch.compile(op.selector, ctx=ctx) assert isinstance(selector, pgast.SelectStmt), \ "expected ast.SelectStmt" target = selector.target_list[0] if not target.name: target = selector.target_list[0] = pgast.ResTarget( name=ctx.env.aliases.get('res'), val=target.val, ) rvar = relctx.rvar_for_rel(selector, ctx=ctx) result_row = pgast.RowExpr( args=[ pgast.StringConstant(val='REM'), pgast.StringConstant(val=str(op.scope)), pgast.StringConstant(val=op.name), astutils.get_column(rvar, target.name), ] ) result = pgast.FuncCall( name=('jsonb_build_array',), args=result_row.args, null_safe=True, ser_safe=True, ) stmt = pgast.SelectStmt( target_list=[ pgast.ResTarget( val=result, ), ], ) if rvar is not None: stmt.from_clause = [rvar] elif op.scope is qltypes.ConfigScope.DATABASE: stmt = pgast.DeleteStmt( relation=pgast.RelRangeVar( relation=pgast.Relation( name='_db_config', schemaname='edgedb', ), ), where_clause=astutils.new_binop( lexpr=pgast.ColumnRef(name=['name']), rexpr=pgast.StringConstant(val=op.name), op='=', ), ) elif op.scope is qltypes.ConfigScope.SESSION: stmt = pgast.DeleteStmt( relation=pgast.RelRangeVar( relation=pgast.Relation( name='_edgecon_state', ), ), where_clause=astutils.new_binop( lexpr=astutils.new_binop( lexpr=pgast.ColumnRef(name=['name']), rexpr=pgast.StringConstant(val=op.name), op='=', ), rexpr=astutils.new_binop( lexpr=pgast.ColumnRef(name=['type']), rexpr=pgast.StringConstant(val='C'), op='=', ), op='AND', ) ) else: raise AssertionError(f'unexpected configuration scope: {op.scope}') return stmt
def compile_ConfigSet( op: irast.ConfigSet, *, ctx: context.CompilerContextLevel, ) -> pgast.BaseExpr: val = _compile_config_value(op, ctx=ctx) result: pgast.BaseExpr if op.scope is qltypes.ConfigScope.INSTANCE and op.backend_setting: if not ctx.env.backend_runtime_params.has_configfile_access: raise errors.UnsupportedBackendFeatureError( "configuring backend parameters via CONFIGURE INSTANCE" " is not supported by the current backend") result = pgast.AlterSystem( name=op.backend_setting, value=val, ) elif op.scope is qltypes.ConfigScope.DATABASE and op.backend_setting: if not isinstance(val, pgast.StringConstant): val = pgast.TypeCast( arg=val, type_name=pgast.TypeName(name=('text', )), ) fcall = pgast.FuncCall( name=('edgedb', '_alter_current_database_set'), args=[pgast.StringConstant(val=op.backend_setting), val], ) result = output.wrap_script_stmt( pgast.SelectStmt(target_list=[pgast.ResTarget(val=fcall)]), suppress_all_output=True, env=ctx.env, ) elif op.scope is qltypes.ConfigScope.SESSION and op.backend_setting: if not isinstance(val, pgast.StringConstant): val = pgast.TypeCast( arg=val, type_name=pgast.TypeName(name=('text', )), ) fcall = pgast.FuncCall( name=('pg_catalog', 'set_config'), args=[ pgast.StringConstant(val=op.backend_setting), val, pgast.BooleanConstant(val='false'), ], ) result = output.wrap_script_stmt( pgast.SelectStmt(target_list=[pgast.ResTarget(val=fcall)]), suppress_all_output=True, env=ctx.env, ) elif op.scope is qltypes.ConfigScope.INSTANCE: result_row = pgast.RowExpr(args=[ pgast.StringConstant(val='SET'), pgast.StringConstant(val=str(op.scope)), pgast.StringConstant(val=op.name), val, ]) result = pgast.FuncCall( name=('jsonb_build_array', ), args=result_row.args, null_safe=True, ser_safe=True, ) result = pgast.SelectStmt(target_list=[ pgast.ResTarget(val=result, ), ], ) elif op.scope in (qltypes.ConfigScope.SESSION, qltypes.ConfigScope.GLOBAL): flag = 'G' if op.scope is qltypes.ConfigScope.GLOBAL else 'C' result = pgast.InsertStmt( relation=pgast.RelRangeVar(relation=pgast.Relation( name='_edgecon_state', ), ), select_stmt=pgast.SelectStmt(values=[ pgast.ImplicitRowExpr(args=[ pgast.StringConstant(val=op.name, ), val, pgast.StringConstant(val=flag, ), ]) ]), cols=[ pgast.ColumnRef(name=['name']), pgast.ColumnRef(name=['value']), pgast.ColumnRef(name=['type']), ], on_conflict=pgast.OnConflictClause( action='update', infer=pgast.InferClause(index_elems=[ pgast.ColumnRef(name=['name']), pgast.ColumnRef(name=['type']), ], ), target_list=[ pgast.MultiAssignRef( columns=[pgast.ColumnRef(name=['value'])], source=pgast.RowExpr(args=[ val, ], ), ), ], ), ) if op.scope is qltypes.ConfigScope.GLOBAL: result_row = pgast.RowExpr(args=[ pgast.StringConstant(val='SET'), pgast.StringConstant(val=str(op.scope)), pgast.StringConstant(val=op.name), val, ]) build_array = pgast.FuncCall( name=('jsonb_build_array', ), args=result_row.args, null_safe=True, ser_safe=True, ) result = pgast.SelectStmt( ctes=[pgast.CommonTableExpr( name='ins', query=result, )], target_list=[pgast.ResTarget(val=build_array)], ) elif op.scope is qltypes.ConfigScope.DATABASE: result = pgast.InsertStmt( relation=pgast.RelRangeVar(relation=pgast.Relation( name='_db_config', schemaname='edgedb', ), ), select_stmt=pgast.SelectStmt(values=[ pgast.ImplicitRowExpr(args=[ pgast.StringConstant(val=op.name, ), val, ]) ]), cols=[ pgast.ColumnRef(name=['name']), pgast.ColumnRef(name=['value']), ], on_conflict=pgast.OnConflictClause( action='update', infer=pgast.InferClause(index_elems=[ pgast.ColumnRef(name=['name']), ], ), target_list=[ pgast.MultiAssignRef( columns=[pgast.ColumnRef(name=['value'])], source=pgast.RowExpr(args=[ val, ], ), ), ], ), ) else: raise AssertionError(f'unexpected configuration scope: {op.scope}') return result