joist-core 2.3.0-next.77 → 2.3.0-next.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.cjs +1 -0
- package/build/index.cjs.map +1 -1
- package/build/index.d.cts +2 -2
- package/build/index.d.cts.map +1 -1
- package/build/index.d.mts +2 -2
- package/build/index.d.mts.map +1 -1
- package/build/index.js +2 -2
- package/build/index.js.map +1 -1
- package/build/query.cjs +95 -13
- package/build/query.cjs.map +1 -1
- package/build/query.d.cts +51 -3
- package/build/query.d.cts.map +1 -1
- package/build/query.d.mts +51 -3
- package/build/query.d.mts.map +1 -1
- package/build/query.js +95 -14
- package/build/query.js.map +1 -1
- package/package.json +2 -2
package/build/query.d.cts
CHANGED
|
@@ -105,6 +105,11 @@ type QueryJoins = readonly (QueryJoin | undefined)[];
|
|
|
105
105
|
type WithSource = Subquery<unknown, string>;
|
|
106
106
|
/** One CTE or an array of them; an `undefined` entry prunes, like any other clause. */
|
|
107
107
|
type WithInput = WithSource | readonly (WithSource | undefined)[];
|
|
108
|
+
/** How a recursive CTE combines its two terms: `UNION ALL` keeps every row, `UNION` drops duplicates. */
|
|
109
|
+
interface RecursiveOptions {
|
|
110
|
+
/** Defaults to `"all"`. `"distinct"` emits UNION, which stops a cyclic graph from looping forever. */
|
|
111
|
+
union?: "all" | "distinct";
|
|
112
|
+
}
|
|
108
113
|
/**
|
|
109
114
|
* An expression order-by entry: the direction is the key and the expression is the value, unlike
|
|
110
115
|
* the keyed form's field name and `"ASC" | "DESC"` value. `never` on the other key keeps an
|
|
@@ -508,6 +513,31 @@ declare function query<const Q extends SetQuery<readonly SetOperand[]>, Name ext
|
|
|
508
513
|
as?: Name;
|
|
509
514
|
}): Subquery<SetQueryRow<Q>, Name>;
|
|
510
515
|
declare function query<F extends QuerySource, S extends QuerySelect = never, J extends QueryJoins = [], Name extends string = "?">(q: QueryArg<F, S, J, Name>): QueryValue<S, J, Name>;
|
|
516
|
+
/**
|
|
517
|
+
* Declares a `WITH RECURSIVE` CTE from its two terms, and returns the CTE as a readable value.
|
|
518
|
+
*
|
|
519
|
+
* `base` is the non-recursive term, which seeds the rows and, as in PostgreSQL, supplies the CTE's
|
|
520
|
+
* columns. `step` is the recursive term: it receives the CTE itself, so it can join back to the rows
|
|
521
|
+
* found so far. The two terms are combined with UNION ALL, or UNION when `union: "distinct"` drops
|
|
522
|
+
* duplicates, which is how a cyclic graph is kept from looping forever.
|
|
523
|
+
*
|
|
524
|
+
* ```ts
|
|
525
|
+
* const [a] = tables(Author);
|
|
526
|
+
* const tree = recursiveQuery(
|
|
527
|
+
* "tree",
|
|
528
|
+
* { from: a, where: a.mentor_id.isNull(), select: { id: a.id, mentorId: a.mentor_id } },
|
|
529
|
+
* (self) => ({
|
|
530
|
+
* from: a,
|
|
531
|
+
* join: [{ inner: self, on: a.mentor_id.eq(self.id) }],
|
|
532
|
+
* select: { id: a.id, mentorId: a.mentor_id },
|
|
533
|
+
* }),
|
|
534
|
+
* );
|
|
535
|
+
* const rows = await em.query({ with: tree, from: tree, select: tree });
|
|
536
|
+
* ```
|
|
537
|
+
*
|
|
538
|
+
* Unlike `query()`, the name is required, because the step term must name it.
|
|
539
|
+
*/
|
|
540
|
+
declare function recursiveQuery<Name extends string, F extends QuerySource, S extends QuerySelect, J extends QueryJoins>(name: Name, base: QueryArg<F, S, J, Name>, step: (self: Subquery<QueryRow<S, J>, Name>) => SetOperand, opts?: RecursiveOptions): Subquery<QueryRow<S, J>, Name>;
|
|
511
541
|
/**
|
|
512
542
|
* Builds a SQL expression from a tagged template.
|
|
513
543
|
*
|
|
@@ -3857,8 +3887,16 @@ interface QueryOutput {
|
|
|
3857
3887
|
}
|
|
3858
3888
|
/** The runtime identity of a `query(...)` value; `Ctx.aliasFor` keys on it, like a table's `TableMgmt`. */
|
|
3859
3889
|
declare class SubqueryHandle {
|
|
3860
|
-
|
|
3861
|
-
|
|
3890
|
+
#private;
|
|
3891
|
+
readonly recursive: boolean;
|
|
3892
|
+
constructor(q: AnyReadQuery, recursive?: boolean);
|
|
3893
|
+
get q(): AnyReadQuery;
|
|
3894
|
+
/**
|
|
3895
|
+
* Gives a recursive CTE its finished body. `recursiveQuery` starts the handle on its base term, so
|
|
3896
|
+
* the step term can read the CTE's columns while the body that will hold that step is still being
|
|
3897
|
+
* built. The base term supplies the CTE's columns either way, PostgreSQL's rule for a recursive WITH.
|
|
3898
|
+
*/
|
|
3899
|
+
setBody(q: AnyReadQuery): void;
|
|
3862
3900
|
get name(): string | undefined;
|
|
3863
3901
|
/** The select keys, for `select: <subquery>` and for reporting unknown columns. */
|
|
3864
3902
|
columnKeys(): string[];
|
|
@@ -3907,6 +3945,8 @@ declare class Ctx implements ExprContext {
|
|
|
3907
3945
|
private pendingCtes;
|
|
3908
3946
|
/** CTEs already read by this query's `from`/`join`, so a second read fails instead of colliding. */
|
|
3909
3947
|
private usedCtes;
|
|
3948
|
+
/** The recursive CTE whose body this query is part of, if any; see `recursiveSelf`. */
|
|
3949
|
+
private ownRecursiveSelf;
|
|
3910
3950
|
readonly outerRefs: Set<string>;
|
|
3911
3951
|
constructor(assigner: AliasAssigner, parent: Ctx | undefined);
|
|
3912
3952
|
/**
|
|
@@ -3926,6 +3966,14 @@ declare class Ctx implements ExprContext {
|
|
|
3926
3966
|
* is not a correlated reference, so it must not keep an enclosing join alive.
|
|
3927
3967
|
*/
|
|
3928
3968
|
cteAliasFor(handle: object): string | undefined;
|
|
3969
|
+
/**
|
|
3970
|
+
* The recursive CTE this query's terms belong to, inherited from the enclosing query.
|
|
3971
|
+
*
|
|
3972
|
+
* PostgreSQL requires a recursive term to reference its own CTE, so that reference is not optional
|
|
3973
|
+
* and must survive pruning, unlike an ordinary explicit join that nothing else reads.
|
|
3974
|
+
*/
|
|
3975
|
+
get recursiveSelf(): SubqueryHandle | undefined;
|
|
3976
|
+
setRecursiveSelf(handle: SubqueryHandle): void;
|
|
3929
3977
|
/** Whether `handle` is a CTE with no SQL yet, i.e. itself or a later `with` entry. */
|
|
3930
3978
|
isPendingCte(handle: object): boolean;
|
|
3931
3979
|
/**
|
|
@@ -3960,5 +4008,5 @@ declare function injectedConditions(source: {
|
|
|
3960
4008
|
*/
|
|
3961
4009
|
declare function conditionToSql(cond: QueryCondition | undefined, ctx: Ctx, topLevel: boolean): SqlFragment | undefined;
|
|
3962
4010
|
//#endregion
|
|
3963
|
-
export { CheckReadQuery, CheckScope, CheckSetQuery, Clauses, Ctx, EntityHydrator, EntityQuery, ExistsQuery, MaybeNull, NameOf, NotWidened, OrderByDirection, OrderByKeys, Plan, Query, QueryArg, QueryCondition, QueryJoin, QueryJoins, QueryOrderBy, QueryOutput, QueryRow, QuerySelect, QuerySource, QueryValue, ReadQueryRow, ScalarQuery, SetOperand, SetOperation, SetQuery, SetQueryRow, Subquery, SubqueryBrand, SubqueryHandle, WithInput, WithSource, conditionToSql, entityQueryBrand, injectedConditions, isReadQueryValue, parseUserQuery, projectionToSql, query, scalarQueryBrand, sql, subqueryBrand };
|
|
4011
|
+
export { CheckReadQuery, CheckScope, CheckSetQuery, Clauses, Ctx, EntityHydrator, EntityQuery, ExistsQuery, MaybeNull, NameOf, NotWidened, OrderByDirection, OrderByKeys, Plan, Query, QueryArg, QueryCondition, QueryJoin, QueryJoins, QueryOrderBy, QueryOutput, QueryRow, QuerySelect, QuerySource, QueryValue, ReadQueryRow, RecursiveOptions, ScalarQuery, SetOperand, SetOperation, SetQuery, SetQueryRow, Subquery, SubqueryBrand, SubqueryHandle, WithInput, WithSource, conditionToSql, entityQueryBrand, injectedConditions, isReadQueryValue, parseUserQuery, projectionToSql, query, recursiveQuery, scalarQueryBrand, sql, subqueryBrand };
|
|
3964
4012
|
//# sourceMappingURL=query.d.cts.map
|
package/build/query.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.cts","names":[],"sources":["../src/query.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAgGa;cACA;cACA;;KAGD,cAAc,4BAA4B,YAAY;YAAsB;;;;;;;;;KAS5E,iBACR,eACA;EAEM,KAAK,MAAM;EAA6B;EAAY;EAAgB;;EACpE,IAAI,MAAM;EAA6B;EAAa;EAAgB;;EACpE;;EACJ,QAAQ;EAAyB;EAAmB;EAAa;;EACjE,WAAW;EAAyB;EAAgB;EAAa;;;UAGtD,cAAc,GAAG;WACvB,OAAO;WACP,QAAQ;;;KAIP;YACI,YAAY;;YACZ,gBAAgB;;;;;;;KAOpB,YAAY,UAAU,aAAa,kBAAkB,SAAS,aAAa;KAC3E,uBAAuB;;;;;;;KAQvB,aAAa;;KAGb,YAAY,uBAAuB
|
|
1
|
+
{"version":3,"file":"query.d.cts","names":[],"sources":["../src/query.ts"],"mappings":"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"}
|
package/build/query.d.mts
CHANGED
|
@@ -105,6 +105,11 @@ type QueryJoins = readonly (QueryJoin | undefined)[];
|
|
|
105
105
|
type WithSource = Subquery<unknown, string>;
|
|
106
106
|
/** One CTE or an array of them; an `undefined` entry prunes, like any other clause. */
|
|
107
107
|
type WithInput = WithSource | readonly (WithSource | undefined)[];
|
|
108
|
+
/** How a recursive CTE combines its two terms: `UNION ALL` keeps every row, `UNION` drops duplicates. */
|
|
109
|
+
interface RecursiveOptions {
|
|
110
|
+
/** Defaults to `"all"`. `"distinct"` emits UNION, which stops a cyclic graph from looping forever. */
|
|
111
|
+
union?: "all" | "distinct";
|
|
112
|
+
}
|
|
108
113
|
/**
|
|
109
114
|
* An expression order-by entry: the direction is the key and the expression is the value, unlike
|
|
110
115
|
* the keyed form's field name and `"ASC" | "DESC"` value. `never` on the other key keeps an
|
|
@@ -508,6 +513,31 @@ declare function query<const Q extends SetQuery<readonly SetOperand[]>, Name ext
|
|
|
508
513
|
as?: Name;
|
|
509
514
|
}): Subquery<SetQueryRow<Q>, Name>;
|
|
510
515
|
declare function query<F extends QuerySource, S extends QuerySelect = never, J extends QueryJoins = [], Name extends string = "?">(q: QueryArg<F, S, J, Name>): QueryValue<S, J, Name>;
|
|
516
|
+
/**
|
|
517
|
+
* Declares a `WITH RECURSIVE` CTE from its two terms, and returns the CTE as a readable value.
|
|
518
|
+
*
|
|
519
|
+
* `base` is the non-recursive term, which seeds the rows and, as in PostgreSQL, supplies the CTE's
|
|
520
|
+
* columns. `step` is the recursive term: it receives the CTE itself, so it can join back to the rows
|
|
521
|
+
* found so far. The two terms are combined with UNION ALL, or UNION when `union: "distinct"` drops
|
|
522
|
+
* duplicates, which is how a cyclic graph is kept from looping forever.
|
|
523
|
+
*
|
|
524
|
+
* ```ts
|
|
525
|
+
* const [a] = tables(Author);
|
|
526
|
+
* const tree = recursiveQuery(
|
|
527
|
+
* "tree",
|
|
528
|
+
* { from: a, where: a.mentor_id.isNull(), select: { id: a.id, mentorId: a.mentor_id } },
|
|
529
|
+
* (self) => ({
|
|
530
|
+
* from: a,
|
|
531
|
+
* join: [{ inner: self, on: a.mentor_id.eq(self.id) }],
|
|
532
|
+
* select: { id: a.id, mentorId: a.mentor_id },
|
|
533
|
+
* }),
|
|
534
|
+
* );
|
|
535
|
+
* const rows = await em.query({ with: tree, from: tree, select: tree });
|
|
536
|
+
* ```
|
|
537
|
+
*
|
|
538
|
+
* Unlike `query()`, the name is required, because the step term must name it.
|
|
539
|
+
*/
|
|
540
|
+
declare function recursiveQuery<Name extends string, F extends QuerySource, S extends QuerySelect, J extends QueryJoins>(name: Name, base: QueryArg<F, S, J, Name>, step: (self: Subquery<QueryRow<S, J>, Name>) => SetOperand, opts?: RecursiveOptions): Subquery<QueryRow<S, J>, Name>;
|
|
511
541
|
/**
|
|
512
542
|
* Builds a SQL expression from a tagged template.
|
|
513
543
|
*
|
|
@@ -3857,8 +3887,16 @@ interface QueryOutput {
|
|
|
3857
3887
|
}
|
|
3858
3888
|
/** The runtime identity of a `query(...)` value; `Ctx.aliasFor` keys on it, like a table's `TableMgmt`. */
|
|
3859
3889
|
declare class SubqueryHandle {
|
|
3860
|
-
|
|
3861
|
-
|
|
3890
|
+
#private;
|
|
3891
|
+
readonly recursive: boolean;
|
|
3892
|
+
constructor(q: AnyReadQuery, recursive?: boolean);
|
|
3893
|
+
get q(): AnyReadQuery;
|
|
3894
|
+
/**
|
|
3895
|
+
* Gives a recursive CTE its finished body. `recursiveQuery` starts the handle on its base term, so
|
|
3896
|
+
* the step term can read the CTE's columns while the body that will hold that step is still being
|
|
3897
|
+
* built. The base term supplies the CTE's columns either way, PostgreSQL's rule for a recursive WITH.
|
|
3898
|
+
*/
|
|
3899
|
+
setBody(q: AnyReadQuery): void;
|
|
3862
3900
|
get name(): string | undefined;
|
|
3863
3901
|
/** The select keys, for `select: <subquery>` and for reporting unknown columns. */
|
|
3864
3902
|
columnKeys(): string[];
|
|
@@ -3907,6 +3945,8 @@ declare class Ctx implements ExprContext {
|
|
|
3907
3945
|
private pendingCtes;
|
|
3908
3946
|
/** CTEs already read by this query's `from`/`join`, so a second read fails instead of colliding. */
|
|
3909
3947
|
private usedCtes;
|
|
3948
|
+
/** The recursive CTE whose body this query is part of, if any; see `recursiveSelf`. */
|
|
3949
|
+
private ownRecursiveSelf;
|
|
3910
3950
|
readonly outerRefs: Set<string>;
|
|
3911
3951
|
constructor(assigner: AliasAssigner, parent: Ctx | undefined);
|
|
3912
3952
|
/**
|
|
@@ -3926,6 +3966,14 @@ declare class Ctx implements ExprContext {
|
|
|
3926
3966
|
* is not a correlated reference, so it must not keep an enclosing join alive.
|
|
3927
3967
|
*/
|
|
3928
3968
|
cteAliasFor(handle: object): string | undefined;
|
|
3969
|
+
/**
|
|
3970
|
+
* The recursive CTE this query's terms belong to, inherited from the enclosing query.
|
|
3971
|
+
*
|
|
3972
|
+
* PostgreSQL requires a recursive term to reference its own CTE, so that reference is not optional
|
|
3973
|
+
* and must survive pruning, unlike an ordinary explicit join that nothing else reads.
|
|
3974
|
+
*/
|
|
3975
|
+
get recursiveSelf(): SubqueryHandle | undefined;
|
|
3976
|
+
setRecursiveSelf(handle: SubqueryHandle): void;
|
|
3929
3977
|
/** Whether `handle` is a CTE with no SQL yet, i.e. itself or a later `with` entry. */
|
|
3930
3978
|
isPendingCte(handle: object): boolean;
|
|
3931
3979
|
/**
|
|
@@ -3960,5 +4008,5 @@ declare function injectedConditions(source: {
|
|
|
3960
4008
|
*/
|
|
3961
4009
|
declare function conditionToSql(cond: QueryCondition | undefined, ctx: Ctx, topLevel: boolean): SqlFragment | undefined;
|
|
3962
4010
|
//#endregion
|
|
3963
|
-
export { CheckReadQuery, CheckScope, CheckSetQuery, Clauses, Ctx, EntityHydrator, EntityQuery, ExistsQuery, MaybeNull, NameOf, NotWidened, OrderByDirection, OrderByKeys, Plan, Query, QueryArg, QueryCondition, QueryJoin, QueryJoins, QueryOrderBy, QueryOutput, QueryRow, QuerySelect, QuerySource, QueryValue, ReadQueryRow, ScalarQuery, SetOperand, SetOperation, SetQuery, SetQueryRow, Subquery, SubqueryBrand, SubqueryHandle, WithInput, WithSource, conditionToSql, entityQueryBrand, injectedConditions, isReadQueryValue, parseUserQuery, projectionToSql, query, scalarQueryBrand, sql, subqueryBrand };
|
|
4011
|
+
export { CheckReadQuery, CheckScope, CheckSetQuery, Clauses, Ctx, EntityHydrator, EntityQuery, ExistsQuery, MaybeNull, NameOf, NotWidened, OrderByDirection, OrderByKeys, Plan, Query, QueryArg, QueryCondition, QueryJoin, QueryJoins, QueryOrderBy, QueryOutput, QueryRow, QuerySelect, QuerySource, QueryValue, ReadQueryRow, RecursiveOptions, ScalarQuery, SetOperand, SetOperation, SetQuery, SetQueryRow, Subquery, SubqueryBrand, SubqueryHandle, WithInput, WithSource, conditionToSql, entityQueryBrand, injectedConditions, isReadQueryValue, parseUserQuery, projectionToSql, query, recursiveQuery, scalarQueryBrand, sql, subqueryBrand };
|
|
3964
4012
|
//# sourceMappingURL=query.d.mts.map
|
package/build/query.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.mts","names":[],"sources":["../src/query.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAgGa;cACA;cACA;;KAGD,cAAc,4BAA4B,YAAY;YAAsB;;;;;;;;;KAS5E,iBACR,eACA;EAEM,KAAK,MAAM;EAA6B;EAAY;EAAgB;;EACpE,IAAI,MAAM;EAA6B;EAAa;EAAgB;;EACpE;;EACJ,QAAQ;EAAyB;EAAmB;EAAa;;EACjE,WAAW;EAAyB;EAAgB;EAAa;;;UAGtD,cAAc,GAAG;WACvB,OAAO;WACP,QAAQ;;;KAIP;YACI,YAAY;;YACZ,gBAAgB;;;;;;;KAOpB,YAAY,UAAU,aAAa,kBAAkB,SAAS,aAAa;KAC3E,uBAAuB;;;;;;;KAQvB,aAAa;;KAGb,YAAY,uBAAuB
|
|
1
|
+
{"version":3,"file":"query.d.mts","names":[],"sources":["../src/query.ts"],"mappings":"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"}
|
package/build/query.js
CHANGED
|
@@ -58,6 +58,46 @@ function query(q) {
|
|
|
58
58
|
else return newSubqueryProxy(handle);
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
|
+
* Declares a `WITH RECURSIVE` CTE from its two terms, and returns the CTE as a readable value.
|
|
62
|
+
*
|
|
63
|
+
* `base` is the non-recursive term, which seeds the rows and, as in PostgreSQL, supplies the CTE's
|
|
64
|
+
* columns. `step` is the recursive term: it receives the CTE itself, so it can join back to the rows
|
|
65
|
+
* found so far. The two terms are combined with UNION ALL, or UNION when `union: "distinct"` drops
|
|
66
|
+
* duplicates, which is how a cyclic graph is kept from looping forever.
|
|
67
|
+
*
|
|
68
|
+
* ```ts
|
|
69
|
+
* const [a] = tables(Author);
|
|
70
|
+
* const tree = recursiveQuery(
|
|
71
|
+
* "tree",
|
|
72
|
+
* { from: a, where: a.mentor_id.isNull(), select: { id: a.id, mentorId: a.mentor_id } },
|
|
73
|
+
* (self) => ({
|
|
74
|
+
* from: a,
|
|
75
|
+
* join: [{ inner: self, on: a.mentor_id.eq(self.id) }],
|
|
76
|
+
* select: { id: a.id, mentorId: a.mentor_id },
|
|
77
|
+
* }),
|
|
78
|
+
* );
|
|
79
|
+
* const rows = await em.query({ with: tree, from: tree, select: tree });
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* Unlike `query()`, the name is required, because the step term must name it.
|
|
83
|
+
*/
|
|
84
|
+
function recursiveQuery(name, base, step, opts = {}) {
|
|
85
|
+
if (typeof name !== "string" || name === "") fail("A recursive CTE needs a name");
|
|
86
|
+
if (opts.union !== void 0 && opts.union !== "all" && opts.union !== "distinct") fail("A recursive CTE's union must be 'all' or 'distinct'");
|
|
87
|
+
const handle = new SubqueryHandle(toQuery(base), true);
|
|
88
|
+
if (handle.output().kind !== "pojo") fail("A recursive CTE's base term needs a named projection");
|
|
89
|
+
const self = newSubqueryProxy(handle);
|
|
90
|
+
const operands = [base, step(self)];
|
|
91
|
+
handle.setBody(opts.union === "distinct" ? {
|
|
92
|
+
union: operands,
|
|
93
|
+
as: name
|
|
94
|
+
} : {
|
|
95
|
+
unionAll: operands,
|
|
96
|
+
as: name
|
|
97
|
+
});
|
|
98
|
+
return self;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
61
101
|
* Builds a SQL expression from a tagged template.
|
|
62
102
|
*
|
|
63
103
|
* For an Author alias `a` assigned the SQL alias `a1`:
|
|
@@ -146,9 +186,23 @@ function projectionToSql(select, ctx) {
|
|
|
146
186
|
}
|
|
147
187
|
/** The runtime identity of a `query(...)` value; `Ctx.aliasFor` keys on it, like a table's `TableMgmt`. */
|
|
148
188
|
var SubqueryHandle = class {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
189
|
+
recursive;
|
|
190
|
+
#q;
|
|
191
|
+
constructor(q, recursive = false) {
|
|
192
|
+
this.recursive = recursive;
|
|
193
|
+
this.#q = q;
|
|
194
|
+
}
|
|
195
|
+
get q() {
|
|
196
|
+
return this.#q;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Gives a recursive CTE its finished body. `recursiveQuery` starts the handle on its base term, so
|
|
200
|
+
* the step term can read the CTE's columns while the body that will hold that step is still being
|
|
201
|
+
* built. The base term supplies the CTE's columns either way, PostgreSQL's rule for a recursive WITH.
|
|
202
|
+
*/
|
|
203
|
+
setBody(q) {
|
|
204
|
+
if (!this.recursive) fail("Only a recursive CTE replaces its body");
|
|
205
|
+
this.#q = q;
|
|
152
206
|
}
|
|
153
207
|
get name() {
|
|
154
208
|
return this.q.as;
|
|
@@ -493,10 +547,11 @@ var OutputExpr = class extends BaseExpr {
|
|
|
493
547
|
* output positions without moving DISTINCT/order/pagination or repeating volatile selected expressions.
|
|
494
548
|
* Parenthesizing each accumulated left side preserves array association and explicit nested grouping.
|
|
495
549
|
*/
|
|
496
|
-
function parseSetQuery(q, parent, assigner) {
|
|
550
|
+
function parseSetQuery(q, parent, assigner, recursiveSelf) {
|
|
497
551
|
const [operation, operands] = setOperands(q);
|
|
498
552
|
const output = queryOutput(q);
|
|
499
553
|
const ctx = new Ctx(assigner, parent);
|
|
554
|
+
if (recursiveSelf) ctx.setRecursiveSelf(recursiveSelf);
|
|
500
555
|
const ctes = registerCtes(q, ctx, assigner);
|
|
501
556
|
const plans = operands.map((operand) => parseQuery(toQuery(operand), ctx, assigner));
|
|
502
557
|
let sql = "";
|
|
@@ -582,6 +637,8 @@ var Ctx = class {
|
|
|
582
637
|
pendingCtes = /* @__PURE__ */ new Map();
|
|
583
638
|
/** CTEs already read by this query's `from`/`join`, so a second read fails instead of colliding. */
|
|
584
639
|
usedCtes = /* @__PURE__ */ new Set();
|
|
640
|
+
/** The recursive CTE whose body this query is part of, if any; see `recursiveSelf`. */
|
|
641
|
+
ownRecursiveSelf;
|
|
585
642
|
outerRefs = /* @__PURE__ */ new Set();
|
|
586
643
|
constructor(assigner, parent) {
|
|
587
644
|
this.assigner = assigner;
|
|
@@ -616,6 +673,18 @@ var Ctx = class {
|
|
|
616
673
|
cteAliasFor(handle) {
|
|
617
674
|
return this.ctes.get(handle) ?? this.parent?.cteAliasFor(handle);
|
|
618
675
|
}
|
|
676
|
+
/**
|
|
677
|
+
* The recursive CTE this query's terms belong to, inherited from the enclosing query.
|
|
678
|
+
*
|
|
679
|
+
* PostgreSQL requires a recursive term to reference its own CTE, so that reference is not optional
|
|
680
|
+
* and must survive pruning, unlike an ordinary explicit join that nothing else reads.
|
|
681
|
+
*/
|
|
682
|
+
get recursiveSelf() {
|
|
683
|
+
return this.ownRecursiveSelf ?? this.parent?.recursiveSelf;
|
|
684
|
+
}
|
|
685
|
+
setRecursiveSelf(handle) {
|
|
686
|
+
this.ownRecursiveSelf = handle;
|
|
687
|
+
}
|
|
619
688
|
/** Whether `handle` is a CTE with no SQL yet, i.e. itself or a later `with` entry. */
|
|
620
689
|
isPendingCte(handle) {
|
|
621
690
|
return this.pendingCtes.has(handle) || (this.parent?.isPendingCte(handle) ?? false);
|
|
@@ -661,10 +730,11 @@ function describeHandle(handle) {
|
|
|
661
730
|
* 3. Prune: drop joins nothing references (see below), then reject a kept join whose ON collapsed.
|
|
662
731
|
* 4. Assemble the SQL from the kept fragments, so pruned bindings disappear with their SQL.
|
|
663
732
|
*/
|
|
664
|
-
function parseQuery(q, parent, assigner) {
|
|
733
|
+
function parseQuery(q, parent, assigner, recursiveSelf) {
|
|
665
734
|
validateReadQuery(q);
|
|
666
|
-
if (isSetQuery(q)) return parseSetQuery(q, parent, assigner);
|
|
735
|
+
if (isSetQuery(q)) return parseSetQuery(q, parent, assigner, recursiveSelf);
|
|
667
736
|
const ctx = new Ctx(assigner, parent);
|
|
737
|
+
if (recursiveSelf) ctx.setRecursiveSelf(recursiveSelf);
|
|
668
738
|
const joinEntries = [...q.join ?? []].filter(isDefined);
|
|
669
739
|
const ctes = registerCtes(q, ctx, assigner);
|
|
670
740
|
const parseFrom = registerSource(q.from, ctx, assigner);
|
|
@@ -711,7 +781,7 @@ function parseQuery(q, parent, assigner) {
|
|
|
711
781
|
const having = conditionToSql(q.having, ctx, true);
|
|
712
782
|
const groupBys = (q.groupBy ?? []).map((g) => asExpr(g, "groupBy").toSql(ctx));
|
|
713
783
|
const orderBys = orderBysToSql(q, ctx);
|
|
714
|
-
const { joins: kept, ctes: keptCtes } = pruneJoins(q, from, joins, ctes, [
|
|
784
|
+
const { joins: kept, ctes: keptCtes } = pruneJoins(q, ctx, from, joins, ctes, [
|
|
715
785
|
...selects,
|
|
716
786
|
...groupBys,
|
|
717
787
|
...orderBys,
|
|
@@ -1152,8 +1222,11 @@ function refsOf(parsed) {
|
|
|
1152
1222
|
* CTEs prune on the same rule and through the same dependency map: a `with` entry nothing reads
|
|
1153
1223
|
* anymore drops with the join that read it, and a CTE read only by another CTE survives with it.
|
|
1154
1224
|
* A CTE joined into the query shares its alias with that join, so their dependencies are merged.
|
|
1225
|
+
*
|
|
1226
|
+
* The one join that never prunes is a recursive term's reference to its own CTE: PostgreSQL requires
|
|
1227
|
+
* it, so it is not the caller's optional filter (see `Ctx.recursiveSelf`).
|
|
1155
1228
|
*/
|
|
1156
|
-
function pruneJoins(q, from, joins, ctes, used) {
|
|
1229
|
+
function pruneJoins(q, ctx, from, joins, ctes, used) {
|
|
1157
1230
|
if (q.pruneJoins === false) return {
|
|
1158
1231
|
joins,
|
|
1159
1232
|
ctes
|
|
@@ -1176,6 +1249,7 @@ function pruneJoins(q, from, joins, ctes, used) {
|
|
|
1176
1249
|
markRequired(from.alias);
|
|
1177
1250
|
for (const r of used.flatMap((u) => u.refs)) markRequired(r);
|
|
1178
1251
|
for (const j of joins) if (j.keep) markRequired(j.source.alias);
|
|
1252
|
+
for (const j of joins) if (j.source.handle === ctx.recursiveSelf) markRequired(j.source.alias);
|
|
1179
1253
|
return {
|
|
1180
1254
|
joins: joins.filter((j) => required.has(j.source.alias)),
|
|
1181
1255
|
ctes: ctes.filter((c) => required.has(c.alias))
|
|
@@ -1195,11 +1269,13 @@ function registerCtes(q, ctx, assigner) {
|
|
|
1195
1269
|
const aliases = handles.map((handle) => assigner.getLiteralAlias(handle.name ?? "cte"));
|
|
1196
1270
|
handles.forEach((handle, i) => ctx.declareCte(handle, aliases[i]));
|
|
1197
1271
|
return handles.map((handle, i) => {
|
|
1198
|
-
|
|
1199
|
-
ctx.
|
|
1272
|
+
if (handle.recursive) ctx.promoteCte(handle);
|
|
1273
|
+
const plan = parseQuery(handle.q, ctx, assigner, handle.recursive ? handle : void 0);
|
|
1274
|
+
if (!handle.recursive) ctx.promoteCte(handle);
|
|
1200
1275
|
return {
|
|
1201
1276
|
alias: aliases[i],
|
|
1202
|
-
plan
|
|
1277
|
+
plan,
|
|
1278
|
+
recursive: handle.recursive
|
|
1203
1279
|
};
|
|
1204
1280
|
});
|
|
1205
1281
|
}
|
|
@@ -1208,10 +1284,15 @@ function withEntryHandle(entry) {
|
|
|
1208
1284
|
if (!isSubqueryValue(entry)) fail(entry instanceof SubqueryExpr || isEntityQueryValue(entry) ? "A `with` entry needs named columns; entity and scalar query(...) values have none" : "A `with` entry must be a query(...) value");
|
|
1209
1285
|
return readValueHandle(entry);
|
|
1210
1286
|
}
|
|
1211
|
-
/**
|
|
1287
|
+
/**
|
|
1288
|
+
* Renders `WITH a AS (...), b AS (...) `, whose bindings lead the statement, as their SQL does.
|
|
1289
|
+
*
|
|
1290
|
+
* One recursive CTE makes the whole clause `WITH RECURSIVE`, PostgreSQL's rule: the keyword is on the
|
|
1291
|
+
* clause, not on the entry that needs it, and it does not force the other entries to be recursive.
|
|
1292
|
+
*/
|
|
1212
1293
|
function withFragment(ctes) {
|
|
1213
1294
|
return {
|
|
1214
|
-
sql: `WITH ${ctes.map((c) => `${safeKq(c.alias)} AS (${c.plan.sql})`).join(", ")} `,
|
|
1295
|
+
sql: `WITH${ctes.some((c) => c.recursive) ? " RECURSIVE" : ""} ${ctes.map((c) => `${safeKq(c.alias)} AS (${c.plan.sql})`).join(", ")} `,
|
|
1215
1296
|
bindings: ctes.flatMap((c) => c.plan.bindings),
|
|
1216
1297
|
refs: []
|
|
1217
1298
|
};
|
|
@@ -1231,6 +1312,6 @@ function isDefined(value) {
|
|
|
1231
1312
|
return value !== void 0;
|
|
1232
1313
|
}
|
|
1233
1314
|
//#endregion
|
|
1234
|
-
export { Ctx, SubqueryHandle, conditionToSql, entityQueryBrand, injectedConditions, isReadQueryValue, parseUserQuery, projectionToSql, query, scalarQueryBrand, sql, subqueryBrand };
|
|
1315
|
+
export { Ctx, SubqueryHandle, conditionToSql, entityQueryBrand, injectedConditions, isReadQueryValue, parseUserQuery, projectionToSql, query, recursiveQuery, scalarQueryBrand, sql, subqueryBrand };
|
|
1235
1316
|
|
|
1236
1317
|
//# sourceMappingURL=query.js.map
|