@medusajs/index 3.0.0-snapshot-20250410112222 → 3.0.0-snapshot-20251104004624
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/dist/loaders/index.d.ts.map +1 -1
- package/dist/loaders/index.js +1 -1
- package/dist/loaders/index.js.map +1 -1
- package/dist/migrations/Migration20231019174230.d.ts +1 -1
- package/dist/migrations/Migration20231019174230.d.ts.map +1 -1
- package/dist/migrations/Migration20231019174230.js +3 -3
- package/dist/migrations/Migration20231019174230.js.map +1 -1
- package/dist/migrations/Migration20241209173313.d.ts +1 -1
- package/dist/migrations/Migration20241209173313.d.ts.map +1 -1
- package/dist/migrations/Migration20241209173313.js +1 -1
- package/dist/migrations/Migration20241209173313.js.map +1 -1
- package/dist/migrations/Migration20250122154720.d.ts +1 -1
- package/dist/migrations/Migration20250122154720.d.ts.map +1 -1
- package/dist/migrations/Migration20250122154720.js +1 -1
- package/dist/migrations/Migration20250122154720.js.map +1 -1
- package/dist/migrations/Migration20250127105159.d.ts +1 -1
- package/dist/migrations/Migration20250127105159.d.ts.map +1 -1
- package/dist/migrations/Migration20250127105159.js +1 -1
- package/dist/migrations/Migration20250127105159.js.map +1 -1
- package/dist/migrations/Migration20250127144442.d.ts +1 -1
- package/dist/migrations/Migration20250127144442.d.ts.map +1 -1
- package/dist/migrations/Migration20250127144442.js +1 -1
- package/dist/migrations/Migration20250127144442.js.map +1 -1
- package/dist/migrations/Migration20250128132404.d.ts +1 -1
- package/dist/migrations/Migration20250128132404.d.ts.map +1 -1
- package/dist/migrations/Migration20250128132404.js +1 -1
- package/dist/migrations/Migration20250128132404.js.map +1 -1
- package/dist/migrations/Migration20250218132404.d.ts +1 -1
- package/dist/migrations/Migration20250218132404.d.ts.map +1 -1
- package/dist/migrations/Migration20250218132404.js +1 -1
- package/dist/migrations/Migration20250218132404.js.map +1 -1
- package/dist/migrations/Migration20250515161913.d.ts +6 -0
- package/dist/migrations/Migration20250515161913.d.ts.map +1 -0
- package/dist/migrations/Migration20250515161913.js +62 -0
- package/dist/migrations/Migration20250515161913.js.map +1 -0
- package/dist/services/data-synchronizer.d.ts.map +1 -1
- package/dist/services/data-synchronizer.js +8 -7
- package/dist/services/data-synchronizer.js.map +1 -1
- package/dist/services/index-data.d.ts +4 -1
- package/dist/services/index-data.d.ts.map +1 -1
- package/dist/services/index-metadata.d.ts +4 -1
- package/dist/services/index-metadata.d.ts.map +1 -1
- package/dist/services/index-module-service.d.ts +37 -2
- package/dist/services/index-module-service.d.ts.map +1 -1
- package/dist/services/index-module-service.js +261 -29
- package/dist/services/index-module-service.js.map +1 -1
- package/dist/services/index-relation.d.ts +4 -1
- package/dist/services/index-relation.d.ts.map +1 -1
- package/dist/services/index-sync.d.ts +4 -1
- package/dist/services/index-sync.d.ts.map +1 -1
- package/dist/services/postgres-provider.d.ts +1 -1
- package/dist/services/postgres-provider.d.ts.map +1 -1
- package/dist/services/postgres-provider.js +14 -61
- package/dist/services/postgres-provider.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/base-graphql-schema.d.ts +2 -0
- package/dist/utils/base-graphql-schema.d.ts.map +1 -0
- package/dist/utils/base-graphql-schema.js +10 -0
- package/dist/utils/base-graphql-schema.js.map +1 -0
- package/dist/utils/build-config.d.ts +5 -1
- package/dist/utils/build-config.d.ts.map +1 -1
- package/dist/utils/build-config.js +488 -142
- package/dist/utils/build-config.js.map +1 -1
- package/dist/utils/create-partitions.d.ts +1 -1
- package/dist/utils/create-partitions.d.ts.map +1 -1
- package/dist/utils/create-partitions.js +33 -12
- package/dist/utils/create-partitions.js.map +1 -1
- package/dist/utils/default-schema.js +6 -6
- package/dist/utils/gql-to-types.d.ts +2 -1
- package/dist/utils/gql-to-types.d.ts.map +1 -1
- package/dist/utils/gql-to-types.js +19 -12
- package/dist/utils/gql-to-types.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/normalze-table-name.d.ts +3 -0
- package/dist/utils/normalze-table-name.d.ts.map +1 -0
- package/dist/utils/normalze-table-name.js +13 -0
- package/dist/utils/normalze-table-name.js.map +1 -0
- package/dist/utils/query-builder.d.ts +11 -12
- package/dist/utils/query-builder.d.ts.map +1 -1
- package/dist/utils/query-builder.js +335 -230
- package/dist/utils/query-builder.js.map +1 -1
- package/dist/utils/sync/configuration.js +17 -15
- package/dist/utils/sync/configuration.js.map +1 -1
- package/dist/utils/sync/orchestrator.d.ts +3 -2
- package/dist/utils/sync/orchestrator.d.ts.map +1 -1
- package/dist/utils/sync/orchestrator.js +19 -7
- package/dist/utils/sync/orchestrator.js.map +1 -1
- package/package.json +14 -30
|
@@ -8,6 +8,47 @@ var _QueryBuilder_searchVectorColumnName;
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.QueryBuilder = exports.OPERATOR_MAP = void 0;
|
|
10
10
|
const utils_1 = require("@medusajs/framework/utils");
|
|
11
|
+
const normalze_table_name_1 = require("./normalze-table-name");
|
|
12
|
+
const AND_OPERATOR = "$and";
|
|
13
|
+
const OR_OPERATOR = "$or";
|
|
14
|
+
const NOT_OPERATOR = "$not";
|
|
15
|
+
function escapeJsonPathString(val) {
|
|
16
|
+
// Escape for JSONPath string
|
|
17
|
+
return val.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/'/g, "\\'");
|
|
18
|
+
}
|
|
19
|
+
function buildSafeJsonPathQuery(field, operator, value) {
|
|
20
|
+
let jsonPathOperator = operator;
|
|
21
|
+
let caseInsensitiveFlag = "";
|
|
22
|
+
if (operator === "=") {
|
|
23
|
+
jsonPathOperator = "==";
|
|
24
|
+
}
|
|
25
|
+
else if (operator.toUpperCase().includes("LIKE")) {
|
|
26
|
+
jsonPathOperator = "like_regex";
|
|
27
|
+
if (operator.toUpperCase() === "ILIKE") {
|
|
28
|
+
caseInsensitiveFlag = ' flag "i"';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else if (operator === "IS") {
|
|
32
|
+
jsonPathOperator = "==";
|
|
33
|
+
}
|
|
34
|
+
else if (operator === "IS NOT") {
|
|
35
|
+
jsonPathOperator = "!=";
|
|
36
|
+
}
|
|
37
|
+
if (typeof value === "string") {
|
|
38
|
+
let val = value;
|
|
39
|
+
if (jsonPathOperator === "like_regex") {
|
|
40
|
+
// Convert SQL LIKE wildcards to regex
|
|
41
|
+
val = val.replace(/%/g, ".*").replace(/_/g, ".");
|
|
42
|
+
}
|
|
43
|
+
value = `"${escapeJsonPathString(val)}"`;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
if ((operator === "IS" || operator === "IS NOT") && value === null) {
|
|
47
|
+
value = "null";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return `$.${field} ${jsonPathOperator} ${value}${caseInsensitiveFlag}`;
|
|
51
|
+
}
|
|
11
52
|
exports.OPERATOR_MAP = {
|
|
12
53
|
$eq: "=",
|
|
13
54
|
$lt: "<",
|
|
@@ -16,6 +57,7 @@ exports.OPERATOR_MAP = {
|
|
|
16
57
|
$gte: ">=",
|
|
17
58
|
$ne: "!=",
|
|
18
59
|
$in: "IN",
|
|
60
|
+
$nin: "NOT IN",
|
|
19
61
|
$is: "IS",
|
|
20
62
|
$like: "LIKE",
|
|
21
63
|
$ilike: "ILIKE",
|
|
@@ -32,9 +74,29 @@ class QueryBuilder {
|
|
|
32
74
|
this.allSchemaFields = new Set(Object.values(this.schema).flatMap((entity) => entity.fields ?? []));
|
|
33
75
|
this.rawConfig = args.rawConfig;
|
|
34
76
|
this.requestedFields = args.requestedFields;
|
|
77
|
+
this.idsOnly = args.idsOnly ?? false;
|
|
78
|
+
}
|
|
79
|
+
isLogicalOperator(key) {
|
|
80
|
+
return key === AND_OPERATOR || key === OR_OPERATOR || key === NOT_OPERATOR;
|
|
35
81
|
}
|
|
36
82
|
getStructureKeys(structure) {
|
|
37
|
-
|
|
83
|
+
const collectKeys = (obj, keys = new Set()) => {
|
|
84
|
+
if (!(0, utils_1.isObject)(obj)) {
|
|
85
|
+
return keys;
|
|
86
|
+
}
|
|
87
|
+
Object.keys(obj).forEach((key) => {
|
|
88
|
+
if (this.isLogicalOperator(key)) {
|
|
89
|
+
if (Array.isArray(obj[key])) {
|
|
90
|
+
obj[key].forEach((item) => collectKeys(item, keys));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else if (key !== "entity") {
|
|
94
|
+
keys.add(key);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
return keys;
|
|
98
|
+
};
|
|
99
|
+
return [...collectKeys(structure ?? {})];
|
|
38
100
|
}
|
|
39
101
|
getEntity(path, throwWhenNotFound = true) {
|
|
40
102
|
if (!this.schema._schemaPropertiesMap[path]) {
|
|
@@ -46,20 +108,18 @@ class QueryBuilder {
|
|
|
46
108
|
return this.schema._schemaPropertiesMap[path];
|
|
47
109
|
}
|
|
48
110
|
getGraphQLType(path, field) {
|
|
111
|
+
if (this.isLogicalOperator(field)) {
|
|
112
|
+
return "JSON";
|
|
113
|
+
}
|
|
49
114
|
const entity = this.getEntity(path)?.ref?.entity;
|
|
50
115
|
const fieldRef = this.entityMap[entity]._fields[field];
|
|
51
116
|
if (!fieldRef) {
|
|
52
117
|
throw new Error(`Field ${field} is not indexed.`);
|
|
53
118
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
isArray = true;
|
|
59
|
-
}
|
|
60
|
-
currentType = currentType.ofType;
|
|
61
|
-
}
|
|
62
|
-
return currentType.name + (isArray ? "[]" : "");
|
|
119
|
+
const fieldType = fieldRef.type.toString();
|
|
120
|
+
const isArray = fieldType.startsWith("[");
|
|
121
|
+
const currentType = fieldType.replace(/\[|\]|\!/g, "");
|
|
122
|
+
return currentType + (isArray ? "[]" : "");
|
|
63
123
|
}
|
|
64
124
|
transformValueToType(path, field, value) {
|
|
65
125
|
if (value === null) {
|
|
@@ -120,10 +180,11 @@ class QueryBuilder {
|
|
|
120
180
|
coalesce: generateCoalesceExpression,
|
|
121
181
|
};
|
|
122
182
|
}
|
|
123
|
-
parseWhere(aliasMapping, obj, builder) {
|
|
183
|
+
parseWhere(aliasMapping, obj, builder, parentPath = "") {
|
|
124
184
|
const keys = Object.keys(obj);
|
|
125
185
|
const getPathAndField = (key) => {
|
|
126
|
-
const
|
|
186
|
+
const fullKey = parentPath ? `${parentPath}.${key}` : key;
|
|
187
|
+
const path = fullKey.split(".");
|
|
127
188
|
const field = [path.pop()];
|
|
128
189
|
while (!aliasMapping[path.join(".")] && path.length > 0) {
|
|
129
190
|
field.unshift(path.pop());
|
|
@@ -140,52 +201,125 @@ class QueryBuilder {
|
|
|
140
201
|
return JSON.stringify(result);
|
|
141
202
|
};
|
|
142
203
|
keys.forEach((key) => {
|
|
204
|
+
const pathAsArray = (parentPath ? `${parentPath}.${key}` : key).split(".");
|
|
205
|
+
const fieldOrLogicalOperator = pathAsArray.pop();
|
|
143
206
|
let value = obj[key];
|
|
144
|
-
if ((
|
|
207
|
+
if (this.isLogicalOperator(fieldOrLogicalOperator) &&
|
|
208
|
+
!Array.isArray(value)) {
|
|
145
209
|
value = [value];
|
|
146
210
|
}
|
|
147
|
-
if (
|
|
211
|
+
if (fieldOrLogicalOperator === AND_OPERATOR && Array.isArray(value)) {
|
|
148
212
|
builder.where((qb) => {
|
|
149
213
|
value.forEach((cond) => {
|
|
150
|
-
qb.andWhere((subBuilder) => this.parseWhere(aliasMapping, cond, subBuilder));
|
|
214
|
+
qb.andWhere((subBuilder) => this.parseWhere(aliasMapping, cond, subBuilder, pathAsArray.join(".")));
|
|
151
215
|
});
|
|
152
216
|
});
|
|
153
217
|
}
|
|
154
|
-
else if (
|
|
218
|
+
else if (fieldOrLogicalOperator === OR_OPERATOR &&
|
|
219
|
+
Array.isArray(value)) {
|
|
155
220
|
builder.where((qb) => {
|
|
156
221
|
value.forEach((cond) => {
|
|
157
|
-
qb.orWhere((subBuilder) => this.parseWhere(aliasMapping, cond, subBuilder));
|
|
222
|
+
qb.orWhere((subBuilder) => this.parseWhere(aliasMapping, cond, subBuilder, pathAsArray.join(".")));
|
|
158
223
|
});
|
|
159
224
|
});
|
|
160
225
|
}
|
|
161
|
-
else if (
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
const subValue = this.transformValueToType(attr, field, value[subKey]);
|
|
169
|
-
const castType = this.getPostgresCastType(attr, [field]).cast;
|
|
170
|
-
const val = operator === "IN" ? subValue : [subValue];
|
|
171
|
-
if (operator === "=" && subValue === null) {
|
|
172
|
-
operator = "IS";
|
|
173
|
-
}
|
|
174
|
-
else if (operator === "!=" && subValue === null) {
|
|
175
|
-
operator = "IS NOT";
|
|
176
|
-
}
|
|
177
|
-
if (operator === "=") {
|
|
178
|
-
builder.whereRaw(`${aliasMapping[attr]}.data @> '${getPathOperation(attr, field, subValue)}'::jsonb`);
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
builder.whereRaw(`(${aliasMapping[attr]}.data${nested}->>?)${castType} ${operator} ?`, [...field, ...val]);
|
|
182
|
-
}
|
|
226
|
+
else if (fieldOrLogicalOperator === NOT_OPERATOR &&
|
|
227
|
+
(Array.isArray(value) || (0, utils_1.isObject)(value))) {
|
|
228
|
+
builder.whereNot((qb) => {
|
|
229
|
+
if (Array.isArray(value)) {
|
|
230
|
+
value.forEach((cond) => {
|
|
231
|
+
qb.andWhere((subBuilder) => this.parseWhere(aliasMapping, cond, subBuilder, pathAsArray.join(".")));
|
|
232
|
+
});
|
|
183
233
|
}
|
|
184
234
|
else {
|
|
185
|
-
|
|
235
|
+
this.parseWhere(aliasMapping, value, qb, pathAsArray.join("."));
|
|
186
236
|
}
|
|
187
237
|
});
|
|
188
238
|
}
|
|
239
|
+
else if ((0, utils_1.isObject)(value) &&
|
|
240
|
+
!Array.isArray(value) &&
|
|
241
|
+
!this.isLogicalOperator(fieldOrLogicalOperator)) {
|
|
242
|
+
const currentPath = parentPath ? `${parentPath}.${key}` : key;
|
|
243
|
+
const subKeys = Object.keys(value);
|
|
244
|
+
const hasOperators = subKeys.some((subKey) => exports.OPERATOR_MAP[subKey]);
|
|
245
|
+
if (hasOperators) {
|
|
246
|
+
const { field, attr } = getPathAndField(key);
|
|
247
|
+
const subKeys = Object.keys(value);
|
|
248
|
+
subKeys.forEach((subKey) => {
|
|
249
|
+
let operator = exports.OPERATOR_MAP[subKey];
|
|
250
|
+
if (operator) {
|
|
251
|
+
const nested = new Array(field.length).join("->?");
|
|
252
|
+
const subValue = this.transformValueToType(attr, field, value[subKey]);
|
|
253
|
+
let val = operator === "IN" || operator === "NOT IN"
|
|
254
|
+
? subValue
|
|
255
|
+
: [subValue];
|
|
256
|
+
if (operator === "=" && subValue === null) {
|
|
257
|
+
operator = "IS";
|
|
258
|
+
}
|
|
259
|
+
else if (operator === "!=" && subValue === null) {
|
|
260
|
+
operator = "IS NOT";
|
|
261
|
+
}
|
|
262
|
+
if (operator === "=") {
|
|
263
|
+
const hasId = field[field.length - 1] === "id";
|
|
264
|
+
if (hasId) {
|
|
265
|
+
builder.whereRaw(`${aliasMapping[attr]}.id = ?`, subValue);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
builder.whereRaw(`${aliasMapping[attr]}.data @> '${getPathOperation(attr, field, subValue)}'::jsonb`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
else if (operator === "IN" || operator === "NOT IN") {
|
|
272
|
+
if (val && !Array.isArray(val)) {
|
|
273
|
+
val = [val];
|
|
274
|
+
}
|
|
275
|
+
if (!val || val.length === 0) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const inPlaceholders = val.map(() => "?").join(",");
|
|
279
|
+
const hasId = field[field.length - 1] === "id";
|
|
280
|
+
const isNegated = operator === "NOT IN";
|
|
281
|
+
if (hasId) {
|
|
282
|
+
builder.whereRaw(`${aliasMapping[attr]}.id ${isNegated ? "NOT IN" : "IN"} (${inPlaceholders})`, val);
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
const targetField = field[field.length - 1];
|
|
286
|
+
const jsonbValues = val.map((item) => JSON.stringify({
|
|
287
|
+
[targetField]: item === null ? null : item,
|
|
288
|
+
}));
|
|
289
|
+
if (isNegated) {
|
|
290
|
+
builder.whereRaw(`NOT EXISTS (SELECT 1 FROM unnest(ARRAY[${inPlaceholders}]::JSONB[]) AS v(val) WHERE ${aliasMapping[attr]}.data${nested} @> v.val)`, jsonbValues);
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
builder.whereRaw(`${aliasMapping[attr]}.data${nested} @> ANY(ARRAY[${inPlaceholders}]::JSONB[])`, jsonbValues);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
const potentialIdFields = field[field.length - 1];
|
|
299
|
+
const hasId = potentialIdFields === "id";
|
|
300
|
+
if (hasId) {
|
|
301
|
+
builder.whereRaw(`(${aliasMapping[attr]}.id) ${operator} ?`, [
|
|
302
|
+
...val,
|
|
303
|
+
]);
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
const targetField = field[field.length - 1];
|
|
307
|
+
const jsonPath = buildSafeJsonPathQuery(targetField, operator, val[0]);
|
|
308
|
+
builder.whereRaw(`${aliasMapping[attr]}.data${nested} @@ ?`, [
|
|
309
|
+
jsonPath,
|
|
310
|
+
]);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
throw new Error(`Unsupported operator: ${subKey}`);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
this.parseWhere(aliasMapping, value, builder, currentPath);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
189
323
|
else {
|
|
190
324
|
const { field, attr } = getPathAndField(key);
|
|
191
325
|
const nested = new Array(field.length).join("->?");
|
|
@@ -194,49 +328,76 @@ class QueryBuilder {
|
|
|
194
328
|
if (value.length === 0) {
|
|
195
329
|
return;
|
|
196
330
|
}
|
|
197
|
-
const castType = this.getPostgresCastType(attr, field).cast;
|
|
198
331
|
const inPlaceholders = value.map(() => "?").join(",");
|
|
199
|
-
|
|
332
|
+
const hasId = field[field.length - 1] === "id";
|
|
333
|
+
if (hasId) {
|
|
334
|
+
builder.whereRaw(`${aliasMapping[attr]}.id IN (${inPlaceholders})`, [...value]);
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
const targetField = field[field.length - 1];
|
|
338
|
+
const jsonbValues = value.map((item) => JSON.stringify({ [targetField]: item === null ? null : item }));
|
|
339
|
+
builder.whereRaw(`${aliasMapping[attr]}.data${nested} @> ANY(ARRAY[${inPlaceholders}]::JSONB[])`, jsonbValues);
|
|
340
|
+
}
|
|
200
341
|
}
|
|
201
342
|
else if ((0, utils_1.isDefined)(value)) {
|
|
202
|
-
|
|
343
|
+
let operator = "=";
|
|
203
344
|
if (operator === "=") {
|
|
204
|
-
|
|
345
|
+
const hasId = field[field.length - 1] === "id";
|
|
346
|
+
if (hasId) {
|
|
347
|
+
builder.whereRaw(`${aliasMapping[attr]}.id = ?`, value);
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
builder.whereRaw(`${aliasMapping[attr]}.data @> '${getPathOperation(attr, field, value)}'::jsonb`);
|
|
351
|
+
}
|
|
205
352
|
}
|
|
206
353
|
else {
|
|
207
|
-
|
|
208
|
-
|
|
354
|
+
if (value === null) {
|
|
355
|
+
operator = "IS";
|
|
356
|
+
}
|
|
357
|
+
const hasId = field[field.length - 1] === "id";
|
|
358
|
+
if (hasId) {
|
|
359
|
+
builder.whereRaw(`(${aliasMapping[attr]}.id) ${operator} ?`, [
|
|
360
|
+
value,
|
|
361
|
+
]);
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
const targetField = field[field.length - 1];
|
|
365
|
+
const jsonPath = buildSafeJsonPathQuery(targetField, operator, value);
|
|
366
|
+
builder.whereRaw(`${aliasMapping[attr]}.data${nested} @@ ?`, [
|
|
367
|
+
jsonPath,
|
|
368
|
+
]);
|
|
369
|
+
}
|
|
209
370
|
}
|
|
210
371
|
}
|
|
211
372
|
}
|
|
212
373
|
});
|
|
213
374
|
return builder;
|
|
214
375
|
}
|
|
215
|
-
getShortAlias(aliasMapping, alias) {
|
|
376
|
+
getShortAlias(aliasMapping, alias, level = 0) {
|
|
216
377
|
aliasMapping.__aliasIndex ??= 0;
|
|
217
378
|
if (aliasMapping[alias]) {
|
|
218
379
|
return aliasMapping[alias];
|
|
219
380
|
}
|
|
220
|
-
aliasMapping[alias] =
|
|
381
|
+
aliasMapping[alias] =
|
|
382
|
+
"t_" + aliasMapping.__aliasIndex++ + (level > 0 ? `_${level}` : "");
|
|
221
383
|
return aliasMapping[alias];
|
|
222
384
|
}
|
|
223
385
|
buildQueryParts(structure, parentAlias, parentEntity, parentProperty, aliasPath = [], level = 0, aliasMapping = {}) {
|
|
224
386
|
const currentAliasPath = [...aliasPath, parentProperty].join(".");
|
|
225
387
|
const isSelectableField = this.allSchemaFields.has(parentProperty);
|
|
226
388
|
const entities = this.getEntity(currentAliasPath, false);
|
|
227
|
-
const entityRef = entities?.ref;
|
|
228
389
|
// !entityRef.alias means the object has not table, it's a nested object
|
|
229
|
-
if (isSelectableField || !entities || !
|
|
390
|
+
if (isSelectableField || !entities || !entities?.ref?.alias) {
|
|
230
391
|
// We are currently selecting a specific field of the parent entity or the entity is not found on the index schema
|
|
231
392
|
// We don't need to build the query parts for this as there is no join
|
|
232
393
|
return [];
|
|
233
394
|
}
|
|
234
|
-
const mainEntity =
|
|
235
|
-
const mainAlias = this.getShortAlias(aliasMapping, mainEntity.toLowerCase()
|
|
395
|
+
const mainEntity = entities;
|
|
396
|
+
const mainAlias = this.getShortAlias(aliasMapping, mainEntity.ref.entity.toLowerCase(), level);
|
|
236
397
|
const allEntities = [];
|
|
237
398
|
if (!entities.shortCutOf) {
|
|
238
399
|
allEntities.push({
|
|
239
|
-
entity:
|
|
400
|
+
entity: entities,
|
|
240
401
|
parEntity: parentEntity,
|
|
241
402
|
parAlias: parentAlias,
|
|
242
403
|
alias: mainAlias,
|
|
@@ -250,26 +411,24 @@ class QueryBuilder {
|
|
|
250
411
|
break;
|
|
251
412
|
}
|
|
252
413
|
intermediateAlias.pop();
|
|
253
|
-
if (intermediateEntity.ref.entity === parentEntity) {
|
|
414
|
+
if (intermediateEntity.ref.entity === parentEntity?.ref.entity) {
|
|
254
415
|
break;
|
|
255
416
|
}
|
|
256
417
|
const parentIntermediateEntity = this.getEntity(intermediateAlias.join("."));
|
|
257
|
-
const alias = this.getShortAlias(aliasMapping, intermediateEntity.ref.entity.toLowerCase()) +
|
|
258
|
-
level +
|
|
418
|
+
const alias = this.getShortAlias(aliasMapping, intermediateEntity.ref.entity.toLowerCase(), level) +
|
|
259
419
|
"_" +
|
|
260
420
|
x;
|
|
261
|
-
const parAlias = parentIntermediateEntity.ref.entity === parentEntity
|
|
421
|
+
const parAlias = parentIntermediateEntity.ref.entity === parentEntity?.ref.entity
|
|
262
422
|
? parentAlias
|
|
263
|
-
: this.getShortAlias(aliasMapping, parentIntermediateEntity.ref.entity.toLowerCase()) +
|
|
264
|
-
level +
|
|
423
|
+
: this.getShortAlias(aliasMapping, parentIntermediateEntity.ref.entity.toLowerCase(), level) +
|
|
265
424
|
"_" +
|
|
266
425
|
(x + 1);
|
|
267
426
|
if (x === 0) {
|
|
268
427
|
aliasMapping[currentAliasPath] = alias;
|
|
269
428
|
}
|
|
270
429
|
allEntities.unshift({
|
|
271
|
-
entity: intermediateEntity
|
|
272
|
-
parEntity: parentIntermediateEntity
|
|
430
|
+
entity: intermediateEntity,
|
|
431
|
+
parEntity: parentIntermediateEntity,
|
|
273
432
|
parAlias,
|
|
274
433
|
alias,
|
|
275
434
|
});
|
|
@@ -281,12 +440,20 @@ class QueryBuilder {
|
|
|
281
440
|
const { alias, entity, parEntity, parAlias } = join;
|
|
282
441
|
aliasMapping[currentAliasPath] = alias;
|
|
283
442
|
if (level > 0) {
|
|
284
|
-
const cName = entity.
|
|
285
|
-
const pName = `${parEntity}${entity}`.toLowerCase();
|
|
443
|
+
const cName = (0, normalze_table_name_1.normalizeTableName)(entity.ref.entity);
|
|
286
444
|
let joinTable = `cat_${cName} AS ${alias}`;
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
445
|
+
if (entity.isInverse || parEntity.isInverse) {
|
|
446
|
+
const pName = `${entity.ref.entity}${parEntity.ref.entity}`.toLowerCase();
|
|
447
|
+
const pivotTable = (0, normalze_table_name_1.getPivotTableName)(pName);
|
|
448
|
+
joinBuilder.leftJoin(`${pivotTable} AS ${alias}_ref`, `${alias}_ref.child_id`, `${parAlias}.id`);
|
|
449
|
+
joinBuilder.leftJoin(joinTable, `${alias}.id`, `${alias}_ref.parent_id`);
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
const pName = `${parEntity.ref.entity}${entity.ref.entity}`.toLowerCase();
|
|
453
|
+
const pivotTable = (0, normalze_table_name_1.getPivotTableName)(pName);
|
|
454
|
+
joinBuilder.leftJoin(`${pivotTable} AS ${alias}_ref`, `${alias}_ref.parent_id`, `${parAlias}.id`);
|
|
455
|
+
joinBuilder.leftJoin(joinTable, `${alias}.id`, `${alias}_ref.child_id`);
|
|
456
|
+
}
|
|
290
457
|
const joinWhere = this.selector.joinWhere ?? {};
|
|
291
458
|
const joinKey = Object.keys(joinWhere).find((key) => {
|
|
292
459
|
const k = key.split(".");
|
|
@@ -294,7 +461,7 @@ class QueryBuilder {
|
|
|
294
461
|
const curPath = k.join(".");
|
|
295
462
|
if (curPath === currentAliasPath) {
|
|
296
463
|
const relEntity = this.getEntity(curPath, false);
|
|
297
|
-
return relEntity?.ref?.entity === entity;
|
|
464
|
+
return relEntity?.ref?.entity === entity.ref.entity;
|
|
298
465
|
}
|
|
299
466
|
return false;
|
|
300
467
|
});
|
|
@@ -323,7 +490,12 @@ class QueryBuilder {
|
|
|
323
490
|
const parentAliasPath = aliasPath.join(".");
|
|
324
491
|
const alias = aliasMapping[parentAliasPath];
|
|
325
492
|
delete selectParts[parentAliasPath];
|
|
326
|
-
|
|
493
|
+
if (parentProperty === "id") {
|
|
494
|
+
selectParts[currentAliasPath] = `${alias}.id`;
|
|
495
|
+
}
|
|
496
|
+
else if (!this.idsOnly) {
|
|
497
|
+
selectParts[currentAliasPath] = this.knex.raw(`${alias}.data->'${parentProperty}'`);
|
|
498
|
+
}
|
|
327
499
|
return selectParts;
|
|
328
500
|
}
|
|
329
501
|
const alias = aliasMapping[currentAliasPath];
|
|
@@ -331,7 +503,9 @@ class QueryBuilder {
|
|
|
331
503
|
if (!alias) {
|
|
332
504
|
return selectParts;
|
|
333
505
|
}
|
|
334
|
-
|
|
506
|
+
if (!this.idsOnly) {
|
|
507
|
+
selectParts[currentAliasPath] = `${alias}.data`;
|
|
508
|
+
}
|
|
335
509
|
selectParts[currentAliasPath + ".id"] = `${alias}.id`;
|
|
336
510
|
const children = this.getStructureKeys(structure);
|
|
337
511
|
for (const child of children) {
|
|
@@ -372,21 +546,22 @@ class QueryBuilder {
|
|
|
372
546
|
arr.forEach((obj) => nested(obj));
|
|
373
547
|
return result;
|
|
374
548
|
}
|
|
375
|
-
buildQuery({ hasPagination = true, hasCount = false,
|
|
376
|
-
const queryBuilder = this.knex.queryBuilder();
|
|
549
|
+
buildQuery({ hasPagination = true, hasCount = false, }) {
|
|
377
550
|
const selectOnlyStructure = this.selector.select;
|
|
378
551
|
const structure = this.requestedFields;
|
|
379
552
|
const filter = this.selector.where ?? {};
|
|
380
553
|
const { orderBy: order, skip, take } = this.options ?? {};
|
|
381
554
|
const orderBy = this.transformOrderBy((order && !Array.isArray(order) ? [order] : order) ?? []);
|
|
555
|
+
const take_ = !isNaN(+take) ? +take : 15;
|
|
556
|
+
const skip_ = !isNaN(+skip) ? +skip : 0;
|
|
382
557
|
const rootKey = this.getStructureKeys(structure)[0];
|
|
383
558
|
const rootStructure = structure[rootKey];
|
|
384
|
-
const entity = this.getEntity(rootKey)
|
|
385
|
-
const rootEntity = entity.toLowerCase();
|
|
559
|
+
const entity = this.getEntity(rootKey);
|
|
560
|
+
const rootEntity = entity.ref.entity.toLowerCase();
|
|
386
561
|
const aliasMapping = {};
|
|
387
562
|
let hasTextSearch = false;
|
|
388
563
|
let textSearchQuery = null;
|
|
389
|
-
const searchQueryFilterProp = `${
|
|
564
|
+
const searchQueryFilterProp = `${rootKey}.q`;
|
|
390
565
|
if (searchQueryFilterProp in filter) {
|
|
391
566
|
if (!filter[searchQueryFilterProp]) {
|
|
392
567
|
delete filter[searchQueryFilterProp];
|
|
@@ -397,179 +572,109 @@ class QueryBuilder {
|
|
|
397
572
|
delete filter[searchQueryFilterProp];
|
|
398
573
|
}
|
|
399
574
|
}
|
|
400
|
-
const
|
|
575
|
+
const filterSortStructure = (0, utils_1.unflattenObjectKeys)({
|
|
576
|
+
...(this.rawConfig?.filters
|
|
577
|
+
? (0, utils_1.unflattenObjectKeys)(this.rawConfig?.filters)
|
|
578
|
+
: {}),
|
|
579
|
+
...orderBy,
|
|
580
|
+
})[rootKey] ?? {};
|
|
581
|
+
const joinParts = this.buildQueryParts(filterSortStructure, "", entity, rootKey, [], 0, aliasMapping);
|
|
401
582
|
const rootAlias = aliasMapping[rootKey];
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
583
|
+
const innerQueryBuilder = this.knex.queryBuilder();
|
|
584
|
+
// Outer query to select the full data based on the paginated IDs
|
|
585
|
+
const outerQueryBuilder = this.knex.queryBuilder();
|
|
586
|
+
innerQueryBuilder.distinct(`${rootAlias}.id`);
|
|
587
|
+
const orderBySelects = [];
|
|
588
|
+
const orderByClauses = [];
|
|
589
|
+
for (const aliasPath in orderBy) {
|
|
590
|
+
const path = aliasPath.split(".");
|
|
591
|
+
const field = path.pop();
|
|
592
|
+
const attr = path.join(".");
|
|
593
|
+
const alias = aliasMapping[attr];
|
|
594
|
+
const direction = orderBy[aliasPath];
|
|
595
|
+
const pgType = this.getPostgresCastType(attr, [field]);
|
|
596
|
+
const hasId = field === "id";
|
|
597
|
+
let orderExpression = `${rootAlias}.id ${direction}`;
|
|
598
|
+
if (alias) {
|
|
599
|
+
const aggregateAlias = `"${aliasPath}_agg"`;
|
|
600
|
+
let aggregateExpression = `(${alias}.data->>'${field}')${pgType.cast}`;
|
|
601
|
+
if (hasId) {
|
|
602
|
+
aggregateExpression = `${alias}.id`;
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
orderBySelects.push(direction === "ASC"
|
|
606
|
+
? this.knex.raw(`MIN(${aggregateExpression}) AS ${aggregateAlias}`)
|
|
607
|
+
: this.knex.raw(`MAX(${aggregateExpression}) AS ${aggregateAlias}`));
|
|
608
|
+
orderExpression = `${aggregateAlias} ${direction}`;
|
|
609
|
+
}
|
|
610
|
+
outerQueryBuilder.orderByRaw(`${aggregateExpression} ${direction}`);
|
|
611
|
+
}
|
|
612
|
+
orderByClauses.push(orderExpression);
|
|
613
|
+
}
|
|
614
|
+
// Add ordering columns to the select list of the inner query
|
|
615
|
+
if (orderBySelects.length > 0) {
|
|
616
|
+
innerQueryBuilder.select(orderBySelects);
|
|
617
|
+
}
|
|
618
|
+
innerQueryBuilder.from(`cat_${(0, normalze_table_name_1.normalizeTableName)(rootEntity)} AS ${this.getShortAlias(aliasMapping, rootKey)}`);
|
|
407
619
|
joinParts.forEach((joinPart) => {
|
|
408
|
-
|
|
620
|
+
innerQueryBuilder.joinRaw(joinPart);
|
|
409
621
|
});
|
|
410
|
-
let searchWhereParts = [];
|
|
411
622
|
if (hasTextSearch) {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
* Apply the search query to the search vector column for every joined tabled except
|
|
415
|
-
* the pivot joined table.
|
|
416
|
-
*/
|
|
417
|
-
searchWhereParts = [
|
|
418
|
-
`${this.getShortAlias(aliasMapping, rootEntity)}.${__classPrivateFieldGet(this, _QueryBuilder_searchVectorColumnName, "f")} @@ plainto_tsquery('simple', '${textSearchQuery}')`,
|
|
623
|
+
const searchWhereParts = [
|
|
624
|
+
`${rootAlias}.${__classPrivateFieldGet(this, _QueryBuilder_searchVectorColumnName, "f")} @@ plainto_tsquery('simple', ?)`,
|
|
419
625
|
...joinParts.flatMap((part) => {
|
|
420
626
|
const aliases = part
|
|
421
627
|
.split(" as ")
|
|
422
628
|
.flatMap((chunk) => chunk.split(" on "))
|
|
423
629
|
.filter((alias) => alias.startsWith('"t_') && !alias.includes("_ref"));
|
|
424
|
-
return aliases.map((alias) => `${alias}.${__classPrivateFieldGet(this, _QueryBuilder_searchVectorColumnName, "f")} @@ plainto_tsquery('simple',
|
|
630
|
+
return aliases.map((alias) => `${alias}.${__classPrivateFieldGet(this, _QueryBuilder_searchVectorColumnName, "f")} @@ plainto_tsquery('simple', ?)`);
|
|
425
631
|
}),
|
|
426
632
|
];
|
|
427
|
-
|
|
633
|
+
innerQueryBuilder.whereRaw(`(${searchWhereParts.join(" OR ")})`, Array(searchWhereParts.length).fill(textSearchQuery));
|
|
428
634
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
const path = aliasPath.split(".");
|
|
434
|
-
const field = path.pop();
|
|
435
|
-
const attr = path.join(".");
|
|
436
|
-
const pgType = this.getPostgresCastType(attr, [field]);
|
|
437
|
-
const alias = aliasMapping[attr];
|
|
438
|
-
const direction = orderBy[aliasPath];
|
|
439
|
-
queryBuilder.orderByRaw(`(${alias}.data->>'${field}')${pgType.cast}` + " " + direction);
|
|
635
|
+
this.parseWhere(aliasMapping, filter, innerQueryBuilder);
|
|
636
|
+
// Group by root ID in the inner query
|
|
637
|
+
if (orderBySelects.length > 0) {
|
|
638
|
+
innerQueryBuilder.groupBy(`${rootAlias}.id`);
|
|
440
639
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
let cte = "";
|
|
444
|
-
if (hasPagination) {
|
|
445
|
-
cte = this.buildCTEData({
|
|
446
|
-
hasCount,
|
|
447
|
-
searchWhereParts,
|
|
448
|
-
take: take_,
|
|
449
|
-
skip: skip_,
|
|
450
|
-
orderBy,
|
|
451
|
-
});
|
|
452
|
-
if (hasCount) {
|
|
453
|
-
queryBuilder.select(this.knex.raw("pd.count_total"));
|
|
454
|
-
}
|
|
455
|
-
queryBuilder.joinRaw(`JOIN paginated_data AS pd ON ${rootAlias}.id = pd.id`);
|
|
640
|
+
if (orderByClauses.length > 0) {
|
|
641
|
+
innerQueryBuilder.orderByRaw(orderByClauses.join(", "));
|
|
456
642
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
buildCTEData({ hasCount, searchWhereParts = [], skip, take, orderBy, }) {
|
|
460
|
-
const queryBuilder = this.knex.queryBuilder();
|
|
461
|
-
const hasWhere = (0, utils_1.isPresent)(this.rawConfig?.filters) || (0, utils_1.isPresent)(orderBy);
|
|
462
|
-
const structure = hasWhere && !searchWhereParts.length
|
|
463
|
-
? (0, utils_1.unflattenObjectKeys)({
|
|
464
|
-
...(this.rawConfig?.filters
|
|
465
|
-
? (0, utils_1.unflattenObjectKeys)(this.rawConfig?.filters)
|
|
466
|
-
: {}),
|
|
467
|
-
...orderBy,
|
|
468
|
-
})
|
|
469
|
-
: this.requestedFields;
|
|
470
|
-
const rootKey = this.getStructureKeys(structure)[0];
|
|
471
|
-
const rootStructure = structure[rootKey];
|
|
472
|
-
const entity = this.getEntity(rootKey).ref.entity;
|
|
473
|
-
const rootEntity = entity.toLowerCase();
|
|
474
|
-
const aliasMapping = {};
|
|
475
|
-
const joinParts = this.buildQueryParts(rootStructure, "", entity, rootKey, [], 0, aliasMapping);
|
|
476
|
-
const rootAlias = aliasMapping[rootKey];
|
|
477
|
-
queryBuilder.select(this.knex.raw(`${rootAlias}.id as id`));
|
|
478
|
-
queryBuilder.from(`cat_${rootEntity} AS ${this.getShortAlias(aliasMapping, rootEntity)}`);
|
|
479
|
-
if (hasWhere) {
|
|
480
|
-
joinParts.forEach((joinPart) => {
|
|
481
|
-
queryBuilder.joinRaw(joinPart);
|
|
482
|
-
});
|
|
483
|
-
if (searchWhereParts.length) {
|
|
484
|
-
queryBuilder.whereRaw(`(${searchWhereParts.join(" OR ")})`);
|
|
485
|
-
}
|
|
486
|
-
this.parseWhere(aliasMapping, this.selector.where, queryBuilder);
|
|
643
|
+
else {
|
|
644
|
+
innerQueryBuilder.orderBy(`${rootAlias}.id`, "ASC");
|
|
487
645
|
}
|
|
488
|
-
//
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
const direction = orderBy[aliasPath];
|
|
497
|
-
const orderAlias = `"${alias}.data->>'${field}'"`;
|
|
498
|
-
orderAliases.push(orderAlias + " " + direction);
|
|
499
|
-
// transform the order by clause to a select MIN/MAX
|
|
500
|
-
queryBuilder.select(direction === "ASC"
|
|
501
|
-
? this.knex.raw(`MIN((${alias}.data->>'${field}')${pgType.cast}) as ${orderAlias}`)
|
|
502
|
-
: this.knex.raw(`MAX((${alias}.data->>'${field}')${pgType.cast}) as ${orderAlias}`));
|
|
646
|
+
// Count query to estimate the number of results in parallel
|
|
647
|
+
let countQuery;
|
|
648
|
+
if (hasCount) {
|
|
649
|
+
const estimateQuery = innerQueryBuilder.clone();
|
|
650
|
+
estimateQuery.clearSelect().select(1);
|
|
651
|
+
estimateQuery.clearOrder();
|
|
652
|
+
estimateQuery.clearCounters();
|
|
653
|
+
countQuery = this.knex.raw(`SELECT count_estimate(?) AS estimate_count`, estimateQuery.toQuery());
|
|
503
654
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
655
|
+
// Apply pagination to the inner query
|
|
656
|
+
if (hasPagination) {
|
|
657
|
+
innerQueryBuilder.limit(take_);
|
|
658
|
+
if (skip_ > 0) {
|
|
659
|
+
innerQueryBuilder.offset(skip_);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
const innerQueryAlias = "paginated_ids";
|
|
663
|
+
outerQueryBuilder.from(`cat_${(0, normalze_table_name_1.normalizeTableName)(rootEntity)} AS ${this.getShortAlias(aliasMapping, rootKey)}`);
|
|
664
|
+
outerQueryBuilder.joinRaw(`INNER JOIN (${innerQueryBuilder.toQuery()}) AS ${innerQueryAlias} ON ${rootAlias}.id = ${innerQueryAlias}.id`);
|
|
665
|
+
this.parseWhere(aliasMapping, filter, outerQueryBuilder);
|
|
666
|
+
const joinPartsOuterQuery = this.buildQueryParts(rootStructure, "", entity, rootKey, [], 0, aliasMapping);
|
|
667
|
+
joinPartsOuterQuery.forEach((joinPart) => {
|
|
668
|
+
outerQueryBuilder.joinRaw(joinPart);
|
|
669
|
+
});
|
|
670
|
+
const finalSelectParts = this.buildSelectParts(selectOnlyStructure[rootKey], rootKey, aliasMapping);
|
|
671
|
+
outerQueryBuilder.select(finalSelectParts);
|
|
672
|
+
const finalSql = outerQueryBuilder.toQuery();
|
|
673
|
+
return {
|
|
674
|
+
sql: finalSql,
|
|
675
|
+
sqlCount: countQuery?.toQuery?.(),
|
|
676
|
+
};
|
|
520
677
|
}
|
|
521
|
-
// NOTE: We are keeping the bellow code for now as reference to alternative implementation for us. DO NOT REMOVE
|
|
522
|
-
// public buildQueryCount(): string {
|
|
523
|
-
// const queryBuilder = this.knex.queryBuilder()
|
|
524
|
-
// const hasWhere = isPresent(this.rawConfig?.filters)
|
|
525
|
-
// const structure = hasWhere ? this.rawConfig?.filters! : this.structure
|
|
526
|
-
// const rootKey = this.getStructureKeys(structure)[0]
|
|
527
|
-
// const rootStructure = structure[rootKey] as Select
|
|
528
|
-
// const entity = this.getEntity(rootKey)!.ref.entity
|
|
529
|
-
// const rootEntity = entity.toLowerCase()
|
|
530
|
-
// const aliasMapping: { [path: string]: string } = {}
|
|
531
|
-
// const joinParts = this.buildQueryParts(
|
|
532
|
-
// rootStructure,
|
|
533
|
-
// "",
|
|
534
|
-
// entity,
|
|
535
|
-
// rootKey,
|
|
536
|
-
// [],
|
|
537
|
-
// 0,
|
|
538
|
-
// aliasMapping
|
|
539
|
-
// )
|
|
540
|
-
// const rootAlias = aliasMapping[rootKey]
|
|
541
|
-
// queryBuilder.select(this.knex.raw(`COUNT(${rootAlias}.id) as count`))
|
|
542
|
-
// queryBuilder.from(
|
|
543
|
-
// `cat_${rootEntity} AS ${this.getShortAlias(aliasMapping, rootEntity)}`
|
|
544
|
-
// )
|
|
545
|
-
// const self = this
|
|
546
|
-
// if (hasWhere && joinParts.length) {
|
|
547
|
-
// const fromExistsRaw = joinParts.shift()!
|
|
548
|
-
// const [joinPartsExists, fromExistsPart] =
|
|
549
|
-
// fromExistsRaw.split(" left join ")
|
|
550
|
-
// const [fromExists, whereExists] = fromExistsPart.split(" on ")
|
|
551
|
-
// joinParts.unshift(joinPartsExists)
|
|
552
|
-
// queryBuilder.whereExists(function () {
|
|
553
|
-
// this.select(self.knex.raw(`1`))
|
|
554
|
-
// this.from(self.knex.raw(`${fromExists}`))
|
|
555
|
-
// this.joinRaw(joinParts.join("\n"))
|
|
556
|
-
// if (hasWhere) {
|
|
557
|
-
// self.parseWhere(aliasMapping, self.selector.where!, this)
|
|
558
|
-
// this.whereRaw(self.knex.raw(whereExists))
|
|
559
|
-
// return
|
|
560
|
-
// }
|
|
561
|
-
// this.whereRaw(self.knex.raw(whereExists))
|
|
562
|
-
// })
|
|
563
|
-
// } else {
|
|
564
|
-
// queryBuilder.whereExists(function () {
|
|
565
|
-
// this.select(self.knex.raw(`1`))
|
|
566
|
-
// if (hasWhere) {
|
|
567
|
-
// self.parseWhere(aliasMapping, self.selector.where!, this)
|
|
568
|
-
// }
|
|
569
|
-
// })
|
|
570
|
-
// }
|
|
571
|
-
// return queryBuilder.toQuery()
|
|
572
|
-
// }
|
|
573
678
|
buildObjectFromResultset(resultSet) {
|
|
574
679
|
const structure = this.structure;
|
|
575
680
|
const rootKey = this.getStructureKeys(structure)[0];
|