Skip to content

Commit

Permalink
Implement new syntax for the SET command.
Browse files Browse the repository at this point in the history
Supported variants:

* SET CONFIG name := expr;
* SET MODULE default;
* SET ALIAS my_foo AS MODULE foo;

Partially addresses issue #347.
  • Loading branch information
1st1 committed Dec 6, 2018
1 parent 5eb6e8f commit 6bd9021
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 29 deletions.
24 changes: 17 additions & 7 deletions edb/lang/edgeql/ast.py
Expand Up @@ -100,17 +100,31 @@ class SortExpr(Clause):


class BaseAlias(Clause):
pass
alias: str


class AliasedExpr(BaseAlias):
expr: Expr
alias: str


class ModuleAliasDecl(BaseAlias):
module: str
alias: str


class BaseSessionSetting:
pass


class SessionSettingModuleDecl(ModuleAliasDecl, BaseSessionSetting):
pass


class SessionSettingConfigDecl(AliasedExpr, BaseSessionSetting):
pass


class SetSessionState(Expr):
items: typing.List[BaseSessionSetting]


class BaseObjectRef(Expr):
Expand Down Expand Up @@ -835,10 +849,6 @@ class DropCast(DropObject, CastCommand):
pass


class SessionStateDecl(Expr):
items: typing.List[BaseAlias]


class _Optional(Expr):
expr: Expr

Expand Down
20 changes: 18 additions & 2 deletions edb/lang/edgeql/codegen.py
Expand Up @@ -304,7 +304,7 @@ def visit_GroupBuiltin(self, node):
def visit_ModuleAliasDecl(self, node):
if node.alias:
self.write(ident_to_str(node.alias))
self.write(' := ')
self.write(' AS ')
self.write('MODULE ')
self.write(any_ident_to_str(node.module))

Expand Down Expand Up @@ -1076,7 +1076,23 @@ def visit_FuncParam(self, node):
self.write(' = ')
self.visit(node.default)

def visit_SessionStateDecl(self, node):
def visit_SessionSettingConfigDecl(self, node):
self.write(' CONFIG ')
self.write(ident_to_str(node.alias))
self.write(' := ')
self.visit(node.expr)

def visit_SessionSettingModuleDecl(self, node):
if node.alias:
self.write(' ALIAS ')
self.write(ident_to_str(node.alias))
self.write(' AS MODULE ')
self.write(node.module)
else:
self.write(' MODULE')
self.write(node.module)

def visit_SetSessionState(self, node):
self.write('SET')
self._block_ws(1)
self.visit_list(node.items)
Expand Down
11 changes: 6 additions & 5 deletions edb/lang/edgeql/compiler/stmt.py
Expand Up @@ -354,16 +354,16 @@ def compile_DeleteQuery(
return result


@dispatch.compile.register(qlast.SessionStateDecl)
def compile_SessionStateDecl(
decl: qlast.SessionStateDecl, *,
@dispatch.compile.register(qlast.SetSessionState)
def compile_SetSessionState(
decl: qlast.SetSessionState, *,
ctx: context.ContextLevel) -> irast.SessionStateCmd:

aliases = {}
testmode = False

for item in decl.items:
if isinstance(item, qlast.ModuleAliasDecl):
if isinstance(item, qlast.SessionSettingModuleDecl):
try:
module = ctx.env.schema.get(item.module)
except s_err.ItemNotFoundError:
Expand All @@ -374,7 +374,8 @@ def compile_SessionStateDecl(

aliases[item.alias] = module

elif item.alias == '__internal_testmode':
elif (isinstance(item, qlast.SessionSettingConfigDecl) and
item.alias == '__internal_testmode'):
try:
testmode_ir = dispatch.compile(item.expr, ctx=ctx)
testmode = ireval.evaluate_to_python_val(
Expand Down
2 changes: 1 addition & 1 deletion edb/lang/edgeql/parser/grammar/expressions.py
Expand Up @@ -227,7 +227,7 @@ def reduce_MODULE_ModuleName(self, *kids):
self.val = qlast.ModuleAliasDecl(
module='.'.join(kids[1].val))

def reduce_Identifier_ASSIGN_MODULE_ModuleName(self, *kids):
def reduce_Identifier_AS_MODULE_ModuleName(self, *kids):
self.val = qlast.ModuleAliasDecl(
alias=kids[0].val,
module='.'.join(kids[3].val))
Expand Down
3 changes: 2 additions & 1 deletion edb/lang/edgeql/parser/grammar/keywords.py
Expand Up @@ -29,6 +29,7 @@
unreserved_keywords = frozenset([
"abstract",
"after",
"alias",
"allow",
"as",
"asc",
Expand All @@ -38,6 +39,7 @@
"by",
"cardinality",
"cast",
"config",
"constraint",
"database",
"default",
Expand Down Expand Up @@ -121,7 +123,6 @@
])


# NOTE: all operators are made into RESERVED keywords for reasons of style.
reserved_keywords = future_reserved_keywords | frozenset([
"__source__",
"__subject__",
Expand Down
17 changes: 14 additions & 3 deletions edb/lang/edgeql/parser/grammar/session.py
Expand Up @@ -32,8 +32,19 @@ def reduce_SetStmt(self, *kids):


class SetDecl(Nonterm):
def reduce_AliasDecl(self, *kids):
self.val = kids[0].val
def reduce_ALIAS_Identifier_AS_MODULE_ModuleName(self, *kids):
self.val = qlast.SessionSettingModuleDecl(
module='.'.join(kids[4].val),
alias=kids[1].val)

def reduce_MODULE_ModuleName(self, *kids):
self.val = qlast.SessionSettingModuleDecl(
module='.'.join(kids[1].val))

def reduce_CONFIG_Identifier_ASSIGN_Expr(self, *kids):
self.val = qlast.SessionSettingConfigDecl(
alias=kids[1].val,
expr=kids[3].val)


class SetDeclList(ListNonterm, element=SetDecl,
Expand All @@ -43,6 +54,6 @@ class SetDeclList(ListNonterm, element=SetDecl,

class SetStmt(Nonterm):
def reduce_SET_SetDeclList(self, *kids):
self.val = qlast.SessionStateDecl(
self.val = qlast.SetSessionState(
items=kids[1].val
)
2 changes: 1 addition & 1 deletion edb/server/_testbase.py
Expand Up @@ -229,7 +229,7 @@ class DatabaseTestCase(ConnectedTestCase):

def setUp(self):
self.loop.run_until_complete(
self.con.execute('SET __internal_testmode := true;'))
self.con.execute('SET CONFIG __internal_testmode := true;'))

if self.ISOLATED_METHODS:
self.loop.run_until_complete(
Expand Down
2 changes: 1 addition & 1 deletion edb/server/planner.py
Expand Up @@ -73,7 +73,7 @@ async def plan_statement(stmt, backend, flags={}, *, timer):
# BEGIN/COMMIT
return TransactionStatement(stmt)

elif isinstance(stmt, qlast.SessionStateDecl):
elif isinstance(stmt, qlast.SetSessionState):
# SET ...
with timer.timeit('compile_eql_to_ir'):
ir = ql_compiler.compile_ast_to_ir(
Expand Down
2 changes: 1 addition & 1 deletion tests/test_edgeql_ddl.py
Expand Up @@ -577,7 +577,7 @@ async def test_edgeql_ddl_18(self):
CREATE MODULE foo;
CREATE MODULE bar;
SET MODULE foo, b := MODULE bar;
SET MODULE foo, ALIAS b AS MODULE bar;
CREATE SCALAR TYPE foo_t EXTENDING int64 {
CREATE CONSTRAINT expression ON (__subject__ > 0);
Expand Down
6 changes: 3 additions & 3 deletions tests/test_edgeql_syntax.py
Expand Up @@ -1752,7 +1752,7 @@ def test_edgeql_syntax_with_01(self):
"""
WITH
MODULE test,
extra := MODULE lib.extra,
extra AS MODULE lib.extra,
foo := Bar.foo,
baz := (SELECT extra::Foo.baz)
SELECT Bar {
Expand Down Expand Up @@ -3305,12 +3305,12 @@ def test_edgeql_syntax_set_command_01(self):

def test_edgeql_syntax_set_command_02(self):
"""
SET foo := MODULE default;
SET ALIAS foo AS MODULE default;
"""

def test_edgeql_syntax_set_command_03(self):
"""
SET MODULE default, foo := (SELECT User);
SET MODULE default, CONFIG foo := (SELECT User);
"""

def test_edgeql_syntax_ddl_view_01(self):
Expand Down
8 changes: 4 additions & 4 deletions tests/test_session.py
Expand Up @@ -93,7 +93,7 @@ async def test_session_set_command_02(self):

async def test_session_set_command_03(self):
await self.assert_query_result("""
SET MODULE foo, bar := MODULE default;
SET MODULE foo, ALIAS bar AS MODULE default;
SELECT (Entity.name, bar::User.name);
""", [
Expand All @@ -108,17 +108,17 @@ async def test_session_set_command_04(self):
err.EdgeQLError,
'expression aliases in SET are not supported yet'):
await self.assert_query_result("""
SET foo := 1 + 1;
SET CONFIG foo := 1 + 1;
""", [
None,
])

async def test_session_set_command_05(self):
# Check that local WITH overrides the session level setting.
await self.assert_query_result("""
SET MODULE default, bar := MODULE foo;
SET MODULE default, ALIAS bar AS MODULE foo;
WITH MODULE foo, bar := MODULE default
WITH MODULE foo, bar AS MODULE default
SELECT (Entity.name, bar::User.name);
""", [

Expand Down

0 comments on commit 6bd9021

Please sign in to comment.