objection 3.9.0 → 4.0.0-rc.1

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 (248) hide show
  1. package/lib/dbErrors/LICENSE +21 -0
  2. package/lib/dbErrors/errorCodes/mssql.js +19 -0
  3. package/lib/dbErrors/errorCodes/mysql.js +805 -0
  4. package/lib/dbErrors/errorCodes/postgres.js +241 -0
  5. package/lib/dbErrors/errors/CheckViolationError.js +10 -0
  6. package/lib/dbErrors/errors/ConstraintViolationError.js +3 -0
  7. package/lib/dbErrors/errors/DBError.js +9 -0
  8. package/lib/dbErrors/errors/DataError.js +3 -0
  9. package/lib/dbErrors/errors/ForeignKeyViolationError.js +11 -0
  10. package/lib/dbErrors/errors/NotNullViolationError.js +12 -0
  11. package/lib/dbErrors/errors/UniqueViolationError.js +12 -0
  12. package/lib/dbErrors/index.js +59 -0
  13. package/lib/dbErrors/parsers/mssql/DBError/CheckViolationError/parser.js +28 -0
  14. package/lib/dbErrors/parsers/mssql/DBError/DataError/parser.js +25 -0
  15. package/lib/dbErrors/parsers/mssql/DBError/ForeignKeyViolationError/parser.js +39 -0
  16. package/lib/dbErrors/parsers/mssql/DBError/NotNullViolationError/parser.js +30 -0
  17. package/lib/dbErrors/parsers/mssql/DBError/UniqueViolationError/parser.js +53 -0
  18. package/lib/dbErrors/parsers/mssql/DBError/parser.js +51 -0
  19. package/lib/dbErrors/parsers/mssql/DBError/util.js +16 -0
  20. package/lib/dbErrors/parsers/mysql/DBError/ConstraintViolationError/ForeignKeyViolationError/parser.js +43 -0
  21. package/lib/dbErrors/parsers/mysql/DBError/ConstraintViolationError/NotNullViolationError/parser.js +29 -0
  22. package/lib/dbErrors/parsers/mysql/DBError/ConstraintViolationError/UniqueViolationError/parser.js +27 -0
  23. package/lib/dbErrors/parsers/mysql/DBError/ConstraintViolationError/parser.js +23 -0
  24. package/lib/dbErrors/parsers/mysql/DBError/DataError/parser.js +24 -0
  25. package/lib/dbErrors/parsers/mysql/DBError/parser.js +28 -0
  26. package/lib/dbErrors/parsers/postgres/DBError/ConstraintViolationError/CheckViolationError/parser.js +18 -0
  27. package/lib/dbErrors/parsers/postgres/DBError/ConstraintViolationError/ForeignKeyViolationError/parser.js +18 -0
  28. package/lib/dbErrors/parsers/postgres/DBError/ConstraintViolationError/NotNullViolationError/parser.js +18 -0
  29. package/lib/dbErrors/parsers/postgres/DBError/ConstraintViolationError/UniqueViolationError/parser.js +40 -0
  30. package/lib/dbErrors/parsers/postgres/DBError/ConstraintViolationError/parser.js +25 -0
  31. package/lib/dbErrors/parsers/postgres/DBError/DataError/parser.js +16 -0
  32. package/lib/dbErrors/parsers/postgres/DBError/parser.js +27 -0
  33. package/lib/dbErrors/parsers/sqlite/DBError/ConstraintViolationError/CheckViolationError/parser.js +20 -0
  34. package/lib/dbErrors/parsers/sqlite/DBError/ConstraintViolationError/ForeignKeyViolationError/parser.js +20 -0
  35. package/lib/dbErrors/parsers/sqlite/DBError/ConstraintViolationError/NotNullViolationError/parser.js +27 -0
  36. package/lib/dbErrors/parsers/sqlite/DBError/ConstraintViolationError/UniqueViolationError/parser.js +28 -0
  37. package/lib/dbErrors/parsers/sqlite/DBError/ConstraintViolationError/parser.js +24 -0
  38. package/lib/dbErrors/parsers/sqlite/DBError/parser.js +23 -0
  39. package/lib/dbErrors/utils/sqlState.js +3 -0
  40. package/lib/initialize.js +1 -7
  41. package/lib/model/AjvValidator.js +51 -117
  42. package/lib/model/Model.js +84 -59
  43. package/lib/model/ModifierNotFoundError.js +1 -7
  44. package/lib/model/NotFoundError.js +1 -7
  45. package/lib/model/RelationDoesNotExistError.js +1 -7
  46. package/lib/model/ValidationError.js +3 -10
  47. package/lib/model/Validator.js +1 -7
  48. package/lib/model/getModel.js +7 -6
  49. package/lib/model/inheritModel.js +1 -7
  50. package/lib/model/modelBindKnex.js +4 -10
  51. package/lib/model/modelClone.js +5 -11
  52. package/lib/model/modelColPropMap.js +3 -10
  53. package/lib/model/modelId.js +3 -10
  54. package/lib/model/modelJsonAttributes.js +35 -16
  55. package/lib/model/modelParseRelations.js +2 -8
  56. package/lib/model/modelQueryProps.js +43 -27
  57. package/lib/model/modelSet.js +89 -41
  58. package/lib/model/modelTableMetadata.js +4 -11
  59. package/lib/model/modelToJson.js +8 -23
  60. package/lib/model/modelUtils.js +14 -13
  61. package/lib/model/modelValidate.js +3 -9
  62. package/lib/model/modelValues.js +5 -14
  63. package/lib/model/modelVisitor.js +1 -7
  64. package/lib/objection.js +33 -71
  65. package/lib/queryBuilder/FunctionBuilder.js +4 -11
  66. package/lib/queryBuilder/InternalOptions.js +4 -9
  67. package/lib/queryBuilder/JoinBuilder.js +5 -8
  68. package/lib/queryBuilder/QueryBuilder.js +126 -95
  69. package/lib/queryBuilder/QueryBuilderBase.js +41 -123
  70. package/lib/queryBuilder/QueryBuilderContext.js +2 -8
  71. package/lib/queryBuilder/QueryBuilderContextBase.js +2 -8
  72. package/lib/queryBuilder/QueryBuilderOperationSupport.js +7 -21
  73. package/lib/queryBuilder/QueryBuilderUserContext.js +1 -7
  74. package/lib/queryBuilder/RawBuilder.js +5 -13
  75. package/lib/queryBuilder/ReferenceBuilder.js +20 -48
  76. package/lib/queryBuilder/RelationExpression.js +18 -16
  77. package/lib/queryBuilder/StaticHookArguments.js +74 -16
  78. package/lib/queryBuilder/ValueBuilder.js +11 -13
  79. package/lib/queryBuilder/getJoinBuilder.js +10 -0
  80. package/lib/queryBuilder/graph/GraphLoader.js +304 -0
  81. package/lib/queryBuilder/graph/GraphNode.js +235 -0
  82. package/lib/queryBuilder/graph/GraphOptions.js +55 -248
  83. package/lib/queryBuilder/graph/GraphPlan.js +395 -0
  84. package/lib/queryBuilder/graph/GraphUpsert.js +466 -410
  85. package/lib/queryBuilder/graph/GraphWriter.js +1263 -0
  86. package/lib/queryBuilder/join/JoinResultColumn.js +1 -7
  87. package/lib/queryBuilder/join/JoinResultParser.js +6 -11
  88. package/lib/queryBuilder/join/RelationJoiner.js +66 -84
  89. package/lib/queryBuilder/join/TableNode.js +2 -8
  90. package/lib/queryBuilder/join/TableTree.js +3 -9
  91. package/lib/queryBuilder/join/utils.js +5 -15
  92. package/lib/queryBuilder/jsonDialects/JsonDialect.js +51 -0
  93. package/lib/queryBuilder/jsonDialects/MySqlJsonDialect.js +81 -0
  94. package/lib/queryBuilder/jsonDialects/PostgresJsonDialect.js +45 -0
  95. package/lib/queryBuilder/jsonDialects/SqliteJsonDialect.js +67 -0
  96. package/lib/queryBuilder/jsonDialects/index.js +44 -0
  97. package/lib/queryBuilder/operations/DelegateOperation.js +2 -8
  98. package/lib/queryBuilder/operations/DeleteOperation.js +13 -35
  99. package/lib/queryBuilder/operations/FindByIdOperation.js +7 -12
  100. package/lib/queryBuilder/operations/FindByIdsOperation.js +4 -8
  101. package/lib/queryBuilder/operations/FindOperation.js +14 -34
  102. package/lib/queryBuilder/operations/FirstOperation.js +6 -10
  103. package/lib/queryBuilder/operations/FromOperation.js +3 -9
  104. package/lib/queryBuilder/operations/InsertAndFetchOperation.js +13 -12
  105. package/lib/queryBuilder/operations/InsertGraphAndFetchOperation.js +4 -10
  106. package/lib/queryBuilder/operations/InsertGraphOperation.js +7 -18
  107. package/lib/queryBuilder/operations/InsertOperation.js +118 -43
  108. package/lib/queryBuilder/operations/InstanceDeleteOperation.js +5 -12
  109. package/lib/queryBuilder/operations/InstanceFindOperation.js +4 -11
  110. package/lib/queryBuilder/operations/InstanceInsertOperation.js +2 -8
  111. package/lib/queryBuilder/operations/InstanceUpdateOperation.js +7 -14
  112. package/lib/queryBuilder/operations/JoinRelatedOperation.js +5 -11
  113. package/lib/queryBuilder/operations/KnexOperation.js +2 -8
  114. package/lib/queryBuilder/operations/LimitPerParentOperation.js +7 -69
  115. package/lib/queryBuilder/operations/MergeOperation.js +5 -11
  116. package/lib/queryBuilder/operations/NoneOperation.js +2 -8
  117. package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +20 -49
  118. package/lib/queryBuilder/operations/OnBuildKnexOperation.js +2 -8
  119. package/lib/queryBuilder/operations/OnBuildOperation.js +2 -8
  120. package/lib/queryBuilder/operations/OnErrorOperation.js +2 -8
  121. package/lib/queryBuilder/operations/QueryBuilderOperation.js +1 -7
  122. package/lib/queryBuilder/operations/RangeOperation.js +11 -26
  123. package/lib/queryBuilder/operations/RelateOperation.js +2 -8
  124. package/lib/queryBuilder/operations/ReturningOperation.js +3 -9
  125. package/lib/queryBuilder/operations/RunAfterOperation.js +2 -12
  126. package/lib/queryBuilder/operations/RunBeforeOperation.js +2 -8
  127. package/lib/queryBuilder/operations/UnrelateOperation.js +2 -8
  128. package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +14 -17
  129. package/lib/queryBuilder/operations/UpdateOperation.js +39 -125
  130. package/lib/queryBuilder/operations/UpsertGraphAndFetchOperation.js +8 -11
  131. package/lib/queryBuilder/operations/UpsertGraphOperation.js +6 -12
  132. package/lib/queryBuilder/operations/WhereCompositeOperation.js +3 -9
  133. package/lib/queryBuilder/operations/WhereGroupOperation.js +2 -8
  134. package/lib/queryBuilder/operations/eager/EagerOperation.js +3 -9
  135. package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +72 -10
  136. package/lib/queryBuilder/operations/eager/NaiveEagerOperation.js +2 -8
  137. package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +23 -44
  138. package/lib/queryBuilder/operations/fieldExpressions.js +122 -0
  139. package/lib/queryBuilder/operations/jsonApi/WhereJsonHasOperation.js +20 -0
  140. package/lib/queryBuilder/operations/jsonApi/WhereJsonOperation.js +44 -0
  141. package/lib/queryBuilder/operations/jsonApi/WhereJsonTypeOperation.js +14 -0
  142. package/lib/queryBuilder/operations/select/SelectOperation.js +11 -21
  143. package/lib/queryBuilder/operations/select/Selection.js +19 -17
  144. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +4 -10
  145. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +4 -10
  146. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +4 -10
  147. package/lib/queryBuilder/operations/windowOrder.js +56 -0
  148. package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +3 -7
  149. package/lib/queryBuilder/parsers/relationExpressionParser.js +42 -43
  150. package/lib/queryBuilder/parsers/relationExpressionParser.pegjs +39 -36
  151. package/lib/queryBuilder/transformations/CompositeQueryTransformation.js +2 -8
  152. package/lib/queryBuilder/transformations/QueryTransformation.js +1 -7
  153. package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +3 -9
  154. package/lib/queryBuilder/transformations/index.js +3 -11
  155. package/lib/queryBuilder/whereGroups.js +9 -24
  156. package/lib/queryBuilder/withoutOrder.js +4 -11
  157. package/lib/relations/Relation.js +47 -28
  158. package/lib/relations/RelationDeleteOperation.js +4 -14
  159. package/lib/relations/RelationFindOperation.js +119 -90
  160. package/lib/relations/RelationInsertOperation.js +2 -8
  161. package/lib/relations/RelationOwner.js +5 -11
  162. package/lib/relations/RelationProperty.js +4 -10
  163. package/lib/relations/RelationUpdateOperation.js +4 -14
  164. package/lib/relations/RelationWriteResultOperation.js +15 -0
  165. package/lib/relations/belongsToMany/BelongsToManyDeleteOperation.js +23 -0
  166. package/lib/relations/belongsToMany/BelongsToManyFindOperation.js +35 -0
  167. package/lib/relations/belongsToMany/BelongsToManyInsertOperation.js +28 -0
  168. package/lib/relations/belongsToMany/BelongsToManyRelateOperation.js +16 -0
  169. package/lib/relations/belongsToMany/BelongsToManyRelation.js +276 -0
  170. package/lib/relations/belongsToMany/BelongsToManyUnrelateOperation.js +11 -0
  171. package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +2 -8
  172. package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +6 -11
  173. package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +3 -9
  174. package/lib/relations/belongsToOne/BelongsToOneRelation.js +8 -19
  175. package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +53 -27
  176. package/lib/relations/hasMany/HasManyInsertOperation.js +8 -9
  177. package/lib/relations/hasMany/HasManyRelateOperation.js +5 -11
  178. package/lib/relations/hasMany/HasManyRelation.js +9 -11
  179. package/lib/relations/hasMany/HasManyUnrelateOperation.js +3 -9
  180. package/lib/relations/hasOne/HasOneRelation.js +2 -8
  181. package/lib/relations/hasOneThrough/HasOneThroughRelation.js +2 -8
  182. package/lib/relations/manyToMany/ManyToManyModifyMixin.js +10 -15
  183. package/lib/relations/manyToMany/ManyToManyMySqlModifyMixin.js +2 -8
  184. package/lib/relations/manyToMany/ManyToManyRelation.js +82 -50
  185. package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +2 -8
  186. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +5 -9
  187. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +2 -8
  188. package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +3 -9
  189. package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +20 -59
  190. package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +6 -11
  191. package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +4 -10
  192. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateMySqlOperation.js +3 -9
  193. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +5 -9
  194. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +3 -9
  195. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +3 -9
  196. package/lib/relations/manyToMany/update/ManyToManyUpdateMySqlOperation.js +3 -9
  197. package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +5 -9
  198. package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +79 -64
  199. package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +3 -9
  200. package/lib/transaction.js +3 -9
  201. package/lib/utils/assert.js +3 -11
  202. package/lib/utils/buildUtils.js +2 -8
  203. package/lib/utils/classUtils.js +1 -7
  204. package/lib/utils/createModifier.js +2 -8
  205. package/lib/utils/identifierMapping.js +23 -27
  206. package/lib/utils/internalPropUtils.js +1 -7
  207. package/lib/utils/knexUtils.js +84 -40
  208. package/lib/utils/mixin.js +3 -10
  209. package/lib/utils/normalizeIds.js +2 -8
  210. package/lib/utils/objectUtils.js +41 -60
  211. package/lib/utils/parseFieldExpression.js +29 -14
  212. package/lib/utils/promiseUtils/after.js +2 -8
  213. package/lib/utils/promiseUtils/afterReturn.js +2 -8
  214. package/lib/utils/promiseUtils/index.js +7 -16
  215. package/lib/utils/promiseUtils/isPromise.js +2 -8
  216. package/lib/utils/promiseUtils/map.js +25 -14
  217. package/lib/utils/promiseUtils/mapAfterAllReturn.js +2 -8
  218. package/lib/utils/promiseUtils/try.js +2 -8
  219. package/lib/utils/resolveModel.js +10 -17
  220. package/lib/utils/tmpColumnUtils.js +2 -9
  221. package/lib/utils/warnings.js +2 -14
  222. package/package.json +25 -17
  223. package/typings/objection/index.d.ts +3217 -2179
  224. package/lib/.eslintrc.json +0 -8
  225. package/lib/model/graph/ModelGraph.js +0 -80
  226. package/lib/model/graph/ModelGraphBuilder.js +0 -241
  227. package/lib/model/graph/ModelGraphEdge.js +0 -52
  228. package/lib/model/graph/ModelGraphNode.js +0 -253
  229. package/lib/queryBuilder/graph/GraphAction.js +0 -69
  230. package/lib/queryBuilder/graph/GraphData.js +0 -53
  231. package/lib/queryBuilder/graph/GraphFetcher.js +0 -199
  232. package/lib/queryBuilder/graph/GraphNodeDbExistence.js +0 -184
  233. package/lib/queryBuilder/graph/GraphOperation.js +0 -27
  234. package/lib/queryBuilder/graph/delete/GraphDelete.js +0 -73
  235. package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +0 -88
  236. package/lib/queryBuilder/graph/insert/DeferredRelationGraphInsertAction.js +0 -57
  237. package/lib/queryBuilder/graph/insert/GraphInsert.js +0 -257
  238. package/lib/queryBuilder/graph/insert/GraphInsertAction.js +0 -238
  239. package/lib/queryBuilder/graph/insert/JoinRowGraphInsertAction.js +0 -92
  240. package/lib/queryBuilder/graph/patch/GraphPatch.js +0 -20
  241. package/lib/queryBuilder/graph/patch/GraphPatchAction.js +0 -277
  242. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsert.js +0 -31
  243. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsertAction.js +0 -126
  244. package/lib/queryBuilder/operations/jsonApi/WhereJsonHasPostgresOperation.js +0 -30
  245. package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectPostgresOperation.js +0 -37
  246. package/lib/queryBuilder/operations/jsonApi/WhereJsonPostgresOperation.js +0 -62
  247. package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +0 -192
  248. package/lib/utils/wrapDbError.js +0 -50
@@ -1,8 +1,6 @@
1
- 'use strict';
1
+ import { QueryBuilderOperation } from './QueryBuilderOperation.js';
2
2
 
3
- const { QueryBuilderOperation } = require('./QueryBuilderOperation');
4
-
5
- class RunBeforeOperation extends QueryBuilderOperation {
3
+ export class RunBeforeOperation extends QueryBuilderOperation {
6
4
  constructor(name, opt) {
7
5
  super(name, opt);
8
6
  this.func = null;
@@ -23,7 +21,3 @@ class RunBeforeOperation extends QueryBuilderOperation {
23
21
  return clone;
24
22
  }
25
23
  }
26
-
27
- module.exports = {
28
- RunBeforeOperation,
29
- };
@@ -1,8 +1,6 @@
1
- 'use strict';
1
+ import { QueryBuilderOperation } from './QueryBuilderOperation.js';
2
2
 
3
- const { QueryBuilderOperation } = require('./QueryBuilderOperation');
4
-
5
- class UnrelateOperation extends QueryBuilderOperation {
3
+ export class UnrelateOperation extends QueryBuilderOperation {
6
4
  constructor(name, opt) {
7
5
  super(name, opt);
8
6
 
@@ -17,7 +15,3 @@ class UnrelateOperation extends QueryBuilderOperation {
17
15
  return clone;
18
16
  }
19
17
  }
20
-
21
- module.exports = {
22
- UnrelateOperation,
23
- };
@@ -1,11 +1,8 @@
1
- 'use strict';
1
+ import { DelegateOperation } from './DelegateOperation.js';
2
+ import { FindByIdOperation } from './FindByIdOperation.js';
3
+ import { UpdateOperation } from './UpdateOperation.js';
2
4
 
3
- const { DelegateOperation } = require('./DelegateOperation');
4
- const { FindByIdOperation } = require('./FindByIdOperation');
5
- const { UpdateOperation } = require('./UpdateOperation');
6
- const { addWhereGroup, assignWhereGroup } = require('../whereGroups');
7
-
8
- class UpdateAndFetchOperation extends DelegateOperation {
5
+ export class UpdateAndFetchOperation extends DelegateOperation {
9
6
  constructor(name, opt) {
10
7
  super(name, opt);
11
8
 
@@ -42,7 +39,7 @@ class UpdateAndFetchOperation extends DelegateOperation {
42
39
 
43
40
  onBuild(builder) {
44
41
  if (!this.skipIdWhere) {
45
- addWhereGroup(builder, () => builder.findById(this.id));
42
+ builder.findById(this.id);
46
43
  }
47
44
 
48
45
  super.onBuild(builder);
@@ -67,6 +64,13 @@ class UpdateAndFetchOperation extends DelegateOperation {
67
64
  .castTo(builder.resultModelClass());
68
65
 
69
66
  if (fetched) {
67
+ if (!fetched.$isObjectionModel) {
68
+ throw new Error(
69
+ `Unable to merge the result of ${builder.modelClass().name}.afterFind() in ` +
70
+ `${this.name}(): expected a model.`,
71
+ );
72
+ }
73
+
70
74
  this.model.$set(fetched);
71
75
  // A custom `select` may not include the id. The row was fetched by
72
76
  // id, so make sure the result still has it.
@@ -84,12 +88,9 @@ class UpdateAndFetchOperation extends DelegateOperation {
84
88
  // many-to-many updates move to a subquery when the query is built.
85
89
  const delegate = this.delegate.toFindOperation(builder);
86
90
 
87
- // Keep the id condition in its own where group, like `onBuild()` does. The
88
- // delegate isn't named `findById`, as that would put all the wheres that it
89
- // adds in the user's group.
90
91
  return delegate
91
92
  ? new FindByIdDelegateOperation('find', { delegate, id: this.id })
92
- : assignWhereGroup(new FindByIdOperation('findById', { id: this.id }));
93
+ : new FindByIdOperation('findById', { id: this.id });
93
94
  }
94
95
 
95
96
  clone() {
@@ -107,10 +108,6 @@ class UpdateAndFetchOperation extends DelegateOperation {
107
108
  class FindByIdDelegateOperation extends DelegateOperation {
108
109
  onBuild(builder) {
109
110
  super.onBuild(builder);
110
- addWhereGroup(builder, () => builder.findById(this.opt.id));
111
+ builder.findById(this.opt.id);
111
112
  }
112
113
  }
113
-
114
- module.exports = {
115
- UpdateAndFetchOperation,
116
- };
@@ -1,18 +1,14 @@
1
- 'use strict';
2
-
3
- const { ref } = require('../../queryBuilder/ReferenceBuilder');
4
- const { isEmpty, isObject } = require('../../utils/objectUtils');
5
- const {
6
- isFieldExpressionKey,
7
- toPostgresJsonPathLiteral,
8
- } = require('../../utils/parseFieldExpression');
9
- const { isKnexRaw, isKnexQueryBuilder } = require('../../utils/knexUtils');
10
- const { QueryBuilderOperation } = require('./QueryBuilderOperation');
11
- const { warnIfNotPostgres } = require('./jsonApi/postgresJsonApi');
12
- const { StaticHookArguments } = require('../StaticHookArguments');
13
- const { ValidationErrorType } = require('../../model/ValidationError');
14
-
15
- class UpdateOperation extends QueryBuilderOperation {
1
+ import { isEmpty } from '../../utils/objectUtils.js';
2
+ import { QueryBuilderOperation } from './QueryBuilderOperation.js';
3
+ import { StaticHookArguments } from '../StaticHookArguments.js';
4
+ import { removeOverriddenValues } from '../../model/modelQueryProps.js';
5
+ import {
6
+ checkFieldExpressions,
7
+ convertFieldExpressionsToRaw,
8
+ removeFieldExpressions,
9
+ } from './fieldExpressions.js';
10
+
11
+ export class UpdateOperation extends QueryBuilderOperation {
16
12
  constructor(name, opt) {
17
13
  super(name, opt);
18
14
 
@@ -31,6 +27,7 @@ class UpdateOperation extends QueryBuilderOperation {
31
27
 
32
28
  async onBefore2(builder, result) {
33
29
  await callBeforeUpdate(builder, this.model, this.modelOptions);
30
+ removeOverriddenValues(this.model);
34
31
  return result;
35
32
  }
36
33
 
@@ -52,15 +49,38 @@ class UpdateOperation extends QueryBuilderOperation {
52
49
  return builder.isExplicitlyResolvedOrRejected() && !this.hasNothingToUpdate;
53
50
  }
54
51
 
52
+ // Returns true if the query was resolved without writing anything, by a hook
53
+ // or because there is nothing to update in the table.
54
+ // @overridable
55
+ isResolvedWithoutWrite(builder) {
56
+ return builder.isExplicitlyResolvedOrRejected();
57
+ }
58
+
59
+ // knex leaves the offset out of updates, and on SQL Server the limit as well.
60
+ // Throw when the query is executed.
61
+ onAfterBuild(builder) {
62
+ if (builder.has('offset')) {
63
+ throw new Error('offset() is not supported in update queries, as knex leaves it out.');
64
+ }
65
+ }
66
+
55
67
  onBuildKnex(knexBuilder, builder) {
56
68
  const json = this.model.$toDatabaseJson(builder);
57
- const convertedJson = convertFieldExpressionsToRaw(builder, this.model, json);
58
69
 
59
- return knexBuilder.update(convertedJson);
70
+ if (this.modelOptions.patch) {
71
+ return knexBuilder.update(convertFieldExpressionsToRaw(builder, json));
72
+ } else {
73
+ checkFieldExpressions(builder.modelClass(), this.model, 'update');
74
+ return knexBuilder.update(json);
75
+ }
60
76
  }
61
77
 
62
- onAfter2(builder, numUpdated) {
63
- return callAfterUpdate(builder, this.model, this.modelOptions, numUpdated);
78
+ async onAfter2(builder, numUpdated) {
79
+ await this.model.$afterUpdate(this.modelOptions, builder.context());
80
+ // The patched model is what the write returns, e.g. to `upsertGraph()` and
81
+ // `patchAndFetch()`, or what it merges into the instance of `$query()`:
82
+ removeFieldExpressions(builder.modelClass(), this.model);
83
+ return numUpdated;
64
84
  }
65
85
 
66
86
  toFindOperation() {
@@ -88,109 +108,3 @@ function callStaticBeforeUpdate(builder) {
88
108
  const args = StaticHookArguments.create({ builder });
89
109
  return builder.modelClass().beforeUpdate(args);
90
110
  }
91
-
92
- async function callAfterUpdate(builder, model, modelOptions, result) {
93
- await callInstanceAfterUpdate(builder, model, modelOptions);
94
- return callStaticAfterUpdate(builder, result);
95
- }
96
-
97
- function callInstanceAfterUpdate(builder, model, modelOptions) {
98
- return model.$afterUpdate(modelOptions, builder.context());
99
- }
100
-
101
- async function callStaticAfterUpdate(builder, result) {
102
- const args = StaticHookArguments.create({ builder, result });
103
- const maybeResult = await builder.modelClass().afterUpdate(args);
104
-
105
- if (maybeResult === undefined) {
106
- return result;
107
- } else {
108
- return maybeResult;
109
- }
110
- }
111
-
112
- function convertFieldExpressionsToRaw(builder, model, json) {
113
- const knex = builder.knex();
114
- const modelClass = builder.modelClass();
115
- const declaredColumns = getDeclaredColumns(modelClass);
116
- const convertedJson = {};
117
-
118
- for (const key of Object.keys(json)) {
119
- let val = json[key];
120
-
121
- if (isFieldExpressionKey(key, declaredColumns)) {
122
- // 'col:attr' : ref('other:lol') is transformed to
123
- // "col" : raw(`jsonb_set("table"."col", '{attr}', to_jsonb("other"#>'{lol}'), true)`)
124
- // with the column qualified, as it is ambiguous with `excluded` in merge().
125
- warnIfNotPostgres(knex);
126
-
127
- let parsed = ref(key);
128
-
129
- // The field expression would be lost or produce invalid SQL next to a
130
- // value for the whole json column. Report it with the property names:
131
- if (Object.prototype.hasOwnProperty.call(json, parsed.column)) {
132
- const property = modelClass.columnNameToPropertyName(parsed.column);
133
- throw modelClass.createValidationError({
134
- type: ValidationErrorType.ModelValidation,
135
- data: {
136
- [modelClass.columnNameToPropertyName(key)]: [
137
- {
138
- message: `can't be combined with a value for the json column '${property}'`,
139
- keyword: null,
140
- params: { property },
141
- },
142
- ],
143
- },
144
- });
145
- }
146
-
147
- let jsonPath = toPostgresJsonPathLiteral(parsed.parsedExpr.access);
148
- let valuePlaceholder = '?';
149
-
150
- if (isKnexQueryBuilder(val) || isKnexRaw(val)) {
151
- valuePlaceholder = 'to_jsonb(?)';
152
- } else {
153
- val = JSON.stringify(val);
154
- }
155
-
156
- convertedJson[parsed.column] = knex.raw(
157
- `jsonb_set(??, ${jsonPath}, ${valuePlaceholder}, true)`,
158
- [convertedJson[parsed.column] || `${builder.tableRef()}.${parsed.column}`, val],
159
- );
160
-
161
- delete model[key];
162
- } else {
163
- convertedJson[key] = val;
164
- }
165
- }
166
-
167
- return convertedJson;
168
- }
169
-
170
- const declaredColumnsByModelClass = new WeakMap();
171
-
172
- // The keys of `json` are column names, so map the properties with a ':' that the
173
- // schema declares to their columns, once per model class. Properties that only
174
- // the schema returned by `$beforeValidate()` declares aren't known here.
175
- function getDeclaredColumns(modelClass) {
176
- let declaredColumns = declaredColumnsByModelClass.get(modelClass);
177
-
178
- if (!declaredColumns) {
179
- const jsonSchema = modelClass.getJsonSchema();
180
- const properties = jsonSchema && jsonSchema.properties;
181
- declaredColumns = Object.fromEntries(
182
- (isObject(properties) ? Object.keys(properties) : [])
183
- .filter((key) => key.includes(':'))
184
- .map((key) => [modelClass.propertyNameToColumnName(key), true]),
185
- );
186
- declaredColumnsByModelClass.set(modelClass, declaredColumns);
187
- }
188
-
189
- return declaredColumns;
190
- }
191
-
192
- module.exports = {
193
- UpdateOperation,
194
- convertFieldExpressionsToRaw,
195
- getDeclaredColumns,
196
- };
@@ -1,10 +1,8 @@
1
- 'use strict';
1
+ import { DelegateOperation } from './DelegateOperation.js';
2
+ import { UpsertGraphOperation } from './UpsertGraphOperation.js';
3
+ import { RelationExpression } from '../RelationExpression.js';
2
4
 
3
- const { DelegateOperation } = require('./DelegateOperation');
4
- const { UpsertGraphOperation } = require('./UpsertGraphOperation');
5
- const { RelationExpression } = require('../RelationExpression');
6
-
7
- class UpsertGraphAndFetchOperation extends DelegateOperation {
5
+ export class UpsertGraphAndFetchOperation extends DelegateOperation {
8
6
  constructor(name, opt) {
9
7
  super(name, opt);
10
8
 
@@ -21,7 +19,10 @@ class UpsertGraphAndFetchOperation extends DelegateOperation {
21
19
  return this.delegate.isArray;
22
20
  }
23
21
 
24
- async onAfter3(builder) {
22
+ // Refetch the graph before the graph operations of the query run, so that a
23
+ // `withGraphFetched()` with its modifiers and options loads its relations
24
+ // into the fetched models, like in `InsertGraphAndFetchOperation` (#839).
25
+ async onAfter2(builder) {
25
26
  if (this.models.length === 0) {
26
27
  return this.isArray ? [] : null;
27
28
  }
@@ -39,7 +40,3 @@ class UpsertGraphAndFetchOperation extends DelegateOperation {
39
40
  return this.isArray ? models : models[0] || null;
40
41
  }
41
42
  }
42
-
43
- module.exports = {
44
- UpsertGraphAndFetchOperation,
45
- };
@@ -1,10 +1,8 @@
1
- 'use strict';
1
+ import { QueryBuilderOperation } from './QueryBuilderOperation.js';
2
+ import { GraphUpsert } from '../graph/GraphUpsert.js';
3
+ import { RelationFindOperation } from '../../relations/RelationFindOperation.js';
2
4
 
3
- const { QueryBuilderOperation } = require('./QueryBuilderOperation');
4
- const { GraphUpsert } = require('../graph/GraphUpsert');
5
- const { RelationFindOperation } = require('../../relations/RelationFindOperation');
6
-
7
- class UpsertGraphOperation extends QueryBuilderOperation {
5
+ export class UpsertGraphOperation extends QueryBuilderOperation {
8
6
  constructor(name, opt) {
9
7
  super(
10
8
  name,
@@ -41,14 +39,14 @@ class UpsertGraphOperation extends QueryBuilderOperation {
41
39
  }
42
40
 
43
41
  onBefore1(builder, result) {
44
- GraphUpsert.warnOnConflict(builder, this.name);
42
+ GraphUpsert.checkForOnConflict(builder, this.name);
45
43
  return result;
46
44
  }
47
45
 
48
46
  onAfter1(builder) {
49
47
  if (hasOtherSqlModifyingQueryBuilderCalls(builder)) {
50
48
  throw new Error(
51
- 'upsertGraph query should contain no other query builder calls like `findById`, `where` or `$relatedQuery` that would affect the SQL. They have no effect.',
49
+ 'upsertGraph query should contain no other query builder calls like `findById`, `where`, `$query` or `$relatedQuery` that would affect the SQL. They have no effect.',
52
50
  );
53
51
  }
54
52
 
@@ -65,7 +63,3 @@ class UpsertGraphOperation extends QueryBuilderOperation {
65
63
  function hasOtherSqlModifyingQueryBuilderCalls(builder) {
66
64
  return builder.has(/where/) || builder.has(RelationFindOperation);
67
65
  }
68
-
69
- module.exports = {
70
- UpsertGraphOperation,
71
- };
@@ -1,9 +1,7 @@
1
- 'use strict';
1
+ import { ObjectionToKnexConvertingOperation } from './ObjectionToKnexConvertingOperation.js';
2
+ import { asSingle } from '../../utils/objectUtils.js';
2
3
 
3
- const { ObjectionToKnexConvertingOperation } = require('./ObjectionToKnexConvertingOperation');
4
- const { asSingle } = require('../../utils/objectUtils');
5
-
6
- class WhereCompositeOperation extends ObjectionToKnexConvertingOperation {
4
+ export class WhereCompositeOperation extends ObjectionToKnexConvertingOperation {
7
5
  onBuildKnex(knexBuilder, builder) {
8
6
  const args = this.getKnexArgs(builder);
9
7
 
@@ -51,7 +49,3 @@ function buildCompositeWhereArgs(cols, op, values) {
51
49
  },
52
50
  ];
53
51
  }
54
-
55
- module.exports = {
56
- WhereCompositeOperation,
57
- };
@@ -1,10 +1,8 @@
1
- 'use strict';
2
-
3
- const { QueryBuilderOperation } = require('./QueryBuilderOperation');
1
+ import { QueryBuilderOperation } from './QueryBuilderOperation.js';
4
2
 
5
3
  // Builds a set of where operations inside a single knex `where(callback)`
6
4
  // group, i.e. wraps them in parentheses. See `getWhereGroupOperations()`.
7
- class WhereGroupOperation extends QueryBuilderOperation {
5
+ export class WhereGroupOperation extends QueryBuilderOperation {
8
6
  constructor(name, opt) {
9
7
  super(name, opt);
10
8
  this.operations = opt.operations;
@@ -29,7 +27,3 @@ class WhereGroupOperation extends QueryBuilderOperation {
29
27
  });
30
28
  }
31
29
  }
32
-
33
- module.exports = {
34
- WhereGroupOperation,
35
- };
@@ -1,9 +1,7 @@
1
- 'use strict';
1
+ import { QueryBuilderOperation } from '../QueryBuilderOperation.js';
2
+ import { RelationExpression } from '../../RelationExpression.js';
2
3
 
3
- const { QueryBuilderOperation } = require('../QueryBuilderOperation');
4
- const { RelationExpression } = require('../../RelationExpression');
5
-
6
- class EagerOperation extends QueryBuilderOperation {
4
+ export class EagerOperation extends QueryBuilderOperation {
7
5
  constructor(name, opt) {
8
6
  super(name, opt);
9
7
 
@@ -57,7 +55,3 @@ class EagerOperation extends QueryBuilderOperation {
57
55
  function getModifierName(index) {
58
56
  return `_f${index}_`;
59
57
  }
60
-
61
- module.exports = {
62
- EagerOperation,
63
- };
@@ -1,12 +1,13 @@
1
- 'use strict';
1
+ import { EagerOperation } from './EagerOperation.js';
2
+ import { RelationJoiner } from '../../join/RelationJoiner.js';
3
+ import { JoinedStaticHookArguments } from '../../StaticHookArguments.js';
4
+ import { asArray } from '../../../utils/objectUtils.js';
2
5
 
3
- const { EagerOperation } = require('./EagerOperation');
4
- const { RelationJoiner } = require('../../join/RelationJoiner');
5
-
6
- class JoinEagerOperation extends EagerOperation {
6
+ export class JoinEagerOperation extends EagerOperation {
7
7
  constructor(name, opt) {
8
8
  super(name, opt);
9
9
  this.joiner = null;
10
+ this.models = null;
10
11
  }
11
12
 
12
13
  onAdd(builder) {
@@ -43,7 +44,72 @@ class JoinEagerOperation extends EagerOperation {
43
44
  }
44
45
 
45
46
  onRawResult(builder, rows) {
46
- return this.joiner.parseResult(builder, rows);
47
+ this.models = this.joiner.parseResult(builder, rows);
48
+ return this.models;
49
+ }
50
+
51
+ // Call the static `afterFind()` hooks of the joined relations bottom-up, after
52
+ // the `$afterFind()` hooks of all models, and assign the related models that
53
+ // they return, like `withGraphFetched()` does.
54
+ async onAfter3(builder, result) {
55
+ if (Array.isArray(this.models)) {
56
+ const [rootNode, ...nodes] = this.joiner.tableTree.nodes;
57
+ const modelsByNode = new Map([[rootNode, this.models]]);
58
+ const ownerByModel = new Map();
59
+
60
+ // The nodes are ordered from the root down, so the owners come first:
61
+ for (const node of nodes) {
62
+ const models = [];
63
+
64
+ for (const owner of modelsByNode.get(node.parentNode)) {
65
+ for (const model of asArray(owner[node.relationProperty])) {
66
+ if (model) {
67
+ models.push(model);
68
+ ownerByModel.set(model, owner);
69
+ }
70
+ }
71
+ }
72
+
73
+ modelsByNode.set(node, models);
74
+ }
75
+
76
+ for (const node of nodes.reverse()) {
77
+ const { modelClass, relation, relationProperty } = node;
78
+ const owners = modelsByNode.get(node.parentNode);
79
+ const models = modelsByNode.get(node);
80
+ const args = JoinedStaticHookArguments.create({
81
+ builder,
82
+ result: models,
83
+ relation,
84
+ items: owners,
85
+ });
86
+ const related = await modelClass.afterFind(args);
87
+
88
+ if (related !== undefined) {
89
+ const relatedByOwner = new Map(owners.map((owner) => [owner, []]));
90
+
91
+ for (const model of asArray(related)) {
92
+ const relatedOfOwner = relatedByOwner.get(ownerByModel.get(model));
93
+
94
+ if (!relatedOfOwner) {
95
+ throw new Error(
96
+ `Unable to assign the result of ${modelClass.name}.afterFind() to the relation ` +
97
+ `"${relation.name}" of ${relation.ownerModelClass.name}: return the models ` +
98
+ 'you got, filtered or reordered.',
99
+ );
100
+ }
101
+
102
+ relatedOfOwner.push(model);
103
+ }
104
+
105
+ for (const [owner, related] of relatedByOwner) {
106
+ owner[relationProperty] = relation.isOneToOne() ? related[0] || null : related;
107
+ }
108
+ }
109
+ }
110
+ }
111
+
112
+ return result;
47
113
  }
48
114
 
49
115
  clone() {
@@ -52,7 +118,3 @@ class JoinEagerOperation extends EagerOperation {
52
118
  return clone;
53
119
  }
54
120
  }
55
-
56
- module.exports = {
57
- JoinEagerOperation,
58
- };
@@ -1,13 +1,7 @@
1
- 'use strict';
1
+ import { WhereInEagerOperation } from './WhereInEagerOperation.js';
2
2
 
3
- const { WhereInEagerOperation } = require('./WhereInEagerOperation');
4
-
5
- class NaiveEagerOperation extends WhereInEagerOperation {
3
+ export class NaiveEagerOperation extends WhereInEagerOperation {
6
4
  batchSize() {
7
5
  return 1;
8
6
  }
9
7
  }
10
-
11
- module.exports = {
12
- NaiveEagerOperation,
13
- };
@@ -1,17 +1,16 @@
1
- 'use strict';
2
-
3
- const promiseUtils = require('../../../utils/promiseUtils');
4
-
5
- const { EagerOperation } = require('./EagerOperation');
6
- const { LimitPerParentOperation } = require('../LimitPerParentOperation');
7
- const { isMsSql, isOracle, isSqlite, hasWindowFunctions } = require('../../../utils/knexUtils');
8
- const { isObject, asArray, flatten, chunk } = require('../../../utils/objectUtils');
9
- const { ValidationErrorType } = require('../../../model/ValidationError');
10
- const { createModifier } = require('../../../utils/createModifier');
11
- const { RelationDoesNotExistError } = require('../../../model/RelationDoesNotExistError');
12
- const { RelationOwner } = require('../../../relations/RelationOwner');
13
-
14
- class WhereInEagerOperation extends EagerOperation {
1
+ import * as promiseUtils from '../../../utils/promiseUtils/index.js';
2
+
3
+ import { EagerOperation } from './EagerOperation.js';
4
+ import { LimitPerParentOperation } from '../LimitPerParentOperation.js';
5
+ import { isMsSql, isOracle, isSqlite } from '../../../utils/knexUtils.js';
6
+ import { isObject, asArray, flatten, chunk } from '../../../utils/objectUtils.js';
7
+ import { ValidationErrorType } from '../../../model/ValidationError.js';
8
+ import { createModifier } from '../../../utils/createModifier.js';
9
+ import { RelationDoesNotExistError } from '../../../model/RelationDoesNotExistError.js';
10
+ import { RelationOwner } from '../../../relations/RelationOwner.js';
11
+ import { hasAliasSelection } from '../select/Selection.js';
12
+
13
+ export class WhereInEagerOperation extends EagerOperation {
15
14
  constructor(name, opt) {
16
15
  super(name, opt);
17
16
 
@@ -64,10 +63,6 @@ class WhereInEagerOperation extends EagerOperation {
64
63
  async onAfter2(builder, result) {
65
64
  const modelClass = builder.resultModelClass();
66
65
 
67
- if (!result) {
68
- return result;
69
- }
70
-
71
66
  const models = asArray(result);
72
67
 
73
68
  // Check models to be actual objects, to filter out `count` results (#2397).
@@ -86,9 +81,7 @@ class WhereInEagerOperation extends EagerOperation {
86
81
 
87
82
  async fetchRelation(builder, models, relation, expr) {
88
83
  const modelClass = builder.resultModelClass();
89
- const batchSize = this.shouldFetchPerParent(builder, models, relation, expr)
90
- ? 1
91
- : this.batchSize(builder.knex());
84
+ const batchSize = this.batchSize(builder.knex());
92
85
  const modelBatches = chunk(models, batchSize);
93
86
 
94
87
  const result = await promiseUtils.map(
@@ -139,30 +132,16 @@ class WhereInEagerOperation extends EagerOperation {
139
132
  }
140
133
  }
141
134
 
142
- if (this.graphOptions.limitPerParent) {
135
+ if (this.graphOptions.limitPerParent !== false) {
143
136
  queryBuilder.addOperation(
144
137
  new LimitPerParentOperation('limitPerParent', { findOperation }),
145
138
  [],
146
139
  );
147
140
  }
148
141
 
149
- return queryBuilder;
150
- }
151
-
152
- // Without window functions, the related models can only be limited per
153
- // parent with one query per parent.
154
- shouldFetchPerParent(builder, models, relation, expr) {
155
- if (this.graphOptions.limitPerParent && !hasWindowFunctions(builder.knex())) {
156
- // Build the query to find its limits, also those of the relation's
157
- // `modify` and of `onBuildKnex()` hooks. This runs its modifiers and
158
- // build hooks once more than for fetching the relation.
159
- const query = this.fetchRelationBatch(builder, models, relation, expr);
160
- query.executeOnBuild();
161
- const knexQuery = query.executeOnBuildKnex(query.knex().queryBuilder());
162
- return !!query.findOperation(LimitPerParentOperation)?.getRange(knexQuery, query);
163
- } else {
164
- return false;
165
- }
142
+ // The relation gets what its query returns, after its hooks and `runAfter()`
143
+ // callbacks:
144
+ return queryBuilder.then((result) => findOperation.assignResult(queryBuilder, result));
166
145
  }
167
146
 
168
147
  shouldSkipFetched(models, relation, expr) {
@@ -262,7 +241,11 @@ function findRelationPropsToSelect(builder, relationsToFetch) {
262
241
  const prop = ownerProp.props[c];
263
242
  const col = ownerProp.cols[c];
264
243
 
265
- if (!builder.hasSelectionAs(fullCol, col) && selectionsToAdd.indexOf(fullCol) === -1) {
244
+ if (
245
+ !builder.hasSelectionAs(fullCol, col) &&
246
+ !hasAliasSelection(builder, col) &&
247
+ selectionsToAdd.indexOf(fullCol) === -1
248
+ ) {
266
249
  selectedProps.push(prop);
267
250
  selectionsToAdd.push(fullCol);
268
251
  }
@@ -294,7 +277,3 @@ function getRelatedModels(models, expr) {
294
277
 
295
278
  return allRelated;
296
279
  }
297
-
298
- module.exports = {
299
- WhereInEagerOperation,
300
- };