@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,29 +1,23 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const { QueryBuilderOperation } = require('./QueryBuilderOperation');
|
|
4
|
-
|
|
5
3
|
class RunAfterOperation extends QueryBuilderOperation {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
clone.func = this.func;
|
|
23
|
-
return clone;
|
|
24
|
-
}
|
|
4
|
+
constructor(name, opt) {
|
|
5
|
+
super(name, opt);
|
|
6
|
+
this.func = null;
|
|
7
|
+
}
|
|
8
|
+
onAdd(_, args) {
|
|
9
|
+
this.func = args[0];
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
onAfter3(builder, result) {
|
|
13
|
+
return this.func.call(builder, result, builder);
|
|
14
|
+
}
|
|
15
|
+
clone() {
|
|
16
|
+
const clone = super.clone();
|
|
17
|
+
clone.func = this.func;
|
|
18
|
+
return clone;
|
|
19
|
+
}
|
|
25
20
|
}
|
|
26
|
-
|
|
27
21
|
module.exports = {
|
|
28
|
-
|
|
22
|
+
RunAfterOperation,
|
|
29
23
|
};
|
|
@@ -1,29 +1,23 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const { QueryBuilderOperation } = require('./QueryBuilderOperation');
|
|
4
|
-
|
|
5
3
|
class RunBeforeOperation extends QueryBuilderOperation {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
clone.func = this.func;
|
|
23
|
-
return clone;
|
|
24
|
-
}
|
|
4
|
+
constructor(name, opt) {
|
|
5
|
+
super(name, opt);
|
|
6
|
+
this.func = null;
|
|
7
|
+
}
|
|
8
|
+
onAdd(_, args) {
|
|
9
|
+
this.func = args[0];
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
onBefore1(builder, result) {
|
|
13
|
+
return this.func.call(builder, result, builder);
|
|
14
|
+
}
|
|
15
|
+
clone() {
|
|
16
|
+
const clone = super.clone();
|
|
17
|
+
clone.func = this.func;
|
|
18
|
+
return clone;
|
|
19
|
+
}
|
|
25
20
|
}
|
|
26
|
-
|
|
27
21
|
module.exports = {
|
|
28
|
-
|
|
22
|
+
RunBeforeOperation,
|
|
29
23
|
};
|
|
@@ -1,23 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const { QueryBuilderOperation } = require('./QueryBuilderOperation');
|
|
4
|
-
|
|
5
3
|
class UnrelateOperation extends QueryBuilderOperation {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return clone;
|
|
18
|
-
}
|
|
4
|
+
constructor(name, opt) {
|
|
5
|
+
super(name, opt);
|
|
6
|
+
this.relation = opt.relation;
|
|
7
|
+
this.owner = opt.owner;
|
|
8
|
+
this.ids = null;
|
|
9
|
+
}
|
|
10
|
+
clone() {
|
|
11
|
+
const clone = super.clone();
|
|
12
|
+
clone.ids = this.ids;
|
|
13
|
+
return clone;
|
|
14
|
+
}
|
|
19
15
|
}
|
|
20
|
-
|
|
21
16
|
module.exports = {
|
|
22
|
-
|
|
17
|
+
UnrelateOperation,
|
|
23
18
|
};
|
|
@@ -1,80 +1,63 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const { withWhereScope } = require('../whereScopes');
|
|
4
3
|
const { DelegateOperation } = require('./DelegateOperation');
|
|
5
4
|
const { FindByIdOperation } = require('./FindByIdOperation');
|
|
6
5
|
const { UpdateOperation } = require('./UpdateOperation');
|
|
7
|
-
|
|
8
6
|
class UpdateAndFetchOperation extends DelegateOperation {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
constructor(name, opt) {
|
|
8
|
+
super(name, opt);
|
|
9
|
+
if (!this.delegate.is(UpdateOperation)) {
|
|
10
|
+
throw new Error('Invalid delegate');
|
|
11
|
+
}
|
|
12
|
+
this.id = null;
|
|
13
|
+
this.skipIdWhere = false;
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
this.skipIdWhere = false;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
get model() {
|
|
21
|
-
return this.delegate.model;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
onAdd(builder, args) {
|
|
25
|
-
this.id = args[0];
|
|
26
|
-
return this.delegate.onAdd(builder, args.slice(1));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
onBuild(builder) {
|
|
30
|
-
if (!this.skipIdWhere) {
|
|
31
|
-
withWhereScope(builder, () => builder.findById(this.id));
|
|
15
|
+
get model() {
|
|
16
|
+
return this.delegate.model;
|
|
32
17
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
async onAfter2(builder, numUpdated) {
|
|
38
|
-
if (numUpdated == 0) {
|
|
39
|
-
// If nothing was updated, we should fetch nothing.
|
|
40
|
-
await super.onAfter2(builder, numUpdated);
|
|
41
|
-
return undefined;
|
|
18
|
+
onAdd(builder, args) {
|
|
19
|
+
this.id = args[0];
|
|
20
|
+
return this.delegate.onAdd(builder, args.slice(1));
|
|
42
21
|
}
|
|
43
|
-
|
|
44
|
-
const fetched = await builder
|
|
45
|
-
.emptyInstance()
|
|
46
|
-
.childQueryOf(builder)
|
|
47
|
-
.modify((builder) => {
|
|
22
|
+
onBuild(builder) {
|
|
48
23
|
if (!this.skipIdWhere) {
|
|
49
|
-
|
|
24
|
+
withWhereScope(builder, () => builder.findById(this.id));
|
|
25
|
+
}
|
|
26
|
+
super.onBuild(builder);
|
|
27
|
+
}
|
|
28
|
+
async onAfter2(builder, numUpdated) {
|
|
29
|
+
if (numUpdated == 0) {
|
|
30
|
+
// If nothing was updated, we should fetch nothing.
|
|
31
|
+
await super.onAfter2(builder, numUpdated);
|
|
32
|
+
return undefined;
|
|
50
33
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
34
|
+
const fetched = await builder
|
|
35
|
+
.emptyInstance()
|
|
36
|
+
.childQueryOf(builder)
|
|
37
|
+
.modify((builder) => {
|
|
38
|
+
if (!this.skipIdWhere) {
|
|
39
|
+
builder.findById(this.id);
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
.castTo(builder.resultModelClass());
|
|
43
|
+
if (fetched) {
|
|
44
|
+
this.model.$set(fetched);
|
|
45
|
+
}
|
|
46
|
+
await super.onAfter2(builder, numUpdated);
|
|
47
|
+
return fetched ? this.model : undefined;
|
|
48
|
+
}
|
|
49
|
+
toFindOperation() {
|
|
50
|
+
return new FindByIdOperation('findById', {
|
|
51
|
+
id: this.id,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
clone() {
|
|
55
|
+
const clone = super.clone();
|
|
56
|
+
clone.id = this.id;
|
|
57
|
+
clone.skipIdWhere = this.skipIdWhere;
|
|
58
|
+
return clone;
|
|
56
59
|
}
|
|
57
|
-
|
|
58
|
-
await super.onAfter2(builder, numUpdated);
|
|
59
|
-
return fetched ? this.model : undefined;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
toFindOperation() {
|
|
63
|
-
return new FindByIdOperation('findById', {
|
|
64
|
-
id: this.id,
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
clone() {
|
|
69
|
-
const clone = super.clone();
|
|
70
|
-
|
|
71
|
-
clone.id = this.id;
|
|
72
|
-
clone.skipIdWhere = this.skipIdWhere;
|
|
73
|
-
|
|
74
|
-
return clone;
|
|
75
|
-
}
|
|
76
60
|
}
|
|
77
|
-
|
|
78
61
|
module.exports = {
|
|
79
|
-
|
|
62
|
+
UpdateAndFetchOperation,
|
|
80
63
|
};
|
|
@@ -1,155 +1,130 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const { ref } = require('../../queryBuilder/ReferenceBuilder');
|
|
4
3
|
const { isEmpty } = require('../../utils/objectUtils');
|
|
5
4
|
const { isKnexRaw, isKnexQueryBuilder } = require('../../utils/knexUtils');
|
|
6
5
|
const { toPgJsonPathLiteral, getJsonDialect } = require('../../utils/postgresJsonPath');
|
|
7
|
-
const { toMySqlJsonPath } = require('../../utils/mysqlJsonPath');
|
|
6
|
+
const { toMySqlJsonPath, toJsonSql } = require('../../utils/mysqlJsonPath');
|
|
8
7
|
const { QueryBuilderOperation } = require('./QueryBuilderOperation');
|
|
9
|
-
const { StaticHookArguments } = require('../StaticHookArguments');
|
|
10
|
-
|
|
8
|
+
const { StaticHookArguments, hasStaticHook } = require('../StaticHookArguments');
|
|
11
9
|
class UpdateOperation extends QueryBuilderOperation {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
10
|
+
constructor(name, opt) {
|
|
11
|
+
super(name, opt);
|
|
12
|
+
this.model = null;
|
|
13
|
+
this.modelOptions = Object.assign({}, this.opt.modelOptions || {});
|
|
14
|
+
}
|
|
15
|
+
onAdd(builder, args) {
|
|
16
|
+
const json = args[0];
|
|
17
|
+
const modelClass = builder.modelClass();
|
|
18
|
+
this.model = modelClass.ensureModel(json, this.modelOptions);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
async onBefore2(builder, result) {
|
|
22
|
+
await callBeforeUpdate(builder, this.model, this.modelOptions);
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
onBefore3(builder) {
|
|
26
|
+
const row = this.model.$toDatabaseJson(builder);
|
|
27
|
+
if (isEmpty(row)) {
|
|
28
|
+
// Resolve the query if there is nothing to update.
|
|
29
|
+
builder.resolve(0);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
onBuildKnex(knexBuilder, builder) {
|
|
33
|
+
const json = this.model.$toDatabaseJson(builder);
|
|
34
|
+
const convertedJson = convertFieldExpressionsToRaw(builder, this.model, json);
|
|
35
|
+
return knexBuilder.update(convertedJson);
|
|
36
|
+
}
|
|
37
|
+
onAfter2(builder, numUpdated) {
|
|
38
|
+
return callAfterUpdate(builder, this.model, this.modelOptions, numUpdated);
|
|
39
|
+
}
|
|
40
|
+
toFindOperation() {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
clone() {
|
|
44
|
+
const clone = super.clone();
|
|
45
|
+
clone.model = this.model;
|
|
46
|
+
return clone;
|
|
38
47
|
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
onBuildKnex(knexBuilder, builder) {
|
|
42
|
-
const json = this.model.$toDatabaseJson(builder);
|
|
43
|
-
const convertedJson = convertFieldExpressionsToRaw(builder, this.model, json);
|
|
44
|
-
|
|
45
|
-
return knexBuilder.update(convertedJson);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
onAfter2(builder, numUpdated) {
|
|
49
|
-
return callAfterUpdate(builder, this.model, this.modelOptions, numUpdated);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
toFindOperation() {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
clone() {
|
|
57
|
-
const clone = super.clone();
|
|
58
|
-
clone.model = this.model;
|
|
59
|
-
return clone;
|
|
60
|
-
}
|
|
61
48
|
}
|
|
62
|
-
|
|
63
49
|
async function callBeforeUpdate(builder, model, modelOptions) {
|
|
64
|
-
|
|
65
|
-
|
|
50
|
+
await callInstanceBeforeUpdate(builder, model, modelOptions);
|
|
51
|
+
return callStaticBeforeUpdate(builder);
|
|
66
52
|
}
|
|
67
|
-
|
|
68
53
|
function callInstanceBeforeUpdate(builder, model, modelOptions) {
|
|
69
|
-
|
|
54
|
+
return model.$beforeUpdate(modelOptions, builder.context());
|
|
70
55
|
}
|
|
71
|
-
|
|
72
56
|
function callStaticBeforeUpdate(builder) {
|
|
73
|
-
|
|
74
|
-
|
|
57
|
+
if (!hasStaticHook(builder.modelClass(), 'beforeUpdate')) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
const args = StaticHookArguments.create({ builder });
|
|
61
|
+
return builder.modelClass().beforeUpdate(args);
|
|
75
62
|
}
|
|
76
|
-
|
|
77
63
|
async function callAfterUpdate(builder, model, modelOptions, result) {
|
|
78
|
-
|
|
79
|
-
|
|
64
|
+
await callInstanceAfterUpdate(builder, model, modelOptions);
|
|
65
|
+
return callStaticAfterUpdate(builder, result);
|
|
80
66
|
}
|
|
81
|
-
|
|
82
67
|
function callInstanceAfterUpdate(builder, model, modelOptions) {
|
|
83
|
-
|
|
68
|
+
return model.$afterUpdate(modelOptions, builder.context());
|
|
84
69
|
}
|
|
85
|
-
|
|
86
70
|
async function callStaticAfterUpdate(builder, result) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
71
|
+
if (!hasStaticHook(builder.modelClass(), 'afterUpdate')) {
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
const args = StaticHookArguments.create({ builder, result });
|
|
75
|
+
const maybeResult = await builder.modelClass().afterUpdate(args);
|
|
76
|
+
if (maybeResult === undefined) {
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
return maybeResult;
|
|
81
|
+
}
|
|
95
82
|
}
|
|
96
|
-
|
|
97
83
|
function convertFieldExpressionsToRaw(builder, model, json) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
`jsonb_set(${column}, ${toPgJsonPathLiteral(access)}, ${value}, true)`,
|
|
139
|
-
[target, val],
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
delete model[key];
|
|
144
|
-
} else {
|
|
145
|
-
convertedJson[key] = val;
|
|
84
|
+
const knex = builder.knex();
|
|
85
|
+
const convertedJson = {};
|
|
86
|
+
for (const key of Object.keys(json)) {
|
|
87
|
+
let val = json[key];
|
|
88
|
+
if (key.indexOf(':') > -1) {
|
|
89
|
+
// 'col:attr' : ref('other:lol') is transformed to
|
|
90
|
+
// "col" : raw(`jsonb_set(COALESCE("col", '{}'), '{attr}', to_jsonb("other"#>'{lol}'), true)`)
|
|
91
|
+
// on postgres and to
|
|
92
|
+
// `col` : raw("JSON_SET(COALESCE(`col`, JSON_OBJECT()), '$.\"attr\"', JSON_EXTRACT(`other`, '$.\"lol\"'))")
|
|
93
|
+
// on mysql. A NULL column is treated as an empty object (or array).
|
|
94
|
+
const parsed = ref(key);
|
|
95
|
+
const access = parsed.parsedExpr.access;
|
|
96
|
+
const isSqlValue = isKnexQueryBuilder(val) || isKnexRaw(val);
|
|
97
|
+
// When the column is set by an earlier key, that expression is used instead.
|
|
98
|
+
const target = convertedJson[parsed.column] || parsed.column;
|
|
99
|
+
const isFirstSet = !convertedJson[parsed.column];
|
|
100
|
+
if (!isSqlValue) {
|
|
101
|
+
val = JSON.stringify(val);
|
|
102
|
+
}
|
|
103
|
+
if (getJsonDialect(knex, key) === 'mysql') {
|
|
104
|
+
const empty = access[0].type === 'array' ? 'JSON_ARRAY()' : 'JSON_OBJECT()';
|
|
105
|
+
const column = isFirstSet ? `COALESCE(??, ${empty})` : '??';
|
|
106
|
+
const value = isSqlValue ? '?' : toJsonSql('?', knex);
|
|
107
|
+
convertedJson[parsed.column] = knex.raw(`JSON_SET(${column}, ?, ${value})`, [
|
|
108
|
+
target,
|
|
109
|
+
toMySqlJsonPath(access),
|
|
110
|
+
val,
|
|
111
|
+
]);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const empty = access[0].type === 'array' ? `'[]'::jsonb` : `'{}'::jsonb`;
|
|
115
|
+
const column = isFirstSet ? `COALESCE(??, ${empty})` : '??';
|
|
116
|
+
const value = isSqlValue ? 'to_jsonb(?)' : '?';
|
|
117
|
+
convertedJson[parsed.column] = knex.raw(`jsonb_set(${column}, ${toPgJsonPathLiteral(access)}, ${value}, true)`, [target, val]);
|
|
118
|
+
}
|
|
119
|
+
delete model[key];
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
convertedJson[key] = val;
|
|
123
|
+
}
|
|
146
124
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
return convertedJson;
|
|
125
|
+
return convertedJson;
|
|
150
126
|
}
|
|
151
|
-
|
|
152
127
|
module.exports = {
|
|
153
|
-
|
|
154
|
-
|
|
128
|
+
UpdateOperation,
|
|
129
|
+
convertFieldExpressionsToRaw,
|
|
155
130
|
};
|
|
@@ -1,45 +1,35 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const { DelegateOperation } = require('./DelegateOperation');
|
|
4
3
|
const { UpsertGraphOperation } = require('./UpsertGraphOperation');
|
|
5
4
|
const { RelationExpression } = require('../RelationExpression');
|
|
6
|
-
|
|
7
5
|
class UpsertGraphAndFetchOperation extends DelegateOperation {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
constructor(name, opt) {
|
|
7
|
+
super(name, opt);
|
|
8
|
+
if (!this.delegate.is(UpsertGraphOperation)) {
|
|
9
|
+
throw new Error('Invalid delegate');
|
|
10
|
+
}
|
|
13
11
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
12
|
+
get models() {
|
|
13
|
+
return this.delegate.models;
|
|
14
|
+
}
|
|
15
|
+
get isArray() {
|
|
16
|
+
return this.delegate.isArray;
|
|
17
|
+
}
|
|
18
|
+
async onAfter3(builder) {
|
|
19
|
+
if (this.models.length === 0) {
|
|
20
|
+
return this.isArray ? [] : null;
|
|
21
|
+
}
|
|
22
|
+
const eager = RelationExpression.fromModelGraph(this.models);
|
|
23
|
+
const modelClass = this.models[0].constructor;
|
|
24
|
+
const ids = this.models.map((model) => model.$id());
|
|
25
|
+
const models = await modelClass
|
|
26
|
+
.query()
|
|
27
|
+
.childQueryOf(builder)
|
|
28
|
+
.findByIds(ids)
|
|
29
|
+
.withGraphFetched(eager);
|
|
30
|
+
return this.isArray ? models : models[0] || null;
|
|
27
31
|
}
|
|
28
|
-
|
|
29
|
-
const eager = RelationExpression.fromModelGraph(this.models);
|
|
30
|
-
const modelClass = this.models[0].constructor;
|
|
31
|
-
const ids = this.models.map((model) => model.$id());
|
|
32
|
-
|
|
33
|
-
const models = await modelClass
|
|
34
|
-
.query()
|
|
35
|
-
.childQueryOf(builder)
|
|
36
|
-
.findByIds(ids)
|
|
37
|
-
.withGraphFetched(eager);
|
|
38
|
-
|
|
39
|
-
return this.isArray ? models : models[0] || null;
|
|
40
|
-
}
|
|
41
32
|
}
|
|
42
|
-
|
|
43
33
|
module.exports = {
|
|
44
|
-
|
|
34
|
+
UpsertGraphAndFetchOperation,
|
|
45
35
|
};
|