@abedmurrar/objection 4.0.0-alpha.0 → 4.0.0-beta.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.
- package/README.md +103 -67
- package/lib/index.mjs +6 -0
- package/lib/initialize.js +6 -9
- package/lib/model/AjvValidator.js +235 -282
- package/lib/model/Model.js +653 -823
- package/lib/model/ModifierNotFoundError.js +5 -7
- package/lib/model/NotFoundError.js +14 -18
- package/lib/model/RelationDoesNotExistError.js +6 -9
- package/lib/model/ValidationError.js +33 -41
- package/lib/model/Validator.js +15 -21
- package/lib/model/getModel.js +1 -3
- package/lib/model/graph/ModelGraph.js +44 -64
- package/lib/model/graph/ModelGraphBuilder.js +164 -217
- package/lib/model/graph/ModelGraphEdge.js +31 -43
- package/lib/model/graph/ModelGraphNode.js +192 -231
- package/lib/model/inheritModel.js +9 -18
- package/lib/model/modelBindKnex.js +48 -62
- package/lib/model/modelClone.js +79 -98
- package/lib/model/modelColPropMap.js +16 -26
- package/lib/model/modelConcurrency.js +24 -0
- package/lib/model/modelId.js +44 -49
- package/lib/model/modelJsonAttributes.js +56 -76
- package/lib/model/modelParseRelations.js +68 -67
- package/lib/model/modelQueryProps.js +76 -107
- package/lib/model/modelSet.js +92 -112
- package/lib/model/modelTableMetadata.js +60 -72
- package/lib/model/modelToJson.js +120 -150
- package/lib/model/modelUtils.js +30 -37
- package/lib/model/modelValidate.js +34 -42
- package/lib/model/modelValues.js +78 -91
- package/lib/model/modelVisitor.js +22 -29
- package/lib/objection.js +42 -67
- package/lib/queryBuilder/FunctionBuilder.js +231 -279
- package/lib/queryBuilder/InternalOptions.js +19 -24
- package/lib/queryBuilder/JoinBuilder.js +116 -149
- package/lib/queryBuilder/QueryBuilder.js +1009 -1271
- package/lib/queryBuilder/QueryBuilderBase.js +647 -865
- package/lib/queryBuilder/QueryBuilderContext.js +14 -21
- package/lib/queryBuilder/QueryBuilderContextBase.js +20 -29
- package/lib/queryBuilder/QueryBuilderOperationSupport.js +462 -536
- package/lib/queryBuilder/QueryBuilderUserContext.js +19 -25
- package/lib/queryBuilder/RawBuilder.js +58 -73
- package/lib/queryBuilder/ReferenceBuilder.js +232 -270
- package/lib/queryBuilder/RelationExpression.js +322 -380
- package/lib/queryBuilder/StaticHookArguments.js +94 -106
- package/lib/queryBuilder/ValueBuilder.js +100 -112
- package/lib/queryBuilder/expressions.js +86 -116
- package/lib/queryBuilder/functions/mysql.js +642 -697
- package/lib/queryBuilder/graph/GraphAction.js +44 -59
- package/lib/queryBuilder/graph/GraphData.js +7 -9
- package/lib/queryBuilder/graph/GraphFetcher.js +115 -151
- package/lib/queryBuilder/graph/GraphNodeDbExistence.js +114 -152
- package/lib/queryBuilder/graph/GraphOperation.js +16 -22
- package/lib/queryBuilder/graph/GraphOptions.js +143 -185
- package/lib/queryBuilder/graph/GraphUpsert.js +167 -241
- package/lib/queryBuilder/graph/delete/GraphDelete.js +8 -13
- package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +44 -62
- package/lib/queryBuilder/graph/insert/GraphInsert.js +99 -128
- package/lib/queryBuilder/graph/insert/GraphInsertAction.js +151 -193
- package/lib/queryBuilder/graph/insert/JoinRowGraphInsertAction.js +57 -79
- package/lib/queryBuilder/graph/patch/GraphPatch.js +8 -13
- package/lib/queryBuilder/graph/patch/GraphPatchAction.js +181 -234
- package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsert.js +16 -21
- package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsertAction.js +80 -110
- package/lib/queryBuilder/join/JoinResultColumn.js +14 -18
- package/lib/queryBuilder/join/JoinResultParser.js +88 -101
- package/lib/queryBuilder/join/RelationJoiner.js +205 -288
- package/lib/queryBuilder/join/TableNode.js +117 -144
- package/lib/queryBuilder/join/TableTree.js +60 -76
- package/lib/queryBuilder/join/utils.js +10 -16
- package/lib/queryBuilder/operations/DelegateOperation.js +93 -133
- package/lib/queryBuilder/operations/DeleteOperation.js +33 -37
- package/lib/queryBuilder/operations/FindByIdOperation.js +20 -28
- package/lib/queryBuilder/operations/FindByIdsOperation.js +17 -23
- package/lib/queryBuilder/operations/FindOperation.js +114 -131
- package/lib/queryBuilder/operations/FirstOperation.js +14 -19
- package/lib/queryBuilder/operations/FromOperation.js +69 -88
- package/lib/queryBuilder/operations/InsertAndFetchOperation.js +28 -39
- package/lib/queryBuilder/operations/InsertGraphAndFetchOperation.js +25 -35
- package/lib/queryBuilder/operations/InsertGraphOperation.js +77 -98
- package/lib/queryBuilder/operations/InsertOperation.js +132 -165
- package/lib/queryBuilder/operations/InstanceDeleteOperation.js +27 -36
- package/lib/queryBuilder/operations/InstanceFindOperation.js +9 -13
- package/lib/queryBuilder/operations/InstanceInsertOperation.js +13 -17
- package/lib/queryBuilder/operations/InstanceUpdateOperation.js +32 -46
- package/lib/queryBuilder/operations/JoinRelatedOperation.js +66 -86
- package/lib/queryBuilder/operations/KnexOperation.js +4 -7
- package/lib/queryBuilder/operations/MergeOperation.js +32 -45
- package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +131 -150
- package/lib/queryBuilder/operations/OnBuildKnexOperation.js +17 -23
- package/lib/queryBuilder/operations/OnBuildOperation.js +17 -23
- package/lib/queryBuilder/operations/OnErrorOperation.js +17 -23
- package/lib/queryBuilder/operations/QueryBuilderOperation.js +231 -270
- package/lib/queryBuilder/operations/RangeOperation.js +30 -40
- package/lib/queryBuilder/operations/RelateOperation.js +14 -21
- package/lib/queryBuilder/operations/ReturningOperation.js +12 -18
- package/lib/queryBuilder/operations/RunAfterOperation.js +17 -23
- package/lib/queryBuilder/operations/RunBeforeOperation.js +17 -23
- package/lib/queryBuilder/operations/UnrelateOperation.js +12 -17
- package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +48 -65
- package/lib/queryBuilder/operations/UpdateOperation.js +104 -129
- package/lib/queryBuilder/operations/UpsertGraphAndFetchOperation.js +25 -35
- package/lib/queryBuilder/operations/UpsertGraphOperation.js +36 -55
- package/lib/queryBuilder/operations/WhereCompositeOperation.js +30 -39
- package/lib/queryBuilder/operations/WhereInOperation.js +34 -36
- package/lib/queryBuilder/operations/eager/EagerOperation.js +37 -52
- package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +34 -44
- package/lib/queryBuilder/operations/eager/NaiveEagerOperation.js +4 -7
- package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +193 -251
- package/lib/queryBuilder/operations/jsonApi/WhereJsonHasOperation.js +18 -25
- package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectOperation.js +25 -41
- package/lib/queryBuilder/operations/jsonApi/WhereJsonOperation.js +19 -20
- package/lib/queryBuilder/operations/jsonApi/WhereJsonOverlapsOperation.js +23 -21
- package/lib/queryBuilder/operations/jsonApi/mysqlJsonApi.js +106 -118
- package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +79 -108
- package/lib/queryBuilder/operations/select/SelectOperation.js +37 -53
- package/lib/queryBuilder/operations/select/Selection.js +94 -105
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +68 -101
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +65 -75
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +75 -84
- package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +760 -859
- package/lib/queryBuilder/parsers/relationExpressionParser.js +840 -952
- package/lib/queryBuilder/transformations/CompositeQueryTransformation.js +10 -15
- package/lib/queryBuilder/transformations/QueryTransformation.js +4 -6
- package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +35 -49
- package/lib/queryBuilder/transformations/index.js +3 -9
- package/lib/queryBuilder/whereScopes.js +158 -186
- package/lib/relations/Relation.js +279 -363
- package/lib/relations/RelationDeleteOperation.js +16 -22
- package/lib/relations/RelationFindOperation.js +100 -133
- package/lib/relations/RelationInsertOperation.js +19 -27
- package/lib/relations/RelationOwner.js +167 -204
- package/lib/relations/RelationProperty.js +177 -217
- package/lib/relations/RelationUpdateOperation.js +16 -23
- package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +11 -16
- package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +24 -35
- package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +30 -41
- package/lib/relations/belongsToOne/BelongsToOneRelation.js +33 -41
- package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +38 -53
- package/lib/relations/hasMany/HasManyInsertOperation.js +35 -51
- package/lib/relations/hasMany/HasManyRelateOperation.js +38 -54
- package/lib/relations/hasMany/HasManyRelation.js +30 -38
- package/lib/relations/hasMany/HasManyUnrelateOperation.js +19 -26
- package/lib/relations/hasOne/HasOneRelation.js +4 -7
- package/lib/relations/hasOneThrough/HasOneThroughRelation.js +4 -7
- package/lib/relations/manyToMany/ManyToManyModifyMixin.js +67 -90
- package/lib/relations/manyToMany/ManyToManyRelation.js +349 -451
- package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +19 -26
- package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +3 -5
- package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +14 -20
- package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +3 -7
- package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +71 -94
- package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +31 -43
- package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +50 -67
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +4 -7
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +20 -27
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +5 -10
- package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +3 -5
- package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +55 -72
- package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +3 -7
- package/lib/transaction.js +53 -83
- package/lib/utils/assert.js +15 -21
- package/lib/utils/buildUtils.js +17 -19
- package/lib/utils/classUtils.js +7 -11
- package/lib/utils/cloneDeep.js +365 -0
- package/lib/utils/createModifier.js +36 -41
- package/lib/utils/deprecate.js +8 -12
- package/lib/utils/identifierMapping.js +153 -192
- package/lib/utils/internalPropUtils.js +4 -8
- package/lib/utils/knexUtils.js +61 -56
- package/lib/utils/mixin.js +16 -23
- package/lib/utils/mysqlJsonPath.js +55 -40
- package/lib/utils/normalizeIds.js +110 -127
- package/lib/utils/objectUtils.js +236 -338
- package/lib/utils/parseFieldExpression.js +66 -44
- package/lib/utils/postgresJsonPath.js +48 -62
- package/lib/utils/promiseUtils/after.js +10 -13
- package/lib/utils/promiseUtils/afterReturn.js +10 -13
- package/lib/utils/promiseUtils/index.js +15 -17
- package/lib/utils/promiseUtils/isPromise.js +6 -9
- package/lib/utils/promiseUtils/map.js +75 -89
- package/lib/utils/promiseUtils/mapAfterAllReturn.js +17 -23
- package/lib/utils/promiseUtils/try.js +15 -18
- package/lib/utils/resolveModel.js +91 -94
- package/lib/utils/tmpColumnUtils.js +4 -13
- package/package.json +50 -23
- package/typings/objection/index.d.mts +362 -0
- package/typings/objection/index.d.ts +36 -9
- package/lib/.eslintrc.json +0 -8
- package/lib/queryBuilder/parsers/jsonFieldExpressionParser.pegjs +0 -97
- package/lib/queryBuilder/parsers/relationExpressionParser.pegjs +0 -141
- package/lib/utils/clone.js +0 -2329
|
@@ -1,108 +1,87 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const { DelegateOperation } = require('./DelegateOperation');
|
|
4
3
|
const { InsertOperation } = require('./InsertOperation');
|
|
5
4
|
const { GraphUpsert } = require('../graph/GraphUpsert');
|
|
6
|
-
|
|
7
5
|
class InsertGraphOperation extends DelegateOperation {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
constructor(name, opt = null) {
|
|
7
|
+
super(name, opt);
|
|
8
|
+
if (!this.delegate.is(InsertOperation)) {
|
|
9
|
+
throw new Error('Invalid delegate');
|
|
10
|
+
}
|
|
11
|
+
Object.assign(this.delegate.modelOptions, GraphUpsert.modelOptions);
|
|
12
|
+
this.upsertOptions = opt.opt || {};
|
|
13
|
+
this.upsert = null;
|
|
13
14
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
15
|
+
get models() {
|
|
16
|
+
return this.delegate.models;
|
|
17
|
+
}
|
|
18
|
+
get isArray() {
|
|
19
|
+
return this.delegate.isArray;
|
|
20
|
+
}
|
|
21
|
+
get relation() {
|
|
22
|
+
return this.delegate.relation;
|
|
23
|
+
}
|
|
24
|
+
onAdd(builder, args) {
|
|
25
|
+
const retVal = super.onAdd(builder, args);
|
|
26
|
+
this.upsert = new GraphUpsert({
|
|
27
|
+
objects: this.models,
|
|
28
|
+
rootModelClass: builder.modelClass(),
|
|
29
|
+
upsertOptions: Object.assign({}, this.upsertOptions, {
|
|
30
|
+
noUpdate: true,
|
|
31
|
+
noDelete: true,
|
|
32
|
+
noUnrelate: true,
|
|
33
|
+
insertMissing: true,
|
|
34
|
+
}),
|
|
35
|
+
});
|
|
36
|
+
// We resolve this query here and will not execute it. This is because the root
|
|
37
|
+
// value may depend on other models in the graph and cannot be inserted first.
|
|
38
|
+
builder.resolve([]);
|
|
39
|
+
return retVal;
|
|
40
|
+
}
|
|
41
|
+
onBefore1(_, result) {
|
|
42
|
+
// Do nothing.
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
onBefore2(builder, result) {
|
|
46
|
+
// We override this with empty implementation so that the $beforeInsert()
|
|
47
|
+
// hooks are not called twice for the root models.
|
|
48
|
+
if (this.relation) {
|
|
49
|
+
// We still need to call the relation before insert hook if the the
|
|
50
|
+
// delegate operation is a RelationInsertOperation.
|
|
51
|
+
return this.relation.executeBeforeInsert(this.models, builder.context(), result);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
onBefore3(_, result) {
|
|
58
|
+
// Do nothing.
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
onBuild() {
|
|
62
|
+
// Do nothing.
|
|
63
|
+
}
|
|
64
|
+
onBuildKnex(knexBuilder) {
|
|
65
|
+
// Do nothing.
|
|
66
|
+
return knexBuilder;
|
|
67
|
+
}
|
|
68
|
+
// We overrode all other hooks but this one and do all the work in here.
|
|
69
|
+
// This is a bit hacky.
|
|
70
|
+
async onAfter1(builder, ...restArgs) {
|
|
71
|
+
await this.upsert.run(builder);
|
|
72
|
+
return await super.onAfter1(builder, ...restArgs);
|
|
73
|
+
}
|
|
74
|
+
onAfter2() {
|
|
75
|
+
// We override this with empty implementation so that the $afterInsert() hooks
|
|
76
|
+
// are not called twice for the root models.
|
|
77
|
+
return this.isArray ? this.models : this.models[0] || null;
|
|
78
|
+
}
|
|
79
|
+
clone() {
|
|
80
|
+
const clone = super.clone();
|
|
81
|
+
clone.upsert = this.upsert;
|
|
82
|
+
return clone;
|
|
69
83
|
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
onBefore3(_, result) {
|
|
73
|
-
// Do nothing.
|
|
74
|
-
return result;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
onBuild() {
|
|
78
|
-
// Do nothing.
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
onBuildKnex(knexBuilder) {
|
|
82
|
-
// Do nothing.
|
|
83
|
-
return knexBuilder;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// We overrode all other hooks but this one and do all the work in here.
|
|
87
|
-
// This is a bit hacky.
|
|
88
|
-
async onAfter1(builder, ...restArgs) {
|
|
89
|
-
await this.upsert.run(builder);
|
|
90
|
-
return await super.onAfter1(builder, ...restArgs);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
onAfter2() {
|
|
94
|
-
// We override this with empty implementation so that the $afterInsert() hooks
|
|
95
|
-
// are not called twice for the root models.
|
|
96
|
-
return this.isArray ? this.models : this.models[0] || null;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
clone() {
|
|
100
|
-
const clone = super.clone();
|
|
101
|
-
clone.upsert = this.upsert;
|
|
102
|
-
return clone;
|
|
103
|
-
}
|
|
104
84
|
}
|
|
105
|
-
|
|
106
85
|
module.exports = {
|
|
107
|
-
|
|
86
|
+
InsertGraphOperation,
|
|
108
87
|
};
|
|
@@ -1,206 +1,173 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
/* global BigInt */
|
|
4
|
-
|
|
5
3
|
const { QueryBuilderOperation } = require('./QueryBuilderOperation');
|
|
6
|
-
const { StaticHookArguments } = require('../StaticHookArguments');
|
|
4
|
+
const { StaticHookArguments, hasStaticHook } = require('../StaticHookArguments');
|
|
7
5
|
const { after, mapAfterAllReturn } = require('../../utils/promiseUtils');
|
|
8
6
|
const { isSqlite, isMySql } = require('../../utils/knexUtils');
|
|
9
7
|
const { isObject } = require('../../utils/objectUtils');
|
|
10
|
-
|
|
11
8
|
// `@@auto_increment_increment` for each MySQL knex instance, keyed by the knex config,
|
|
12
9
|
// which transactions share with the knex they were started from.
|
|
13
10
|
const autoIncrementIncrements = new WeakMap();
|
|
14
|
-
|
|
15
11
|
// Base class for all insert operations.
|
|
16
12
|
class InsertOperation extends QueryBuilderOperation {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
this.autoIncrementIncrement = null;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
onAdd(builder, args) {
|
|
27
|
-
const json = args[0];
|
|
28
|
-
const modelClass = builder.modelClass();
|
|
29
|
-
|
|
30
|
-
this.isArray = Array.isArray(json);
|
|
31
|
-
this.models = modelClass.ensureModelArray(json, this.modelOptions);
|
|
32
|
-
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async onBefore2(builder, result) {
|
|
37
|
-
await callBeforeInsert(builder, this.models);
|
|
38
|
-
|
|
39
|
-
if (this.models.length > 1 && isMySql(builder.knex())) {
|
|
40
|
-
await this.prepareMySqlBatchInsert(builder);
|
|
13
|
+
constructor(name, opt) {
|
|
14
|
+
super(name, opt);
|
|
15
|
+
this.models = null;
|
|
16
|
+
this.isArray = false;
|
|
17
|
+
this.modelOptions = Object.assign({}, this.opt.modelOptions || {});
|
|
18
|
+
this.autoIncrementIncrement = null;
|
|
41
19
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// `innodb_autoinc_lock_mode`), so the other ids can be computed from it and
|
|
49
|
-
// `@@auto_increment_increment`.
|
|
50
|
-
async prepareMySqlBatchInsert(builder) {
|
|
51
|
-
const withId = this.models.filter((model) => model.$hasId()).length;
|
|
52
|
-
|
|
53
|
-
if (withId === this.models.length) {
|
|
54
|
-
return;
|
|
20
|
+
onAdd(builder, args) {
|
|
21
|
+
const json = args[0];
|
|
22
|
+
const modelClass = builder.modelClass();
|
|
23
|
+
this.isArray = Array.isArray(json);
|
|
24
|
+
this.models = modelClass.ensureModelArray(json, this.modelOptions);
|
|
25
|
+
return true;
|
|
55
26
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (Array.isArray(builder.modelClass().getIdColumn())) {
|
|
64
|
-
return;
|
|
27
|
+
async onBefore2(builder, result) {
|
|
28
|
+
await callBeforeInsert(builder, this.models);
|
|
29
|
+
if (this.models.length > 1 && isMySql(builder.knex())) {
|
|
30
|
+
await this.prepareMySqlBatchInsert(builder);
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
65
33
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
34
|
+
// MySQL only returns the id of the first row of a multi-row insert. InnoDB
|
|
35
|
+
// gives the rows of one multi-row VALUES insert consecutive ids (in every
|
|
36
|
+
// `innodb_autoinc_lock_mode`), so the other ids can be computed from it and
|
|
37
|
+
// `@@auto_increment_increment`.
|
|
38
|
+
async prepareMySqlBatchInsert(builder) {
|
|
39
|
+
const withId = this.models.filter((model) => model.$hasId()).length;
|
|
40
|
+
if (withId === this.models.length) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (withId > 0) {
|
|
44
|
+
throw new Error(`batch insert on MySQL can't return ids when only some rows have an id. Set the id on all rows or none.`);
|
|
45
|
+
}
|
|
46
|
+
if (Array.isArray(builder.modelClass().getIdColumn())) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const knex = builder.knex();
|
|
50
|
+
let increment = autoIncrementIncrements.get(knex.client.config);
|
|
51
|
+
if (increment === undefined) {
|
|
52
|
+
const [rows] = await knex.raw('select @@auto_increment_increment as increment');
|
|
53
|
+
increment = Number(rows[0].increment);
|
|
54
|
+
autoIncrementIncrements.set(knex.client.config, increment);
|
|
55
|
+
}
|
|
56
|
+
this.autoIncrementIncrement = increment;
|
|
74
57
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// that at least the identifier is returned. SQLite only returns the
|
|
86
|
-
// id of the last row without one.
|
|
87
|
-
knexBuilder = knexBuilder.returning(builder.modelClass().getIdColumn());
|
|
58
|
+
onBuildKnex(knexBuilder, builder) {
|
|
59
|
+
const knex = builder.knex();
|
|
60
|
+
const returnsIds = !isMySql(knex) && (!isSqlite(knex) || this.models.length > 1);
|
|
61
|
+
if (returnsIds && !builder.has(/returning/)) {
|
|
62
|
+
// If the user hasn't specified a `returning` clause, we make sure
|
|
63
|
+
// that at least the identifier is returned. SQLite only returns the
|
|
64
|
+
// id of the last row without one.
|
|
65
|
+
knexBuilder = knexBuilder.returning(builder.modelClass().getIdColumn());
|
|
66
|
+
}
|
|
67
|
+
return knexBuilder.insert(this.models.map((model) => model.$toDatabaseJson(builder)));
|
|
88
68
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
69
|
+
onAfter1(builder, ret) {
|
|
70
|
+
if (!Array.isArray(ret) || !ret.length || ret === this.models) {
|
|
71
|
+
// Early exit if there is nothing to do.
|
|
72
|
+
return this.models;
|
|
73
|
+
}
|
|
74
|
+
if (ret.length === 1 && this.models.length > 1) {
|
|
75
|
+
this.setMySqlBatchInsertIds(builder, ret[0]);
|
|
76
|
+
}
|
|
77
|
+
else if (isObject(ret[0])) {
|
|
78
|
+
// If the user specified a `returning` clause the result may be an array of objects.
|
|
79
|
+
// Merge all values of the objects to our models.
|
|
80
|
+
for (let i = 0, l = this.models.length; i < l; ++i) {
|
|
81
|
+
this.models[i].$setDatabaseJson(ret[i]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
// If the return value is not an array of objects, we assume it is an array of identifiers.
|
|
86
|
+
for (let i = 0, l = this.models.length; i < l; ++i) {
|
|
87
|
+
const model = this.models[i];
|
|
88
|
+
// Don't set the id if the model already has one. MySQL and Sqlite don't return the correct
|
|
89
|
+
// primary key value if the id is not generated in db, but given explicitly.
|
|
90
|
+
if (!model.$id()) {
|
|
91
|
+
model.$id(ret[i]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return this.models;
|
|
97
96
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
} else {
|
|
108
|
-
// If the return value is not an array of objects, we assume it is an array of identifiers.
|
|
109
|
-
for (let i = 0, l = this.models.length; i < l; ++i) {
|
|
110
|
-
const model = this.models[i];
|
|
111
|
-
|
|
112
|
-
// Don't set the id if the model already has one. MySQL and Sqlite don't return the correct
|
|
113
|
-
// primary key value if the id is not generated in db, but given explicitly.
|
|
114
|
-
if (!model.$id()) {
|
|
115
|
-
model.$id(ret[i]);
|
|
97
|
+
setMySqlBatchInsertIds(builder, firstId) {
|
|
98
|
+
const increment = this.autoIncrementIncrement;
|
|
99
|
+
// `onConflict()` may skip or update rows, which breaks the id sequence.
|
|
100
|
+
if (increment === null || builder.has(/onConflict/) || !firstId) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
for (let i = 0, l = this.models.length; i < l; ++i) {
|
|
104
|
+
this.models[i].$id(addToId(firstId, i * increment));
|
|
116
105
|
}
|
|
117
|
-
}
|
|
118
106
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
// `onConflict()` may skip or update rows, which breaks the id sequence.
|
|
127
|
-
if (increment === null || builder.has(/onConflict/) || !firstId) {
|
|
128
|
-
return;
|
|
107
|
+
onAfter2(builder, models) {
|
|
108
|
+
const result = this.isArray ? models : models[0] || null;
|
|
109
|
+
return callAfterInsert(builder, this.models, result);
|
|
110
|
+
}
|
|
111
|
+
toFindOperation() {
|
|
112
|
+
return null;
|
|
129
113
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
114
|
+
clone() {
|
|
115
|
+
const clone = super.clone();
|
|
116
|
+
clone.models = this.models;
|
|
117
|
+
clone.isArray = this.isArray;
|
|
118
|
+
clone.autoIncrementIncrement = this.autoIncrementIncrement;
|
|
119
|
+
return clone;
|
|
133
120
|
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
onAfter2(builder, models) {
|
|
137
|
-
const result = this.isArray ? models : models[0] || null;
|
|
138
|
-
return callAfterInsert(builder, this.models, result);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
toFindOperation() {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
clone() {
|
|
146
|
-
const clone = super.clone();
|
|
147
|
-
|
|
148
|
-
clone.models = this.models;
|
|
149
|
-
clone.isArray = this.isArray;
|
|
150
|
-
clone.autoIncrementIncrement = this.autoIncrementIncrement;
|
|
151
|
-
|
|
152
|
-
return clone;
|
|
153
|
-
}
|
|
154
121
|
}
|
|
155
|
-
|
|
156
122
|
// The id can be a string or a BigInt when the driver is configured to
|
|
157
123
|
// return big numbers that way.
|
|
158
124
|
function addToId(id, amount) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
125
|
+
if (typeof id === 'number') {
|
|
126
|
+
return id + amount;
|
|
127
|
+
}
|
|
128
|
+
else if (typeof id === 'bigint') {
|
|
129
|
+
return id + BigInt(amount);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
return String(BigInt(id) + BigInt(amount));
|
|
133
|
+
}
|
|
166
134
|
}
|
|
167
|
-
|
|
168
135
|
function callBeforeInsert(builder, models) {
|
|
169
|
-
|
|
170
|
-
|
|
136
|
+
const maybePromise = callInstanceBeforeInsert(builder, models);
|
|
137
|
+
return after(maybePromise, () => callStaticBeforeInsert(builder));
|
|
171
138
|
}
|
|
172
|
-
|
|
173
139
|
function callInstanceBeforeInsert(builder, models) {
|
|
174
|
-
|
|
140
|
+
return mapAfterAllReturn(models, (model) => model.$beforeInsert(builder.context()), models);
|
|
175
141
|
}
|
|
176
|
-
|
|
177
142
|
function callStaticBeforeInsert(builder) {
|
|
178
|
-
|
|
179
|
-
|
|
143
|
+
if (!hasStaticHook(builder.modelClass(), 'beforeInsert')) {
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
const args = StaticHookArguments.create({ builder });
|
|
147
|
+
return builder.modelClass().beforeInsert(args);
|
|
180
148
|
}
|
|
181
|
-
|
|
182
149
|
function callAfterInsert(builder, models, result) {
|
|
183
|
-
|
|
184
|
-
|
|
150
|
+
const maybePromise = callInstanceAfterInsert(builder, models);
|
|
151
|
+
return after(maybePromise, () => callStaticAfterInsert(builder, result));
|
|
185
152
|
}
|
|
186
|
-
|
|
187
153
|
function callInstanceAfterInsert(builder, models) {
|
|
188
|
-
|
|
154
|
+
return mapAfterAllReturn(models, (model) => model.$afterInsert(builder.context()), models);
|
|
189
155
|
}
|
|
190
|
-
|
|
191
156
|
function callStaticAfterInsert(builder, result) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return after(maybePromise, (maybeResult) => {
|
|
196
|
-
if (maybeResult === undefined) {
|
|
197
|
-
return result;
|
|
198
|
-
} else {
|
|
199
|
-
return maybeResult;
|
|
157
|
+
if (!hasStaticHook(builder.modelClass(), 'afterInsert')) {
|
|
158
|
+
return result;
|
|
200
159
|
}
|
|
201
|
-
|
|
160
|
+
const args = StaticHookArguments.create({ builder, result });
|
|
161
|
+
const maybePromise = builder.modelClass().afterInsert(args);
|
|
162
|
+
return after(maybePromise, (maybeResult) => {
|
|
163
|
+
if (maybeResult === undefined) {
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
return maybeResult;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
202
170
|
}
|
|
203
|
-
|
|
204
171
|
module.exports = {
|
|
205
|
-
|
|
172
|
+
InsertOperation,
|
|
206
173
|
};
|
|
@@ -1,46 +1,37 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const { withWhereScope } = require('../whereScopes');
|
|
4
3
|
const { DeleteOperation } = require('./DeleteOperation');
|
|
5
4
|
const { InstanceFindOperation } = require('./InstanceFindOperation');
|
|
6
5
|
const { assertHasId } = require('../../utils/assert');
|
|
7
|
-
|
|
8
6
|
class InstanceDeleteOperation extends DeleteOperation {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
7
|
+
constructor(name, opt) {
|
|
8
|
+
super(name, opt);
|
|
9
|
+
this.instance = opt.instance;
|
|
10
|
+
}
|
|
11
|
+
async onBefore2(builder, result) {
|
|
12
|
+
await this.instance.$beforeDelete(builder.context());
|
|
13
|
+
await super.onBefore2(builder, result);
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
onBuild(builder) {
|
|
17
|
+
super.onBuild(builder);
|
|
18
|
+
assertHasId(this.instance);
|
|
19
|
+
withWhereScope(builder, () => builder.findById(this.instance.$id()));
|
|
20
|
+
}
|
|
21
|
+
async onAfter2(builder, result) {
|
|
22
|
+
// The result may be an object if `returning` was used.
|
|
23
|
+
if (Array.isArray(result)) {
|
|
24
|
+
result = result[0];
|
|
25
|
+
}
|
|
26
|
+
await this.instance.$afterDelete(builder.context());
|
|
27
|
+
return super.onAfter2(builder, result);
|
|
28
|
+
}
|
|
29
|
+
toFindOperation() {
|
|
30
|
+
return new InstanceFindOperation('find', {
|
|
31
|
+
instance: this.instance,
|
|
32
|
+
});
|
|
31
33
|
}
|
|
32
|
-
|
|
33
|
-
await this.instance.$afterDelete(builder.context());
|
|
34
|
-
return super.onAfter2(builder, result);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
toFindOperation() {
|
|
38
|
-
return new InstanceFindOperation('find', {
|
|
39
|
-
instance: this.instance,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
34
|
}
|
|
43
|
-
|
|
44
35
|
module.exports = {
|
|
45
|
-
|
|
36
|
+
InstanceDeleteOperation,
|
|
46
37
|
};
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const { withWhereScope } = require('../whereScopes');
|
|
4
3
|
const { FindOperation } = require('./FindOperation');
|
|
5
4
|
const { assertHasId } = require('../../utils/assert');
|
|
6
|
-
|
|
7
5
|
class InstanceFindOperation extends FindOperation {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
6
|
+
constructor(name, opt) {
|
|
7
|
+
super(name, opt);
|
|
8
|
+
this.instance = opt.instance;
|
|
9
|
+
}
|
|
10
|
+
onBuild(builder) {
|
|
11
|
+
assertHasId(this.instance);
|
|
12
|
+
withWhereScope(builder, () => builder.findById(this.instance.$id()));
|
|
13
|
+
}
|
|
17
14
|
}
|
|
18
|
-
|
|
19
15
|
module.exports = {
|
|
20
|
-
|
|
16
|
+
InstanceFindOperation,
|
|
21
17
|
};
|
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const { InsertOperation } = require('./InsertOperation');
|
|
4
|
-
|
|
5
3
|
class InstanceInsertOperation extends InsertOperation {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
constructor(name, opt) {
|
|
5
|
+
super(name, opt);
|
|
6
|
+
this.instance = opt.instance;
|
|
7
|
+
}
|
|
8
|
+
onAdd(builder, args) {
|
|
9
|
+
if (!args || args.length === 0) {
|
|
10
|
+
args = [this.instance];
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
args[0] = this.instance;
|
|
14
|
+
}
|
|
15
|
+
return super.onAdd(builder, args);
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
return super.onAdd(builder, args);
|
|
19
|
-
}
|
|
20
17
|
}
|
|
21
|
-
|
|
22
18
|
module.exports = {
|
|
23
|
-
|
|
19
|
+
InstanceInsertOperation,
|
|
24
20
|
};
|