Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
bfc014a
:construction: create & drop namespace语法和pg schema落地所需代码准备基本完成,待补edb …
Apr 27, 2023
272f64e
:construction: 进行中,edb schema更新逻辑
Apr 28, 2023
367b99d
Merge branch 'dp/2.1' into dp/namespace
Apr 28, 2023
fe482cd
:construction: create/drop namespace后pg schema的创建/删除逻辑完成,namespace数据库…
Apr 30, 2023
2373126
:art: 完善namespace相关的报错信息
Apr 30, 2023
0b3ba35
:sparkles: dump & restore支持外部表
May 11, 2023
044a0c8
:sparkles: binary v0 增加dump & restore支持外部表
May 12, 2023
aecdac7
:memo: 备份验证v0逻辑的script
May 12, 2023
b879622
:mute: 删除dump&restore debug期间的日志打印
May 15, 2023
6c18fdd
:white_check_mark: 编写外部表dump&restore测试代码
May 15, 2023
47b58e1
Merge branch 'dp/dump_restore_external' into dp/namespace
May 16, 2023
2dfed87
:construction: 编写namespace信息在compile过程中起效的逻辑
May 17, 2023
ed53572
Merge branch 'dp/2.1' into dp/namespace
May 18, 2023
7c991f1
:bug: 去除新建namespace和db时block传入的ns信息
May 18, 2023
55e26ad
:construction: 编写namespace信息在compile过程中起效的逻辑
May 22, 2023
b6092e7
Merge branch 'dp/2.1' into dp/namespace
May 22, 2023
ed3de3c
:construction: 完成namespace在compile期间的起效逻辑,ddl&select&update&delete测试通…
May 23, 2023
0b0c463
:construction: 完成namespace切换逻辑,待补测试
May 23, 2023
edd33f6
:sparkles: dump&restore对namespace的支持
May 30, 2023
9f8d910
:bug: 修正兼容dp/2.1的external_views不存在情况时的逻辑
May 30, 2023
653384f
:white_check_mark: 添加namespace并发DDL情况的测试代码
May 31, 2023
a8cf496
:sparkles: create/drop db/ns增加pg event
Jun 5, 2023
46fc159
Merge branch 'dp/2.1' into dp/namespace
Jun 7, 2023
0f8e5ae
:white_check_mark: 检查configure相关逻辑,更新测试
Jun 7, 2023
98f5204
:white_check_mark: 更新create type测试
Jun 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions edb/edgeql-parser/src/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub const UNRESERVED_KEYWORDS: &[&str] = &[
"cube",
"current",
"database",
"namespace",
"ddl",
"declare",
"default",
Expand Down Expand Up @@ -99,6 +100,8 @@ pub const UNRESERVED_KEYWORDS: &[&str] = &[
"version",
"view",
"write",
"use",
"show",
];


Expand Down
18 changes: 18 additions & 0 deletions edb/edgeql/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ class SessionResetAllAliases(BaseSessionReset):
pass


class UseNameSpaceCommand(BaseSessionCommand):
name: str


class BaseObjectRef(Base):
__abstract_node__ = True

Expand Down Expand Up @@ -836,6 +840,20 @@ class DropDatabase(DropObject, DatabaseCommand):
pass


class NameSpaceCommand(ExternalObjectCommand):
__abstract_node__ = True
object_class: qltypes.SchemaObjectClass = (
qltypes.SchemaObjectClass.NAMESPACE)


class CreateNameSpace(CreateObject, NameSpaceCommand):
pass


class DropNameSpace(DropObject, NameSpaceCommand):
pass


class ExtensionPackageCommand(GlobalObjectCommand):
__abstract_node__ = True
object_class: qltypes.SchemaObjectClass = (
Expand Down
13 changes: 13 additions & 0 deletions edb/edgeql/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,12 @@ def visit_AlterDatabase(self, node: qlast.AlterDatabase) -> None:
def visit_DropDatabase(self, node: qlast.DropDatabase) -> None:
self._visit_DropObject(node, 'DATABASE')

def visit_CreateNameSpace(self, node: qlast.CreateNameSpace) -> None:
self._visit_CreateObject(node, 'NAMESPACE')

def visit_DropNameSpace(self, node: qlast.DropNameSpace) -> None:
self._visit_DropObject(node, 'NAMESPACE')

def visit_CreateRole(self, node: qlast.CreateRole) -> None:
after_name = lambda: self._ddl_visit_bases(node)
keywords = []
Expand Down Expand Up @@ -2185,6 +2191,13 @@ def visit_SessionResetAliasDecl(
self._write_keywords('RESET ALIAS ')
self.write(node.alias)

def visit_UseNameSpaceCommand(
self,
node: qlast.UseNameSpaceCommand
) -> None:
self._write_keywords('USE NAMESPACE ')
self.write(node.name)

def visit_StartTransaction(self, node: qlast.StartTransaction) -> None:
self._write_keywords('START TRANSACTION')

Expand Down
35 changes: 35 additions & 0 deletions edb/edgeql/parser/grammar/ddl.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class DDLStmt(Nonterm):
def reduce_DatabaseStmt(self, *kids):
self.val = kids[0].val

def reduce_NameSpaceStmt(self, *kids):
self.val = kids[0].val

def reduce_RoleStmt(self, *kids):
self.val = kids[0].val

Expand Down Expand Up @@ -665,6 +668,38 @@ def reduce_DROP_DATABASE_DatabaseName(self, *kids):
self.val = qlast.DropDatabase(name=kids[2].val)


#
# NAMESPACE
#
class NameSpaceStmt(Nonterm):

def reduce_CreateNameSpaceStmt(self, *kids):
self.val = kids[0].val

def reduce_DropNameSpaceStmt(self, *kids):
self.val = kids[0].val


class CreateNameSpaceStmt(Nonterm):
def reduce_CREATE_NAMESPACE_Identifier(self, *kids):
self.val = qlast.CreateNameSpace(
name=qlast.ObjectRef(
module=None,
name=kids[2].val
)
)


class DropNameSpaceStmt(Nonterm):
def reduce_DROP_NAMESPACE_Identifier(self, *kids):
self.val = qlast.DropNameSpace(
name=qlast.ObjectRef(
module=None,
name=kids[2].val
)
)


#
# EXTENSION PACKAGE
#
Expand Down
22 changes: 19 additions & 3 deletions edb/edgeql/parser/grammar/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@

from __future__ import annotations

from edb.edgeql import ast as qlast

from .expressions import Nonterm
from edb.pgsql import common as pg_common
from .tokens import * # NOQA
from .expressions import * # NOQA

Expand All @@ -32,6 +30,12 @@ def reduce_SetStmt(self, *kids):
def reduce_ResetStmt(self, *kids):
self.val = kids[0].val

def reduce_UseNameSpaceStmt(self, *kids):
self.val = kids[0].val

def reduce_ShowNameSpaceStmt(self, *kids):
self.val = kids[0].val


class SetStmt(Nonterm):
def reduce_SET_ALIAS_Identifier_AS_MODULE_ModuleName(self, *kids):
Expand All @@ -54,3 +58,15 @@ def reduce_RESET_MODULE(self, *kids):

def reduce_RESET_ALIAS_STAR(self, *kids):
self.val = qlast.SessionResetAllAliases()


class UseNameSpaceStmt(Nonterm):
def reduce_USE_NAMESPACE_Identifier(self, *kids):
self.val = qlast.UseNameSpaceCommand(name=kids[2].val)


class ShowNameSpaceStmt(Nonterm):
def reduce_SHOW_NAMESPACE(self, *kids):
self.val = qlast.SelectQuery(
result=qlast.StringConstant(value=pg_common.NAMESPACE)
)
1 change: 1 addition & 0 deletions edb/edgeql/qltypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ class SchemaObjectClass(s_enum.StrEnum):
SCALAR_TYPE = 'SCALAR TYPE'
TUPLE_TYPE = 'TUPLE TYPE'
TYPE = 'TYPE'
NAMESPACE = 'NAMESPACE'


class LinkTargetDeleteAction(s_enum.StrEnum):
Expand Down
8 changes: 8 additions & 0 deletions edb/errors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ class UnknownParameterError(InvalidReferenceError):
_code = 0x_04_03_00_06


class UnknownSchemaError(InvalidReferenceError):
_code = 0x_04_03_00_07


class SchemaError(QueryError):
_code = 0x_04_04_00_00

Expand Down Expand Up @@ -309,6 +313,10 @@ class DuplicateCastDefinitionError(DuplicateDefinitionError):
_code = 0x_04_05_02_0A


class DuplicateNameSpaceDefinitionError(DuplicateDefinitionError):
_code = 0x_04_05_02_0B


class SessionTimeoutError(QueryError):
_code = 0x_04_06_00_00

Expand Down
10 changes: 6 additions & 4 deletions edb/graphql/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@


GQLCoreCache: Dict[
str,
Tuple[str, str],
Dict[
(s_schema.FlatSchema, uuid.UUID, s_schema.FlatSchema, str),
graphql.GQLCoreSchema
Expand All @@ -40,19 +40,20 @@

def _get_gqlcore(
dbname: str,
namespace: str,
std_schema: s_schema.FlatSchema,
user_schema: s_schema.FlatSchema,
global_schema: s_schema.FlatSchema,
module: str = None
) -> graphql.GQLCoreSchema:
key = (std_schema, user_schema.version_id, global_schema, module)
if cache := GQLCoreCache.get(dbname):
if cache := GQLCoreCache.get((dbname, namespace)):
if key in cache:
return cache[key]
else:
cache.clear()
else:
cache = GQLCoreCache.setdefault(dbname, {})
cache = GQLCoreCache.setdefault((dbname, namespace), {})

core = graphql.GQLCoreSchema(
s_schema.ChainedSchema(
Expand All @@ -68,6 +69,7 @@ def _get_gqlcore(

def compile_graphql(
dbname: str,
namespace: str,
std_schema: s_schema.FlatSchema,
user_schema: s_schema.FlatSchema,
global_schema: s_schema.FlatSchema,
Expand All @@ -88,7 +90,7 @@ def compile_graphql(
else:
ast = graphql.parse_tokens(gql, tokens)

gqlcore = _get_gqlcore(dbname, std_schema, user_schema, global_schema, module)
gqlcore = _get_gqlcore(dbname, namespace, std_schema, user_schema, global_schema, module)

return graphql.translate_ast(
gqlcore,
Expand Down
36 changes: 28 additions & 8 deletions edb/graphql/extension.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ async def handle_request(
globals = None
query = None
module = None
namespace = edbdef.DEFAULT_NS
limit = 0

try:
Expand All @@ -111,6 +112,7 @@ async def handle_request(
variables = body.get('variables')
module = body.get('module')
limit = body.get('limit', 0)
namespace = body.get('namespace', edbdef.DEFAULT_NS)
globals = body.get('globals')
elif request.content_type == 'application/graphql':
query = request.body.decode('utf-8')
Expand Down Expand Up @@ -157,6 +159,12 @@ async def handle_request(
else:
limit = 0

namespace = qs.get('namespace')
if namespace is not None:
namespace = namespace[0]
else:
namespace = edbdef.DEFAULT_NS

else:
raise TypeError('expected a GET or a POST request')

Expand Down Expand Up @@ -186,7 +194,7 @@ async def handle_request(
response.content_type = b'application/json'
try:
result = await _execute(
db, server, query,
db, namespace, server, query,
operation_name, variables, globals,
query_only, module or None, limit
)
Expand Down Expand Up @@ -216,6 +224,7 @@ async def handle_request(

async def compile(
db,
ns,
server,
query: str,
tokens: Optional[List[Tuple[int, int, int, str]]],
Expand All @@ -229,9 +238,10 @@ async def compile(
compiler_pool = server.get_compiler_pool()
return await compiler_pool.compile_graphql(
db.name,
db.user_schema,
ns.name,
ns.user_schema,
server.get_global_schema(),
db.reflection_cache,
ns.reflection_cache,
db.db_config,
server.get_compilation_system_config(),
query,
Expand All @@ -246,9 +256,17 @@ async def compile(


async def _execute(
db, server, query, operation_name, variables,
db, namespace, server, query, operation_name, variables,
globals, query_only, module, limit
):

if namespace not in db.ns_map:
raise errors.QueryError(
f'NameSpace: [{namespace}] not in current db [{db.name}](ver:{db.dbver}).'
f'Current NameSpace(s): [{", ".join(db.ns_map.keys())}]'
)
ns = db.ns_map[namespace]

dbver = db.dbver
query_cache = server._http_query_cache

Expand Down Expand Up @@ -298,7 +316,7 @@ async def _execute(
print(f'key_vars: {key_var_names}')
print(f'variables: {vars}')

cache_key = ('graphql', prepared_query, key_vars, operation_name, dbver, query_only, module, limit)
cache_key = ('graphql', prepared_query, key_vars, operation_name, dbver, query_only, namespace, module, limit)
use_prep_stmt = False

entry: CacheEntry = None
Expand All @@ -307,13 +325,14 @@ async def _execute(

if isinstance(entry, CacheRedirect):
key_vars2 = tuple(vars[k] for k in entry.key_vars)
cache_key2 = (prepared_query, key_vars2, operation_name, dbver, query_only, module, limit)
cache_key2 = (prepared_query, key_vars2, operation_name, dbver, query_only, namespace, module, limit)
entry = query_cache.get(cache_key2, None)

if entry is None:
if rewritten is not None:
qug, gql_op = await compile(
db,
ns,
server,
query,
rewritten.tokens(gql_lexer.TokenKind),
Expand All @@ -327,6 +346,7 @@ async def _execute(
else:
qug, gql_op = await compile(
db,
ns,
server,
query,
None,
Expand All @@ -349,7 +369,7 @@ async def _execute(
query_cache[cache_key] = redir
key_vars2 = tuple(vars[k] for k in key_var_names)
cache_key2 = (
'graphql', prepared_query, key_vars2, operation_name, dbver, query_only, module, limit
'graphql', prepared_query, key_vars2, operation_name, dbver, query_only, namespace, module, limit
)
query_cache[cache_key2] = qug, gql_op
if gql_op.is_introspection:
Expand All @@ -372,7 +392,7 @@ async def _execute(
dbv = await server.new_dbview(
dbname=db.name,
query_cache=False,
protocol_version=edbdef.CURRENT_PROTOCOL,
protocol_version=edbdef.CURRENT_PROTOCOL
)

pgcon = await server.acquire_pgcon(db.name)
Expand Down
2 changes: 2 additions & 0 deletions edb/ir/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ class TypeRef(ImmutableBase):
is_opaque_union: bool = False
# True, if this describes an sequnce type
is_sequence: bool = False
# True, if this contains enums
has_enum: bool = False

def __repr__(self) -> str:
return f'<ir.TypeRef \'{self.name_hint}\' at 0x{id(self):x}>'
Expand Down
Loading