Skip to content

Commit

Permalink
Raise error when computed global is set or reset. (#7374)
Browse files Browse the repository at this point in the history
After `set global foo := false;`, attempting to run `set global lol := false;` produces the following error:
```
error: ConfigurationError: global 'foo' is computed from an expression and cannot be modified
  ┌─ <query>:1:12
  │
1 │ set global foo := false;
  │            ^^^ error
```
  • Loading branch information
dnwpark authored May 24, 2024
1 parent d8ae9ec commit 37317ea
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 1 deletion.
11 changes: 10 additions & 1 deletion edb/edgeql/compiler/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,11 +292,20 @@ def _validate_config_object(
def _validate_global_op(
expr: qlast.ConfigOp, *, ctx: context.ContextLevel
) -> SettingInfo:
glob_name = s_utils.ast_ref_to_name(expr.name)
glob = ctx.env.get_schema_object_and_track(
s_utils.ast_ref_to_name(expr.name), expr.name,
glob_name, expr.name,
modaliases=ctx.modaliases, type=s_globals.Global)
assert isinstance(glob, s_globals.Global)

if isinstance(expr, (qlast.ConfigSet, qlast.ConfigReset)):
if glob.get_expr(ctx.env.schema):
raise errors.ConfigurationError(
f"global '{glob_name}' is computed from an expression and "
f"cannot be modified",
span=expr.name.span
)

param_type = glob.get_target(ctx.env.schema)

return SettingInfo(param_name=str(glob.get_name(ctx.env.schema)),
Expand Down
107 changes: 107 additions & 0 deletions tests/test_edgeql_globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,113 @@ async def test_edgeql_globals_13(self):
my_param='1 sec',
)

async def test_edgeql_globals_14(self):
with self.assertRaisesRegex(
edgedb.ConfigurationError,
"global 'def_cur_user_excited' is computed from an expression "
"and cannot be modified",
):
await self.con.execute(
'''
set global def_cur_user_excited := 'yay!'
''',
)

async def test_edgeql_globals_15(self):
await self.con.execute('''
create global foo := 1;
''')

with self.assertRaisesRegex(
edgedb.ConfigurationError,
"global 'def_cur_user_excited' is computed from an expression "
"and cannot be modified",
):
await self.con.execute(
'''
reset global def_cur_user_excited
''',
)

async def test_edgeql_globals_client_01(self):
con = edgedb.create_async_client(
**self.get_connect_args(database=self.con.dbname)
)
try:
globs = dict(
cur_user='Alice',
)
scon = con.with_globals(**globs)
res = await scon.query_single(
f'select {{ cur_user := global cur_user }}'
)
dres = dataclasses.asdict(res)
self.assertEqual(dres, {'cur_user': 'Alice'})
finally:
await con.aclose()

async def test_edgeql_globals_client_02(self):
con = edgedb.create_async_client(
**self.get_connect_args(database=self.con.dbname)
)
try:
globs = dict(
cur_user=1, # wrong type
)
scon = con.with_globals(**globs)
with self.assertRaisesRegex(
edgedb.InvalidArgumentError,
r"invalid input for state argument default::cur_user := 1 "
r"\(expected str, got int\)",
):
await scon.query_single(
f'select {{ cur_user := global cur_user }}'
)
finally:
await con.aclose()

async def test_edgeql_globals_client_03(self):
con = edgedb.create_async_client(
**self.get_connect_args(database=self.con.dbname)
)
try:
globs = dict(
def_cur_user_excited='yay!', # computed
)
scon = con.with_globals(**globs)
with self.assertRaisesRegex(
edgedb.QueryArgumentError,
r"got {'default::def_cur_user_excited'}, "
r"extra {'default::def_cur_user_excited'}",
):
await scon.query_single(
f'select {{'
f' def_cur_user_excited := global def_cur_user_excited'
f'}}'
)
finally:
await con.aclose()

async def test_edgeql_globals_client_04(self):
con = edgedb.create_async_client(
**self.get_connect_args(database=self.con.dbname)
)
try:
globs = dict(
imaginary='!', # doesn't exist
)
scon = con.with_globals(**globs)
with self.assertRaisesRegex(
edgedb.QueryArgumentError,
r"got {'default::imaginary'}, "
r"extra {'default::imaginary'}",
):
await scon.query_single(
f'select {{ imaginary := global imaginary }}'
)
finally:
await con.aclose()

async def test_edgeql_globals_state_cardinality(self):
await self.con.execute('''
set global cur_user := {};
Expand Down

0 comments on commit 37317ea

Please sign in to comment.