mythix-orm 1.8.3 → 1.10.2
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/lib/connection/connection-base.d.ts +1 -0
- package/lib/connection/connection-base.js +67 -0
- package/lib/connection/query-generator-base.js +11 -11
- package/lib/model.d.ts +17 -0
- package/lib/model.js +5 -0
- package/lib/query-engine/field-scope.js +2 -2
- package/lib/query-engine/model-scope.js +15 -15
- package/lib/query-engine/query-engine-base.js +107 -34
- package/lib/query-engine/query-engine.d.ts +29 -24
- package/lib/query-engine/query-engine.js +33 -22
- package/lib/types/virtual/models-type.js +1 -1
- package/lib/types/virtual/relational-type-base.js +2 -2
- package/lib/utils/model-utils.js +3 -2
- package/package.json +1 -1
|
@@ -81,6 +81,7 @@ declare class ConnectionBase extends EventEmitter {
|
|
|
81
81
|
public getOptions(): ConnectionBaseOptions;
|
|
82
82
|
public isStarted(): boolean;
|
|
83
83
|
public toQueryEngine(queryEngineLike: any): QueryEngine | undefined;
|
|
84
|
+
public finalizeQuery(operation: string, query: QueryEngine, options: GenericObject): Promise<QueryEngine>
|
|
84
85
|
public registerModel<T = ModelClass>(Model: T, options?: GenericObject): T;
|
|
85
86
|
public registerModels(models: Models | Array<ModelClass>, options?: GenericObject): Models | undefined;
|
|
86
87
|
public getContextValue(key: any, defaultValue?: any): any;
|
|
@@ -489,6 +489,73 @@ class ConnectionBase extends EventEmitter {
|
|
|
489
489
|
return queryEngine;
|
|
490
490
|
}
|
|
491
491
|
|
|
492
|
+
async finalizeQuery(crudOperation, queryEngine, options) {
|
|
493
|
+
if (!QueryEngine.isQuery(queryEngine))
|
|
494
|
+
return queryEngine;
|
|
495
|
+
|
|
496
|
+
const finalizeQueryForModel = async (query, parent, contextKey, depth) => {
|
|
497
|
+
let operations = query.getOperationStack();
|
|
498
|
+
|
|
499
|
+
// Has query already been finalized?
|
|
500
|
+
let lastOperation = operations[operations.length - 1];
|
|
501
|
+
if (lastOperation && Object.prototype.hasOwnProperty.call(lastOperation, '_queryFinalized') && lastOperation._queryFinalized)
|
|
502
|
+
return query;
|
|
503
|
+
|
|
504
|
+
let newQuery = query.clone();
|
|
505
|
+
let alreadyVisitedModels = new Set();
|
|
506
|
+
|
|
507
|
+
for (let i = 0, il = operations.length; i < il; i++) {
|
|
508
|
+
let operation = operations[i];
|
|
509
|
+
if (!Object.prototype.hasOwnProperty.call(operation, 'modelName'))
|
|
510
|
+
continue;
|
|
511
|
+
|
|
512
|
+
let modelName = operation.modelName;
|
|
513
|
+
if (alreadyVisitedModels.has(modelName))
|
|
514
|
+
continue;
|
|
515
|
+
|
|
516
|
+
alreadyVisitedModels.add(modelName);
|
|
517
|
+
|
|
518
|
+
let Model = operation.Model;
|
|
519
|
+
if (typeof Model.finalizeQuery !== 'function')
|
|
520
|
+
continue;
|
|
521
|
+
|
|
522
|
+
newQuery = await Model.finalizeQuery({
|
|
523
|
+
type: crudOperation,
|
|
524
|
+
query: newQuery,
|
|
525
|
+
queryDepth: depth,
|
|
526
|
+
operationIndex: i,
|
|
527
|
+
connection: this,
|
|
528
|
+
Model,
|
|
529
|
+
modelName,
|
|
530
|
+
operation,
|
|
531
|
+
operations,
|
|
532
|
+
parent,
|
|
533
|
+
contextKey,
|
|
534
|
+
options,
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
if (parent && contextKey)
|
|
538
|
+
parent[contextKey] = newQuery;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// Mark as finalized
|
|
542
|
+
newQuery.getOperationContext()._queryFinalized = true;
|
|
543
|
+
|
|
544
|
+
return newQuery;
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
let promises = [];
|
|
548
|
+
|
|
549
|
+
queryEngine.walk((query, parent, contextKey, depth) => {
|
|
550
|
+
promises.push(finalizeQueryForModel(query, parent, contextKey, depth));
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
if (promises.length > 0)
|
|
554
|
+
await Promise.all(promises);
|
|
555
|
+
|
|
556
|
+
return await finalizeQueryForModel(queryEngine, null, null, 0);
|
|
557
|
+
}
|
|
558
|
+
|
|
492
559
|
/// Register the provided model class.
|
|
493
560
|
///
|
|
494
561
|
/// This will register the provided model class with this
|
|
@@ -124,13 +124,13 @@ class QueryGeneratorBase {
|
|
|
124
124
|
// eslint-disable-next-line no-unused-vars
|
|
125
125
|
getAllModelsUsedInQuery(queryEngine, _options) {
|
|
126
126
|
let options = _options || {};
|
|
127
|
-
let queryEngineContextID = queryEngine.
|
|
127
|
+
let queryEngineContextID = queryEngine.getQueryID();
|
|
128
128
|
let cache = this.getOptionsCache(_options, `getAllModelsUsedInQuery.${queryEngineContextID}`);
|
|
129
129
|
if (cache)
|
|
130
130
|
return cache;
|
|
131
131
|
|
|
132
132
|
let Models = new Map();
|
|
133
|
-
let query = queryEngine.
|
|
133
|
+
let query = queryEngine.getOperationStack();
|
|
134
134
|
|
|
135
135
|
for (let i = 0, il = query.length; i < il; i++) {
|
|
136
136
|
let queryPart = query[i];
|
|
@@ -257,7 +257,7 @@ class QueryGeneratorBase {
|
|
|
257
257
|
}
|
|
258
258
|
|
|
259
259
|
getProjectionFromQueryEngine(queryEngine, options) {
|
|
260
|
-
let queryEngineContextID = queryEngine.
|
|
260
|
+
let queryEngineContextID = queryEngine.getQueryID();
|
|
261
261
|
let cache = this.getOptionsCache(options, `getProjectionFromQueryEngine.${queryEngineContextID}`);
|
|
262
262
|
if (cache)
|
|
263
263
|
return cache;
|
|
@@ -413,13 +413,13 @@ class QueryGeneratorBase {
|
|
|
413
413
|
return result;
|
|
414
414
|
};
|
|
415
415
|
|
|
416
|
-
let rawQueryContext = queryEngine.
|
|
416
|
+
let rawQueryContext = queryEngine.getOperationContext();
|
|
417
417
|
let RootModel = rawQueryContext.rootModel;
|
|
418
418
|
if (!RootModel)
|
|
419
419
|
throw new Error('QueryGeneratorBase::getProjectionFromQueryEngine: No root model found for query. Root model is required to generate a projection.');
|
|
420
420
|
|
|
421
421
|
let hasDistinct = rawQueryContext.distinct;
|
|
422
|
-
let projections = collectProjectionValuesFromQuery(RootModel, queryEngine.
|
|
422
|
+
let projections = collectProjectionValuesFromQuery(RootModel, queryEngine.getOperationStack());
|
|
423
423
|
let projectedFields = new Map();
|
|
424
424
|
let allModels = this.getAllModelsUsedInQuery(queryEngine, options);
|
|
425
425
|
let isAdding = true;
|
|
@@ -707,13 +707,13 @@ class QueryGeneratorBase {
|
|
|
707
707
|
|
|
708
708
|
// eslint-disable-next-line no-unused-vars
|
|
709
709
|
getOrderLimitOffset(queryEngine, options) {
|
|
710
|
-
let queryEngineContextID = queryEngine.
|
|
710
|
+
let queryEngineContextID = queryEngine.getQueryID();
|
|
711
711
|
let cache = this.getOptionsCache(options, `getOrderLimitOffset.${queryEngineContextID}`);
|
|
712
712
|
if (cache)
|
|
713
713
|
return cache;
|
|
714
714
|
|
|
715
|
-
let query = queryEngine.
|
|
716
|
-
let rootModel = queryEngine.
|
|
715
|
+
let query = queryEngine.getOperationStack();
|
|
716
|
+
let rootModel = queryEngine.getOperationContext().rootModel;
|
|
717
717
|
let limit;
|
|
718
718
|
let offset;
|
|
719
719
|
let order;
|
|
@@ -785,10 +785,10 @@ class QueryGeneratorBase {
|
|
|
785
785
|
}
|
|
786
786
|
|
|
787
787
|
getQuerySliceFromQueryPart(queryPart) {
|
|
788
|
-
let
|
|
789
|
-
let index =
|
|
788
|
+
let operationStack = queryPart.operationStack;
|
|
789
|
+
let index = operationStack.indexOf(queryPart);
|
|
790
790
|
|
|
791
|
-
return
|
|
791
|
+
return operationStack.slice(index);
|
|
792
792
|
}
|
|
793
793
|
|
|
794
794
|
_averageLiteralToString(literal, options) {
|
package/lib/model.d.ts
CHANGED
|
@@ -42,6 +42,21 @@ export declare interface IterateFieldsContext {
|
|
|
42
42
|
|
|
43
43
|
export declare type IterateFieldsCallback = (context: IterateFieldsContext) => any;
|
|
44
44
|
|
|
45
|
+
export declare interface FinalizeQueryContext {
|
|
46
|
+
type: 'create' | 'read' | 'update' | 'delete';
|
|
47
|
+
query: QueryEngine;
|
|
48
|
+
queryDepth: number;
|
|
49
|
+
connection: ConnectionBase;
|
|
50
|
+
Model: Model;
|
|
51
|
+
modelName: string;
|
|
52
|
+
operationIndex: number;
|
|
53
|
+
operation: GenericObject;
|
|
54
|
+
operations: Array<GenericObject>;
|
|
55
|
+
parent: GenericObject | null;
|
|
56
|
+
contextKey: string | null;
|
|
57
|
+
options: GenericObject | null;
|
|
58
|
+
}
|
|
59
|
+
|
|
45
60
|
export declare class Model {
|
|
46
61
|
declare public static fields: LooseFields | undefined;
|
|
47
62
|
declare public static _sortedFields: Array<Field> | null;
|
|
@@ -83,6 +98,8 @@ export declare class Model {
|
|
|
83
98
|
public static defaultScope(query: QueryEngine): QueryEngine;
|
|
84
99
|
public defaultScope(query: QueryEngine): QueryEngine;
|
|
85
100
|
|
|
101
|
+
public static finalizeQuery(context: FinalizeQueryContext): Promise<QueryEngine>;
|
|
102
|
+
|
|
86
103
|
public static getQueryEngine(connection?: ConnectionBase, options?: GenericObject): QueryEngine;
|
|
87
104
|
public getQueryEngine(connection?: ConnectionBase, options?: GenericObject): QueryEngine;
|
|
88
105
|
|
package/lib/model.js
CHANGED
|
@@ -673,6 +673,11 @@ class Model {
|
|
|
673
673
|
return this.constructor.defaultScope(queryEngine);
|
|
674
674
|
}
|
|
675
675
|
|
|
676
|
+
// eslint-disable-next-line no-unused-vars
|
|
677
|
+
static finalizeQuery({ type, query, queryDepth, operationIndex, operation, operations, parent, contextKey, options }) {
|
|
678
|
+
return query;
|
|
679
|
+
}
|
|
680
|
+
|
|
676
681
|
/// This method is called any time a `Model.where` or
|
|
677
682
|
/// `Model.$` property is accessed. It returns a query,
|
|
678
683
|
/// based off this model class (as the root model).
|
|
@@ -19,14 +19,14 @@ function addOperatorToQuery(name, inverseName, value, extraOptions) {
|
|
|
19
19
|
if (extraOptions)
|
|
20
20
|
conditionalParams = Object.assign(conditionalParams, extraOptions);
|
|
21
21
|
|
|
22
|
-
this.
|
|
22
|
+
this._pushOperationOntoStack(conditionalParams);
|
|
23
23
|
|
|
24
24
|
return this._fetchScope('model');
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
class FieldScope extends QueryEngineBase {
|
|
28
28
|
NOT = ProxyClass.autoCall(function() {
|
|
29
|
-
this.
|
|
29
|
+
this._pushOperationOntoStack({ logical: true, operator: 'NOT', not: !this.currentContext.not });
|
|
30
30
|
return this[ProxyClass.PROXY];
|
|
31
31
|
});
|
|
32
32
|
|
|
@@ -47,17 +47,17 @@ class ModelScope extends QueryEngineBase {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
NOT = ProxyClass.autoCall(function() {
|
|
50
|
-
this.
|
|
50
|
+
this._pushOperationOntoStack({ logical: true, operator: 'NOT', not: !this.currentContext.not });
|
|
51
51
|
return this._fetchScope('model');
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
AND = ProxyClass.autoCall(function(value) {
|
|
55
|
-
this.
|
|
55
|
+
this._pushOperationOntoStack({ logical: true, operator: 'AND', and: true, or: false, not: false, value });
|
|
56
56
|
return this._fetchScope('model');
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
OR = ProxyClass.autoCall(function(value) {
|
|
60
|
-
this.
|
|
60
|
+
this._pushOperationOntoStack({ logical: true, operator: 'OR', and: false, or: true, not: false, value });
|
|
61
61
|
return this._fetchScope('model');
|
|
62
62
|
});
|
|
63
63
|
|
|
@@ -67,7 +67,7 @@ class ModelScope extends QueryEngineBase {
|
|
|
67
67
|
throw new Error('QueryEngine::ModelScope::LIMIT: Value provided must be a valid positive number, or Infinity.');
|
|
68
68
|
|
|
69
69
|
value = Math.round(value);
|
|
70
|
-
this.
|
|
70
|
+
this._pushOperationOntoStack({ control: true, operator: 'LIMIT', value, limit: value });
|
|
71
71
|
|
|
72
72
|
return this._fetchScope('model');
|
|
73
73
|
}
|
|
@@ -78,7 +78,7 @@ class ModelScope extends QueryEngineBase {
|
|
|
78
78
|
throw new Error('QueryEngine::ModelScope::OFFSET: Value provided must be a valid positive number.');
|
|
79
79
|
|
|
80
80
|
value = Math.round(value);
|
|
81
|
-
this.
|
|
81
|
+
this._pushOperationOntoStack({ control: true, operator: 'OFFSET', value, offset: value });
|
|
82
82
|
|
|
83
83
|
return this._fetchScope('model');
|
|
84
84
|
}
|
|
@@ -96,7 +96,7 @@ class ModelScope extends QueryEngineBase {
|
|
|
96
96
|
return true;
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
this.
|
|
99
|
+
this._pushOperationOntoStack({ control: true, operator: 'ORDER', value: values, order: values });
|
|
100
100
|
return this._fetchScope('model');
|
|
101
101
|
}
|
|
102
102
|
|
|
@@ -125,7 +125,7 @@ class ModelScope extends QueryEngineBase {
|
|
|
125
125
|
return value;
|
|
126
126
|
}).filter(Boolean);
|
|
127
127
|
|
|
128
|
-
this.
|
|
128
|
+
this._pushOperationOntoStack({ control: true, operator: 'PROJECT', value: values });
|
|
129
129
|
return this._fetchScope('model');
|
|
130
130
|
}
|
|
131
131
|
|
|
@@ -134,7 +134,7 @@ class ModelScope extends QueryEngineBase {
|
|
|
134
134
|
let distinctValue = fullyQualifiedName;
|
|
135
135
|
|
|
136
136
|
if (arguments.length === 0) {
|
|
137
|
-
let context = this.
|
|
137
|
+
let context = this.getOperationContext();
|
|
138
138
|
let rootModel = context.rootModel;
|
|
139
139
|
if (!rootModel)
|
|
140
140
|
throw new Error(`${this.constructor.name}::DISTINCT: Attempted to apply DISTINCT to the root model of the query, but no root model was found.`);
|
|
@@ -150,32 +150,32 @@ class ModelScope extends QueryEngineBase {
|
|
|
150
150
|
currentQuery = this.PROJECT(`-${fullyQualifiedName}`);
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
currentQuery.
|
|
153
|
+
currentQuery._pushOperationOntoStack({ control: true, operator: 'DISTINCT', value: distinctValue, distinct: distinctValue });
|
|
154
154
|
return this._fetchScope('model');
|
|
155
155
|
});
|
|
156
156
|
|
|
157
157
|
INNER_JOIN = ProxyClass.autoCall(function() {
|
|
158
|
-
this.
|
|
158
|
+
this._pushOperationOntoStack({ control: true, operator: 'JOIN', value: 'inner', joinType: 'inner', joinOuter: false });
|
|
159
159
|
return this._fetchScope('model');
|
|
160
160
|
});
|
|
161
161
|
|
|
162
162
|
LEFT_JOIN = ProxyClass.autoCall(function(outerJoin) {
|
|
163
|
-
this.
|
|
163
|
+
this._pushOperationOntoStack({ control: true, operator: 'JOIN', value: 'left', joinType: 'left', joinOuter: !!outerJoin });
|
|
164
164
|
return this._fetchScope('model');
|
|
165
165
|
});
|
|
166
166
|
|
|
167
167
|
RIGHT_JOIN = ProxyClass.autoCall(function(outerJoin) {
|
|
168
|
-
this.
|
|
168
|
+
this._pushOperationOntoStack({ control: true, operator: 'JOIN', value: 'right', joinType: 'right', joinOuter: !!outerJoin });
|
|
169
169
|
return this._fetchScope('model');
|
|
170
170
|
});
|
|
171
171
|
|
|
172
172
|
FULL_JOIN = ProxyClass.autoCall(function(outerJoin) {
|
|
173
|
-
this.
|
|
173
|
+
this._pushOperationOntoStack({ control: true, operator: 'JOIN', value: 'full', joinType: 'full', joinOuter: !!outerJoin });
|
|
174
174
|
return this._fetchScope('model');
|
|
175
175
|
});
|
|
176
176
|
|
|
177
177
|
CROSS_JOIN = ProxyClass.autoCall(function() {
|
|
178
|
-
this.
|
|
178
|
+
this._pushOperationOntoStack({ control: true, operator: 'JOIN', value: 'cross', joinType: 'cross', joinOuter: false });
|
|
179
179
|
return this._fetchScope('model');
|
|
180
180
|
});
|
|
181
181
|
|
|
@@ -183,7 +183,7 @@ class ModelScope extends QueryEngineBase {
|
|
|
183
183
|
if (!(Nife.instanceOf(type, 'string') || LiteralBase.isLiteral(type)))
|
|
184
184
|
throw new Error('QueryEngine::ModelScope::JOIN: Invalid value provided. Value must be a valid string or Literal specifying JOIN type.');
|
|
185
185
|
|
|
186
|
-
this.
|
|
186
|
+
this._pushOperationOntoStack({ control: true, operator: 'JOIN', value: type, joinType: type, joinOuter: false });
|
|
187
187
|
return this._fetchScope('model');
|
|
188
188
|
}
|
|
189
189
|
}
|
|
@@ -27,7 +27,7 @@ class QueryEngineBase extends ProxyClass {
|
|
|
27
27
|
if (value._isQueryEngine)
|
|
28
28
|
return true;
|
|
29
29
|
|
|
30
|
-
if (typeof value.
|
|
30
|
+
if (typeof value.getOperationContext === 'function')
|
|
31
31
|
return true;
|
|
32
32
|
|
|
33
33
|
return false;
|
|
@@ -63,6 +63,10 @@ class QueryEngineBase extends ProxyClass {
|
|
|
63
63
|
return this.getQueryEngineScope().getFieldScopeClass();
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
getQueryEngineScopeClass() {
|
|
67
|
+
return this.getQueryEngineScope().constructor;
|
|
68
|
+
}
|
|
69
|
+
|
|
66
70
|
_inheritContext(context, name, ...args) {
|
|
67
71
|
let newContext = Object.assign(
|
|
68
72
|
Object.create(context),
|
|
@@ -82,7 +86,7 @@ class QueryEngineBase extends ProxyClass {
|
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
_fetchScope(...scopeNames) {
|
|
85
|
-
let context = this.
|
|
89
|
+
let context = this.getOperationContext();
|
|
86
90
|
|
|
87
91
|
for (let i = 0, il = scopeNames.length; i < il; i++) {
|
|
88
92
|
let scopeName = scopeNames[i];
|
|
@@ -149,7 +153,7 @@ class QueryEngineBase extends ProxyClass {
|
|
|
149
153
|
// We shouldn't add this scope if this is
|
|
150
154
|
// already the current model of the scope
|
|
151
155
|
if (context.Model !== Model)
|
|
152
|
-
context.
|
|
156
|
+
context.operationStack.push(newContext);
|
|
153
157
|
|
|
154
158
|
// But we always need to return the scope
|
|
155
159
|
// for the proxy to work properly
|
|
@@ -173,7 +177,7 @@ class QueryEngineBase extends ProxyClass {
|
|
|
173
177
|
// We shouldn't add this scope if this is
|
|
174
178
|
// already the current field of the scope
|
|
175
179
|
if (context.Field !== Field)
|
|
176
|
-
context.
|
|
180
|
+
context.operationStack.push(newContext);
|
|
177
181
|
|
|
178
182
|
// But we always need to return the scope
|
|
179
183
|
// for the proxy to work properly
|
|
@@ -193,8 +197,8 @@ class QueryEngineBase extends ProxyClass {
|
|
|
193
197
|
context.rootContext = context;
|
|
194
198
|
}
|
|
195
199
|
|
|
196
|
-
if (!context.
|
|
197
|
-
context.
|
|
200
|
+
if (!context.operationStack)
|
|
201
|
+
context.operationStack = [];
|
|
198
202
|
|
|
199
203
|
if (!('and' in context))
|
|
200
204
|
context.and = true;
|
|
@@ -204,19 +208,19 @@ class QueryEngineBase extends ProxyClass {
|
|
|
204
208
|
|
|
205
209
|
// console.log(`Creating new ${this.constructor.name} scope: `, context, Object.getPrototypeOf(context));
|
|
206
210
|
|
|
207
|
-
let
|
|
211
|
+
let operationStack = context.operationStack;
|
|
208
212
|
Object.defineProperties(this, {
|
|
209
|
-
|
|
213
|
+
operationStack: {
|
|
210
214
|
writable: false,
|
|
211
215
|
enumerable: false,
|
|
212
216
|
configurable: true,
|
|
213
|
-
value:
|
|
217
|
+
value: operationStack,
|
|
214
218
|
},
|
|
215
219
|
currentContext: {
|
|
216
220
|
enumerable: false,
|
|
217
221
|
configurable: true,
|
|
218
222
|
get: () => {
|
|
219
|
-
let currentContext =
|
|
223
|
+
let currentContext = operationStack[operationStack.length - 1];
|
|
220
224
|
return currentContext || context;
|
|
221
225
|
},
|
|
222
226
|
set: () => {},
|
|
@@ -224,20 +228,20 @@ class QueryEngineBase extends ProxyClass {
|
|
|
224
228
|
});
|
|
225
229
|
}
|
|
226
230
|
|
|
227
|
-
|
|
231
|
+
getQueryID() {
|
|
228
232
|
return this.currentContext.contextID;
|
|
229
233
|
}
|
|
230
234
|
|
|
231
|
-
|
|
235
|
+
getOperationContext() {
|
|
232
236
|
return this.currentContext;
|
|
233
237
|
}
|
|
234
238
|
|
|
235
|
-
|
|
236
|
-
return this.currentContext.
|
|
239
|
+
getOperationStack() {
|
|
240
|
+
return this.currentContext.operationStack;
|
|
237
241
|
}
|
|
238
242
|
|
|
239
|
-
|
|
240
|
-
let queryParts = this.
|
|
243
|
+
isLastOperationControl() {
|
|
244
|
+
let queryParts = this.getOperationStack();
|
|
241
245
|
let lastPart = queryParts[queryParts.length - 1];
|
|
242
246
|
|
|
243
247
|
if (Object.prototype.hasOwnProperty.call(lastPart, 'control') && lastPart.control === true)
|
|
@@ -246,8 +250,8 @@ class QueryEngineBase extends ProxyClass {
|
|
|
246
250
|
return false;
|
|
247
251
|
}
|
|
248
252
|
|
|
249
|
-
|
|
250
|
-
let queryParts = this.
|
|
253
|
+
isLastOperationCondition() {
|
|
254
|
+
let queryParts = this.getOperationStack();
|
|
251
255
|
let lastPart = queryParts[queryParts.length - 1];
|
|
252
256
|
|
|
253
257
|
if (Object.prototype.hasOwnProperty.call(lastPart, 'condition') && lastPart.condition === true)
|
|
@@ -256,13 +260,13 @@ class QueryEngineBase extends ProxyClass {
|
|
|
256
260
|
return false;
|
|
257
261
|
}
|
|
258
262
|
|
|
259
|
-
|
|
260
|
-
let context = this.
|
|
263
|
+
queryHasConditions() {
|
|
264
|
+
let context = this.getOperationContext();
|
|
261
265
|
return context.hasCondition;
|
|
262
266
|
}
|
|
263
267
|
|
|
264
|
-
|
|
265
|
-
let queryParts = this.
|
|
268
|
+
queryHasJoins() {
|
|
269
|
+
let queryParts = this.getOperationStack();
|
|
266
270
|
for (let i = 0, il = queryParts.length; i < il; i++) {
|
|
267
271
|
let queryPart = queryParts[i];
|
|
268
272
|
if (QueryEngineBase.isQuery(queryPart.value) && !queryPart.value.hasCondition)
|
|
@@ -272,8 +276,8 @@ class QueryEngineBase extends ProxyClass {
|
|
|
272
276
|
return false;
|
|
273
277
|
}
|
|
274
278
|
|
|
275
|
-
|
|
276
|
-
let query = this.
|
|
279
|
+
logQueryOperations() {
|
|
280
|
+
let query = this.getOperationStack();
|
|
277
281
|
for (let i = 0, il = query.length; i < il; i++) {
|
|
278
282
|
let queryPart = query[i];
|
|
279
283
|
let operator = queryPart.operator;
|
|
@@ -288,11 +292,11 @@ class QueryEngineBase extends ProxyClass {
|
|
|
288
292
|
|
|
289
293
|
}
|
|
290
294
|
|
|
291
|
-
|
|
292
|
-
let context = _context || this.
|
|
293
|
-
let
|
|
295
|
+
_pushOperationOntoStack(queryPart, _context) {
|
|
296
|
+
let context = _context || this.getOperationContext();
|
|
297
|
+
let operationStack = context.operationStack;
|
|
294
298
|
|
|
295
|
-
|
|
299
|
+
operationStack.push(
|
|
296
300
|
this._inheritContext(
|
|
297
301
|
context,
|
|
298
302
|
null,
|
|
@@ -327,14 +331,83 @@ class QueryEngineBase extends ProxyClass {
|
|
|
327
331
|
}
|
|
328
332
|
|
|
329
333
|
clone() {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
+
return this.map((part) => part)._fetchScope('model');
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
filter(callback) {
|
|
338
|
+
const Klass = this.getQueryEngineScopeClass();
|
|
339
|
+
let context = this.getOperationContext();
|
|
340
|
+
let parts = this.getOperationStack();
|
|
341
|
+
let query = new Klass({
|
|
342
|
+
...context.rootContext,
|
|
343
|
+
connection: this.getConnection(),
|
|
344
|
+
operationStack: [],
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
for (let i = 0, il = parts.length; i < il; i++) {
|
|
348
|
+
let part = parts[i];
|
|
349
|
+
if (!part)
|
|
350
|
+
continue;
|
|
351
|
+
|
|
352
|
+
if (!callback(part, i, parts, query))
|
|
353
|
+
continue;
|
|
354
|
+
|
|
355
|
+
query._pushOperationOntoStack({ ...part });
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return query;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
map(callback) {
|
|
362
|
+
const Klass = this.getQueryEngineScopeClass();
|
|
363
|
+
let context = this.getOperationContext();
|
|
364
|
+
let parts = this.getOperationStack();
|
|
365
|
+
let query = new Klass({
|
|
366
|
+
...context.rootContext,
|
|
367
|
+
connection: this.getConnection(),
|
|
368
|
+
operationStack: [],
|
|
369
|
+
});
|
|
334
370
|
|
|
335
|
-
|
|
371
|
+
for (let i = 0, il = parts.length; i < il; i++) {
|
|
372
|
+
let part = parts[i];
|
|
373
|
+
if (!part)
|
|
374
|
+
continue;
|
|
375
|
+
|
|
376
|
+
let newPart = callback({ ...part }, i, parts, query);
|
|
377
|
+
if (!newPart || typeof newPart !== 'object')
|
|
378
|
+
continue;
|
|
379
|
+
|
|
380
|
+
query._pushOperationOntoStack(newPart);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return query;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
walk(callback, _checkContextKeys) {
|
|
387
|
+
const walkQueries = (query, parent, contextKey, depth) => {
|
|
388
|
+
let parts = query.getOperationStack();
|
|
389
|
+
for (let i = 0, il = parts.length; i < il; i++) {
|
|
390
|
+
let part = parts[i];
|
|
391
|
+
if (!part)
|
|
392
|
+
continue;
|
|
393
|
+
|
|
394
|
+
for (let j = 0, jl = checkContextKeys.length; j < jl; j++) {
|
|
395
|
+
let contextKey = checkContextKeys[j];
|
|
396
|
+
if (!Object.prototype.hasOwnProperty.call(part, contextKey))
|
|
397
|
+
continue;
|
|
398
|
+
|
|
399
|
+
let value = part[contextKey];
|
|
400
|
+
if (value && this.constructor.isQuery(value))
|
|
401
|
+
walkQueries(value, part, contextKey, depth + 1);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (parent !== null)
|
|
406
|
+
callback(query, parent, contextKey, depth);
|
|
407
|
+
};
|
|
336
408
|
|
|
337
|
-
|
|
409
|
+
let checkContextKeys = _checkContextKeys || [ 'value' ];
|
|
410
|
+
walkQueries(this, null, null, 0);
|
|
338
411
|
}
|
|
339
412
|
}
|
|
340
413
|
|
|
@@ -6,14 +6,14 @@ import Field from '../field';
|
|
|
6
6
|
|
|
7
7
|
export declare interface QueryEngineOptions {
|
|
8
8
|
connection: ConnectionBase;
|
|
9
|
-
[
|
|
9
|
+
[key: string]: any;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export declare type QueryEngineClass = typeof QueryEngine;
|
|
13
13
|
|
|
14
14
|
export declare interface CallableInterface {
|
|
15
15
|
(...args: Array<any>): QueryEngine;
|
|
16
|
-
[
|
|
16
|
+
[key: string]: QueryEngine;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export declare class QueryEngine<T = ConnectionBase> {
|
|
@@ -31,33 +31,37 @@ export declare class QueryEngine<T = ConnectionBase> {
|
|
|
31
31
|
public _newModelScope(Model: ModelClass): QueryEngine;
|
|
32
32
|
public _newFieldScope(Field: Field): QueryEngine;
|
|
33
33
|
public constructor(context: QueryEngineOptions);
|
|
34
|
-
public
|
|
35
|
-
public
|
|
36
|
-
public
|
|
37
|
-
public
|
|
38
|
-
public
|
|
39
|
-
public
|
|
40
|
-
public
|
|
41
|
-
public
|
|
42
|
-
public
|
|
34
|
+
public getQueryID(): number;
|
|
35
|
+
public getOperationContext(): GenericObject;
|
|
36
|
+
public getOperationStack(): Array<GenericObject>;
|
|
37
|
+
public isLastOperationControl(): boolean;
|
|
38
|
+
public isLastOperationCondition(): boolean;
|
|
39
|
+
public queryHasConditions(): boolean;
|
|
40
|
+
public queryHasJoins(): boolean;
|
|
41
|
+
public logQueryOperations(): void;
|
|
42
|
+
public _pushOperationOntoStack(queryPart: GenericObject, context: GenericObject): void;
|
|
43
43
|
public getConnection(): ConnectionBase;
|
|
44
44
|
public getModel(modelName: string): ModelClass | undefined;
|
|
45
45
|
public getQueryEngineScope(): QueryEngine;
|
|
46
46
|
public getQueryEngineClass(): QueryEngineClass;
|
|
47
47
|
public clone(): QueryEngine;
|
|
48
|
+
public filter(callback: (operation: GenericObject, index: number, operations: Array<GenericObject>, query: QueryEngine) => GenericObject): QueryEngine;
|
|
49
|
+
public map(callback: (operation: GenericObject, index: number, operations: Array<GenericObject>, query: QueryEngine) => GenericObject): QueryEngine;
|
|
50
|
+
public walk(callback: (query: QueryEngine, parent: GenericObject | null, contextKey: string, depth: number) => GenericObject, checkContextKeys?: Array<string>): void;
|
|
48
51
|
|
|
49
52
|
// QueryEngine
|
|
50
53
|
public getModelScopeClass(): QueryEngineClass;
|
|
51
54
|
public getFieldScopeClass(): QueryEngineClass;
|
|
55
|
+
public getQueryEngineScopeClass(): QueryEngineClass;
|
|
52
56
|
public Model(modelName: string): QueryEngine;
|
|
53
57
|
public unscoped(context?: GenericObject): QueryEngine;
|
|
54
58
|
public toString(options?: GenericObject): string;
|
|
55
59
|
public MERGE(queryEngine: QueryEngine): QueryEngine;
|
|
56
60
|
public all<T extends Model = Model>(options?: GenericObject): Promise<Array<T>>;
|
|
57
|
-
public
|
|
61
|
+
public cursor<T extends Model = Model>(options?: GenericObject): AsyncGenerator<T>;
|
|
58
62
|
public first<T extends Model = Model>(limit?: number | null | undefined, options?: GenericObject): Promise<T | undefined>;
|
|
59
63
|
public last<T extends Model = Model>(limit?: number | null | undefined, options?: GenericObject): Promise<T | undefined>;
|
|
60
|
-
public
|
|
64
|
+
public updateAll<T extends Model = Model>(attributes: T | GenericObject, options?: GenericObject): Promise<number>;
|
|
61
65
|
public destroy(options?: GenericObject): Promise<number>;
|
|
62
66
|
public average(field: Field | string, options?: GenericObject): Promise<number>;
|
|
63
67
|
public count(field: Field | string, options?: GenericObject): Promise<number>;
|
|
@@ -66,6 +70,7 @@ export declare class QueryEngine<T = ConnectionBase> {
|
|
|
66
70
|
public sum(field: Field | string, options?: GenericObject): Promise<number>;
|
|
67
71
|
public pluck(fields: string | Array<string>, options?: GenericObject): Promise<Array<any>>;
|
|
68
72
|
public exists(options?: GenericObject): Promise<boolean>;
|
|
73
|
+
public finalizeQuery(operation: string, options: GenericObject): Promise<QueryEngine>;
|
|
69
74
|
|
|
70
75
|
// ModelScope
|
|
71
76
|
public _getField(fieldName: string): Field | undefined;
|
|
@@ -80,70 +85,70 @@ export declare class QueryEngine<T = ConnectionBase> {
|
|
|
80
85
|
(): QueryEngine;
|
|
81
86
|
|
|
82
87
|
name: QueryEngine;
|
|
83
|
-
[
|
|
88
|
+
[key: string]: QueryEngine;
|
|
84
89
|
};
|
|
85
90
|
|
|
86
91
|
declare public AND: {
|
|
87
92
|
(query: QueryEngine): QueryEngine;
|
|
88
93
|
|
|
89
94
|
name: QueryEngine;
|
|
90
|
-
[
|
|
95
|
+
[key: string]: QueryEngine;
|
|
91
96
|
};
|
|
92
97
|
|
|
93
98
|
declare public OR: {
|
|
94
99
|
(query: QueryEngine): QueryEngine;
|
|
95
100
|
|
|
96
101
|
name: QueryEngine;
|
|
97
|
-
[
|
|
102
|
+
[key: string]: QueryEngine;
|
|
98
103
|
};
|
|
99
104
|
|
|
100
105
|
declare public DISTINCT: {
|
|
101
106
|
(fullyQualifiedName: string | Field): QueryEngine;
|
|
102
107
|
|
|
103
108
|
name: QueryEngine;
|
|
104
|
-
[
|
|
109
|
+
[key: string]: QueryEngine;
|
|
105
110
|
};
|
|
106
111
|
|
|
107
112
|
declare public INNER_JOIN: {
|
|
108
113
|
(): QueryEngine;
|
|
109
114
|
|
|
110
115
|
name: QueryEngine;
|
|
111
|
-
[
|
|
116
|
+
[key: string]: QueryEngine;
|
|
112
117
|
};
|
|
113
118
|
|
|
114
119
|
declare public LEFT_JOIN: {
|
|
115
120
|
(): QueryEngine;
|
|
116
121
|
|
|
117
122
|
name: QueryEngine;
|
|
118
|
-
[
|
|
123
|
+
[key: string]: QueryEngine;
|
|
119
124
|
};
|
|
120
125
|
|
|
121
126
|
declare public RIGHT_JOIN: {
|
|
122
127
|
(): QueryEngine;
|
|
123
128
|
|
|
124
129
|
name: QueryEngine;
|
|
125
|
-
[
|
|
130
|
+
[key: string]: QueryEngine;
|
|
126
131
|
};
|
|
127
132
|
|
|
128
133
|
declare public FULL_JOIN: {
|
|
129
134
|
(): QueryEngine;
|
|
130
135
|
|
|
131
136
|
name: QueryEngine;
|
|
132
|
-
[
|
|
137
|
+
[key: string]: QueryEngine;
|
|
133
138
|
};
|
|
134
139
|
|
|
135
140
|
declare public CROSS_JOIN: {
|
|
136
141
|
(): QueryEngine;
|
|
137
142
|
|
|
138
143
|
name: QueryEngine;
|
|
139
|
-
[
|
|
144
|
+
[key: string]: QueryEngine;
|
|
140
145
|
};
|
|
141
146
|
|
|
142
147
|
declare public JOIN: {
|
|
143
148
|
(type: string | LiteralBase): QueryEngine;
|
|
144
149
|
|
|
145
150
|
name: QueryEngine;
|
|
146
|
-
[
|
|
151
|
+
[key: string]: QueryEngine;
|
|
147
152
|
};
|
|
148
153
|
|
|
149
154
|
// FieldScope
|
|
@@ -158,7 +163,7 @@ export declare class QueryEngine<T = ConnectionBase> {
|
|
|
158
163
|
public NOT_LIKE(value: string, options?: { caseSensitive: boolean }): QueryEngine;
|
|
159
164
|
|
|
160
165
|
name: QueryEngine;
|
|
161
|
-
[
|
|
166
|
+
[key: string]: any;
|
|
162
167
|
}
|
|
163
168
|
|
|
164
169
|
export class ModelScope extends QueryEngine { }
|
|
@@ -64,11 +64,11 @@ class QueryEngine extends QueryEngineBase {
|
|
|
64
64
|
if (!queryEngine)
|
|
65
65
|
return this;
|
|
66
66
|
|
|
67
|
-
let thisQueryContext = this.
|
|
67
|
+
let thisQueryContext = this.getOperationContext();
|
|
68
68
|
if (!QueryEngine.isQuery(queryEngine) && Nife.instanceOf(queryEngine, 'array', 'object', 'map', 'set'))
|
|
69
69
|
queryEngine = Utils.generateQueryFromFilter(this.getConnection(), thisQueryContext.rootModel, queryEngine);
|
|
70
70
|
|
|
71
|
-
let sourceQuery = queryEngine.
|
|
71
|
+
let sourceQuery = queryEngine.getOperationStack();
|
|
72
72
|
let currentModel = thisQueryContext.Model;
|
|
73
73
|
let skipLogicalOperators = true;
|
|
74
74
|
|
|
@@ -83,10 +83,11 @@ class QueryEngine extends QueryEngineBase {
|
|
|
83
83
|
'isQueryContext',
|
|
84
84
|
'modelContext',
|
|
85
85
|
'queryEngineScope',
|
|
86
|
-
'
|
|
86
|
+
'operationStack',
|
|
87
87
|
'rootContext',
|
|
88
88
|
'rootModel',
|
|
89
89
|
'rootModelName',
|
|
90
|
+
'_queryFinalized',
|
|
90
91
|
]);
|
|
91
92
|
|
|
92
93
|
// For merges, we want to skip the first logical operators
|
|
@@ -114,7 +115,7 @@ class QueryEngine extends QueryEngineBase {
|
|
|
114
115
|
}
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
this.
|
|
118
|
+
this._pushOperationOntoStack(Object.assign({
|
|
118
119
|
Model: queryPart.Model,
|
|
119
120
|
modelName: queryPart.modelName,
|
|
120
121
|
Field: queryPart.Field,
|
|
@@ -125,23 +126,25 @@ class QueryEngine extends QueryEngineBase {
|
|
|
125
126
|
return this;
|
|
126
127
|
}
|
|
127
128
|
|
|
128
|
-
all(options) {
|
|
129
|
+
async all(options) {
|
|
129
130
|
let connection = this.getConnection(options && options.connection);
|
|
130
131
|
|
|
131
132
|
if (options && options.stream)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
throw new TypeError('QueryEngine::all: "stream" option set to true. For streaming, please use the "cursor" method instead.');
|
|
134
|
+
|
|
135
|
+
return await Utils.collect(connection.select(await this.finalizeQuery('read', options), options));
|
|
135
136
|
}
|
|
136
137
|
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
async *cursor(_options) {
|
|
139
|
+
let options = _options || {};
|
|
140
|
+
let connection = this.getConnection(options && options.connection);
|
|
141
|
+
return yield *connection.select(await this.finalizeQuery('read', options), { ...options, stream: true });
|
|
139
142
|
}
|
|
140
143
|
|
|
141
144
|
async first(_limit, options) {
|
|
142
145
|
let limit = (_limit == null) ? 1 : _limit;
|
|
143
146
|
let connection = this.getConnection(options && options.connection);
|
|
144
|
-
let query = this.clone().LIMIT(limit);
|
|
147
|
+
let query = (await this.finalizeQuery('read', options)).clone().LIMIT(limit);
|
|
145
148
|
|
|
146
149
|
let result = await Utils.collect(connection.select(query, options));
|
|
147
150
|
return (_limit == null) ? result[0] : result;
|
|
@@ -150,55 +153,63 @@ class QueryEngine extends QueryEngineBase {
|
|
|
150
153
|
async last(_limit, options) {
|
|
151
154
|
let limit = (_limit == null) ? 1 : _limit;
|
|
152
155
|
let connection = this.getConnection(options && options.connection);
|
|
153
|
-
let query = this.clone().LIMIT(limit);
|
|
156
|
+
let query = (await this.finalizeQuery('read', options)).clone().LIMIT(limit);
|
|
154
157
|
|
|
155
158
|
let result = await Utils.collect(connection.select(query, Object.assign({}, options || {}, { reverseOrder: true })));
|
|
156
159
|
return (_limit == null) ? result[0] : result.reverse();
|
|
157
160
|
}
|
|
158
161
|
|
|
159
|
-
async
|
|
162
|
+
async updateAll(attributes, options) {
|
|
160
163
|
let connection = this.getConnection(options && options.connection);
|
|
161
|
-
return await connection.updateAll(this, attributes, options);
|
|
164
|
+
return await connection.updateAll(await this.finalizeQuery('update', options), attributes, options);
|
|
162
165
|
}
|
|
163
166
|
|
|
164
167
|
async destroy(options) {
|
|
165
168
|
let connection = this.getConnection(options && options.connection);
|
|
166
|
-
return await connection.destroy(this, options);
|
|
169
|
+
return await connection.destroy(await this.finalizeQuery('delete', options), options);
|
|
167
170
|
}
|
|
168
171
|
|
|
169
172
|
async average(field, options) {
|
|
170
173
|
let connection = this.getConnection(options && options.connection);
|
|
171
|
-
return await connection.average(this, field, options);
|
|
174
|
+
return await connection.average(await this.finalizeQuery('read', options), field, options);
|
|
172
175
|
}
|
|
173
176
|
|
|
174
177
|
async count(field, options) {
|
|
175
178
|
let connection = this.getConnection(options && options.connection);
|
|
176
|
-
return await connection.count(this, field, options);
|
|
179
|
+
return await connection.count(await this.finalizeQuery('read', options), field, options);
|
|
177
180
|
}
|
|
178
181
|
|
|
179
182
|
async min(field, options) {
|
|
180
183
|
let connection = this.getConnection(options && options.connection);
|
|
181
|
-
return await connection.min(this, field, options);
|
|
184
|
+
return await connection.min(await this.finalizeQuery('read', options), field, options);
|
|
182
185
|
}
|
|
183
186
|
|
|
184
187
|
async max(field, options) {
|
|
185
188
|
let connection = this.getConnection(options && options.connection);
|
|
186
|
-
return await connection.max(this, field, options);
|
|
189
|
+
return await connection.max(await this.finalizeQuery('read', options), field, options);
|
|
187
190
|
}
|
|
188
191
|
|
|
189
192
|
async sum(field, options) {
|
|
190
193
|
let connection = this.getConnection(options && options.connection);
|
|
191
|
-
return await connection.sum(this, field, options);
|
|
194
|
+
return await connection.sum(await this.finalizeQuery('read', options), field, options);
|
|
192
195
|
}
|
|
193
196
|
|
|
194
197
|
async pluck(fields, options) {
|
|
195
198
|
let connection = this.getConnection(options && options.connection);
|
|
196
|
-
return await connection.pluck(this, fields, options);
|
|
199
|
+
return await connection.pluck(await this.finalizeQuery('read', options), fields, options);
|
|
197
200
|
}
|
|
198
201
|
|
|
199
202
|
async exists(options) {
|
|
200
203
|
let connection = this.getConnection(options && options.connection);
|
|
201
|
-
return await connection.exists(this, options);
|
|
204
|
+
return await connection.exists(await this.finalizeQuery('read', options), options);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async finalizeQuery(crudOperation, options) {
|
|
208
|
+
let connection = this.getConnection();
|
|
209
|
+
if (connection && typeof connection.finalizeQuery === 'function')
|
|
210
|
+
return await connection.finalizeQuery(crudOperation, this, options);
|
|
211
|
+
|
|
212
|
+
return this;
|
|
202
213
|
}
|
|
203
214
|
|
|
204
215
|
[ProxyClass.MISSING](target, prop) {
|
|
@@ -125,7 +125,7 @@ const TYPE_OPERATIONS = {
|
|
|
125
125
|
'get': function({ field, type }, userQuery, options, ...args) {
|
|
126
126
|
const doGet = async function*() {
|
|
127
127
|
let query = await type.prepareQuery({ connection: null, self: this, field, options }, [ userQuery ].concat(args));
|
|
128
|
-
let results = query.
|
|
128
|
+
let results = query.cursor(options);
|
|
129
129
|
let primaryModelRelationalArray = [];
|
|
130
130
|
|
|
131
131
|
this[field.fieldName] = primaryModelRelationalArray;
|
|
@@ -170,7 +170,7 @@ class RelationalTypeBase extends Type {
|
|
|
170
170
|
let PrimaryModel = (context.self && context.self.getModel());
|
|
171
171
|
let primaryModelName = PrimaryModel.getModelName();
|
|
172
172
|
let query = await this.prepareQuery(Object.assign({ connection }, context), args);
|
|
173
|
-
let queryParts = query.
|
|
173
|
+
let queryParts = query.getOperationStack();
|
|
174
174
|
let queryContext = (queryParts[queryParts.length - 1] || {});
|
|
175
175
|
let TargetModel = queryContext.rootModel;
|
|
176
176
|
let TargetField = queryContext.rootField;
|
|
@@ -186,7 +186,7 @@ class RelationalTypeBase extends Type {
|
|
|
186
186
|
let rightQueryContext = null;
|
|
187
187
|
|
|
188
188
|
if (QueryEngine.isQuery(conditionValue)) {
|
|
189
|
-
rightQueryContext = conditionValue.
|
|
189
|
+
rightQueryContext = conditionValue.getOperationContext();
|
|
190
190
|
if (rightQueryContext.condition)
|
|
191
191
|
continue;
|
|
192
192
|
} else {
|
package/lib/utils/model-utils.js
CHANGED
|
@@ -9,8 +9,9 @@ function isUUID(value) {
|
|
|
9
9
|
return UUID.validate(value);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
function sanitizeFieldString(
|
|
13
|
-
|
|
12
|
+
function sanitizeFieldString(_str) {
|
|
13
|
+
let str = (typeof _str === 'symbol') ? (_str.toString()) : (_str + '');
|
|
14
|
+
return str.replace(/[^\w:.]+/g, '').replace(/([:.])+/g, '$1');
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
/// Parse a fully qualified field name.
|