From fc74e1861ba1a25ff300be68be71e996ece00784 Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Tue, 7 Nov 2023 11:17:01 -0500 Subject: [PATCH 01/15] anyobject returns the anytype --- packages/generate/src/syntax/hydrate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/generate/src/syntax/hydrate.ts b/packages/generate/src/syntax/hydrate.ts index 1be07429d..6ba0d08c1 100644 --- a/packages/generate/src/syntax/hydrate.ts +++ b/packages/generate/src/syntax/hydrate.ts @@ -98,7 +98,7 @@ export function makeType( ): T { const type = spec.get(id); - if (type.name === "anytype" || type.name === "std::anypoint") { + if (type.name === "anytype" || type.name === "std::anypoint" || type.name === "anyobject") { if (anytype) return anytype as unknown as T; throw new Error("anytype not provided"); } From 33cc24dc2c05cb01cc0f4b7ea58f4fe96d6348d5 Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Tue, 7 Nov 2023 12:00:53 -0500 Subject: [PATCH 02/15] Allow NamedTuple as select expression --- integration-tests/stable/fts.test.ts | 61 ++++++++++++++++++++++ integration-tests/stable/package.json | 3 +- packages/generate/src/syntax/path.ts | 29 +++++++--- packages/generate/src/syntax/select.ts | 39 ++++++++++++-- packages/generate/src/syntax/typesystem.ts | 2 +- 5 files changed, 121 insertions(+), 13 deletions(-) create mode 100644 integration-tests/stable/fts.test.ts diff --git a/integration-tests/stable/fts.test.ts b/integration-tests/stable/fts.test.ts new file mode 100644 index 000000000..95e72b640 --- /dev/null +++ b/integration-tests/stable/fts.test.ts @@ -0,0 +1,61 @@ +import type { Client } from "edgedb"; +import e, { type $infer } from "./dbschema/edgeql-js"; +import { setupTests, tc, teardownTests } from "./setupTeardown"; + +describe("full-text search", () => { + let client: Client; + beforeAll(async () => { + const setup = await setupTests(); + ({ client } = setup); + }); + + afterAll(async () => { + await teardownTests(client); + }, 10_000); + + test("basic fts", async () => { + const posts = [ + "Full-text search is a technique for searching text content. It works by storing every unique word that appears in a document.", + "To perform a full-text search, the search engine examines all the words in the specified document or set of documents.", + "The process of full-text search begins with the user entering a string of characters (the search string).", + "The search engine then retrieves all instances of the search string in the document or collection of documents.", + "Full-text search can be used in many applications that require search capability, such as web search engines, document management systems, and digital libraries.", + ]; + const inserted = await e + .params({ posts: e.array(e.str) }, (params) => { + return e.for(e.array_unpack(params.posts), (post) => + e.insert(e.Post, { text: post }) + ); + }) + .run(client, { posts }); + + const allQuery = e.select(e.fts.search(e.Post, "search"), () => ({ + object: true, + score: true, + })); + const all = await allQuery.run(client); + + expect(all.length).toBe(inserted.length); + + tc.assert< + tc.IsExact< + $infer, + { + object: Record; + score: number; + }[] + > + >(true); + + const filteredQuery = e.select(e.fts.search(e.Post, "search"), (post) => ({ + object: true, + score: true, + filter: e.op(post.score, ">", e.float64(0.83)), + })); + console.log(filteredQuery.toEdgeQL()); + const filtered = await filteredQuery.run(client); + + console.log(filtered); + expect(filtered.length).toBe(1); + }); +}); diff --git a/integration-tests/stable/package.json b/integration-tests/stable/package.json index 00c37b84f..1a3d652ac 100644 --- a/integration-tests/stable/package.json +++ b/integration-tests/stable/package.json @@ -15,7 +15,8 @@ "jest": "^29.5.0", "superjson": "^1.12.4", "ts-jest": "^29.1.0", - "typescript": "^5.2.2" + "typescript": "^5.2.2", + "edgedb": "workspaces:*" }, "dependencies": {} } diff --git a/packages/generate/src/syntax/path.ts b/packages/generate/src/syntax/path.ts index 0e03b98c0..dcd1cf1fd 100644 --- a/packages/generate/src/syntax/path.ts +++ b/packages/generate/src/syntax/path.ts @@ -23,6 +23,7 @@ import type { BaseType, Expression, LinkDesc, + NamedTupleType, ObjectType, ObjectTypePointers, ObjectTypeSet, @@ -171,16 +172,28 @@ type pathifyLinkProps< : unknown; }; -export type getPropsShape = typeutil.flatten< - typeutil.stripNever<{ - [k in keyof T["__pointers__"]]: T["__pointers__"][k]["__kind__"] extends "property" - ? true - : never; - }> ->; +export type getPropsShape = + typeutil.flatten< + typeutil.stripNever< + T extends ObjectType + ? { + [k in keyof T["__pointers__"]]: T["__pointers__"][k]["__kind__"] extends "property" + ? true + : never; + } + : { + [k in keyof T["__shape__"]]: T["__shape__"][k]["__kind__"] extends "property" + ? true + : never; + } + > + >; export type $expr_PathNode< - Root extends ObjectTypeSet = ObjectTypeSet, + Root extends TypeSet< + ObjectType | NamedTupleType, + Cardinality + > = ObjectTypeSet, Parent extends PathParent | null = PathParent | null // Exclusive extends boolean = boolean > = Expression<{ diff --git a/packages/generate/src/syntax/select.ts b/packages/generate/src/syntax/select.ts index 60371e7fc..0c857463d 100644 --- a/packages/generate/src/syntax/select.ts +++ b/packages/generate/src/syntax/select.ts @@ -35,6 +35,7 @@ import type { BaseType, ExclusiveTuple, orLiteralValue, + NamedTupleType, } from "./typesystem"; import { @@ -368,7 +369,7 @@ export type InferOffsetLimitCardinality< // Modifiers // >; export type ComputeSelectCardinality< - Expr extends ObjectTypeExpression, + Expr extends ObjectTypeExpression | TypeSet, Modifiers extends UnknownSelectModifiers > = InferOffsetLimitCardinality< undefined extends Modifiers["filter_single"] @@ -780,6 +781,21 @@ export type objectTypeToSelectShape = : any; }> & { [k: string]: unknown }; +export type namedTupleTypeToSelectShape< + T extends NamedTupleType = NamedTupleType +> = Partial< + { + [k in keyof T["__shape__"]]: T["__shape__"][k] extends PropertyDesc + ? + | boolean + | TypeSet< + T["__shape__"][k]["target"], + cardutil.assignable + > + : any; + } & { [k: string]: unknown } +>; + // incorporate __shape__ (computeds) on selection shapes // this works but a major rewrite of setToTsType is required // to incorporate __shape__-based selection shapes into @@ -902,6 +918,19 @@ export function select< >; __cardinality__: ComputeSelectCardinality; }>; + +export function select< + Expr extends TypeSet, + Shape extends namedTupleTypeToSelectShape & + Omit, + Modifiers extends UnknownSelectModifiers = Pick +>( + expr: Expr, + shape: (scope: $scopify) => Readonly +): $expr_Select<{ + __element__: NamedTupleType; + __cardinality__: ComputeSelectCardinality; +}>; /* For the moment is isn't possible to implement both closure-based and plain @@ -1096,7 +1125,8 @@ function resolveShape( // get scoped object if expression is objecttypeset const scope = - expr.__element__.__kind__ === TypeKind.object + expr.__element__.__kind__ === TypeKind.object || + expr.__element__.__kind__ === TypeKind.namedtuple ? $getScopedExpr(expr as any, $existingScopes) : expr; @@ -1117,7 +1147,10 @@ function resolveShape( } else { // for scalar expressions, scope === expr // shape keys are not allowed - if (expr.__element__.__kind__ !== TypeKind.object) { + if ( + expr.__element__.__kind__ !== TypeKind.object && + expr.__element__.__kind__ !== TypeKind.namedtuple + ) { throw new Error( `Invalid select shape key '${key}' on scalar expression, ` + `only modifiers are allowed (filter, order_by, offset and limit)` diff --git a/packages/generate/src/syntax/typesystem.ts b/packages/generate/src/syntax/typesystem.ts index 05c31e407..4909d9645 100644 --- a/packages/generate/src/syntax/typesystem.ts +++ b/packages/generate/src/syntax/typesystem.ts @@ -264,7 +264,7 @@ export interface PropertyDesc< hasDefault: HasDefault; } -export type $scopify = $expr_PathNode< +export type $scopify = $expr_PathNode< TypeSet // null, // true // exclusivity From 02898efe18880bec17a8c384a4b8942b26fe8649 Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Tue, 7 Nov 2023 12:56:08 -0500 Subject: [PATCH 03/15] Do not put named tuple expressions in a scope --- integration-tests/stable/fts.test.ts | 4 +--- packages/generate/src/syntax/select.ts | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/integration-tests/stable/fts.test.ts b/integration-tests/stable/fts.test.ts index 95e72b640..644f925f4 100644 --- a/integration-tests/stable/fts.test.ts +++ b/integration-tests/stable/fts.test.ts @@ -50,12 +50,10 @@ describe("full-text search", () => { const filteredQuery = e.select(e.fts.search(e.Post, "search"), (post) => ({ object: true, score: true, - filter: e.op(post.score, ">", e.float64(0.83)), + filter: e.op(post.score, ">", e.float64(0.81)), })); - console.log(filteredQuery.toEdgeQL()); const filtered = await filteredQuery.run(client); - console.log(filtered); expect(filtered.length).toBe(1); }); }); diff --git a/packages/generate/src/syntax/select.ts b/packages/generate/src/syntax/select.ts index 0c857463d..37e853379 100644 --- a/packages/generate/src/syntax/select.ts +++ b/packages/generate/src/syntax/select.ts @@ -1125,8 +1125,7 @@ function resolveShape( // get scoped object if expression is objecttypeset const scope = - expr.__element__.__kind__ === TypeKind.object || - expr.__element__.__kind__ === TypeKind.namedtuple + expr.__element__.__kind__ === TypeKind.object ? $getScopedExpr(expr as any, $existingScopes) : expr; From 19e887b852f9a241ed3fa1c95a055c2853629cca Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Tue, 7 Nov 2023 13:05:41 -0500 Subject: [PATCH 04/15] Build modifiers like ObjectType --- packages/generate/src/syntax/select.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/generate/src/syntax/select.ts b/packages/generate/src/syntax/select.ts index 37e853379..9eb5f64d9 100644 --- a/packages/generate/src/syntax/select.ts +++ b/packages/generate/src/syntax/select.ts @@ -112,7 +112,9 @@ export type exclusivesToFilterSingle = : orLiteralValue; }; }[number]; -export type SelectModifiers = { +export type SelectModifiers< + T extends ObjectType | NamedTupleType = ObjectType +> = { // export type SelectModifiers = { filter?: SelectFilterExpression; filter_single?: // | Partial< @@ -144,7 +146,9 @@ export type SelectModifiers = { // : never // : never; // }>) - exclusivesToFilterSingle | SelectFilterExpression; + T extends ObjectType + ? exclusivesToFilterSingle | SelectFilterExpression + : never; // | (ObjectType extends T // ? unknown @@ -922,7 +926,7 @@ export function select< export function select< Expr extends TypeSet, Shape extends namedTupleTypeToSelectShape & - Omit, + SelectModifiers, Modifiers extends UnknownSelectModifiers = Pick >( expr: Expr, From 85704c5ead5ee9f62a401874dd3a1d7a74a0efa9 Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Tue, 7 Nov 2023 13:55:39 -0500 Subject: [PATCH 05/15] Handle selecting from named tuple paths --- integration-tests/stable/fts.test.ts | 17 +++++++++++++++-- packages/generate/src/syntax/path.ts | 12 +++++++----- packages/generate/src/syntax/select.ts | 3 ++- packages/generate/src/syntax/typesystem.ts | 2 +- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/integration-tests/stable/fts.test.ts b/integration-tests/stable/fts.test.ts index 644f925f4..86f88a47a 100644 --- a/integration-tests/stable/fts.test.ts +++ b/integration-tests/stable/fts.test.ts @@ -29,7 +29,9 @@ describe("full-text search", () => { }) .run(client, { posts }); - const allQuery = e.select(e.fts.search(e.Post, "search"), () => ({ + const searchExpr = e.select(e.fts.search(e.Post, "search")); + + const allQuery = e.select(searchExpr, (post) => ({ object: true, score: true, })); @@ -47,7 +49,7 @@ describe("full-text search", () => { > >(true); - const filteredQuery = e.select(e.fts.search(e.Post, "search"), (post) => ({ + const filteredQuery = e.select(searchExpr, (post) => ({ object: true, score: true, filter: e.op(post.score, ">", e.float64(0.81)), @@ -55,5 +57,16 @@ describe("full-text search", () => { const filtered = await filteredQuery.run(client); expect(filtered.length).toBe(1); + + const noShapeQuery = e.select(searchExpr); + const noShape = await noShapeQuery.run(client); + + expect(noShape).toEqual(all); + + const objectSelectQuery = e.select(searchExpr.object, () => ({ + text: true, + })); + const objectSelect = await objectSelectQuery.run(client); + expect(objectSelect).toEqual([]); }); }); diff --git a/packages/generate/src/syntax/path.ts b/packages/generate/src/syntax/path.ts index dcd1cf1fd..9170f58b9 100644 --- a/packages/generate/src/syntax/path.ts +++ b/packages/generate/src/syntax/path.ts @@ -20,6 +20,7 @@ import { $toEdgeQL } from "./toEdgeQL"; import { $queryFunc, $queryFuncJSON } from "./query"; import type { + $expr_TuplePath, BaseType, Expression, LinkDesc, @@ -190,10 +191,7 @@ export type getPropsShape = >; export type $expr_PathNode< - Root extends TypeSet< - ObjectType | NamedTupleType, - Cardinality - > = ObjectTypeSet, + Root extends TypeSet = ObjectTypeSet, Parent extends PathParent | null = PathParent | null // Exclusive extends boolean = boolean > = Expression<{ @@ -328,7 +326,11 @@ export function $pathify( return _root as any; } - const root: $expr_PathNode = _root as any; + const root: $expr_PathNode | $expr_TuplePath = _root as any; + + if (root.__kind__ === ExpressionKind.TuplePath) { + return _root as any; + } let pointers = { ...root.__element__.__pointers__, diff --git a/packages/generate/src/syntax/select.ts b/packages/generate/src/syntax/select.ts index 9eb5f64d9..aa468e632 100644 --- a/packages/generate/src/syntax/select.ts +++ b/packages/generate/src/syntax/select.ts @@ -36,6 +36,7 @@ import type { ExclusiveTuple, orLiteralValue, NamedTupleType, + $expr_TuplePath, } from "./typesystem"; import { @@ -930,7 +931,7 @@ export function select< Modifiers extends UnknownSelectModifiers = Pick >( expr: Expr, - shape: (scope: $scopify) => Readonly + shape: (scope: $expr_TuplePath) => Readonly ): $expr_Select<{ __element__: NamedTupleType; __cardinality__: ComputeSelectCardinality; diff --git a/packages/generate/src/syntax/typesystem.ts b/packages/generate/src/syntax/typesystem.ts index 4909d9645..05c31e407 100644 --- a/packages/generate/src/syntax/typesystem.ts +++ b/packages/generate/src/syntax/typesystem.ts @@ -264,7 +264,7 @@ export interface PropertyDesc< hasDefault: HasDefault; } -export type $scopify = $expr_PathNode< +export type $scopify = $expr_PathNode< TypeSet // null, // true // exclusivity From e4535a3a877b5df6178e70d912d1a1460b1bbfa1 Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Tue, 7 Nov 2023 14:39:50 -0500 Subject: [PATCH 06/15] Use the explicit `anytype` if it exists --- packages/generate/src/edgeql-js/generateObjectTypes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/generate/src/edgeql-js/generateObjectTypes.ts b/packages/generate/src/edgeql-js/generateObjectTypes.ts index a85c145f2..f0ead4c0b 100644 --- a/packages/generate/src/edgeql-js/generateObjectTypes.ts +++ b/packages/generate/src/edgeql-js/generateObjectTypes.ts @@ -40,7 +40,7 @@ export const getStringRepresentation: ( } if (type.name === "anyobject") { return { - staticType: [`$.AnyObjectType`], + staticType: frag`${params.anytype ?? "$.AnyObjectType"}`, runtimeType: [], }; } From 1247f1955e473df81500ce33e457bdcfef011b92 Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Tue, 7 Nov 2023 14:40:12 -0500 Subject: [PATCH 07/15] Add test case for object select --- integration-tests/stable/fts.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/stable/fts.test.ts b/integration-tests/stable/fts.test.ts index 86f88a47a..82fe29fc9 100644 --- a/integration-tests/stable/fts.test.ts +++ b/integration-tests/stable/fts.test.ts @@ -63,8 +63,8 @@ describe("full-text search", () => { expect(noShape).toEqual(all); - const objectSelectQuery = e.select(searchExpr.object, () => ({ - text: true, + const objectSelectQuery = e.select(searchExpr.object, (post) => ({ + text: post.text, })); const objectSelect = await objectSelectQuery.run(client); expect(objectSelect).toEqual([]); From f9ea8d65bf3b4c04e700f20a953992eb68ce24e2 Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Tue, 7 Nov 2023 14:43:38 -0500 Subject: [PATCH 08/15] Fix type expectations --- integration-tests/stable/fts.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/integration-tests/stable/fts.test.ts b/integration-tests/stable/fts.test.ts index 82fe29fc9..459088e52 100644 --- a/integration-tests/stable/fts.test.ts +++ b/integration-tests/stable/fts.test.ts @@ -1,6 +1,7 @@ import type { Client } from "edgedb"; import e, { type $infer } from "./dbschema/edgeql-js"; import { setupTests, tc, teardownTests } from "./setupTeardown"; +import { $Post } from "./dbschema/edgeql-js/modules/default"; describe("full-text search", () => { let client: Client; @@ -43,7 +44,7 @@ describe("full-text search", () => { tc.IsExact< $infer, { - object: Record; + object: { id: string }; score: number; }[] > @@ -68,5 +69,9 @@ describe("full-text search", () => { })); const objectSelect = await objectSelectQuery.run(client); expect(objectSelect).toEqual([]); + + tc.assert, { text: string }[]>>( + true + ); }); }); From 3f17d92fe3c996335d84b52457a98ca42605772c Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Wed, 8 Nov 2023 09:08:47 -0500 Subject: [PATCH 09/15] Fix edgedb version in integration test suite --- integration-tests/stable/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/stable/package.json b/integration-tests/stable/package.json index 1a3d652ac..c1bbb726a 100644 --- a/integration-tests/stable/package.json +++ b/integration-tests/stable/package.json @@ -16,7 +16,7 @@ "superjson": "^1.12.4", "ts-jest": "^29.1.0", "typescript": "^5.2.2", - "edgedb": "workspaces:*" + "edgedb": "^1.4.1" }, "dependencies": {} } From 2447ddfe3ed31b910033fbdb9b7fd82a24aa36ca Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Wed, 8 Nov 2023 09:09:03 -0500 Subject: [PATCH 10/15] Remove unused scope var --- integration-tests/stable/fts.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/stable/fts.test.ts b/integration-tests/stable/fts.test.ts index 459088e52..8c795c995 100644 --- a/integration-tests/stable/fts.test.ts +++ b/integration-tests/stable/fts.test.ts @@ -32,7 +32,7 @@ describe("full-text search", () => { const searchExpr = e.select(e.fts.search(e.Post, "search")); - const allQuery = e.select(searchExpr, (post) => ({ + const allQuery = e.select(searchExpr, () => ({ object: true, score: true, })); From 0a700d0acc9ab5b1911365fc54402b36d229af8f Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Wed, 8 Nov 2023 09:57:01 -0500 Subject: [PATCH 11/15] Remove unnecessary experimental type changes --- packages/generate/src/syntax/path.ts | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/packages/generate/src/syntax/path.ts b/packages/generate/src/syntax/path.ts index 9170f58b9..f58cb7f83 100644 --- a/packages/generate/src/syntax/path.ts +++ b/packages/generate/src/syntax/path.ts @@ -24,7 +24,6 @@ import type { BaseType, Expression, LinkDesc, - NamedTupleType, ObjectType, ObjectTypePointers, ObjectTypeSet, @@ -173,25 +172,16 @@ type pathifyLinkProps< : unknown; }; -export type getPropsShape = - typeutil.flatten< - typeutil.stripNever< - T extends ObjectType - ? { - [k in keyof T["__pointers__"]]: T["__pointers__"][k]["__kind__"] extends "property" - ? true - : never; - } - : { - [k in keyof T["__shape__"]]: T["__shape__"][k]["__kind__"] extends "property" - ? true - : never; - } - > - >; +export type getPropsShape = typeutil.flatten< + typeutil.stripNever<{ + [k in keyof T["__pointers__"]]: T["__pointers__"][k]["__kind__"] extends "property" + ? true + : never; + }> +>; export type $expr_PathNode< - Root extends TypeSet = ObjectTypeSet, + Root extends ObjectTypeSet = ObjectTypeSet, Parent extends PathParent | null = PathParent | null // Exclusive extends boolean = boolean > = Expression<{ From bf42948a57bc6bd5410b625a768b46d7ef2cbbcb Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Wed, 8 Nov 2023 09:57:25 -0500 Subject: [PATCH 12/15] Pathify TuplePath --- packages/generate/src/syntax/path.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/generate/src/syntax/path.ts b/packages/generate/src/syntax/path.ts index f58cb7f83..9ba52ec8f 100644 --- a/packages/generate/src/syntax/path.ts +++ b/packages/generate/src/syntax/path.ts @@ -309,24 +309,20 @@ const pathifyProxyHandlers: ProxyHandler = { }, }; -export function $pathify( - _root: Root -): $pathify { +export function $pathify(_root: Root): $pathify { if (_root.__element__.__kind__ !== TypeKind.object) { - return _root as any; + return _root as $pathify; } - const root: $expr_PathNode | $expr_TuplePath = _root as any; - - if (root.__kind__ === ExpressionKind.TuplePath) { - return _root as any; - } + const root = _root as unknown as + | $expr_PathNode + | $expr_TuplePath; let pointers = { ...root.__element__.__pointers__, }; - if (root.__parent__) { + if (root.__parent__ && root.__kind__ !== ExpressionKind.TuplePath) { const { type, linkName } = root.__parent__; const parentPointer = type.__element__.__pointers__[linkName]; if (parentPointer?.__kind__ === "link") { From 0df0f9d4ce65de9f5805494d6f62910a4b9815e1 Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Wed, 8 Nov 2023 10:30:13 -0500 Subject: [PATCH 13/15] Fix formatting --- packages/generate/src/syntax/hydrate.ts | 6 +++++- packages/generate/src/syntax/select.ts | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/generate/src/syntax/hydrate.ts b/packages/generate/src/syntax/hydrate.ts index 6ba0d08c1..ad6f5991f 100644 --- a/packages/generate/src/syntax/hydrate.ts +++ b/packages/generate/src/syntax/hydrate.ts @@ -98,7 +98,11 @@ export function makeType( ): T { const type = spec.get(id); - if (type.name === "anytype" || type.name === "std::anypoint" || type.name === "anyobject") { + if ( + type.name === "anytype" || + type.name === "std::anypoint" || + type.name === "anyobject" + ) { if (anytype) return anytype as unknown as T; throw new Error("anytype not provided"); } diff --git a/packages/generate/src/syntax/select.ts b/packages/generate/src/syntax/select.ts index aa468e632..b05789a5f 100644 --- a/packages/generate/src/syntax/select.ts +++ b/packages/generate/src/syntax/select.ts @@ -931,7 +931,9 @@ export function select< Modifiers extends UnknownSelectModifiers = Pick >( expr: Expr, - shape: (scope: $expr_TuplePath) => Readonly + shape: ( + scope: $expr_TuplePath + ) => Readonly ): $expr_Select<{ __element__: NamedTupleType; __cardinality__: ComputeSelectCardinality; From 0a64eb0e0b773d89e1f68af0b42c36ff5b2197f4 Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Wed, 8 Nov 2023 10:30:26 -0500 Subject: [PATCH 14/15] Add a select test for named tuples separate from FTS --- integration-tests/lts/select.test.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/integration-tests/lts/select.test.ts b/integration-tests/lts/select.test.ts index 7c2c56da2..403fd41bf 100644 --- a/integration-tests/lts/select.test.ts +++ b/integration-tests/lts/select.test.ts @@ -500,6 +500,28 @@ describe("select", () => { ); }); + test("named tuples", async () => { + const namedTuple = e.tuple({ foo: e.str("bar") }); + const result = await e.select(namedTuple).run(client); + assert.deepEqual(result, { foo: "bar" }); + + const pathResult = await e.select(namedTuple.foo).run(client); + assert.deepEqual(pathResult, "bar"); + + const nestedObjectTuple = e.for(e.select(e.Hero), (hero) => + e.tuple({ + hero, + score: e.random(), + }) + ); + const nestedObjectQuery = e.select(nestedObjectTuple.hero, (hero) => ({ + name: hero.name, + order_by: nestedObjectTuple.score, + })); + const nestedObjectResult = await nestedObjectQuery.run(client); + assert.deepEqual(nestedObjectResult, []); + }); + test("filter by id", async () => { const result = await e .select(e.Hero, () => ({ From f1d68d141964e257b3652512cbb3b7872aee2696 Mon Sep 17 00:00:00 2001 From: Scott Trinh Date: Fri, 10 Nov 2023 08:58:37 -0500 Subject: [PATCH 15/15] Skip with extraction for TuplePath and Select->TuplePath --- integration-tests/lts/select.test.ts | 17 ++++++++++------- integration-tests/stable/fts.test.ts | 9 ++++++++- packages/generate/src/syntax/toEdgeQL.ts | 5 ++++- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/integration-tests/lts/select.test.ts b/integration-tests/lts/select.test.ts index 403fd41bf..35f7e360f 100644 --- a/integration-tests/lts/select.test.ts +++ b/integration-tests/lts/select.test.ts @@ -508,18 +508,21 @@ describe("select", () => { const pathResult = await e.select(namedTuple.foo).run(client); assert.deepEqual(pathResult, "bar"); - const nestedObjectTuple = e.for(e.select(e.Hero), (hero) => - e.tuple({ - hero, - score: e.random(), - }) + const nestedObjectTuple = e.for( + e.enumerate(e.select(e.Hero)), + (enumeration) => + e.tuple({ + hero: enumeration[1], + index: enumeration[0], + }) ); const nestedObjectQuery = e.select(nestedObjectTuple.hero, (hero) => ({ name: hero.name, - order_by: nestedObjectTuple.score, + order_by: nestedObjectTuple.index, })); const nestedObjectResult = await nestedObjectQuery.run(client); - assert.deepEqual(nestedObjectResult, []); + assert.equal(nestedObjectResult.length, 3); + assert.ok(nestedObjectResult.every((r) => Boolean(r.name))); }); test("filter by id", async () => { diff --git a/integration-tests/stable/fts.test.ts b/integration-tests/stable/fts.test.ts index 8c795c995..ad45bbb52 100644 --- a/integration-tests/stable/fts.test.ts +++ b/integration-tests/stable/fts.test.ts @@ -66,9 +66,16 @@ describe("full-text search", () => { const objectSelectQuery = e.select(searchExpr.object, (post) => ({ text: post.text, + order_by: searchExpr.score, })); const objectSelect = await objectSelectQuery.run(client); - expect(objectSelect).toEqual([]); + expect(objectSelect).toEqual([ + { text: posts[0] }, + { text: posts[1] }, + { text: posts[2] }, + { text: posts[3] }, + { text: posts[4] }, + ]); tc.assert, { text: string }[]>>( true diff --git a/packages/generate/src/syntax/toEdgeQL.ts b/packages/generate/src/syntax/toEdgeQL.ts index 98d0afe90..c4c0dd3b0 100644 --- a/packages/generate/src/syntax/toEdgeQL.ts +++ b/packages/generate/src/syntax/toEdgeQL.ts @@ -149,13 +149,16 @@ export function $toEdgeQL(this: any) { if (withVars.has(expr)) { continue; } - // ignore unbound leaves, nodes, and intersections // these should be rendered as is if ( !refData.boundScope && (expr.__kind__ === ExpressionKind.PathLeaf || expr.__kind__ === ExpressionKind.PathNode || + expr.__kind__ === ExpressionKind.TuplePath || + (expr.__kind__ === ExpressionKind.Select && + (expr.__expr__ as SomeExpression).__kind__ === + ExpressionKind.TuplePath) || expr.__kind__ === ExpressionKind.TypeIntersection) ) { continue;