mythix-orm-sql-base 1.7.3 → 1.8.0
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.
|
@@ -10,10 +10,14 @@ const {
|
|
|
10
10
|
Model: ModelBase,
|
|
11
11
|
} = require('mythix-orm');
|
|
12
12
|
|
|
13
|
+
const SQLQueryGeneratorBase = require('./sql-query-generator-base');
|
|
14
|
+
|
|
13
15
|
const SAVE_POINT_NAME_CHARS = [ 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' ];
|
|
14
16
|
const MODEL_RELATIONS = Symbol.for('_mythixModelRelations');
|
|
15
17
|
|
|
16
18
|
class SQLConnectionBase extends ConnectionBase {
|
|
19
|
+
static DefaultQueryGenerator = SQLQueryGeneratorBase;
|
|
20
|
+
|
|
17
21
|
prepareArrayValuesForSQL(_array) {
|
|
18
22
|
let array = Nife.arrayFlatten(_array);
|
|
19
23
|
|
|
@@ -85,7 +89,17 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
85
89
|
return (!parts.length) ? null : parts.join(',');
|
|
86
90
|
};
|
|
87
91
|
|
|
88
|
-
|
|
92
|
+
const isEmptyModel = (model) => {
|
|
93
|
+
if (!model)
|
|
94
|
+
return true;
|
|
95
|
+
|
|
96
|
+
if (model._mythixIsEmpty === false)
|
|
97
|
+
return false;
|
|
98
|
+
|
|
99
|
+
return true;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
let context = queryEngine.getOperationContext();
|
|
89
103
|
let fields = this.findAllFieldsFromFieldProjectionMap(columns);
|
|
90
104
|
let rootModelName = context.rootModelName;
|
|
91
105
|
let modelData = {};
|
|
@@ -140,16 +154,31 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
140
154
|
if (!dataContext)
|
|
141
155
|
dataContext = data[modelName] = {};
|
|
142
156
|
|
|
157
|
+
// Track empty models (can happen for left or right table joins)
|
|
158
|
+
if (remoteValue != null && !Object.prototype.hasOwnProperty.call(dataContext, '_mythixIsEmpty')) {
|
|
159
|
+
Object.defineProperties(dataContext, {
|
|
160
|
+
'_mythixIsEmpty': {
|
|
161
|
+
writable: true,
|
|
162
|
+
enumerable: false,
|
|
163
|
+
configurable: true,
|
|
164
|
+
value: false,
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
143
169
|
dataContext[field.fieldName] = remoteValue;
|
|
144
170
|
}
|
|
145
171
|
|
|
146
172
|
let rootModel;
|
|
147
173
|
for (let j = 0, jl = modelNames.length; j < jl; j++) {
|
|
148
|
-
let modelName
|
|
149
|
-
let
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
174
|
+
let modelName = modelNames[j];
|
|
175
|
+
let model = data[modelName];
|
|
176
|
+
if (isEmptyModel(model))
|
|
177
|
+
continue;
|
|
178
|
+
|
|
179
|
+
let info = modelInfo[modelName];
|
|
180
|
+
let models = modelData[modelName];
|
|
181
|
+
let pkFieldName = info.pkFieldName;
|
|
153
182
|
let index;
|
|
154
183
|
|
|
155
184
|
if (!models)
|
|
@@ -209,7 +238,7 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
209
238
|
if (Nife.isEmpty(modelDataMap))
|
|
210
239
|
return [];
|
|
211
240
|
|
|
212
|
-
let queryContext = queryEngine.
|
|
241
|
+
let queryContext = queryEngine.getOperationContext();
|
|
213
242
|
let rootModelName = queryContext.rootModelName;
|
|
214
243
|
let RootModel = queryContext.rootModel;
|
|
215
244
|
if (!rootModelName || !RootModel)
|
|
@@ -373,6 +402,7 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
373
402
|
throw new Error(`${this.constructor.name}::update: Model's primary key is empty. Models being updated must have a valid primary key.`);
|
|
374
403
|
|
|
375
404
|
query = query[primaryKeyFieldName].EQ(pkFieldValue);
|
|
405
|
+
query = await this.finalizeQuery('update', query, options);
|
|
376
406
|
|
|
377
407
|
let sqlStr = queryGenerator.generateUpdateStatement(Model, model, query, options);
|
|
378
408
|
if (!sqlStr)
|
|
@@ -394,11 +424,13 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
394
424
|
if (!queryEngine)
|
|
395
425
|
throw new Error(`${this.constructor.name}::updateAll: Model class or query is required to update.`);
|
|
396
426
|
|
|
397
|
-
let
|
|
427
|
+
let options = Object.assign({}, _options || {}, { isUpdateOperation: true });
|
|
428
|
+
queryEngine = await this.finalizeQuery('update', queryEngine, options);
|
|
429
|
+
|
|
430
|
+
let rootModel = queryEngine.getOperationContext().rootModel;
|
|
398
431
|
if (!rootModel)
|
|
399
432
|
throw new Error(`${this.constructor.name}::updateAll: Root model not found, and is required to update.`);
|
|
400
433
|
|
|
401
|
-
let options = Object.assign({}, _options || {}, { isUpdateOperation: true });
|
|
402
434
|
let queryGenerator = this.getQueryGenerator();
|
|
403
435
|
let sqlStr = queryGenerator.generateUpdateStatement(rootModel, model, queryEngine, options);
|
|
404
436
|
|
|
@@ -416,8 +448,9 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
416
448
|
if (options.truncate !== true)
|
|
417
449
|
return;
|
|
418
450
|
|
|
451
|
+
let query = await this.finalizeQuery('delete', Model.where(this).unscoped(), options);
|
|
419
452
|
let queryGenerator = this.getQueryGenerator();
|
|
420
|
-
let sqlStr = queryGenerator.generateDeleteStatement(Model,
|
|
453
|
+
let sqlStr = queryGenerator.generateDeleteStatement(Model, query, options);
|
|
421
454
|
|
|
422
455
|
return await this.query(sqlStr, options);
|
|
423
456
|
}
|
|
@@ -453,7 +486,8 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
453
486
|
if (Nife.isEmpty(pkIDs))
|
|
454
487
|
return;
|
|
455
488
|
|
|
456
|
-
let
|
|
489
|
+
let query = await this.finalizeQuery('delete', Model.where(this).id.EQ(pkIDs), options);
|
|
490
|
+
let sqlStr = queryGenerator.generateDeleteStatement(Model, query);
|
|
457
491
|
if (!sqlStr)
|
|
458
492
|
return;
|
|
459
493
|
|
|
@@ -478,11 +512,13 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
478
512
|
if (!queryEngine)
|
|
479
513
|
throw new Error(`${this.constructor.name}::destroy: Model class or query is required to destroy.`);
|
|
480
514
|
|
|
481
|
-
let
|
|
515
|
+
let options = modelsOrOptions || {};
|
|
516
|
+
queryEngine = await this.finalizeQuery('delete', queryEngine, options);
|
|
517
|
+
|
|
518
|
+
let rootModel = queryEngine.getOperationContext().rootModel;
|
|
482
519
|
if (!rootModel)
|
|
483
520
|
throw new Error(`${this.constructor.name}::destroy: Root model not found, and is required to destroy.`);
|
|
484
521
|
|
|
485
|
-
let options = modelsOrOptions || {};
|
|
486
522
|
let queryGenerator = this.getQueryGenerator();
|
|
487
523
|
let sqlStr = queryGenerator.generateDeleteStatement(rootModel, queryEngine, options);
|
|
488
524
|
return await this.query(sqlStr, options);
|
|
@@ -500,8 +536,10 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
500
536
|
throw new TypeError(`${this.constructor.name}::select: First argument must be a model class or a query.`);
|
|
501
537
|
}
|
|
502
538
|
|
|
503
|
-
let
|
|
504
|
-
|
|
539
|
+
let options = _options || {};
|
|
540
|
+
queryEngine = await this.finalizeQuery('read', queryEngine, options);
|
|
541
|
+
|
|
542
|
+
let queryContext = queryEngine.getOperationContext();
|
|
505
543
|
let batchSize = options.batchSize || 500;
|
|
506
544
|
let startIndex = queryContext.offset || 0;
|
|
507
545
|
let queryGenerator = this.getQueryGenerator();
|
|
@@ -549,9 +587,10 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
549
587
|
if (!queryEngine)
|
|
550
588
|
throw new TypeError(`${this.constructor.name}::aggregate: First argument must be a model class or a query.`);
|
|
551
589
|
|
|
590
|
+
queryEngine = await this.finalizeQuery('read', queryEngine, options);
|
|
552
591
|
queryEngine = queryEngine.clone();
|
|
553
592
|
|
|
554
|
-
let queryContext = queryEngine.
|
|
593
|
+
let queryContext = queryEngine.getOperationContext();
|
|
555
594
|
let distinct = queryContext.distinct;
|
|
556
595
|
if (distinct) {
|
|
557
596
|
let fullyQualifiedFieldName = distinct.getFullyQualifiedFieldName();
|
|
@@ -586,7 +625,7 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
586
625
|
if (!queryEngine)
|
|
587
626
|
throw new TypeError(`${this.constructor.name}::average: First argument must be a model class or a query.`);
|
|
588
627
|
|
|
589
|
-
let rootModel = queryEngine.
|
|
628
|
+
let rootModel = queryEngine.getOperationContext().rootModel;
|
|
590
629
|
let field = Utils.fieldToFullyQualifiedName(_field, rootModel);
|
|
591
630
|
|
|
592
631
|
return await this.aggregate(queryEngine, new Literals.AverageLiteral(field), options);
|
|
@@ -597,7 +636,9 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
597
636
|
if (!queryEngine)
|
|
598
637
|
throw new TypeError(`${this.constructor.name}::count: First argument must be a model class or a query.`);
|
|
599
638
|
|
|
600
|
-
|
|
639
|
+
queryEngine = await this.finalizeQuery('read', queryEngine, options);
|
|
640
|
+
|
|
641
|
+
let rootModel = queryEngine.getOperationContext().rootModel;
|
|
601
642
|
let field = (_field) ? Utils.fieldToFullyQualifiedName(_field, rootModel) : null;
|
|
602
643
|
|
|
603
644
|
return await this.aggregate(queryEngine, new Literals.CountLiteral(field), options);
|
|
@@ -608,7 +649,9 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
608
649
|
if (!queryEngine)
|
|
609
650
|
throw new TypeError(`${this.constructor.name}::min: First argument must be a model class or a query.`);
|
|
610
651
|
|
|
611
|
-
|
|
652
|
+
queryEngine = await this.finalizeQuery('read', queryEngine, options);
|
|
653
|
+
|
|
654
|
+
let rootModel = queryEngine.getOperationContext().rootModel;
|
|
612
655
|
let field = Utils.fieldToFullyQualifiedName(_field, rootModel);
|
|
613
656
|
|
|
614
657
|
return await this.aggregate(queryEngine, new Literals.MinLiteral(field), options);
|
|
@@ -619,7 +662,9 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
619
662
|
if (!queryEngine)
|
|
620
663
|
throw new TypeError(`${this.constructor.name}::max: First argument must be a model class or a query.`);
|
|
621
664
|
|
|
622
|
-
|
|
665
|
+
queryEngine = await this.finalizeQuery('read', queryEngine, options);
|
|
666
|
+
|
|
667
|
+
let rootModel = queryEngine.getOperationContext().rootModel;
|
|
623
668
|
let field = Utils.fieldToFullyQualifiedName(_field, rootModel);
|
|
624
669
|
|
|
625
670
|
return await this.aggregate(queryEngine, new Literals.MaxLiteral(field), options);
|
|
@@ -630,7 +675,9 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
630
675
|
if (!queryEngine)
|
|
631
676
|
throw new TypeError(`${this.constructor.name}::sum: First argument must be a model class or a query.`);
|
|
632
677
|
|
|
633
|
-
|
|
678
|
+
queryEngine = await this.finalizeQuery('read', queryEngine, options);
|
|
679
|
+
|
|
680
|
+
let rootModel = queryEngine.getOperationContext().rootModel;
|
|
634
681
|
let field = Utils.fieldToFullyQualifiedName(_field, rootModel);
|
|
635
682
|
|
|
636
683
|
return await this.aggregate(queryEngine, new Literals.SumLiteral(field), options);
|
|
@@ -658,7 +705,9 @@ class SQLConnectionBase extends ConnectionBase {
|
|
|
658
705
|
throw new TypeError(`${this.constructor.name}::pluck: First argument must be a model class or a query.`);
|
|
659
706
|
}
|
|
660
707
|
|
|
661
|
-
|
|
708
|
+
queryEngine = await this.finalizeQuery('read', queryEngine, options);
|
|
709
|
+
|
|
710
|
+
let queryContext = queryEngine.getOperationContext();
|
|
662
711
|
let rootModel = queryContext.rootModel;
|
|
663
712
|
let rootModelName = rootModel.getModelName();
|
|
664
713
|
|
|
@@ -227,7 +227,7 @@ class SQLQueryGeneratorBase extends QueryGeneratorBase {
|
|
|
227
227
|
let sqlOperator = this.generateSelectQueryOperatorFromQueryEngineOperator(queryPart, operator, value, false, options);
|
|
228
228
|
|
|
229
229
|
if (QueryEngine.isQuery(value)) {
|
|
230
|
-
if (!value.
|
|
230
|
+
if (!value.queryHasConditions())
|
|
231
231
|
return '';
|
|
232
232
|
|
|
233
233
|
if (sqlOperator === '=')
|
|
@@ -339,7 +339,7 @@ class SQLQueryGeneratorBase extends QueryGeneratorBase {
|
|
|
339
339
|
items.push(joinInfo);
|
|
340
340
|
};
|
|
341
341
|
|
|
342
|
-
let query = queryEngine.
|
|
342
|
+
let query = queryEngine.getOperationStack();
|
|
343
343
|
let joins = new Map();
|
|
344
344
|
|
|
345
345
|
for (let i = 0, il = query.length; i < il; i++) {
|
|
@@ -353,11 +353,11 @@ class SQLQueryGeneratorBase extends QueryGeneratorBase {
|
|
|
353
353
|
|
|
354
354
|
// If the query has a condition, then it is a sub-query
|
|
355
355
|
// not a join
|
|
356
|
-
if (operatorValue.
|
|
356
|
+
if (operatorValue.getOperationContext().condition)
|
|
357
357
|
continue;
|
|
358
358
|
|
|
359
359
|
let joinType = this.generateSQLJoinTypeFromQueryEngineJoinType(queryPart.joinType, queryPart.joinOuter, options);
|
|
360
|
-
let joinInfo = this.getJoinTableInfoFromQueryContexts(queryPart, operatorValue.
|
|
360
|
+
let joinInfo = this.getJoinTableInfoFromQueryContexts(queryPart, operatorValue.getOperationContext(), joinType, options);
|
|
361
361
|
|
|
362
362
|
addToJoins(joinInfo);
|
|
363
363
|
}
|
|
@@ -391,7 +391,7 @@ class SQLQueryGeneratorBase extends QueryGeneratorBase {
|
|
|
391
391
|
return '';
|
|
392
392
|
};
|
|
393
393
|
|
|
394
|
-
let query = queryEngine.
|
|
394
|
+
let query = queryEngine.getOperationStack();
|
|
395
395
|
let sqlParts = [];
|
|
396
396
|
let hasValue = false;
|
|
397
397
|
|
|
@@ -590,7 +590,7 @@ class SQLQueryGeneratorBase extends QueryGeneratorBase {
|
|
|
590
590
|
if (options.includeRelations === true)
|
|
591
591
|
queryEngine = queryEngine.clone().PROJECT('*');
|
|
592
592
|
|
|
593
|
-
let rootModel = queryEngine.
|
|
593
|
+
let rootModel = queryEngine.getOperationContext().rootModel;
|
|
594
594
|
if (!rootModel)
|
|
595
595
|
throw new Error(`${this.constructor.name}::generateSelectStatement: No root model found.`);
|
|
596
596
|
|
|
@@ -1138,8 +1138,8 @@ class SQLQueryGeneratorBase extends QueryGeneratorBase {
|
|
|
1138
1138
|
}
|
|
1139
1139
|
|
|
1140
1140
|
let escapedTableName = this.getEscapedTableName(Model, options);
|
|
1141
|
-
if (queryEngine && queryEngine.
|
|
1142
|
-
if (queryEngine.
|
|
1141
|
+
if (queryEngine && queryEngine.queryHasConditions()) {
|
|
1142
|
+
if (queryEngine.queryHasJoins()) {
|
|
1143
1143
|
let pkField = Model.getPrimaryKeyField();
|
|
1144
1144
|
if (!pkField)
|
|
1145
1145
|
throw new Error(`${this.constructor.name}::generateDeleteStatement: Can not delete using table joins on a table with no primary key field.`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mythix-orm-sql-base",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "SQL base support for Mythix ORM",
|
|
5
5
|
"main": "lib/index",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"homepage": "https://github.com/th317erd/mythix-orm-sql-base#readme",
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"mythix-orm": "^1.
|
|
36
|
+
"mythix-orm": "^1.10.2"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"luxon": "^3.1.0",
|