@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.
Files changed (192) hide show
  1. package/README.md +103 -67
  2. package/lib/index.mjs +6 -0
  3. package/lib/initialize.js +6 -9
  4. package/lib/model/AjvValidator.js +235 -282
  5. package/lib/model/Model.js +653 -823
  6. package/lib/model/ModifierNotFoundError.js +5 -7
  7. package/lib/model/NotFoundError.js +14 -18
  8. package/lib/model/RelationDoesNotExistError.js +6 -9
  9. package/lib/model/ValidationError.js +33 -41
  10. package/lib/model/Validator.js +15 -21
  11. package/lib/model/getModel.js +1 -3
  12. package/lib/model/graph/ModelGraph.js +44 -64
  13. package/lib/model/graph/ModelGraphBuilder.js +164 -217
  14. package/lib/model/graph/ModelGraphEdge.js +31 -43
  15. package/lib/model/graph/ModelGraphNode.js +192 -231
  16. package/lib/model/inheritModel.js +9 -18
  17. package/lib/model/modelBindKnex.js +48 -62
  18. package/lib/model/modelClone.js +79 -98
  19. package/lib/model/modelColPropMap.js +16 -26
  20. package/lib/model/modelConcurrency.js +24 -0
  21. package/lib/model/modelId.js +44 -49
  22. package/lib/model/modelJsonAttributes.js +56 -76
  23. package/lib/model/modelParseRelations.js +68 -67
  24. package/lib/model/modelQueryProps.js +76 -107
  25. package/lib/model/modelSet.js +92 -112
  26. package/lib/model/modelTableMetadata.js +60 -72
  27. package/lib/model/modelToJson.js +120 -150
  28. package/lib/model/modelUtils.js +30 -37
  29. package/lib/model/modelValidate.js +34 -42
  30. package/lib/model/modelValues.js +78 -91
  31. package/lib/model/modelVisitor.js +22 -29
  32. package/lib/objection.js +42 -67
  33. package/lib/queryBuilder/FunctionBuilder.js +231 -279
  34. package/lib/queryBuilder/InternalOptions.js +19 -24
  35. package/lib/queryBuilder/JoinBuilder.js +116 -149
  36. package/lib/queryBuilder/QueryBuilder.js +1009 -1271
  37. package/lib/queryBuilder/QueryBuilderBase.js +647 -865
  38. package/lib/queryBuilder/QueryBuilderContext.js +14 -21
  39. package/lib/queryBuilder/QueryBuilderContextBase.js +20 -29
  40. package/lib/queryBuilder/QueryBuilderOperationSupport.js +462 -536
  41. package/lib/queryBuilder/QueryBuilderUserContext.js +19 -25
  42. package/lib/queryBuilder/RawBuilder.js +58 -73
  43. package/lib/queryBuilder/ReferenceBuilder.js +232 -270
  44. package/lib/queryBuilder/RelationExpression.js +322 -380
  45. package/lib/queryBuilder/StaticHookArguments.js +94 -106
  46. package/lib/queryBuilder/ValueBuilder.js +100 -112
  47. package/lib/queryBuilder/expressions.js +86 -116
  48. package/lib/queryBuilder/functions/mysql.js +642 -697
  49. package/lib/queryBuilder/graph/GraphAction.js +44 -59
  50. package/lib/queryBuilder/graph/GraphData.js +7 -9
  51. package/lib/queryBuilder/graph/GraphFetcher.js +115 -151
  52. package/lib/queryBuilder/graph/GraphNodeDbExistence.js +114 -152
  53. package/lib/queryBuilder/graph/GraphOperation.js +16 -22
  54. package/lib/queryBuilder/graph/GraphOptions.js +143 -185
  55. package/lib/queryBuilder/graph/GraphUpsert.js +167 -241
  56. package/lib/queryBuilder/graph/delete/GraphDelete.js +8 -13
  57. package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +44 -62
  58. package/lib/queryBuilder/graph/insert/GraphInsert.js +99 -128
  59. package/lib/queryBuilder/graph/insert/GraphInsertAction.js +151 -193
  60. package/lib/queryBuilder/graph/insert/JoinRowGraphInsertAction.js +57 -79
  61. package/lib/queryBuilder/graph/patch/GraphPatch.js +8 -13
  62. package/lib/queryBuilder/graph/patch/GraphPatchAction.js +181 -234
  63. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsert.js +16 -21
  64. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsertAction.js +80 -110
  65. package/lib/queryBuilder/join/JoinResultColumn.js +14 -18
  66. package/lib/queryBuilder/join/JoinResultParser.js +88 -101
  67. package/lib/queryBuilder/join/RelationJoiner.js +205 -288
  68. package/lib/queryBuilder/join/TableNode.js +117 -144
  69. package/lib/queryBuilder/join/TableTree.js +60 -76
  70. package/lib/queryBuilder/join/utils.js +10 -16
  71. package/lib/queryBuilder/operations/DelegateOperation.js +93 -133
  72. package/lib/queryBuilder/operations/DeleteOperation.js +33 -37
  73. package/lib/queryBuilder/operations/FindByIdOperation.js +20 -28
  74. package/lib/queryBuilder/operations/FindByIdsOperation.js +17 -23
  75. package/lib/queryBuilder/operations/FindOperation.js +114 -131
  76. package/lib/queryBuilder/operations/FirstOperation.js +14 -19
  77. package/lib/queryBuilder/operations/FromOperation.js +69 -88
  78. package/lib/queryBuilder/operations/InsertAndFetchOperation.js +28 -39
  79. package/lib/queryBuilder/operations/InsertGraphAndFetchOperation.js +25 -35
  80. package/lib/queryBuilder/operations/InsertGraphOperation.js +77 -98
  81. package/lib/queryBuilder/operations/InsertOperation.js +132 -165
  82. package/lib/queryBuilder/operations/InstanceDeleteOperation.js +27 -36
  83. package/lib/queryBuilder/operations/InstanceFindOperation.js +9 -13
  84. package/lib/queryBuilder/operations/InstanceInsertOperation.js +13 -17
  85. package/lib/queryBuilder/operations/InstanceUpdateOperation.js +32 -46
  86. package/lib/queryBuilder/operations/JoinRelatedOperation.js +66 -86
  87. package/lib/queryBuilder/operations/KnexOperation.js +4 -7
  88. package/lib/queryBuilder/operations/MergeOperation.js +32 -45
  89. package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +131 -150
  90. package/lib/queryBuilder/operations/OnBuildKnexOperation.js +17 -23
  91. package/lib/queryBuilder/operations/OnBuildOperation.js +17 -23
  92. package/lib/queryBuilder/operations/OnErrorOperation.js +17 -23
  93. package/lib/queryBuilder/operations/QueryBuilderOperation.js +231 -270
  94. package/lib/queryBuilder/operations/RangeOperation.js +30 -40
  95. package/lib/queryBuilder/operations/RelateOperation.js +14 -21
  96. package/lib/queryBuilder/operations/ReturningOperation.js +12 -18
  97. package/lib/queryBuilder/operations/RunAfterOperation.js +17 -23
  98. package/lib/queryBuilder/operations/RunBeforeOperation.js +17 -23
  99. package/lib/queryBuilder/operations/UnrelateOperation.js +12 -17
  100. package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +48 -65
  101. package/lib/queryBuilder/operations/UpdateOperation.js +104 -129
  102. package/lib/queryBuilder/operations/UpsertGraphAndFetchOperation.js +25 -35
  103. package/lib/queryBuilder/operations/UpsertGraphOperation.js +36 -55
  104. package/lib/queryBuilder/operations/WhereCompositeOperation.js +30 -39
  105. package/lib/queryBuilder/operations/WhereInOperation.js +34 -36
  106. package/lib/queryBuilder/operations/eager/EagerOperation.js +37 -52
  107. package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +34 -44
  108. package/lib/queryBuilder/operations/eager/NaiveEagerOperation.js +4 -7
  109. package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +193 -251
  110. package/lib/queryBuilder/operations/jsonApi/WhereJsonHasOperation.js +18 -25
  111. package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectOperation.js +25 -41
  112. package/lib/queryBuilder/operations/jsonApi/WhereJsonOperation.js +19 -20
  113. package/lib/queryBuilder/operations/jsonApi/WhereJsonOverlapsOperation.js +23 -21
  114. package/lib/queryBuilder/operations/jsonApi/mysqlJsonApi.js +106 -118
  115. package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +79 -108
  116. package/lib/queryBuilder/operations/select/SelectOperation.js +37 -53
  117. package/lib/queryBuilder/operations/select/Selection.js +94 -105
  118. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +68 -101
  119. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +65 -75
  120. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +75 -84
  121. package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +760 -859
  122. package/lib/queryBuilder/parsers/relationExpressionParser.js +840 -952
  123. package/lib/queryBuilder/transformations/CompositeQueryTransformation.js +10 -15
  124. package/lib/queryBuilder/transformations/QueryTransformation.js +4 -6
  125. package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +35 -49
  126. package/lib/queryBuilder/transformations/index.js +3 -9
  127. package/lib/queryBuilder/whereScopes.js +158 -186
  128. package/lib/relations/Relation.js +279 -363
  129. package/lib/relations/RelationDeleteOperation.js +16 -22
  130. package/lib/relations/RelationFindOperation.js +100 -133
  131. package/lib/relations/RelationInsertOperation.js +19 -27
  132. package/lib/relations/RelationOwner.js +167 -204
  133. package/lib/relations/RelationProperty.js +177 -217
  134. package/lib/relations/RelationUpdateOperation.js +16 -23
  135. package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +11 -16
  136. package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +24 -35
  137. package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +30 -41
  138. package/lib/relations/belongsToOne/BelongsToOneRelation.js +33 -41
  139. package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +38 -53
  140. package/lib/relations/hasMany/HasManyInsertOperation.js +35 -51
  141. package/lib/relations/hasMany/HasManyRelateOperation.js +38 -54
  142. package/lib/relations/hasMany/HasManyRelation.js +30 -38
  143. package/lib/relations/hasMany/HasManyUnrelateOperation.js +19 -26
  144. package/lib/relations/hasOne/HasOneRelation.js +4 -7
  145. package/lib/relations/hasOneThrough/HasOneThroughRelation.js +4 -7
  146. package/lib/relations/manyToMany/ManyToManyModifyMixin.js +67 -90
  147. package/lib/relations/manyToMany/ManyToManyRelation.js +349 -451
  148. package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +19 -26
  149. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +3 -5
  150. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +14 -20
  151. package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +3 -7
  152. package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +71 -94
  153. package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +31 -43
  154. package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +50 -67
  155. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +4 -7
  156. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +20 -27
  157. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +5 -10
  158. package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +3 -5
  159. package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +55 -72
  160. package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +3 -7
  161. package/lib/transaction.js +53 -83
  162. package/lib/utils/assert.js +15 -21
  163. package/lib/utils/buildUtils.js +17 -19
  164. package/lib/utils/classUtils.js +7 -11
  165. package/lib/utils/cloneDeep.js +365 -0
  166. package/lib/utils/createModifier.js +36 -41
  167. package/lib/utils/deprecate.js +8 -12
  168. package/lib/utils/identifierMapping.js +153 -192
  169. package/lib/utils/internalPropUtils.js +4 -8
  170. package/lib/utils/knexUtils.js +61 -56
  171. package/lib/utils/mixin.js +16 -23
  172. package/lib/utils/mysqlJsonPath.js +55 -40
  173. package/lib/utils/normalizeIds.js +110 -127
  174. package/lib/utils/objectUtils.js +236 -338
  175. package/lib/utils/parseFieldExpression.js +66 -44
  176. package/lib/utils/postgresJsonPath.js +48 -62
  177. package/lib/utils/promiseUtils/after.js +10 -13
  178. package/lib/utils/promiseUtils/afterReturn.js +10 -13
  179. package/lib/utils/promiseUtils/index.js +15 -17
  180. package/lib/utils/promiseUtils/isPromise.js +6 -9
  181. package/lib/utils/promiseUtils/map.js +75 -89
  182. package/lib/utils/promiseUtils/mapAfterAllReturn.js +17 -23
  183. package/lib/utils/promiseUtils/try.js +15 -18
  184. package/lib/utils/resolveModel.js +91 -94
  185. package/lib/utils/tmpColumnUtils.js +4 -13
  186. package/package.json +50 -23
  187. package/typings/objection/index.d.mts +362 -0
  188. package/typings/objection/index.d.ts +36 -9
  189. package/lib/.eslintrc.json +0 -8
  190. package/lib/queryBuilder/parsers/jsonFieldExpressionParser.pegjs +0 -97
  191. package/lib/queryBuilder/parsers/relationExpressionParser.pegjs +0 -141
  192. 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
- constructor(transformations) {
7
- super();
8
- this.transformations = transformations;
9
- }
10
-
11
- onConvertQueryBuilderBase(item, builder) {
12
- for (const transformation of this.transformations) {
13
- item = transformation.onConvertQueryBuilderBase(item, builder);
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
- CompositeQueryTransformation,
16
+ CompositeQueryTransformation,
22
17
  };
@@ -1,11 +1,9 @@
1
1
  'use strict';
2
-
3
2
  class QueryTransformation {
4
- onConvertQueryBuilderBase(item, builder) {
5
- return item;
6
- }
3
+ onConvertQueryBuilderBase(item, builder) {
4
+ return item;
5
+ }
7
6
  }
8
-
9
7
  module.exports = {
10
- QueryTransformation,
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
- onConvertQueryBuilderBase(query, parentQuery) {
20
- const knex = parentQuery.unsafeKnex();
21
-
22
- // Cannot detect anything if, for whatever reason, a knex instance
23
- // or a transaction is not registered at this point.
24
- if (!knex) {
25
- return query;
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
- let found = false;
58
-
59
- query.forEachOperation(query.constructor.JoinSelector, (op) => {
60
- if (op.args[0] === tableName) {
61
- found = true;
62
- return false;
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
- WrapMysqlModifySubqueryTransformation,
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
- new WrapMysqlModifySubqueryTransformation(),
5
+ new WrapMysqlModifySubqueryTransformation(),
11
6
  ]);
12
-
13
7
  module.exports = {
14
- transformation,
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
- 'where',
23
- 'andWhere',
24
- 'whereNot',
25
- 'andWhereNot',
26
- 'whereIn',
27
- 'whereNotIn',
28
- 'whereNull',
29
- 'whereNotNull',
30
- 'whereBetween',
31
- 'whereNotBetween',
32
- 'whereExists',
33
- 'whereNotExists',
34
- 'whereColumn',
35
- 'andWhereColumn',
36
- 'whereNotColumn',
37
- 'andWhereNotColumn',
38
- 'whereLike',
39
- 'whereILike',
40
- 'whereWrapped',
41
- 'whereComposite',
42
- 'whereInComposite',
43
- 'whereJsonSupersetOf',
44
- 'whereJsonSubsetOf',
45
- 'whereJsonNotSupersetOf',
46
- 'whereJsonNotSubsetOf',
47
- 'whereJsonHasAny',
48
- 'whereJsonHasAll',
49
- 'whereJsonNotArray',
50
- 'whereJsonNotObject',
51
- 'whereJsonOverlaps',
52
- 'whereJsonNotOverlaps',
53
- 'whereJsonObject',
54
- 'whereNotJsonObject',
55
- 'whereJsonPath',
56
- 'findById',
57
- 'findByIds',
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
- const previous = builder._whereScope;
62
- // A fresh object works as a unique token.
63
- builder._whereScope = {};
64
-
65
- try {
66
- return callback();
67
- } finally {
68
- builder._whereScope = previous;
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
- while (op) {
74
- if (op.whereScope !== null) {
75
- return op.whereScope;
76
- }
77
-
78
- op = op.parentOperation;
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
- const scopes = new Map();
89
-
90
- builder.forEachOperation(WhereSelector, (op) => {
91
- if (!hasWhereAncestor(op)) {
92
- const scope = effectiveWhereScope(op);
93
- const ops = scopes.get(scope) || [];
94
-
95
- ops.push(op);
96
- scopes.set(scope, ops);
97
- }
98
- });
99
-
100
- if (scopes.size < 2) {
101
- return null;
102
- }
103
-
104
- const groupByFirstOp = new Map();
105
- const groupedOps = new Set();
106
-
107
- for (const ops of scopes.values()) {
108
- if (ops.every(isAndOnlyTree)) {
109
- continue;
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
- const ops = [op];
152
-
153
- op.forEachDescendantOperation((it) => {
154
- ops.push(it);
155
- });
156
-
157
- for (const it of ops) {
158
- if (it.hasOnBuildKnex()) {
159
- knexBuilder =
160
- builder.callOperationMethod(it, 'onBuildKnex', [knexBuilder, builder]) || knexBuilder;
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
- for (let parent = op.parentOperation; parent; parent = parent.parentOperation) {
169
- if (WhereSelector.test(parent.name)) {
170
- return true;
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
- if (!isAndOnly(op)) {
179
- return false;
180
- }
181
-
182
- let andOnly = true;
183
-
184
- op.forEachDescendantOperation((it) => {
185
- if (it.hasOnBuildKnex() && !isAndOnly(it)) {
186
- andOnly = false;
187
- return false;
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
- return AND_ONLY_OPERATIONS.has(op.name) && !containsRaw(op.args);
162
+ return AND_ONLY_OPERATIONS.has(op.name) && !containsRaw(op.args);
196
163
  }
197
-
198
164
  function containsRaw(value) {
199
- if (Array.isArray(value)) {
200
- return value.some(containsRaw);
201
- } else if (!isObject(value)) {
202
- return false;
203
- } else if (value.isObjectionReferenceBuilder) {
204
- // A reference is always a single (possibly casted) column or json path.
205
- return false;
206
- } else if (value.isObjectionFunctionBuilder) {
207
- // `fn()` calls and expressions like `ref('a').eq(1)` are wrapped in parentheses,
208
- // so only their arguments can contain anything.
209
- return containsRaw(value._args);
210
- } else if (isKnexRaw(value) || isFunction(value.toKnexRaw)) {
211
- // Raw sql (and anything that is converted into it) can contain anything.
212
- return true;
213
- } else if (value.isObjectionQueryBuilderBase || isFunction(value.toSQL)) {
214
- // Subqueries are always wrapped in parentheses.
215
- return false;
216
- } else if (Object.getPrototypeOf(value) === Object.prototype) {
217
- return Object.values(value).some(containsRaw);
218
- } else {
219
- return false;
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
- withWhereScope,
225
- effectiveWhereScope,
226
- createWhereGrouping,
196
+ withWhereScope,
197
+ effectiveWhereScope,
198
+ createWhereGrouping,
227
199
  };