-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1109 polymorphic types union (#1111)
fixes #1109 We allow union of multiple types in schema computed fields. Some members of the union can extend some other common types, but not all members have to.
- Loading branch information
Showing
12 changed files
with
370 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 4 additions & 0 deletions
4
...um7zhqsaovf7l2sdw2g4dnayfqq-m1xym4iizk6uca3j6edxwxofb3z2ryclmnapjj24apuap2beaqd47a.edgeql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
CREATE MIGRATION m1vk6tojt7l6b3to5psw6kqzrkdfed773ysvabmblc6odywm33ztfa | ||
ONTO m1n37rkzwbdej2nsfr73ujxlwjaum7zhqsaovf7l2sdw2g4dnayfqq | ||
{ | ||
}; |
44 changes: 44 additions & 0 deletions
44
integration-tests/stable/dbschema/migrations/00001-m1xym4i.edgeql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
CREATE MIGRATION m1xym4iizk6uca3j6edxwxofb3z2ryclmnapjj24apuap2beaqd47a | ||
ONTO initial | ||
{ | ||
CREATE EXTENSION pgcrypto VERSION '1.3'; | ||
CREATE EXTENSION auth VERSION '1.0'; | ||
CREATE TYPE default::Documentary { | ||
CREATE REQUIRED PROPERTY title: std::str; | ||
CREATE REQUIRED PROPERTY plot: std::str; | ||
}; | ||
CREATE ABSTRACT TYPE default::Content { | ||
CREATE REQUIRED PROPERTY title: std::str; | ||
CREATE REQUIRED PROPERTY year: std::int16; | ||
}; | ||
CREATE TYPE default::Movie EXTENDING default::Content { | ||
CREATE REQUIRED PROPERTY plot: std::str; | ||
}; | ||
CREATE TYPE default::Show EXTENDING default::Content { | ||
CREATE REQUIRED PROPERTY seasons: std::int16; | ||
}; | ||
CREATE TYPE default::User { | ||
CREATE MULTI LINK documentaries: default::Documentary; | ||
CREATE MULTI LINK movies: default::Movie; | ||
CREATE MULTI LINK shows: default::Show; | ||
CREATE MULTI LINK all_media := (SELECT | ||
((.movies UNION .shows) UNION .documentaries) | ||
); | ||
CREATE MULTI LINK watching_list := (SELECT | ||
(.movies UNION .shows) | ||
ORDER BY | ||
.year ASC | ||
); | ||
CREATE LINK identity: ext::auth::Identity; | ||
}; | ||
CREATE TYPE default::CryptoTest { | ||
CREATE PROPERTY hash_sha256: std::bytes; | ||
}; | ||
CREATE TYPE default::Post { | ||
CREATE REQUIRED PROPERTY text: std::str; | ||
CREATE INDEX fts::index ON (fts::with_options(.text, language := fts::Language.eng)); | ||
}; | ||
CREATE TYPE default::WithMultiRange { | ||
CREATE REQUIRED PROPERTY ranges: multirange<std::int32>; | ||
}; | ||
}; |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
[edgedb] | ||
server-version = "4" | ||
server-version = "5" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
import type * as edgedb from "edgedb"; | ||
import assert from "node:assert/strict"; | ||
|
||
import e, { type $infer } from "./dbschema/edgeql-js"; | ||
import { setupTests, teardownTests, tc } from "./setupTeardown"; | ||
|
||
let client: edgedb.Client; | ||
|
||
describe("select", () => { | ||
beforeAll(async () => { | ||
const setup = await setupTests(); | ||
({ client } = setup); | ||
}); | ||
|
||
afterAll(async () => { | ||
await teardownTests(client); | ||
}, 10_000); | ||
|
||
test("union of polymorphic types in computed schema field", () => { | ||
const WatchingList = e.shape(e.User.watching_list, () => ({ | ||
year: true, | ||
title: true, | ||
...e.is(e.Movie, { | ||
plot: true, | ||
}), | ||
...e.is(e.Show, { | ||
seasons: true, | ||
}), | ||
})); | ||
|
||
const q = e.select(e.User, () => ({ | ||
watching_list: WatchingList, | ||
})); | ||
|
||
type qT = $infer<typeof q>; | ||
|
||
tc.assert< | ||
tc.IsExact< | ||
qT, | ||
{ | ||
watching_list: ( | ||
| { | ||
year: number; | ||
title: string; | ||
plot: string; | ||
__typename: "default::Movie"; | ||
} | ||
| { | ||
year: number; | ||
title: string; | ||
seasons: number; | ||
__typename: "default::Show"; | ||
} | ||
)[]; | ||
}[] | ||
> | ||
>(true); | ||
}); | ||
|
||
test("union of 3 types in computed schema field - two types extend, one doesn't, query the common field only", async () => { | ||
const q = e.select(e.User, () => ({ | ||
all_media: { | ||
title: true, | ||
}, | ||
})); | ||
|
||
type qT = $infer<typeof q>; | ||
|
||
tc.assert< | ||
tc.IsExact< | ||
qT, | ||
{ | ||
all_media: { | ||
title: string; | ||
}[]; | ||
}[] | ||
> | ||
>(true); | ||
|
||
const result = await q.run(client); | ||
const expected = [ | ||
{ | ||
all_media: [ | ||
{ | ||
title: "Inception", | ||
}, | ||
{ | ||
title: "Friends", | ||
}, | ||
{ | ||
title: "Free Solo", | ||
}, | ||
], | ||
}, | ||
]; | ||
assert.deepEqual(result, expected); | ||
}); | ||
|
||
// TODO Fix type for Show in the result: Show doesn't have the plot | ||
test("union of 3 types in computed schema field - two types extend, one doesn't", async () => { | ||
const q = e.select(e.User, () => ({ | ||
all_media: (all_media) => ({ | ||
title: true, | ||
...e.is(e.Content, { year: true }), | ||
...e.is(e.Show, { | ||
seasons: true, | ||
}), | ||
plot: e.op( | ||
all_media.is(e.Movie).plot, | ||
"??", | ||
all_media.is(e.Documentary).plot, | ||
), | ||
}), | ||
})); | ||
|
||
type qT = $infer<typeof q>; | ||
|
||
tc.assert< | ||
tc.IsExact< | ||
qT, | ||
{ | ||
all_media: ( | ||
| { | ||
title: string; | ||
plot: string; | ||
__typename: "default::Documentary"; | ||
} | ||
| { | ||
title: string; | ||
plot: string; | ||
year: number; | ||
__typename: "default::Movie"; | ||
} | ||
| { | ||
title: string; | ||
plot: string; | ||
year: number; | ||
seasons: number; | ||
__typename: "default::Show"; | ||
} | ||
)[]; | ||
}[] | ||
> | ||
>(true); | ||
|
||
const result = await q.run(client); | ||
const expected = [ | ||
{ | ||
all_media: [ | ||
{ | ||
__typename: "default::Movie", | ||
plot: "Inception plot", | ||
seasons: null, | ||
title: "Inception", | ||
year: 2010, | ||
}, | ||
{ | ||
__typename: "default::Show", | ||
plot: null, | ||
seasons: 10, | ||
title: "Friends", | ||
year: 1994, | ||
}, | ||
{ | ||
__typename: "default::Documentary", | ||
plot: "Free Solo plot", | ||
seasons: null, | ||
title: "Free Solo", | ||
year: null, | ||
}, | ||
], | ||
}, | ||
]; | ||
assert.deepEqual(result, expected); | ||
}); | ||
|
||
test("a field cannot be selected as common if it exists in only one of the union types", async () => { | ||
const q = e.select(e.User, () => ({ | ||
watching_list: { | ||
year: true, | ||
title: true, | ||
plot: true, | ||
}, | ||
})); | ||
|
||
type qT = $infer<typeof q>; | ||
|
||
tc.assert< | ||
tc.IsExact< | ||
qT, | ||
{ | ||
watching_list: { | ||
year: number; | ||
title: string; | ||
}[]; | ||
}[] | ||
> | ||
>(true); | ||
|
||
return assert.rejects(async () => await q.run(client), { | ||
message: `Field "plot" does not exist in default::Movie | default::Show`, | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.