edgedb / edgedb

A graph-relational database with declarative schema, built-in migration system, and a next-generation query language
https://edgedb.com
Apache License 2.0
13k stars 400 forks source link

Computable property fails for union type properties #2002

Closed adriangb closed 3 years ago

adriangb commented 3 years ago

This works (as expected):

type Type1;
type Type2;
type Type3 {
    link prop1 -> (Type1 | Type2);
}

So does this:

type Type1;
type Type2;
type Type3 {
    link prop1 -> Type1;
    link prop2 := (
        SELECT .prop1
    );
}

Thus I expected this to work, but it fails:

type Type1;
type Type2;
type Type3 {
    link prop1 -> (Type1 | Type2);
    link prop2 := (
        SELECT .prop1
    );
}

With:

AttributeError: 'UnionType' object has no attribute 'get_name'
Traceback ``` ERROR: InternalServerError: 'UnionType' object has no attribute 'get_name' Hint: This is most likely a bug in EdgeDB. Please consider opening an issue ticket at https://github.com/edgedb/edgedb/issues/new?template=bug_report.md Server traceback: Traceback (most recent call last): File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/site-packages/edb/server/procpool/worker.py", line 75, in worker res = await meth(*args) File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/site-packages/edb/server/compiler/compiler.py", line 1808, in compile_eql_tokens return self._compile(ctx=ctx, tokens=eql_tokens) File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/site-packages/edb/server/compiler/compiler.py", line 1442, in _compile comp: dbstate.BaseQuery = self._compile_dispatch_ql(ctx, stmt) File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/site-packages/edb/server/compiler/compiler.py", line 1365, in _compile_dispatch_ql return self._compile_ql_migration(ctx, ql) File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/site-packages/edb/server/compiler/compiler.py", line 794, in _compile_ql_migration target_schema = s_ddl.apply_sdl( File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/site-packages/edb/schema/ddl.py", line 371, in apply_sdl ddl_stmts = s_decl.sdl_to_ddl(current_schema, documents) File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/site-packages/edb/edgeql/declarative.py", line 230, in sdl_to_ddl trace_dependencies(decl_ast, ctx=ctx) File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/functools.py", line 875, in wrapper return dispatch(args[0].__class__)(*args, **kw) File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/site-packages/edb/edgeql/declarative.py", line 499, in trace_default _register_item(node, ctx=ctx) File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/site-packages/edb/edgeql/declarative.py", line 623, in _register_item trace_dependencies(cmd, ctx=ctx) File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/functools.py", line 875, in wrapper return dispatch(args[0].__class__)(*args, **kw) File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/site-packages/edb/edgeql/declarative.py", line 443, in trace_ConcretePointer _register_item( File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/site-packages/edb/edgeql/declarative.py", line 638, in _register_item tdeps = qltracer.trace_refs( File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/site-packages/edb/edgeql/tracer.py", line 162, in trace_refs trace(qltree, ctx=ctx) File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/functools.py", line 875, in wrapper return dispatch(args[0].__class__)(*args, **kw) File "/usr/lib/x86_64-linux-gnu/edgedb-server-1-alpha6/lib/python3.8/site-packages/edb/edgeql/tracer.py", line 653, in trace_Select ctx.path_prefix = tip.get_name(ctx.schema) AttributeError: 'UnionType' object has no attribute 'get_name' ```

I'm just learning EdgeQL SDL so sorry if this is just user error!

adriangb commented 3 years ago

I kind of got this to work via:

type Type1;
type Type2;
type Type3 {
    link prop1 -> (Type1 | Type2);
    multi link prop2 := (
        (
            (SELECT .prop1[IS Type1] LIMIT 1)
            UNION
            (SELECT .prop1[IS Type2] LIMIT 1)
        )
    )

But I'm not sure this would work for arbitrarily large union types.

adriangb commented 3 years ago

For my use case at least, the following alternative works:

START MIGRATION TO {
    module default {
        abstract type TypeBase {};
        type Type1 extending TypeBase;
        type Type2 extending TypeBase;
        type Type3 {
            link prop1 -> TypeBase;
            link prop2 := (
                SELECT .prop1
            );
        }
    }
};