@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,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const promiseUtils = require('../../../utils/promiseUtils');
|
|
4
|
-
|
|
5
3
|
const { EagerOperation } = require('./EagerOperation');
|
|
6
4
|
const { isMsSql, isOracle, isSqlite } = require('../../../utils/knexUtils');
|
|
7
5
|
const { isObject, asArray, flatten, chunk } = require('../../../utils/objectUtils');
|
|
@@ -9,277 +7,221 @@ const { ValidationErrorType } = require('../../../model/ValidationError');
|
|
|
9
7
|
const { createModifier } = require('../../../utils/createModifier');
|
|
10
8
|
const { RelationDoesNotExistError } = require('../../../model/RelationDoesNotExistError');
|
|
11
9
|
const { RelationOwner } = require('../../../relations/RelationOwner');
|
|
12
|
-
|
|
10
|
+
const { getReadConcurrency } = require('../../../model/modelConcurrency');
|
|
13
11
|
class WhereInEagerOperation extends EagerOperation {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
this.omitProps = [];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
batchSize(knex) {
|
|
22
|
-
if (this.graphOptions.maxBatchSize) {
|
|
23
|
-
return this.graphOptions.maxBatchSize;
|
|
24
|
-
} else if (isMsSql(knex)) {
|
|
25
|
-
// On MSSQL the parameter limit is actually 2100, but since I couldn't figure out
|
|
26
|
-
// if the limit is for all parameters in a query or for individual clauses, we set
|
|
27
|
-
// the limit to 2000 to leave 100 parameters for where clauses etc.
|
|
28
|
-
return 2000;
|
|
29
|
-
} else if (isOracle(knex)) {
|
|
30
|
-
return 1000;
|
|
31
|
-
} else if (isSqlite(knex)) {
|
|
32
|
-
// SQLITE_MAX_VARIABLE_NUMBER is 999 by default
|
|
33
|
-
return 999;
|
|
34
|
-
} else {
|
|
35
|
-
// I'm sure there is some kind of limit for other databases too, but let's lower
|
|
36
|
-
// this if someone ever hits those limits.
|
|
37
|
-
return 10000;
|
|
12
|
+
constructor(name, opt) {
|
|
13
|
+
super(name, opt);
|
|
14
|
+
this.relationsToFetch = [];
|
|
15
|
+
this.omitProps = [];
|
|
38
16
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return result;
|
|
17
|
+
batchSize(knex) {
|
|
18
|
+
if (this.graphOptions.maxBatchSize) {
|
|
19
|
+
return this.graphOptions.maxBatchSize;
|
|
20
|
+
}
|
|
21
|
+
else if (isMsSql(knex)) {
|
|
22
|
+
// On MSSQL the parameter limit is actually 2100, but since I couldn't figure out
|
|
23
|
+
// if the limit is for all parameters in a query or for individual clauses, we set
|
|
24
|
+
// the limit to 2000 to leave 100 parameters for where clauses etc.
|
|
25
|
+
return 2000;
|
|
26
|
+
}
|
|
27
|
+
else if (isOracle(knex)) {
|
|
28
|
+
return 1000;
|
|
29
|
+
}
|
|
30
|
+
else if (isSqlite(knex)) {
|
|
31
|
+
// SQLITE_MAX_VARIABLE_NUMBER is 999 by default
|
|
32
|
+
return 999;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// I'm sure there is some kind of limit for other databases too, but let's lower
|
|
36
|
+
// this if someone ever hits those limits.
|
|
37
|
+
return 10000;
|
|
38
|
+
}
|
|
62
39
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
40
|
+
onBuild(builder) {
|
|
41
|
+
const relationsToFetch = findRelationsToFetch(builder.modelClass(), this.buildFinalExpression());
|
|
42
|
+
const { selectionsToAdd, selectedProps } = findRelationPropsToSelect(builder, relationsToFetch);
|
|
43
|
+
if (selectionsToAdd.length) {
|
|
44
|
+
builder.select(selectionsToAdd);
|
|
45
|
+
}
|
|
46
|
+
this.relationsToFetch = relationsToFetch;
|
|
47
|
+
this.omitProps = selectedProps;
|
|
69
48
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
49
|
+
async onAfter2(builder, result) {
|
|
50
|
+
const modelClass = builder.resultModelClass();
|
|
51
|
+
if (!result) {
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
const models = asArray(result);
|
|
55
|
+
// Check models to be actual objects, to filter out `count` results (#2397).
|
|
56
|
+
if (!models.length || !isObject(models[0])) {
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
await promiseUtils.map(this.relationsToFetch, (it) => this.fetchRelation(builder, models, it.relation, it.childExpression), { concurrency: getReadConcurrency(modelClass, builder.unsafeKnex()) });
|
|
60
|
+
const intOpt = builder.internalOptions();
|
|
61
|
+
if (!this.omitProps.length || intOpt.keepImplicitJoinProps) {
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
// Now that relations have been fetched for `models` we can omit the
|
|
65
|
+
// columns that were implicitly selected by this class.
|
|
66
|
+
for (let i = 0, l = result.length; i < l; ++i) {
|
|
67
|
+
const model = result[i];
|
|
68
|
+
for (let c = 0, lc = this.omitProps.length; c < lc; ++c) {
|
|
69
|
+
modelClass.omitImpl(model, this.omitProps[c]);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
81
73
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
74
|
+
async fetchRelation(builder, models, relation, expr) {
|
|
75
|
+
const modelClass = builder.resultModelClass();
|
|
76
|
+
const batchSize = this.batchSize(builder.knex());
|
|
77
|
+
const modelBatches = chunk(models, batchSize);
|
|
78
|
+
const result = await promiseUtils.map(modelBatches, (batch) => this.fetchRelationBatch(builder, batch, relation, expr), {
|
|
79
|
+
concurrency: getReadConcurrency(modelClass, builder.unsafeKnex()),
|
|
80
|
+
});
|
|
81
|
+
return flatten(result);
|
|
91
82
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
83
|
+
fetchRelationBatch(builder, models, relation, expr) {
|
|
84
|
+
if (this.shouldSkipFetched(models, relation, expr)) {
|
|
85
|
+
return this.createSkippedQuery(builder, models, relation, expr);
|
|
86
|
+
}
|
|
87
|
+
const queryBuilder = this.createRelationQuery(builder, relation, expr);
|
|
88
|
+
const findOperation = relation.find(queryBuilder, RelationOwner.create(models));
|
|
89
|
+
findOperation.alwaysReturnArray = true;
|
|
90
|
+
findOperation.assignResultToOwner = true;
|
|
91
|
+
findOperation.relationProperty = expr.node.$name;
|
|
92
|
+
queryBuilder.addOperation(findOperation, []);
|
|
93
|
+
for (const modifierName of expr.node.$modify) {
|
|
94
|
+
const modifier = createModifier({
|
|
95
|
+
modifier: modifierName,
|
|
96
|
+
modelClass: relation.relatedModelClass,
|
|
97
|
+
modifiers: this.buildFinalModifiers(builder),
|
|
98
|
+
});
|
|
99
|
+
try {
|
|
100
|
+
modifier(queryBuilder);
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
const modelClass = builder.modelClass();
|
|
104
|
+
if (err instanceof modelClass.ModifierNotFoundError) {
|
|
105
|
+
throw modelClass.createValidationError({
|
|
106
|
+
type: ValidationErrorType.RelationExpression,
|
|
107
|
+
message: `could not find modifier "${modifierName}" for relation "${relation.name}"`,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
throw err;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return queryBuilder;
|
|
115
116
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (err instanceof modelClass.ModifierNotFoundError) {
|
|
139
|
-
throw modelClass.createValidationError({
|
|
140
|
-
type: ValidationErrorType.RelationExpression,
|
|
141
|
-
message: `could not find modifier "${modifierName}" for relation "${relation.name}"`,
|
|
142
|
-
});
|
|
143
|
-
} else {
|
|
144
|
-
throw err;
|
|
117
|
+
shouldSkipFetched(models, relation, expr) {
|
|
118
|
+
if (!this.graphOptions.skipFetched) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
if (models.some((it) => it[expr.node.$name] === undefined)) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
const relationsToFetch = findRelationsToFetch(relation.relatedModelClass, expr);
|
|
125
|
+
const childModels = getRelatedModels(models, expr);
|
|
126
|
+
// We can only skip fetching a relation if all already fetched models
|
|
127
|
+
// have all needed relation properties so that we can fetch the next
|
|
128
|
+
// level of relations.
|
|
129
|
+
for (const { relation } of relationsToFetch) {
|
|
130
|
+
const { ownerProp } = relation;
|
|
131
|
+
for (let c = 0, lc = ownerProp.size; c < lc; ++c) {
|
|
132
|
+
const prop = ownerProp.props[c];
|
|
133
|
+
for (const model of childModels) {
|
|
134
|
+
if (model[prop] === undefined) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
145
139
|
}
|
|
146
|
-
|
|
140
|
+
return true;
|
|
147
141
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
142
|
+
createSkippedQuery(builder, models, relation, expr) {
|
|
143
|
+
const childModels = getRelatedModels(models, expr);
|
|
144
|
+
return relation.relatedModelClass
|
|
145
|
+
.query()
|
|
146
|
+
.childQueryOf(builder)
|
|
147
|
+
.findOptions({ dontCallFindHooks: true })
|
|
148
|
+
.withGraphFetched(expr, this.graphOptions)
|
|
149
|
+
.resolve(childModels);
|
|
155
150
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
151
|
+
createRelationQuery(builder, relation, expr) {
|
|
152
|
+
return relation.relatedModelClass
|
|
153
|
+
.query()
|
|
154
|
+
.childQueryOf(builder)
|
|
155
|
+
.withGraphFetched(expr, this.graphOptions)
|
|
156
|
+
.modifiers(this.buildFinalModifiers(builder));
|
|
159
157
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
// have all needed relation properties so that we can fetch the next
|
|
166
|
-
// level of relations.
|
|
167
|
-
for (const { relation } of relationsToFetch) {
|
|
168
|
-
const { ownerProp } = relation;
|
|
169
|
-
|
|
170
|
-
for (let c = 0, lc = ownerProp.size; c < lc; ++c) {
|
|
171
|
-
const prop = ownerProp.props[c];
|
|
172
|
-
|
|
173
|
-
for (const model of childModels) {
|
|
174
|
-
if (model[prop] === undefined) {
|
|
175
|
-
return false;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
158
|
+
clone() {
|
|
159
|
+
const clone = super.clone();
|
|
160
|
+
clone.relationsToFetch = this.relationsToFetch.slice();
|
|
161
|
+
clone.omitProps = this.omitProps.slice();
|
|
162
|
+
return clone;
|
|
179
163
|
}
|
|
180
|
-
|
|
181
|
-
return true;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
createSkippedQuery(builder, models, relation, expr) {
|
|
185
|
-
const childModels = getRelatedModels(models, expr);
|
|
186
|
-
|
|
187
|
-
return relation.relatedModelClass
|
|
188
|
-
.query()
|
|
189
|
-
.childQueryOf(builder)
|
|
190
|
-
.findOptions({ dontCallFindHooks: true })
|
|
191
|
-
.withGraphFetched(expr, this.graphOptions)
|
|
192
|
-
.resolve(childModels);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
createRelationQuery(builder, relation, expr) {
|
|
196
|
-
return relation.relatedModelClass
|
|
197
|
-
.query()
|
|
198
|
-
.childQueryOf(builder)
|
|
199
|
-
.withGraphFetched(expr, this.graphOptions)
|
|
200
|
-
.modifiers(this.buildFinalModifiers(builder));
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
clone() {
|
|
204
|
-
const clone = super.clone();
|
|
205
|
-
|
|
206
|
-
clone.relationsToFetch = this.relationsToFetch.slice();
|
|
207
|
-
clone.omitProps = this.omitProps.slice();
|
|
208
|
-
|
|
209
|
-
return clone;
|
|
210
|
-
}
|
|
211
164
|
}
|
|
212
|
-
|
|
213
165
|
function findRelationsToFetch(modelClass, eagerExpression) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
166
|
+
const relationsToFetch = [];
|
|
167
|
+
try {
|
|
168
|
+
eagerExpression.forEachChildExpression(modelClass, (childExpression, relation) => {
|
|
169
|
+
relationsToFetch.push({
|
|
170
|
+
childExpression,
|
|
171
|
+
relation,
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
if (err instanceof RelationDoesNotExistError) {
|
|
177
|
+
throw modelClass.createValidationError({
|
|
178
|
+
type: ValidationErrorType.RelationExpression,
|
|
179
|
+
message: `unknown relation "${err.relationName}" in an eager expression`,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
throw err;
|
|
229
183
|
}
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
return relationsToFetch;
|
|
184
|
+
return relationsToFetch;
|
|
234
185
|
}
|
|
235
|
-
|
|
236
186
|
function findRelationPropsToSelect(builder, relationsToFetch) {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
selectionsToAdd.push(fullCol);
|
|
253
|
-
}
|
|
187
|
+
const selectionsToAdd = [];
|
|
188
|
+
const selectedProps = [];
|
|
189
|
+
// Collect columns that need to be selected for the eager fetch
|
|
190
|
+
// to work that are not currently selected.
|
|
191
|
+
for (const { relation } of relationsToFetch) {
|
|
192
|
+
const ownerProp = relation.ownerProp;
|
|
193
|
+
for (let c = 0, lc = ownerProp.size; c < lc; ++c) {
|
|
194
|
+
const fullCol = ownerProp.ref(builder, c).fullColumn(builder);
|
|
195
|
+
const prop = ownerProp.props[c];
|
|
196
|
+
const col = ownerProp.cols[c];
|
|
197
|
+
if (!builder.hasSelectionAs(fullCol, col) && selectionsToAdd.indexOf(fullCol) === -1) {
|
|
198
|
+
selectedProps.push(prop);
|
|
199
|
+
selectionsToAdd.push(fullCol);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
254
202
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
selectedProps,
|
|
260
|
-
};
|
|
203
|
+
return {
|
|
204
|
+
selectionsToAdd,
|
|
205
|
+
selectedProps,
|
|
206
|
+
};
|
|
261
207
|
}
|
|
262
|
-
|
|
263
208
|
function getRelatedModels(models, expr) {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
209
|
+
const allRelated = [];
|
|
210
|
+
for (const model of models) {
|
|
211
|
+
const related = model[expr.node.$name];
|
|
212
|
+
if (related) {
|
|
213
|
+
if (Array.isArray(related)) {
|
|
214
|
+
for (const rel of related) {
|
|
215
|
+
allRelated.push(rel);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
allRelated.push(related);
|
|
220
|
+
}
|
|
273
221
|
}
|
|
274
|
-
} else {
|
|
275
|
-
allRelated.push(related);
|
|
276
|
-
}
|
|
277
222
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
return allRelated;
|
|
223
|
+
return allRelated;
|
|
281
224
|
}
|
|
282
|
-
|
|
283
225
|
module.exports = {
|
|
284
|
-
|
|
226
|
+
WhereInEagerOperation,
|
|
285
227
|
};
|
|
@@ -1,36 +1,29 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const postgresJsonApi = require('./postgresJsonApi');
|
|
4
3
|
const mysqlJsonApi = require('./mysqlJsonApi');
|
|
5
4
|
const { getJsonDialect } = require('../../../utils/postgresJsonPath');
|
|
5
|
+
const { jsonCastsForDialect } = require('../../../utils/mysqlJsonPath');
|
|
6
6
|
const { ObjectionToKnexConvertingOperation } = require('../ObjectionToKnexConvertingOperation');
|
|
7
|
-
|
|
8
7
|
// `whereJsonHasAny` and `whereJsonHasAll`.
|
|
9
8
|
class WhereJsonHasOperation extends ObjectionToKnexConvertingOperation {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
} else {
|
|
27
|
-
knexBuilder = knexBuilder.whereRaw(sql, bindings);
|
|
9
|
+
onBuildKnex(knexBuilder, builder) {
|
|
10
|
+
const dialect = getJsonDialect(builder.unsafeKnex(), this.name);
|
|
11
|
+
const args = this.getKnexArgs(builder);
|
|
12
|
+
let [sql, bindings] = dialect === 'mysql'
|
|
13
|
+
? mysqlJsonApi.whereJsonHas(args[0], this.opt.operator, args[1], builder.unsafeKnex())
|
|
14
|
+
: postgresJsonApi.whereJsonFieldRightStringArrayOnLeftQuery(builder.knex(), args[0], this.opt.operator, args[1]);
|
|
15
|
+
if (dialect === 'mysql') {
|
|
16
|
+
sql = jsonCastsForDialect(sql, builder.unsafeKnex());
|
|
17
|
+
}
|
|
18
|
+
if (this.opt.bool === 'or') {
|
|
19
|
+
knexBuilder = knexBuilder.orWhereRaw(sql, bindings);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
knexBuilder = knexBuilder.whereRaw(sql, bindings);
|
|
23
|
+
}
|
|
24
|
+
return knexBuilder;
|
|
28
25
|
}
|
|
29
|
-
|
|
30
|
-
return knexBuilder;
|
|
31
|
-
}
|
|
32
26
|
}
|
|
33
|
-
|
|
34
27
|
module.exports = {
|
|
35
|
-
|
|
28
|
+
WhereJsonHasOperation,
|
|
36
29
|
};
|
|
@@ -1,53 +1,37 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const jsonApi = require('./postgresJsonApi');
|
|
4
3
|
const mysqlJsonApi = require('./mysqlJsonApi');
|
|
5
4
|
const { getJsonDialect } = require('../../../utils/postgresJsonPath');
|
|
5
|
+
const { jsonCastsForDialect } = require('../../../utils/mysqlJsonPath');
|
|
6
6
|
const { ObjectionToKnexConvertingOperation } = require('../ObjectionToKnexConvertingOperation');
|
|
7
|
-
|
|
8
7
|
// `whereJsonNotArray` and `whereJsonNotObject`.
|
|
9
8
|
class WhereJsonNotObjectOperation extends ObjectionToKnexConvertingOperation {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
? knexBuilder.orWhereRaw(sql, bindings)
|
|
22
|
-
: knexBuilder.whereRaw(sql, bindings);
|
|
9
|
+
onBuildKnex(knexBuilder, builder) {
|
|
10
|
+
const dialect = getJsonDialect(builder.unsafeKnex(), this.name);
|
|
11
|
+
const fieldExpression = this.getKnexArgs(builder)[0];
|
|
12
|
+
if (dialect === 'mysql') {
|
|
13
|
+
const [rawSql, bindings] = mysqlJsonApi.whereJsonNotContains(fieldExpression, this.opt.compareValue);
|
|
14
|
+
const sql = jsonCastsForDialect(rawSql, builder.unsafeKnex());
|
|
15
|
+
return this.opt.bool === 'or'
|
|
16
|
+
? knexBuilder.orWhereRaw(sql, bindings)
|
|
17
|
+
: knexBuilder.whereRaw(sql, bindings);
|
|
18
|
+
}
|
|
19
|
+
return this.whereJsonNotObject(knexBuilder, builder.knex(), fieldExpression);
|
|
23
20
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
builder.orWhereRaw(...jsonApi.whereJsonFieldQuery(knex, fieldExpression, 'IS', null));
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
if (this.opt.bool === 'or') {
|
|
42
|
-
knexBuilder = knexBuilder.orWhere(innerQuery);
|
|
43
|
-
} else {
|
|
44
|
-
knexBuilder = knexBuilder.where(innerQuery);
|
|
21
|
+
whereJsonNotObject(knexBuilder, knex, fieldExpression) {
|
|
22
|
+
const innerQuery = (innerQuery) => {
|
|
23
|
+
const builder = jsonApi.whereJsonbRefOnLeftJsonbValOrRefOnRight(innerQuery, fieldExpression, '@>', this.opt.compareValue, 'not');
|
|
24
|
+
builder.orWhereRaw(...jsonApi.whereJsonFieldQuery(knex, fieldExpression, 'IS', null));
|
|
25
|
+
};
|
|
26
|
+
if (this.opt.bool === 'or') {
|
|
27
|
+
knexBuilder = knexBuilder.orWhere(innerQuery);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
knexBuilder = knexBuilder.where(innerQuery);
|
|
31
|
+
}
|
|
32
|
+
return knexBuilder;
|
|
45
33
|
}
|
|
46
|
-
|
|
47
|
-
return knexBuilder;
|
|
48
|
-
}
|
|
49
34
|
}
|
|
50
|
-
|
|
51
35
|
module.exports = {
|
|
52
|
-
|
|
36
|
+
WhereJsonNotObjectOperation,
|
|
53
37
|
};
|