joist-core 2.3.0-next.60 → 2.3.0-next.62
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/Aliases.cjs +345 -120
- package/build/Aliases.cjs.map +1 -1
- package/build/Aliases.d.cts +136 -51
- package/build/Aliases.d.cts.map +1 -1
- package/build/Aliases.d.mts +136 -51
- package/build/Aliases.d.mts.map +1 -1
- package/build/Aliases.js +320 -99
- package/build/Aliases.js.map +1 -1
- package/build/ConditionBuilder.cjs +2 -1
- package/build/ConditionBuilder.cjs.map +1 -1
- package/build/ConditionBuilder.js +2 -1
- package/build/ConditionBuilder.js.map +1 -1
- package/build/EntityManager.cjs +12 -0
- package/build/EntityManager.cjs.map +1 -1
- package/build/EntityManager.d.cts +27 -0
- package/build/EntityManager.d.cts.map +1 -1
- package/build/EntityManager.d.mts +27 -0
- package/build/EntityManager.d.mts.map +1 -1
- package/build/EntityManager.js +12 -0
- package/build/EntityManager.js.map +1 -1
- package/build/Expr.cjs +379 -0
- package/build/Expr.cjs.map +1 -0
- package/build/Expr.d.cts +271 -0
- package/build/Expr.d.cts.map +1 -0
- package/build/Expr.d.mts +271 -0
- package/build/Expr.d.mts.map +1 -0
- package/build/Expr.js +360 -0
- package/build/Expr.js.map +1 -0
- package/build/QueryParser.cjs +39 -16
- package/build/QueryParser.cjs.map +1 -1
- package/build/QueryParser.d.cts +3 -3
- package/build/QueryParser.d.cts.map +1 -1
- package/build/QueryParser.d.mts +3 -3
- package/build/QueryParser.d.mts.map +1 -1
- package/build/QueryParser.js +39 -16
- package/build/QueryParser.js.map +1 -1
- package/build/changes.cjs.map +1 -1
- package/build/changes.d.cts +2 -0
- package/build/changes.d.cts.map +1 -1
- package/build/changes.d.mts +2 -0
- package/build/changes.d.mts.map +1 -1
- package/build/changes.js.map +1 -1
- package/build/index.cjs +9 -1
- package/build/index.cjs.map +1 -1
- package/build/index.d.cts +7 -5
- package/build/index.d.cts.map +1 -1
- package/build/index.d.mts +7 -5
- package/build/index.d.mts.map +1 -1
- package/build/index.js +4 -2
- package/build/index.js.map +1 -1
- package/build/keywords.cjs +16 -1
- package/build/keywords.cjs.map +1 -1
- package/build/keywords.d.cts +12 -2
- package/build/keywords.d.cts.map +1 -1
- package/build/keywords.d.mts +12 -2
- package/build/keywords.d.mts.map +1 -1
- package/build/keywords.js +16 -2
- package/build/keywords.js.map +1 -1
- package/build/query.cjs +719 -0
- package/build/query.cjs.map +1 -0
- package/build/query.d.cts +355 -0
- package/build/query.d.cts.map +1 -0
- package/build/query.d.mts +355 -0
- package/build/query.d.mts.map +1 -0
- package/build/query.js +713 -0
- package/build/query.js.map +1 -0
- package/build/rules.cjs.map +1 -1
- package/build/rules.d.cts +13 -1
- package/build/rules.d.cts.map +1 -1
- package/build/rules.d.mts +13 -1
- package/build/rules.d.mts.map +1 -1
- package/build/rules.js.map +1 -1
- package/build/serde.cjs +65 -21
- package/build/serde.cjs.map +1 -1
- package/build/serde.d.cts +22 -0
- package/build/serde.d.cts.map +1 -1
- package/build/serde.d.mts +22 -0
- package/build/serde.d.mts.map +1 -1
- package/build/serde.js +65 -21
- package/build/serde.js.map +1 -1
- package/build/typeMap.d.cts +20 -1
- package/build/typeMap.d.cts.map +1 -1
- package/build/typeMap.d.mts +20 -1
- package/build/typeMap.d.mts.map +1 -1
- package/package.json +2 -2
package/build/Aliases.cjs
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("./typeMap.cjs");
|
|
3
|
+
const require_keywords = require("./keywords.cjs");
|
|
3
4
|
const require_keys = require("./keys.cjs");
|
|
4
5
|
require("./serde.cjs");
|
|
5
6
|
const require_EntityMetadata = require("./EntityMetadata.cjs");
|
|
6
7
|
const require_utils = require("./utils.cjs");
|
|
8
|
+
const require_Expr = require("./Expr.cjs");
|
|
7
9
|
require("./index.cjs");
|
|
8
10
|
require("./EntityManager.cjs");
|
|
9
11
|
require("./Entity.cjs");
|
|
@@ -11,8 +13,7 @@ const require_configure = require("./configure.cjs");
|
|
|
11
13
|
const require_QueryParser = require("./QueryParser.cjs");
|
|
12
14
|
let joist_utils = require("joist-utils");
|
|
13
15
|
//#region src/Aliases.ts
|
|
14
|
-
|
|
15
|
-
function alias(cstr) {
|
|
16
|
+
function alias(cstr, _name) {
|
|
16
17
|
return newAliasProxy(cstr);
|
|
17
18
|
}
|
|
18
19
|
/** Creates multiple aliases for complex filtering. */
|
|
@@ -25,32 +26,29 @@ function getAliasMgmt(alias) {
|
|
|
25
26
|
}
|
|
26
27
|
/** Returns the metadata for the entity that `alias` is bound to. */
|
|
27
28
|
function getAliasMetadata(alias) {
|
|
28
|
-
|
|
29
|
-
return require_configure.getMetadataForTable(mgmt.tableName);
|
|
29
|
+
return alias[aliasMgmt].meta;
|
|
30
30
|
}
|
|
31
31
|
function newAliasProxy(cstr) {
|
|
32
32
|
const meta = require_EntityMetadata.getMetadata(cstr);
|
|
33
|
-
const callbacks = [];
|
|
34
33
|
const mgmt = {
|
|
35
34
|
tableName: meta.tableName,
|
|
36
|
-
|
|
37
|
-
for (const callback of callbacks) callback(newMeta, newAlias);
|
|
38
|
-
},
|
|
39
|
-
onBind(callback) {
|
|
40
|
-
callbacks.push(callback);
|
|
41
|
-
}
|
|
35
|
+
meta
|
|
42
36
|
};
|
|
43
|
-
|
|
44
|
-
/** Create a column alias for the given field. */
|
|
37
|
+
const proxy = new Proxy(cstr, {
|
|
38
|
+
/** Create a column alias, or a relation join factory, for the given field. */
|
|
45
39
|
get(_, key) {
|
|
46
40
|
if (key === aliasMgmt) return mgmt;
|
|
47
41
|
const field = meta.allFields[key] ?? require_utils.fail(`No field ${String(key)} on ${cstr.name}`);
|
|
48
42
|
switch (field.kind) {
|
|
49
43
|
case "primaryKey":
|
|
50
44
|
case "primitive":
|
|
51
|
-
case "enum": return new PrimitiveAliasImpl(meta, field,
|
|
52
|
-
case "m2o": return new EntityAliasImpl(meta, field,
|
|
53
|
-
case "poly": return new PolyReferenceAlias(meta,
|
|
45
|
+
case "enum": return new PrimitiveAliasImpl(meta, field, field.serde.columns[0], mgmt);
|
|
46
|
+
case "m2o": return new EntityAliasImpl(meta, field, field.serde.columns[0], mgmt);
|
|
47
|
+
case "poly": return new PolyReferenceAlias(meta, mgmt, field);
|
|
48
|
+
case "o2m":
|
|
49
|
+
case "o2o":
|
|
50
|
+
case "lo2m": return new OneToManyAliasImpl(proxy, field);
|
|
51
|
+
case "m2m": return new ManyToManyAliasImpl(proxy, field);
|
|
54
52
|
default: throw new Error(`Unsupported alias field kind ${field.kind}`);
|
|
55
53
|
}
|
|
56
54
|
},
|
|
@@ -58,20 +56,48 @@ function newAliasProxy(cstr) {
|
|
|
58
56
|
return key === aliasMgmt || key in meta.allFields;
|
|
59
57
|
}
|
|
60
58
|
});
|
|
59
|
+
return proxy;
|
|
61
60
|
}
|
|
62
61
|
function isAlias(obj) {
|
|
63
62
|
return obj && typeof obj === "function" && obj[aliasMgmt] !== void 0;
|
|
64
63
|
}
|
|
65
|
-
|
|
64
|
+
/**
|
|
65
|
+
* A single column of an alias.
|
|
66
|
+
*
|
|
67
|
+
* For `em.find`, its methods create `ColumnCondition`s that resolve their alias against each parse's
|
|
68
|
+
* join-literal bindings.
|
|
69
|
+
*
|
|
70
|
+
* For `em.query`, the column also implements `Expr`: it renders as `alias."column"`, decodes result
|
|
71
|
+
* values through the field's serde, and inherits aggregate methods from `BaseExpr`.
|
|
72
|
+
*/
|
|
73
|
+
var AbstractAliasColumn = class AbstractAliasColumn extends require_Expr.BaseExpr {
|
|
66
74
|
meta;
|
|
67
75
|
field;
|
|
68
|
-
callbacks;
|
|
69
76
|
column;
|
|
70
|
-
|
|
77
|
+
mgmt;
|
|
78
|
+
constructor(meta, field, column, mgmt) {
|
|
79
|
+
super();
|
|
71
80
|
this.meta = meta;
|
|
72
81
|
this.field = field;
|
|
73
|
-
this.callbacks = callbacks;
|
|
74
82
|
this.column = column;
|
|
83
|
+
this.mgmt = mgmt;
|
|
84
|
+
}
|
|
85
|
+
toSql(ctx) {
|
|
86
|
+
const alias = ctx.aliasFor(this.mgmt);
|
|
87
|
+
const ctiAlias = getMaybeCtiAlias(this.meta, this.field, this.meta, alias);
|
|
88
|
+
return {
|
|
89
|
+
sql: require_keywords.kqDot(ctiAlias, this.column.columnName),
|
|
90
|
+
bindings: [],
|
|
91
|
+
refs: [alias]
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/** Decodes a result-set value the same way `hydrate` would, i.e. an int into a tagged id. */
|
|
95
|
+
decode(value) {
|
|
96
|
+
if (value === null || value === void 0) return value;
|
|
97
|
+
return this.column.mapFromDb(value);
|
|
98
|
+
}
|
|
99
|
+
encode(value) {
|
|
100
|
+
return this.column.mapToDb(value);
|
|
75
101
|
}
|
|
76
102
|
addCondition(value) {
|
|
77
103
|
const cond = {
|
|
@@ -81,128 +107,121 @@ var AbstractAliasColumn = class {
|
|
|
81
107
|
dbType: this.column.dbType,
|
|
82
108
|
cond: require_QueryParser.mapToDb(this.column, value)
|
|
83
109
|
};
|
|
84
|
-
|
|
85
|
-
|
|
110
|
+
return require_Expr.withDeferredAlias(cond, (resolve) => {
|
|
111
|
+
const r = resolve(this.mgmt);
|
|
112
|
+
cond.alias = getMaybeCtiAlias(this.meta, this.field, r.meta, r.alias);
|
|
86
113
|
});
|
|
87
|
-
return cond;
|
|
88
114
|
}
|
|
89
115
|
addRawCondition(exp, bindings) {
|
|
90
116
|
const cond = {
|
|
91
117
|
kind: "raw",
|
|
92
118
|
aliases: [],
|
|
93
|
-
condition:
|
|
119
|
+
condition: "unset",
|
|
94
120
|
pruneable: false,
|
|
95
121
|
bindings
|
|
96
122
|
};
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
cond.
|
|
123
|
+
return require_Expr.withDeferredAlias(cond, (resolve) => {
|
|
124
|
+
const r = resolve(this.mgmt);
|
|
125
|
+
const alias = getMaybeCtiAlias(this.meta, this.field, r.meta, r.alias);
|
|
126
|
+
cond.aliases = [alias];
|
|
127
|
+
cond.condition = `${alias}.${this.column.columnName} ${exp}`;
|
|
101
128
|
});
|
|
102
|
-
return cond;
|
|
103
129
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
cond.condition = cond.condition.replace("unset1", alias);
|
|
116
|
-
});
|
|
117
|
-
otherColumn.callbacks.push((newMeta, newAlias) => {
|
|
118
|
-
const alias = getMaybeCtiAlias(otherColumn.meta, otherColumn.field, newMeta, newAlias);
|
|
119
|
-
if (!cond.aliases.includes(alias)) cond.aliases.push(alias);
|
|
120
|
-
cond.condition = cond.condition.replace("unset2", alias);
|
|
121
|
-
});
|
|
122
|
-
return cond;
|
|
130
|
+
/**
|
|
131
|
+
* Compares this column to another expression.
|
|
132
|
+
*
|
|
133
|
+
* Another alias column becomes a `DeferredAliasCondition`, which both parsers can resolve, so it also
|
|
134
|
+
* works inside `em.find`'s complex conditions; every other expression (an aggregate, a subquery column,
|
|
135
|
+
* a `sql` template) only exists in `em.query`, so it takes the `ExprContext`-deferred path, which only
|
|
136
|
+
* the `em.query` parser resolves.
|
|
137
|
+
*/
|
|
138
|
+
compareToExpr(op, value) {
|
|
139
|
+
if (value instanceof AbstractAliasColumn) return newCrossColumnCondition(this.meta, this.field, this.mgmt, this.column.columnName, value, op);
|
|
140
|
+
return this.compare(op, value);
|
|
123
141
|
}
|
|
124
142
|
};
|
|
125
|
-
var PrimitiveAliasImpl = class
|
|
143
|
+
var PrimitiveAliasImpl = class extends AbstractAliasColumn {
|
|
126
144
|
eq(value) {
|
|
127
|
-
if (value === void 0) return
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
145
|
+
if (value === void 0) return require_Expr.skipCondition;
|
|
146
|
+
if (value === null) return this.addCondition({ kind: "is-null" });
|
|
147
|
+
if (require_Expr.isExpr(value)) return this.compareToExpr("=", value);
|
|
148
|
+
return this.addCondition({
|
|
131
149
|
kind: "eq",
|
|
132
150
|
value
|
|
133
151
|
});
|
|
134
152
|
}
|
|
135
153
|
ne(value) {
|
|
136
|
-
if (value === void 0) return
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
154
|
+
if (value === void 0) return require_Expr.skipCondition;
|
|
155
|
+
if (value === null) return this.addCondition({ kind: "not-null" });
|
|
156
|
+
if (require_Expr.isExpr(value)) return this.compareToExpr("!=", value);
|
|
157
|
+
return this.addCondition({
|
|
140
158
|
kind: "ne",
|
|
141
159
|
value
|
|
142
160
|
});
|
|
143
161
|
}
|
|
144
162
|
gt(value) {
|
|
145
|
-
if (value === void 0) return
|
|
146
|
-
|
|
147
|
-
|
|
163
|
+
if (value === void 0) return require_Expr.skipCondition;
|
|
164
|
+
if (require_Expr.isExpr(value)) return this.compareToExpr(">", value);
|
|
165
|
+
return this.addCondition({
|
|
148
166
|
kind: "gt",
|
|
149
167
|
value
|
|
150
168
|
});
|
|
151
169
|
}
|
|
152
170
|
gte(value) {
|
|
153
|
-
if (value === void 0) return
|
|
154
|
-
|
|
155
|
-
|
|
171
|
+
if (value === void 0) return require_Expr.skipCondition;
|
|
172
|
+
if (require_Expr.isExpr(value)) return this.compareToExpr(">=", value);
|
|
173
|
+
return this.addCondition({
|
|
156
174
|
kind: "gte",
|
|
157
175
|
value
|
|
158
176
|
});
|
|
159
177
|
}
|
|
160
178
|
lt(value) {
|
|
161
|
-
if (value === void 0) return
|
|
162
|
-
|
|
163
|
-
|
|
179
|
+
if (value === void 0) return require_Expr.skipCondition;
|
|
180
|
+
if (require_Expr.isExpr(value)) return this.compareToExpr("<", value);
|
|
181
|
+
return this.addCondition({
|
|
164
182
|
kind: "lt",
|
|
165
183
|
value
|
|
166
184
|
});
|
|
167
185
|
}
|
|
168
186
|
lte(value) {
|
|
169
|
-
if (value === void 0) return
|
|
170
|
-
|
|
171
|
-
|
|
187
|
+
if (value === void 0) return require_Expr.skipCondition;
|
|
188
|
+
if (require_Expr.isExpr(value)) return this.compareToExpr("<=", value);
|
|
189
|
+
return this.addCondition({
|
|
172
190
|
kind: "lte",
|
|
173
191
|
value
|
|
174
192
|
});
|
|
175
193
|
}
|
|
176
194
|
between(v1, v2) {
|
|
177
|
-
if (v1 === void 0 || v2 === void 0) return
|
|
195
|
+
if (v1 === void 0 || v2 === void 0) return require_Expr.skipCondition;
|
|
178
196
|
return this.addCondition({
|
|
179
197
|
kind: "between",
|
|
180
198
|
value: [v1, v2]
|
|
181
199
|
});
|
|
182
200
|
}
|
|
183
201
|
like(value) {
|
|
184
|
-
if (value === void 0) return
|
|
202
|
+
if (value === void 0) return require_Expr.skipCondition;
|
|
185
203
|
return this.addCondition({
|
|
186
204
|
kind: "like",
|
|
187
205
|
value
|
|
188
206
|
});
|
|
189
207
|
}
|
|
190
208
|
ilike(value) {
|
|
191
|
-
if (value === void 0) return
|
|
209
|
+
if (value === void 0) return require_Expr.skipCondition;
|
|
192
210
|
return this.addCondition({
|
|
193
211
|
kind: "ilike",
|
|
194
212
|
value
|
|
195
213
|
});
|
|
196
214
|
}
|
|
197
215
|
search(value) {
|
|
198
|
-
if (!value) return
|
|
216
|
+
if (!value) return require_Expr.skipCondition;
|
|
199
217
|
return this.addCondition({
|
|
200
218
|
kind: "ilike",
|
|
201
219
|
value: require_QueryParser.makeLike(value)
|
|
202
220
|
});
|
|
203
221
|
}
|
|
204
222
|
in(values) {
|
|
205
|
-
if (values === void 0) return
|
|
223
|
+
if (values === void 0) return require_Expr.skipCondition;
|
|
224
|
+
if (require_Expr.isExpr(values)) return this.inList("IN", values);
|
|
206
225
|
if (values.includes(null)) return { or: [this.addCondition({ kind: "is-null" }), this.addCondition({
|
|
207
226
|
kind: "in",
|
|
208
227
|
value: values.filter((v) => v !== null)
|
|
@@ -212,124 +231,154 @@ var PrimitiveAliasImpl = class PrimitiveAliasImpl extends AbstractAliasColumn {
|
|
|
212
231
|
value: values
|
|
213
232
|
});
|
|
214
233
|
}
|
|
234
|
+
nin(values) {
|
|
235
|
+
if (values === void 0) return require_Expr.skipCondition;
|
|
236
|
+
if (require_Expr.isExpr(values)) return this.inList("NOT IN", values);
|
|
237
|
+
return this.addCondition({
|
|
238
|
+
kind: "nin",
|
|
239
|
+
value: values.filter((v) => v !== null)
|
|
240
|
+
});
|
|
241
|
+
}
|
|
215
242
|
contains(v1) {
|
|
216
|
-
if (v1 === void 0) return
|
|
243
|
+
if (v1 === void 0) return require_Expr.skipCondition;
|
|
217
244
|
return this.addCondition({
|
|
218
245
|
kind: "contains",
|
|
219
246
|
value: v1
|
|
220
247
|
});
|
|
221
248
|
}
|
|
222
249
|
ncontains(v1) {
|
|
223
|
-
if (v1 === void 0) return
|
|
250
|
+
if (v1 === void 0) return require_Expr.skipCondition;
|
|
224
251
|
return this.addCondition({
|
|
225
252
|
kind: "ncontains",
|
|
226
253
|
value: v1
|
|
227
254
|
});
|
|
228
255
|
}
|
|
229
256
|
overlaps(v1) {
|
|
230
|
-
if (v1 === void 0) return
|
|
257
|
+
if (v1 === void 0) return require_Expr.skipCondition;
|
|
231
258
|
return this.addCondition({
|
|
232
259
|
kind: "overlaps",
|
|
233
260
|
value: v1
|
|
234
261
|
});
|
|
235
262
|
}
|
|
236
263
|
noverlaps(v1) {
|
|
237
|
-
if (v1 === void 0) return
|
|
264
|
+
if (v1 === void 0) return require_Expr.skipCondition;
|
|
238
265
|
return this.addCondition({
|
|
239
266
|
kind: "noverlaps",
|
|
240
267
|
value: v1
|
|
241
268
|
});
|
|
242
269
|
}
|
|
243
270
|
pathExists(jsonPath) {
|
|
244
|
-
if (jsonPath === void 0) return
|
|
271
|
+
if (jsonPath === void 0) return require_Expr.skipCondition;
|
|
245
272
|
return this.addCondition({
|
|
246
273
|
kind: "jsonPathExists",
|
|
247
274
|
value: jsonPath
|
|
248
275
|
});
|
|
249
276
|
}
|
|
250
277
|
pathIsTrue(jsonPath) {
|
|
251
|
-
if (jsonPath === void 0) return
|
|
278
|
+
if (jsonPath === void 0) return require_Expr.skipCondition;
|
|
252
279
|
return this.addCondition({
|
|
253
280
|
kind: "jsonPathPredicate",
|
|
254
281
|
value: jsonPath
|
|
255
282
|
});
|
|
256
283
|
}
|
|
257
284
|
raw(exp, bindings) {
|
|
258
|
-
if (bindings === void 0) return
|
|
285
|
+
if (bindings === void 0) return require_Expr.skipCondition;
|
|
259
286
|
return this.addRawCondition(exp, bindings);
|
|
260
287
|
}
|
|
261
288
|
};
|
|
262
289
|
var EntityAliasImpl = class extends AbstractAliasColumn {
|
|
263
290
|
eq(value) {
|
|
264
|
-
if (value === void 0) return
|
|
265
|
-
|
|
266
|
-
|
|
291
|
+
if (value === void 0) return require_Expr.skipCondition;
|
|
292
|
+
if (value === null) return this.addCondition({ kind: "is-null" });
|
|
293
|
+
if (require_Expr.isExpr(value)) return this.compareToExpr("=", value);
|
|
294
|
+
return this.addCondition({
|
|
267
295
|
kind: "eq",
|
|
268
296
|
value
|
|
269
297
|
});
|
|
270
298
|
}
|
|
271
299
|
ne(value) {
|
|
272
|
-
if (value === void 0) return
|
|
273
|
-
|
|
274
|
-
|
|
300
|
+
if (value === void 0) return require_Expr.skipCondition;
|
|
301
|
+
if (value === null) return this.addCondition({ kind: "not-null" });
|
|
302
|
+
if (require_Expr.isExpr(value)) return this.compareToExpr("!=", value);
|
|
303
|
+
return this.addCondition({
|
|
275
304
|
kind: "ne",
|
|
276
305
|
value
|
|
277
306
|
});
|
|
278
307
|
}
|
|
279
308
|
in(values) {
|
|
280
|
-
if (values === void 0) return
|
|
309
|
+
if (values === void 0) return require_Expr.skipCondition;
|
|
281
310
|
else if (values === null) throw new Error("Unsupported");
|
|
311
|
+
else if (require_Expr.isExpr(values)) return this.inList("IN", values);
|
|
312
|
+
else if (values.includes(null)) return { or: [this.addCondition({ kind: "is-null" }), this.addCondition({
|
|
313
|
+
kind: "in",
|
|
314
|
+
value: values.filter((v) => v !== null)
|
|
315
|
+
})] };
|
|
282
316
|
else return this.addCondition({
|
|
283
317
|
kind: "in",
|
|
284
318
|
value: values
|
|
285
319
|
});
|
|
286
320
|
}
|
|
287
|
-
|
|
288
|
-
if (
|
|
289
|
-
else if (
|
|
321
|
+
nin(values) {
|
|
322
|
+
if (values === void 0) return require_Expr.skipCondition;
|
|
323
|
+
else if (values === null) throw new Error("Unsupported");
|
|
324
|
+
else if (require_Expr.isExpr(values)) return this.inList("NOT IN", values);
|
|
290
325
|
else return this.addCondition({
|
|
291
|
-
kind: "
|
|
292
|
-
value
|
|
326
|
+
kind: "nin",
|
|
327
|
+
value: values.filter((v) => v !== null)
|
|
293
328
|
});
|
|
294
329
|
}
|
|
330
|
+
gt(value) {
|
|
331
|
+
return this.compareId(">", "gt", value);
|
|
332
|
+
}
|
|
295
333
|
gte(value) {
|
|
296
|
-
|
|
297
|
-
else if (value === null) throw new Error("Unsupported");
|
|
298
|
-
else return this.addCondition({
|
|
299
|
-
kind: "gte",
|
|
300
|
-
value
|
|
301
|
-
});
|
|
334
|
+
return this.compareId(">=", "gte", value);
|
|
302
335
|
}
|
|
303
336
|
lt(value) {
|
|
304
|
-
|
|
305
|
-
else if (value === null) throw new Error("Unsupported");
|
|
306
|
-
else return this.addCondition({
|
|
307
|
-
kind: "lt",
|
|
308
|
-
value
|
|
309
|
-
});
|
|
337
|
+
return this.compareId("<", "lt", value);
|
|
310
338
|
}
|
|
311
339
|
lte(value) {
|
|
312
|
-
|
|
313
|
-
else if (value === null) throw new Error("Unsupported");
|
|
314
|
-
else return this.addCondition({
|
|
315
|
-
kind: "lte",
|
|
316
|
-
value
|
|
317
|
-
});
|
|
340
|
+
return this.compareId("<=", "lte", value);
|
|
318
341
|
}
|
|
319
342
|
raw(exp, bindings) {
|
|
320
|
-
if (bindings === void 0) return
|
|
343
|
+
if (bindings === void 0) return require_Expr.skipCondition;
|
|
321
344
|
return this.addRawCondition(exp, bindings);
|
|
322
345
|
}
|
|
346
|
+
/** Joins `other` via this FK, INNER for a required reference and LEFT for a nullable one. */
|
|
347
|
+
as(other) {
|
|
348
|
+
return this.joinEntry(this.field.required ? "inner" : "left", other);
|
|
349
|
+
}
|
|
350
|
+
inner(other) {
|
|
351
|
+
return this.joinEntry("inner", other);
|
|
352
|
+
}
|
|
353
|
+
left(other) {
|
|
354
|
+
return this.joinEntry("left", other);
|
|
355
|
+
}
|
|
356
|
+
joinEntry(kind, other) {
|
|
357
|
+
return {
|
|
358
|
+
[kind]: requireAlias(other),
|
|
359
|
+
on: this.eq(idColumnOf(other))
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
compareId(op, kind, value) {
|
|
363
|
+
if (value === void 0) return require_Expr.skipCondition;
|
|
364
|
+
if (value === null) throw new Error("Unsupported");
|
|
365
|
+
if (require_Expr.isExpr(value)) return this.compareToExpr(op, value);
|
|
366
|
+
return this.addCondition({
|
|
367
|
+
kind,
|
|
368
|
+
value
|
|
369
|
+
});
|
|
370
|
+
}
|
|
323
371
|
};
|
|
324
372
|
var PolyReferenceAlias = class {
|
|
325
373
|
meta;
|
|
326
|
-
|
|
374
|
+
mgmt;
|
|
327
375
|
field;
|
|
328
|
-
constructor(meta,
|
|
376
|
+
constructor(meta, mgmt, field) {
|
|
329
377
|
this.meta = meta;
|
|
330
|
-
this.
|
|
378
|
+
this.mgmt = mgmt;
|
|
331
379
|
this.field = field;
|
|
332
380
|
}
|
|
381
|
+
/** Compares to a tagged id, an entity, or another alias's id column, which picks the component (`c.parent.eq(a.id)`). */
|
|
333
382
|
eq(value) {
|
|
334
383
|
return this.addEqOrNe("eq", value);
|
|
335
384
|
}
|
|
@@ -337,7 +386,8 @@ var PolyReferenceAlias = class {
|
|
|
337
386
|
return this.addEqOrNe("ne", value);
|
|
338
387
|
}
|
|
339
388
|
in(values) {
|
|
340
|
-
if (values === void 0) return
|
|
389
|
+
if (values === void 0) return require_Expr.skipCondition;
|
|
390
|
+
if (require_Expr.isExpr(values)) return this.inSubquery(values);
|
|
341
391
|
const idsByConstructor = (0, joist_utils.groupBy)(values, (id) => require_configure.getConstructorFromTaggedId(require_keys.maybeResolveReferenceToId(id)).name);
|
|
342
392
|
return { or: Object.entries(idsByConstructor).map(([cstrName, ids]) => {
|
|
343
393
|
const comp = this.field.components.find((p) => p.otherMetadata().cstr.name === cstrName) ?? require_utils.fail(`No component for ${cstrName}`);
|
|
@@ -347,8 +397,48 @@ var PolyReferenceAlias = class {
|
|
|
347
397
|
});
|
|
348
398
|
}) };
|
|
349
399
|
}
|
|
400
|
+
/** Joins `other` via this poly's component for its entity, INNER when the poly is required. */
|
|
401
|
+
as(other) {
|
|
402
|
+
return this.joinEntry(this.field.required ? "inner" : "left", other);
|
|
403
|
+
}
|
|
404
|
+
inner(other) {
|
|
405
|
+
return this.joinEntry("inner", other);
|
|
406
|
+
}
|
|
407
|
+
left(other) {
|
|
408
|
+
return this.joinEntry("left", other);
|
|
409
|
+
}
|
|
410
|
+
joinEntry(kind, other) {
|
|
411
|
+
return {
|
|
412
|
+
[kind]: requireAlias(other),
|
|
413
|
+
on: this.eq(idColumnOf(other))
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* i.e. `c.parent.in(query({ from: a, ..., select: a.id }))`: like `eq` against an alias column, the
|
|
418
|
+
* subquery's select column picks the component, i.e. authors pick `parent_author_id`.
|
|
419
|
+
*/
|
|
420
|
+
inSubquery(values) {
|
|
421
|
+
const select = require_Expr.asNode(values).subquerySelect;
|
|
422
|
+
if (!(select instanceof AbstractAliasColumn)) return require_utils.fail(`${this.field.fieldName} is polymorphic, so \`in\` needs a subquery selecting an id or FK column`);
|
|
423
|
+
const otherMeta = select.field.kind === "primaryKey" ? select.meta : select.field.kind === "m2o" ? select.field.otherMetadata() : require_utils.fail(`${this.field.fieldName} \`in\` needs an id or FK column, got ${select.field.fieldName}`);
|
|
424
|
+
const comp = this.field.components.find((p) => require_EntityMetadata.getBaseAndSelfMetas(otherMeta).includes(p.otherMetadata())) ?? require_utils.fail(`${this.field.fieldName} has no component for ${otherMeta.type}`);
|
|
425
|
+
return require_Expr.deferredCondition((ctx) => {
|
|
426
|
+
const alias = getMaybeCtiAlias(this.meta, this.field, this.meta, ctx.aliasFor(this.mgmt));
|
|
427
|
+
const sub = require_Expr.asNode(values).toSqlBare(ctx);
|
|
428
|
+
return {
|
|
429
|
+
sql: `${alias}.${comp.columnName} IN (${sub.sql})`,
|
|
430
|
+
bindings: sub.bindings,
|
|
431
|
+
refs: [alias, ...sub.refs]
|
|
432
|
+
};
|
|
433
|
+
});
|
|
434
|
+
}
|
|
350
435
|
addEqOrNe(kind, value) {
|
|
351
|
-
if (value === void 0) return
|
|
436
|
+
if (value === void 0) return require_Expr.skipCondition;
|
|
437
|
+
else if (value instanceof AbstractAliasColumn) {
|
|
438
|
+
const otherMeta = value.meta;
|
|
439
|
+
const comp = this.field.components.find((p) => require_EntityMetadata.getBaseAndSelfMetas(otherMeta).includes(p.otherMetadata())) ?? require_utils.fail(`${this.field.fieldName} has no component for ${otherMeta.type}`);
|
|
440
|
+
return newCrossColumnCondition(this.meta, this.field, this.mgmt, comp.columnName, value, kind === "eq" ? "=" : "!=");
|
|
441
|
+
} else if (require_Expr.isExpr(value)) return require_utils.fail(`${this.field.fieldName} is polymorphic, so it can only be compared to tagged ids or entity alias columns`);
|
|
352
442
|
else if (value === null) {
|
|
353
443
|
const value = kind === "eq" ? { kind: "is-null" } : { kind: "not-null" };
|
|
354
444
|
return { and: this.field.components.map((p) => this.addCondition(p, value)) };
|
|
@@ -369,10 +459,10 @@ var PolyReferenceAlias = class {
|
|
|
369
459
|
dbType: this.field.serde.columns[0].dbType,
|
|
370
460
|
cond: require_QueryParser.mapToDb(column, value)
|
|
371
461
|
};
|
|
372
|
-
|
|
373
|
-
|
|
462
|
+
return require_Expr.withDeferredAlias(cond, (resolve) => {
|
|
463
|
+
const r = resolve(this.mgmt);
|
|
464
|
+
cond.alias = getMaybeCtiAlias(this.meta, this.field, r.meta, r.alias);
|
|
374
465
|
});
|
|
375
|
-
return cond;
|
|
376
466
|
}
|
|
377
467
|
};
|
|
378
468
|
/**
|
|
@@ -385,13 +475,148 @@ function getMaybeCtiAlias(meta, field, newMeta, newAlias) {
|
|
|
385
475
|
}
|
|
386
476
|
return `${newAlias}${field.aliasSuffix}`;
|
|
387
477
|
}
|
|
478
|
+
/**
|
|
479
|
+
* Marks a sugar join entry whose target is a *collection* (o2m/m2m), which filter soft-deletes like
|
|
480
|
+
* em.find's "collections filter out soft-deletes, but m2o/o2o references still return them"; see
|
|
481
|
+
* `QueryParser.addSoftDeleteCondition`'s call site. Reference joins and explicit joins are unmarked.
|
|
482
|
+
*/
|
|
483
|
+
const collectionJoin = Symbol("joist.collectionJoin");
|
|
484
|
+
/** Marks a sugar m2m join entry (`a.tags.as(t)`) with its hidden join-table join; `parseQuery` expands it. */
|
|
485
|
+
const m2mJoinTable = Symbol("joist.m2mJoinTable");
|
|
486
|
+
/** The runtime identity of an m2m join table in a query, i.e. `authors_to_tags`; it has no entity. */
|
|
487
|
+
var JoinTableHandle = class {
|
|
488
|
+
joinTableName;
|
|
489
|
+
constructor(joinTableName) {
|
|
490
|
+
this.joinTableName = joinTableName;
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
/**
|
|
494
|
+
* The `as`/`inner`/`left` join factory for collection relations, i.e. `a.books.as(b)` joins with the
|
|
495
|
+
* relation's default kind (LEFT: a collection may be empty) and `.inner`/`.left` override. m2o/poly
|
|
496
|
+
* relations implement the same three methods directly on their column/impl classes, so `b.author`
|
|
497
|
+
* stays a plain expression that is also a join factory.
|
|
498
|
+
*/
|
|
499
|
+
var AbstractCollectionAlias = class {
|
|
500
|
+
as(other) {
|
|
501
|
+
return this.joinEntry("left", requireAlias(other));
|
|
502
|
+
}
|
|
503
|
+
inner(other) {
|
|
504
|
+
return this.joinEntry("inner", requireAlias(other));
|
|
505
|
+
}
|
|
506
|
+
left(other) {
|
|
507
|
+
return this.joinEntry("left", requireAlias(other));
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
/** An o2m/lo2m/o2o relation: the ON is the other side's FK (an m2o or a poly component) back to our id. */
|
|
511
|
+
var OneToManyAliasImpl = class extends AbstractCollectionAlias {
|
|
512
|
+
proxy;
|
|
513
|
+
field;
|
|
514
|
+
constructor(proxy, field) {
|
|
515
|
+
super();
|
|
516
|
+
this.proxy = proxy;
|
|
517
|
+
this.field = field;
|
|
518
|
+
}
|
|
519
|
+
joinEntry(kind, other) {
|
|
520
|
+
const { field } = this;
|
|
521
|
+
const on = other[field.otherFieldName].eq(this.proxy.id);
|
|
522
|
+
const filtered = field.kind === "o2m" ? field.softDeletes !== "include" : field.kind === "lo2m";
|
|
523
|
+
return {
|
|
524
|
+
[kind]: other,
|
|
525
|
+
on,
|
|
526
|
+
[collectionJoin]: filtered
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
/**
|
|
531
|
+
* An m2m relation, i.e. `a.tags.as(t)`.
|
|
532
|
+
*
|
|
533
|
+
* The entry's own ON is `t.id = att.tag_id`, and the hidden `[m2mJoinTable]` half is
|
|
534
|
+
* `att.author_id = a.id`; only the target's ON references the join table, so reference pruning keeps
|
|
535
|
+
* or drops the pair together. Both are deferred conditions: the join table has no entity metadata, so
|
|
536
|
+
* its alias only exists once the parser registers it.
|
|
537
|
+
*/
|
|
538
|
+
var ManyToManyAliasImpl = class extends AbstractCollectionAlias {
|
|
539
|
+
proxy;
|
|
540
|
+
field;
|
|
541
|
+
constructor(proxy, field) {
|
|
542
|
+
super();
|
|
543
|
+
this.proxy = proxy;
|
|
544
|
+
this.field = field;
|
|
545
|
+
}
|
|
546
|
+
joinEntry(kind, other) {
|
|
547
|
+
const { joinTableName, columnNames } = this.field;
|
|
548
|
+
const [ourColumn, otherColumn] = columnNames;
|
|
549
|
+
const jt = new JoinTableHandle(joinTableName);
|
|
550
|
+
const ourId = this.proxy.id;
|
|
551
|
+
const otherId = idColumnOf(other);
|
|
552
|
+
const jtOn = require_Expr.deferredCondition((ctx) => {
|
|
553
|
+
const jtAlias = ctx.aliasFor(jt);
|
|
554
|
+
const id = ourId.toSql(ctx);
|
|
555
|
+
return {
|
|
556
|
+
sql: `${require_keywords.kqDot(jtAlias, ourColumn)} = ${id.sql}`,
|
|
557
|
+
bindings: id.bindings,
|
|
558
|
+
refs: id.refs
|
|
559
|
+
};
|
|
560
|
+
});
|
|
561
|
+
const on = require_Expr.deferredCondition((ctx) => {
|
|
562
|
+
const jtAlias = ctx.aliasFor(jt);
|
|
563
|
+
const id = otherId.toSql(ctx);
|
|
564
|
+
return {
|
|
565
|
+
sql: `${id.sql} = ${require_keywords.kqDot(jtAlias, otherColumn)}`,
|
|
566
|
+
bindings: id.bindings,
|
|
567
|
+
refs: [...id.refs, jtAlias]
|
|
568
|
+
};
|
|
569
|
+
});
|
|
570
|
+
const filtered = this.field.softDeletes !== "include";
|
|
571
|
+
return {
|
|
572
|
+
[kind]: other,
|
|
573
|
+
on,
|
|
574
|
+
[collectionJoin]: filtered,
|
|
575
|
+
[m2mJoinTable]: {
|
|
576
|
+
handle: jt,
|
|
577
|
+
on: jtOn
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
/** Compares columns with per-parse aliases, i.e. `parent_author_id = <other id>` for `c.parent.eq(a.id)`. */
|
|
583
|
+
function newCrossColumnCondition(meta, field, mgmt, columnName, otherColumn, op) {
|
|
584
|
+
const cond = {
|
|
585
|
+
kind: "raw",
|
|
586
|
+
aliases: [],
|
|
587
|
+
condition: "unset",
|
|
588
|
+
pruneable: false,
|
|
589
|
+
bindings: []
|
|
590
|
+
};
|
|
591
|
+
return require_Expr.withDeferredAlias(cond, (resolve) => {
|
|
592
|
+
const r1 = resolve(mgmt);
|
|
593
|
+
const r2 = resolve(otherColumn.mgmt);
|
|
594
|
+
const a1 = getMaybeCtiAlias(meta, field, r1.meta, r1.alias);
|
|
595
|
+
const a2 = getMaybeCtiAlias(otherColumn.meta, otherColumn.field, r2.meta, r2.alias);
|
|
596
|
+
cond.aliases = [a1, a2];
|
|
597
|
+
cond.condition = `${a1}.${columnName} ${op} ${a2}.${otherColumn.column.columnName}`;
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
/** Fails fast when a join factory is passed something other than an alias. */
|
|
601
|
+
function requireAlias(other) {
|
|
602
|
+
if (!isAlias(other)) return require_utils.fail(`Expected an alias to join, got ${other}`);
|
|
603
|
+
return other;
|
|
604
|
+
}
|
|
605
|
+
/** The id column of a joined alias, for building sugar ON conditions. */
|
|
606
|
+
function idColumnOf(other) {
|
|
607
|
+
return other.id;
|
|
608
|
+
}
|
|
388
609
|
//#endregion
|
|
610
|
+
exports.JoinTableHandle = JoinTableHandle;
|
|
389
611
|
exports.alias = alias;
|
|
612
|
+
exports.aliasMgmt = aliasMgmt;
|
|
390
613
|
exports.aliases = aliases;
|
|
614
|
+
exports.collectionJoin = collectionJoin;
|
|
391
615
|
exports.getAliasMetadata = getAliasMetadata;
|
|
392
616
|
exports.getAliasMgmt = getAliasMgmt;
|
|
393
617
|
exports.getMaybeCtiAlias = getMaybeCtiAlias;
|
|
394
618
|
exports.isAlias = isAlias;
|
|
619
|
+
exports.m2mJoinTable = m2mJoinTable;
|
|
395
620
|
exports.newAliasProxy = newAliasProxy;
|
|
396
621
|
|
|
397
622
|
//# sourceMappingURL=Aliases.cjs.map
|