@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,22 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const { QueryTransformation } = require('./QueryTransformation');
|
|
4
|
-
|
|
5
3
|
class CompositeQueryTransformation extends QueryTransformation {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
constructor(transformations) {
|
|
5
|
+
super();
|
|
6
|
+
this.transformations = transformations;
|
|
7
|
+
}
|
|
8
|
+
onConvertQueryBuilderBase(item, builder) {
|
|
9
|
+
for (const transformation of this.transformations) {
|
|
10
|
+
item = transformation.onConvertQueryBuilderBase(item, builder);
|
|
11
|
+
}
|
|
12
|
+
return item;
|
|
14
13
|
}
|
|
15
|
-
|
|
16
|
-
return item;
|
|
17
|
-
}
|
|
18
14
|
}
|
|
19
|
-
|
|
20
15
|
module.exports = {
|
|
21
|
-
|
|
16
|
+
CompositeQueryTransformation,
|
|
22
17
|
};
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
class QueryTransformation {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
onConvertQueryBuilderBase(item, builder) {
|
|
4
|
+
return item;
|
|
5
|
+
}
|
|
7
6
|
}
|
|
8
|
-
|
|
9
7
|
module.exports = {
|
|
10
|
-
|
|
8
|
+
QueryTransformation,
|
|
11
9
|
};
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const { QueryTransformation } = require('./QueryTransformation');
|
|
4
3
|
const { isMySql } = require('../../utils/knexUtils');
|
|
5
|
-
|
|
6
4
|
/**
|
|
7
5
|
* Mysql doesn't allow queries like this:
|
|
8
6
|
*
|
|
@@ -16,56 +14,44 @@ const { isMySql } = require('../../utils/knexUtils');
|
|
|
16
14
|
* update foo set bar = 1 where id in (select * from (select id from foo))
|
|
17
15
|
*/
|
|
18
16
|
class WrapMysqlModifySubqueryTransformation extends QueryTransformation {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
onConvertQueryBuilderBase(query, parentQuery) {
|
|
18
|
+
const knex = parentQuery.unsafeKnex();
|
|
19
|
+
// Cannot detect anything if, for whatever reason, a knex instance
|
|
20
|
+
// or a transaction is not registered at this point.
|
|
21
|
+
if (!knex) {
|
|
22
|
+
return query;
|
|
23
|
+
}
|
|
24
|
+
// This transformation only applies to MySQL.
|
|
25
|
+
if (!isMySql(knex)) {
|
|
26
|
+
return query;
|
|
27
|
+
}
|
|
28
|
+
// A subquery in a join callback belongs to the query of the join.
|
|
29
|
+
while (parentQuery && typeof parentQuery.isUpdate !== 'function') {
|
|
30
|
+
parentQuery = parentQuery.parentQuery();
|
|
31
|
+
}
|
|
32
|
+
// This transformation only applies to update and delete queries.
|
|
33
|
+
if (!parentQuery || (!parentQuery.isUpdate() && !parentQuery.isDelete())) {
|
|
34
|
+
return query;
|
|
35
|
+
}
|
|
36
|
+
// If the subquery is for another table and the query doesn't join the
|
|
37
|
+
// parent query's table, we're good to go.
|
|
38
|
+
if (parentQuery.tableName() !== query.tableName() &&
|
|
39
|
+
!hasJoinsToTable(query, parentQuery.tableName())) {
|
|
40
|
+
return query;
|
|
41
|
+
}
|
|
42
|
+
return query.modelClass().query().from(query.as('mysql_subquery_fix'));
|
|
26
43
|
}
|
|
27
|
-
|
|
28
|
-
// This transformation only applies to MySQL.
|
|
29
|
-
if (!isMySql(knex)) {
|
|
30
|
-
return query;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// A subquery in a join callback belongs to the query of the join.
|
|
34
|
-
while (parentQuery && typeof parentQuery.isUpdate !== 'function') {
|
|
35
|
-
parentQuery = parentQuery.parentQuery();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// This transformation only applies to update and delete queries.
|
|
39
|
-
if (!parentQuery || (!parentQuery.isUpdate() && !parentQuery.isDelete())) {
|
|
40
|
-
return query;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// If the subquery is for another table and the query doesn't join the
|
|
44
|
-
// parent query's table, we're good to go.
|
|
45
|
-
if (
|
|
46
|
-
parentQuery.tableName() !== query.tableName() &&
|
|
47
|
-
!hasJoinsToTable(query, parentQuery.tableName())
|
|
48
|
-
) {
|
|
49
|
-
return query;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return query.modelClass().query().from(query.as('mysql_subquery_fix'));
|
|
53
|
-
}
|
|
54
44
|
}
|
|
55
|
-
|
|
56
45
|
function hasJoinsToTable(query, tableName) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return found;
|
|
46
|
+
let found = false;
|
|
47
|
+
query.forEachOperation(query.constructor.JoinSelector, (op) => {
|
|
48
|
+
if (op.args[0] === tableName) {
|
|
49
|
+
found = true;
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
return found;
|
|
67
54
|
}
|
|
68
|
-
|
|
69
55
|
module.exports = {
|
|
70
|
-
|
|
56
|
+
WrapMysqlModifySubqueryTransformation,
|
|
71
57
|
};
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const { CompositeQueryTransformation } = require('./CompositeQueryTransformation');
|
|
4
|
-
|
|
5
|
-
const {
|
|
6
|
-
WrapMysqlModifySubqueryTransformation,
|
|
7
|
-
} = require('./WrapMysqlModifySubqueryTransformation');
|
|
8
|
-
|
|
3
|
+
const { WrapMysqlModifySubqueryTransformation, } = require('./WrapMysqlModifySubqueryTransformation');
|
|
9
4
|
const transformation = new CompositeQueryTransformation([
|
|
10
|
-
|
|
5
|
+
new WrapMysqlModifySubqueryTransformation(),
|
|
11
6
|
]);
|
|
12
|
-
|
|
13
7
|
module.exports = {
|
|
14
|
-
|
|
8
|
+
transformation,
|
|
15
9
|
};
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
2
|
const { isObject, isFunction } = require('../utils/objectUtils');
|
|
4
3
|
const { isKnexRaw } = require('../utils/knexUtils');
|
|
5
|
-
|
|
6
4
|
// Where clauses objection adds on its own, like the owner condition of a relation
|
|
7
5
|
// query or the id condition of `$query()`, are tagged with a "where scope". When
|
|
8
6
|
// a query has where clauses from more than one scope, the clauses of each scope
|
|
@@ -12,216 +10,190 @@ const { isKnexRaw } = require('../utils/knexUtils');
|
|
|
12
10
|
//
|
|
13
11
|
// The scopes are only used when the knex query is built. The operation tree is
|
|
14
12
|
// never modified.
|
|
15
|
-
|
|
16
13
|
const WhereSelector = /^(where|orWhere|andWhere|find\w+)/;
|
|
17
|
-
|
|
18
14
|
// Where operations that only ever produce a single predicate or predicates
|
|
19
15
|
// joined with `and`. A scope that only contains these (and no raw arguments)
|
|
20
16
|
// doesn't need to be wrapped in parentheses.
|
|
21
17
|
const AND_ONLY_OPERATIONS = new Set([
|
|
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
|
-
|
|
18
|
+
'where',
|
|
19
|
+
'andWhere',
|
|
20
|
+
'whereNot',
|
|
21
|
+
'andWhereNot',
|
|
22
|
+
'whereIn',
|
|
23
|
+
'whereNotIn',
|
|
24
|
+
'whereNull',
|
|
25
|
+
'whereNotNull',
|
|
26
|
+
'whereBetween',
|
|
27
|
+
'whereNotBetween',
|
|
28
|
+
'whereExists',
|
|
29
|
+
'whereNotExists',
|
|
30
|
+
'whereColumn',
|
|
31
|
+
'andWhereColumn',
|
|
32
|
+
'whereNotColumn',
|
|
33
|
+
'andWhereNotColumn',
|
|
34
|
+
'whereLike',
|
|
35
|
+
'whereILike',
|
|
36
|
+
'whereWrapped',
|
|
37
|
+
'whereComposite',
|
|
38
|
+
'whereInComposite',
|
|
39
|
+
'whereJsonSupersetOf',
|
|
40
|
+
'whereJsonSubsetOf',
|
|
41
|
+
'whereJsonNotSupersetOf',
|
|
42
|
+
'whereJsonNotSubsetOf',
|
|
43
|
+
'whereJsonHasAny',
|
|
44
|
+
'whereJsonHasAll',
|
|
45
|
+
'whereJsonNotArray',
|
|
46
|
+
'whereJsonNotObject',
|
|
47
|
+
'whereJsonOverlaps',
|
|
48
|
+
'whereJsonNotOverlaps',
|
|
49
|
+
'whereJsonObject',
|
|
50
|
+
'whereNotJsonObject',
|
|
51
|
+
'whereJsonPath',
|
|
52
|
+
'findById',
|
|
53
|
+
'findByIds',
|
|
58
54
|
]);
|
|
59
|
-
|
|
60
55
|
function withWhereScope(builder, callback) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
56
|
+
const previous = builder._whereScope;
|
|
57
|
+
// A fresh object works as a unique token.
|
|
58
|
+
builder._whereScope = {};
|
|
59
|
+
try {
|
|
60
|
+
return callback();
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
builder._whereScope = previous;
|
|
64
|
+
}
|
|
70
65
|
}
|
|
71
|
-
|
|
72
66
|
function effectiveWhereScope(op) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return null;
|
|
67
|
+
while (op) {
|
|
68
|
+
if (op.whereScope !== null) {
|
|
69
|
+
return op.whereScope;
|
|
70
|
+
}
|
|
71
|
+
op = op.parentOperation;
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
82
74
|
}
|
|
83
|
-
|
|
84
75
|
// Returns null if no where clauses need to be grouped. Otherwise returns an
|
|
85
76
|
// object that tells, for each operation, whether the operation is built as
|
|
86
77
|
// part of a group.
|
|
87
78
|
function createWhereGrouping(builder) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
groupByFirstOp.set(ops[0], ops);
|
|
113
|
-
|
|
114
|
-
for (const op of ops) {
|
|
115
|
-
groupedOps.add(op);
|
|
116
|
-
op.forEachDescendantOperation((it) => {
|
|
117
|
-
groupedOps.add(it);
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (groupedOps.size === 0) {
|
|
123
|
-
return null;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return {
|
|
127
|
-
isGrouped(op) {
|
|
128
|
-
return groupedOps.has(op);
|
|
129
|
-
},
|
|
130
|
-
|
|
131
|
-
// Builds the whole group if `op` is the first operation of a group.
|
|
132
|
-
build(op, knexBuilder) {
|
|
133
|
-
const ops = groupByFirstOp.get(op);
|
|
134
|
-
|
|
135
|
-
if (!ops) {
|
|
136
|
-
return knexBuilder;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return knexBuilder.where(function () {
|
|
140
|
-
let groupBuilder = this;
|
|
141
|
-
|
|
142
|
-
for (const groupOp of ops) {
|
|
143
|
-
groupBuilder = buildOperationTree(builder, groupOp, groupBuilder);
|
|
79
|
+
const scopes = new Map();
|
|
80
|
+
builder.forEachOperation(WhereSelector, (op) => {
|
|
81
|
+
if (!hasWhereAncestor(op)) {
|
|
82
|
+
const scope = effectiveWhereScope(op);
|
|
83
|
+
const ops = scopes.get(scope) || [];
|
|
84
|
+
ops.push(op);
|
|
85
|
+
scopes.set(scope, ops);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
if (scopes.size < 2) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
const groupByFirstOp = new Map();
|
|
92
|
+
const groupedOps = new Set();
|
|
93
|
+
for (const ops of scopes.values()) {
|
|
94
|
+
if (ops.every(isAndOnlyTree)) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
groupByFirstOp.set(ops[0], ops);
|
|
98
|
+
for (const op of ops) {
|
|
99
|
+
groupedOps.add(op);
|
|
100
|
+
op.forEachDescendantOperation((it) => {
|
|
101
|
+
groupedOps.add(it);
|
|
102
|
+
});
|
|
144
103
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
104
|
+
}
|
|
105
|
+
if (groupedOps.size === 0) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
isGrouped(op) {
|
|
110
|
+
return groupedOps.has(op);
|
|
111
|
+
},
|
|
112
|
+
// Builds the whole group if `op` is the first operation of a group.
|
|
113
|
+
build(op, knexBuilder) {
|
|
114
|
+
const ops = groupByFirstOp.get(op);
|
|
115
|
+
if (!ops) {
|
|
116
|
+
return knexBuilder;
|
|
117
|
+
}
|
|
118
|
+
return knexBuilder.where(function () {
|
|
119
|
+
let groupBuilder = this;
|
|
120
|
+
for (const groupOp of ops) {
|
|
121
|
+
groupBuilder = buildOperationTree(builder, groupOp, groupBuilder);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
},
|
|
125
|
+
};
|
|
148
126
|
}
|
|
149
|
-
|
|
150
127
|
function buildOperationTree(builder, op, knexBuilder) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return knexBuilder;
|
|
128
|
+
const ops = [op];
|
|
129
|
+
op.forEachDescendantOperation((it) => {
|
|
130
|
+
ops.push(it);
|
|
131
|
+
});
|
|
132
|
+
for (const it of ops) {
|
|
133
|
+
if (it.hasOnBuildKnex()) {
|
|
134
|
+
knexBuilder =
|
|
135
|
+
builder.callOperationMethod(it, 'onBuildKnex', [knexBuilder, builder]) || knexBuilder;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return knexBuilder;
|
|
165
139
|
}
|
|
166
|
-
|
|
167
140
|
function hasWhereAncestor(op) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
141
|
+
for (let parent = op.parentOperation; parent; parent = parent.parentOperation) {
|
|
142
|
+
if (WhereSelector.test(parent.name)) {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
171
145
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
return false;
|
|
146
|
+
return false;
|
|
175
147
|
}
|
|
176
|
-
|
|
177
148
|
function isAndOnlyTree(op) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
return andOnly;
|
|
149
|
+
if (!isAndOnly(op)) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
let andOnly = true;
|
|
153
|
+
op.forEachDescendantOperation((it) => {
|
|
154
|
+
if (it.hasOnBuildKnex() && !isAndOnly(it)) {
|
|
155
|
+
andOnly = false;
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
return andOnly;
|
|
192
160
|
}
|
|
193
|
-
|
|
194
161
|
function isAndOnly(op) {
|
|
195
|
-
|
|
162
|
+
return AND_ONLY_OPERATIONS.has(op.name) && !containsRaw(op.args);
|
|
196
163
|
}
|
|
197
|
-
|
|
198
164
|
function containsRaw(value) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
165
|
+
if (Array.isArray(value)) {
|
|
166
|
+
return value.some(containsRaw);
|
|
167
|
+
}
|
|
168
|
+
else if (!isObject(value)) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
else if (value.isObjectionReferenceBuilder) {
|
|
172
|
+
// A reference is always a single (possibly casted) column or json path.
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
else if (value.isObjectionFunctionBuilder) {
|
|
176
|
+
// `fn()` calls and expressions like `ref('a').eq(1)` are wrapped in parentheses,
|
|
177
|
+
// so only their arguments can contain anything.
|
|
178
|
+
return containsRaw(value._args);
|
|
179
|
+
}
|
|
180
|
+
else if (isKnexRaw(value) || isFunction(value.toKnexRaw)) {
|
|
181
|
+
// Raw sql (and anything that is converted into it) can contain anything.
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
else if (value.isObjectionQueryBuilderBase || isFunction(value.toSQL)) {
|
|
185
|
+
// Subqueries are always wrapped in parentheses.
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
else if (Object.getPrototypeOf(value) === Object.prototype) {
|
|
189
|
+
return Object.values(value).some(containsRaw);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
221
194
|
}
|
|
222
|
-
|
|
223
195
|
module.exports = {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
196
|
+
withWhereScope,
|
|
197
|
+
effectiveWhereScope,
|
|
198
|
+
createWhereGrouping,
|
|
227
199
|
};
|