@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,108 +1,87 @@
1
1
  'use strict';
2
-
3
2
  const { DelegateOperation } = require('./DelegateOperation');
4
3
  const { InsertOperation } = require('./InsertOperation');
5
4
  const { GraphUpsert } = require('../graph/GraphUpsert');
6
-
7
5
  class InsertGraphOperation extends DelegateOperation {
8
- constructor(name, opt = null) {
9
- super(name, opt);
10
-
11
- if (!this.delegate.is(InsertOperation)) {
12
- throw new Error('Invalid delegate');
6
+ constructor(name, opt = null) {
7
+ super(name, opt);
8
+ if (!this.delegate.is(InsertOperation)) {
9
+ throw new Error('Invalid delegate');
10
+ }
11
+ Object.assign(this.delegate.modelOptions, GraphUpsert.modelOptions);
12
+ this.upsertOptions = opt.opt || {};
13
+ this.upsert = null;
13
14
  }
14
-
15
- Object.assign(this.delegate.modelOptions, GraphUpsert.modelOptions);
16
- this.upsertOptions = opt.opt || {};
17
- this.upsert = null;
18
- }
19
-
20
- get models() {
21
- return this.delegate.models;
22
- }
23
-
24
- get isArray() {
25
- return this.delegate.isArray;
26
- }
27
-
28
- get relation() {
29
- return this.delegate.relation;
30
- }
31
-
32
- onAdd(builder, args) {
33
- const retVal = super.onAdd(builder, args);
34
-
35
- this.upsert = new GraphUpsert({
36
- objects: this.models,
37
- rootModelClass: builder.modelClass(),
38
-
39
- upsertOptions: Object.assign({}, this.upsertOptions, {
40
- noUpdate: true,
41
- noDelete: true,
42
- noUnrelate: true,
43
- insertMissing: true,
44
- }),
45
- });
46
-
47
- // We resolve this query here and will not execute it. This is because the root
48
- // value may depend on other models in the graph and cannot be inserted first.
49
- builder.resolve([]);
50
-
51
- return retVal;
52
- }
53
-
54
- onBefore1(_, result) {
55
- // Do nothing.
56
- return result;
57
- }
58
-
59
- onBefore2(builder, result) {
60
- // We override this with empty implementation so that the $beforeInsert()
61
- // hooks are not called twice for the root models.
62
-
63
- if (this.relation) {
64
- // We still need to call the relation before insert hook if the the
65
- // delegate operation is a RelationInsertOperation.
66
- return this.relation.executeBeforeInsert(this.models, builder.context(), result);
67
- } else {
68
- return result;
15
+ get models() {
16
+ return this.delegate.models;
17
+ }
18
+ get isArray() {
19
+ return this.delegate.isArray;
20
+ }
21
+ get relation() {
22
+ return this.delegate.relation;
23
+ }
24
+ onAdd(builder, args) {
25
+ const retVal = super.onAdd(builder, args);
26
+ this.upsert = new GraphUpsert({
27
+ objects: this.models,
28
+ rootModelClass: builder.modelClass(),
29
+ upsertOptions: Object.assign({}, this.upsertOptions, {
30
+ noUpdate: true,
31
+ noDelete: true,
32
+ noUnrelate: true,
33
+ insertMissing: true,
34
+ }),
35
+ });
36
+ // We resolve this query here and will not execute it. This is because the root
37
+ // value may depend on other models in the graph and cannot be inserted first.
38
+ builder.resolve([]);
39
+ return retVal;
40
+ }
41
+ onBefore1(_, result) {
42
+ // Do nothing.
43
+ return result;
44
+ }
45
+ onBefore2(builder, result) {
46
+ // We override this with empty implementation so that the $beforeInsert()
47
+ // hooks are not called twice for the root models.
48
+ if (this.relation) {
49
+ // We still need to call the relation before insert hook if the the
50
+ // delegate operation is a RelationInsertOperation.
51
+ return this.relation.executeBeforeInsert(this.models, builder.context(), result);
52
+ }
53
+ else {
54
+ return result;
55
+ }
56
+ }
57
+ onBefore3(_, result) {
58
+ // Do nothing.
59
+ return result;
60
+ }
61
+ onBuild() {
62
+ // Do nothing.
63
+ }
64
+ onBuildKnex(knexBuilder) {
65
+ // Do nothing.
66
+ return knexBuilder;
67
+ }
68
+ // We overrode all other hooks but this one and do all the work in here.
69
+ // This is a bit hacky.
70
+ async onAfter1(builder, ...restArgs) {
71
+ await this.upsert.run(builder);
72
+ return await super.onAfter1(builder, ...restArgs);
73
+ }
74
+ onAfter2() {
75
+ // We override this with empty implementation so that the $afterInsert() hooks
76
+ // are not called twice for the root models.
77
+ return this.isArray ? this.models : this.models[0] || null;
78
+ }
79
+ clone() {
80
+ const clone = super.clone();
81
+ clone.upsert = this.upsert;
82
+ return clone;
69
83
  }
70
- }
71
-
72
- onBefore3(_, result) {
73
- // Do nothing.
74
- return result;
75
- }
76
-
77
- onBuild() {
78
- // Do nothing.
79
- }
80
-
81
- onBuildKnex(knexBuilder) {
82
- // Do nothing.
83
- return knexBuilder;
84
- }
85
-
86
- // We overrode all other hooks but this one and do all the work in here.
87
- // This is a bit hacky.
88
- async onAfter1(builder, ...restArgs) {
89
- await this.upsert.run(builder);
90
- return await super.onAfter1(builder, ...restArgs);
91
- }
92
-
93
- onAfter2() {
94
- // We override this with empty implementation so that the $afterInsert() hooks
95
- // are not called twice for the root models.
96
- return this.isArray ? this.models : this.models[0] || null;
97
- }
98
-
99
- clone() {
100
- const clone = super.clone();
101
- clone.upsert = this.upsert;
102
- return clone;
103
- }
104
84
  }
105
-
106
85
  module.exports = {
107
- InsertGraphOperation,
86
+ InsertGraphOperation,
108
87
  };
@@ -1,206 +1,173 @@
1
1
  'use strict';
2
-
3
2
  /* global BigInt */
4
-
5
3
  const { QueryBuilderOperation } = require('./QueryBuilderOperation');
6
- const { StaticHookArguments } = require('../StaticHookArguments');
4
+ const { StaticHookArguments, hasStaticHook } = require('../StaticHookArguments');
7
5
  const { after, mapAfterAllReturn } = require('../../utils/promiseUtils');
8
6
  const { isSqlite, isMySql } = require('../../utils/knexUtils');
9
7
  const { isObject } = require('../../utils/objectUtils');
10
-
11
8
  // `@@auto_increment_increment` for each MySQL knex instance, keyed by the knex config,
12
9
  // which transactions share with the knex they were started from.
13
10
  const autoIncrementIncrements = new WeakMap();
14
-
15
11
  // Base class for all insert operations.
16
12
  class InsertOperation extends QueryBuilderOperation {
17
- constructor(name, opt) {
18
- super(name, opt);
19
-
20
- this.models = null;
21
- this.isArray = false;
22
- this.modelOptions = Object.assign({}, this.opt.modelOptions || {});
23
- this.autoIncrementIncrement = null;
24
- }
25
-
26
- onAdd(builder, args) {
27
- const json = args[0];
28
- const modelClass = builder.modelClass();
29
-
30
- this.isArray = Array.isArray(json);
31
- this.models = modelClass.ensureModelArray(json, this.modelOptions);
32
-
33
- return true;
34
- }
35
-
36
- async onBefore2(builder, result) {
37
- await callBeforeInsert(builder, this.models);
38
-
39
- if (this.models.length > 1 && isMySql(builder.knex())) {
40
- await this.prepareMySqlBatchInsert(builder);
13
+ constructor(name, opt) {
14
+ super(name, opt);
15
+ this.models = null;
16
+ this.isArray = false;
17
+ this.modelOptions = Object.assign({}, this.opt.modelOptions || {});
18
+ this.autoIncrementIncrement = null;
41
19
  }
42
-
43
- return result;
44
- }
45
-
46
- // MySQL only returns the id of the first row of a multi-row insert. InnoDB
47
- // gives the rows of one multi-row VALUES insert consecutive ids (in every
48
- // `innodb_autoinc_lock_mode`), so the other ids can be computed from it and
49
- // `@@auto_increment_increment`.
50
- async prepareMySqlBatchInsert(builder) {
51
- const withId = this.models.filter((model) => model.$hasId()).length;
52
-
53
- if (withId === this.models.length) {
54
- return;
20
+ onAdd(builder, args) {
21
+ const json = args[0];
22
+ const modelClass = builder.modelClass();
23
+ this.isArray = Array.isArray(json);
24
+ this.models = modelClass.ensureModelArray(json, this.modelOptions);
25
+ return true;
55
26
  }
56
-
57
- if (withId > 0) {
58
- throw new Error(
59
- `batch insert on MySQL can't return ids when only some rows have an id. Set the id on all rows or none.`,
60
- );
61
- }
62
-
63
- if (Array.isArray(builder.modelClass().getIdColumn())) {
64
- return;
27
+ async onBefore2(builder, result) {
28
+ await callBeforeInsert(builder, this.models);
29
+ if (this.models.length > 1 && isMySql(builder.knex())) {
30
+ await this.prepareMySqlBatchInsert(builder);
31
+ }
32
+ return result;
65
33
  }
66
-
67
- const knex = builder.knex();
68
- let increment = autoIncrementIncrements.get(knex.client.config);
69
-
70
- if (increment === undefined) {
71
- const [rows] = await knex.raw('select @@auto_increment_increment as increment');
72
- increment = Number(rows[0].increment);
73
- autoIncrementIncrements.set(knex.client.config, increment);
34
+ // MySQL only returns the id of the first row of a multi-row insert. InnoDB
35
+ // gives the rows of one multi-row VALUES insert consecutive ids (in every
36
+ // `innodb_autoinc_lock_mode`), so the other ids can be computed from it and
37
+ // `@@auto_increment_increment`.
38
+ async prepareMySqlBatchInsert(builder) {
39
+ const withId = this.models.filter((model) => model.$hasId()).length;
40
+ if (withId === this.models.length) {
41
+ return;
42
+ }
43
+ if (withId > 0) {
44
+ throw new Error(`batch insert on MySQL can't return ids when only some rows have an id. Set the id on all rows or none.`);
45
+ }
46
+ if (Array.isArray(builder.modelClass().getIdColumn())) {
47
+ return;
48
+ }
49
+ const knex = builder.knex();
50
+ let increment = autoIncrementIncrements.get(knex.client.config);
51
+ if (increment === undefined) {
52
+ const [rows] = await knex.raw('select @@auto_increment_increment as increment');
53
+ increment = Number(rows[0].increment);
54
+ autoIncrementIncrements.set(knex.client.config, increment);
55
+ }
56
+ this.autoIncrementIncrement = increment;
74
57
  }
75
-
76
- this.autoIncrementIncrement = increment;
77
- }
78
-
79
- onBuildKnex(knexBuilder, builder) {
80
- const knex = builder.knex();
81
- const returnsIds = !isMySql(knex) && (!isSqlite(knex) || this.models.length > 1);
82
-
83
- if (returnsIds && !builder.has(/returning/)) {
84
- // If the user hasn't specified a `returning` clause, we make sure
85
- // that at least the identifier is returned. SQLite only returns the
86
- // id of the last row without one.
87
- knexBuilder = knexBuilder.returning(builder.modelClass().getIdColumn());
58
+ onBuildKnex(knexBuilder, builder) {
59
+ const knex = builder.knex();
60
+ const returnsIds = !isMySql(knex) && (!isSqlite(knex) || this.models.length > 1);
61
+ if (returnsIds && !builder.has(/returning/)) {
62
+ // If the user hasn't specified a `returning` clause, we make sure
63
+ // that at least the identifier is returned. SQLite only returns the
64
+ // id of the last row without one.
65
+ knexBuilder = knexBuilder.returning(builder.modelClass().getIdColumn());
66
+ }
67
+ return knexBuilder.insert(this.models.map((model) => model.$toDatabaseJson(builder)));
88
68
  }
89
-
90
- return knexBuilder.insert(this.models.map((model) => model.$toDatabaseJson(builder)));
91
- }
92
-
93
- onAfter1(builder, ret) {
94
- if (!Array.isArray(ret) || !ret.length || ret === this.models) {
95
- // Early exit if there is nothing to do.
96
- return this.models;
69
+ onAfter1(builder, ret) {
70
+ if (!Array.isArray(ret) || !ret.length || ret === this.models) {
71
+ // Early exit if there is nothing to do.
72
+ return this.models;
73
+ }
74
+ if (ret.length === 1 && this.models.length > 1) {
75
+ this.setMySqlBatchInsertIds(builder, ret[0]);
76
+ }
77
+ else if (isObject(ret[0])) {
78
+ // If the user specified a `returning` clause the result may be an array of objects.
79
+ // Merge all values of the objects to our models.
80
+ for (let i = 0, l = this.models.length; i < l; ++i) {
81
+ this.models[i].$setDatabaseJson(ret[i]);
82
+ }
83
+ }
84
+ else {
85
+ // If the return value is not an array of objects, we assume it is an array of identifiers.
86
+ for (let i = 0, l = this.models.length; i < l; ++i) {
87
+ const model = this.models[i];
88
+ // Don't set the id if the model already has one. MySQL and Sqlite don't return the correct
89
+ // primary key value if the id is not generated in db, but given explicitly.
90
+ if (!model.$id()) {
91
+ model.$id(ret[i]);
92
+ }
93
+ }
94
+ }
95
+ return this.models;
97
96
  }
98
-
99
- if (ret.length === 1 && this.models.length > 1) {
100
- this.setMySqlBatchInsertIds(builder, ret[0]);
101
- } else if (isObject(ret[0])) {
102
- // If the user specified a `returning` clause the result may be an array of objects.
103
- // Merge all values of the objects to our models.
104
- for (let i = 0, l = this.models.length; i < l; ++i) {
105
- this.models[i].$setDatabaseJson(ret[i]);
106
- }
107
- } else {
108
- // If the return value is not an array of objects, we assume it is an array of identifiers.
109
- for (let i = 0, l = this.models.length; i < l; ++i) {
110
- const model = this.models[i];
111
-
112
- // Don't set the id if the model already has one. MySQL and Sqlite don't return the correct
113
- // primary key value if the id is not generated in db, but given explicitly.
114
- if (!model.$id()) {
115
- model.$id(ret[i]);
97
+ setMySqlBatchInsertIds(builder, firstId) {
98
+ const increment = this.autoIncrementIncrement;
99
+ // `onConflict()` may skip or update rows, which breaks the id sequence.
100
+ if (increment === null || builder.has(/onConflict/) || !firstId) {
101
+ return;
102
+ }
103
+ for (let i = 0, l = this.models.length; i < l; ++i) {
104
+ this.models[i].$id(addToId(firstId, i * increment));
116
105
  }
117
- }
118
106
  }
119
-
120
- return this.models;
121
- }
122
-
123
- setMySqlBatchInsertIds(builder, firstId) {
124
- const increment = this.autoIncrementIncrement;
125
-
126
- // `onConflict()` may skip or update rows, which breaks the id sequence.
127
- if (increment === null || builder.has(/onConflict/) || !firstId) {
128
- return;
107
+ onAfter2(builder, models) {
108
+ const result = this.isArray ? models : models[0] || null;
109
+ return callAfterInsert(builder, this.models, result);
110
+ }
111
+ toFindOperation() {
112
+ return null;
129
113
  }
130
-
131
- for (let i = 0, l = this.models.length; i < l; ++i) {
132
- this.models[i].$id(addToId(firstId, i * increment));
114
+ clone() {
115
+ const clone = super.clone();
116
+ clone.models = this.models;
117
+ clone.isArray = this.isArray;
118
+ clone.autoIncrementIncrement = this.autoIncrementIncrement;
119
+ return clone;
133
120
  }
134
- }
135
-
136
- onAfter2(builder, models) {
137
- const result = this.isArray ? models : models[0] || null;
138
- return callAfterInsert(builder, this.models, result);
139
- }
140
-
141
- toFindOperation() {
142
- return null;
143
- }
144
-
145
- clone() {
146
- const clone = super.clone();
147
-
148
- clone.models = this.models;
149
- clone.isArray = this.isArray;
150
- clone.autoIncrementIncrement = this.autoIncrementIncrement;
151
-
152
- return clone;
153
- }
154
121
  }
155
-
156
122
  // The id can be a string or a BigInt when the driver is configured to
157
123
  // return big numbers that way.
158
124
  function addToId(id, amount) {
159
- if (typeof id === 'number') {
160
- return id + amount;
161
- } else if (typeof id === 'bigint') {
162
- return id + BigInt(amount);
163
- } else {
164
- return String(BigInt(id) + BigInt(amount));
165
- }
125
+ if (typeof id === 'number') {
126
+ return id + amount;
127
+ }
128
+ else if (typeof id === 'bigint') {
129
+ return id + BigInt(amount);
130
+ }
131
+ else {
132
+ return String(BigInt(id) + BigInt(amount));
133
+ }
166
134
  }
167
-
168
135
  function callBeforeInsert(builder, models) {
169
- const maybePromise = callInstanceBeforeInsert(builder, models);
170
- return after(maybePromise, () => callStaticBeforeInsert(builder));
136
+ const maybePromise = callInstanceBeforeInsert(builder, models);
137
+ return after(maybePromise, () => callStaticBeforeInsert(builder));
171
138
  }
172
-
173
139
  function callInstanceBeforeInsert(builder, models) {
174
- return mapAfterAllReturn(models, (model) => model.$beforeInsert(builder.context()), models);
140
+ return mapAfterAllReturn(models, (model) => model.$beforeInsert(builder.context()), models);
175
141
  }
176
-
177
142
  function callStaticBeforeInsert(builder) {
178
- const args = StaticHookArguments.create({ builder });
179
- return builder.modelClass().beforeInsert(args);
143
+ if (!hasStaticHook(builder.modelClass(), 'beforeInsert')) {
144
+ return undefined;
145
+ }
146
+ const args = StaticHookArguments.create({ builder });
147
+ return builder.modelClass().beforeInsert(args);
180
148
  }
181
-
182
149
  function callAfterInsert(builder, models, result) {
183
- const maybePromise = callInstanceAfterInsert(builder, models);
184
- return after(maybePromise, () => callStaticAfterInsert(builder, result));
150
+ const maybePromise = callInstanceAfterInsert(builder, models);
151
+ return after(maybePromise, () => callStaticAfterInsert(builder, result));
185
152
  }
186
-
187
153
  function callInstanceAfterInsert(builder, models) {
188
- return mapAfterAllReturn(models, (model) => model.$afterInsert(builder.context()), models);
154
+ return mapAfterAllReturn(models, (model) => model.$afterInsert(builder.context()), models);
189
155
  }
190
-
191
156
  function callStaticAfterInsert(builder, result) {
192
- const args = StaticHookArguments.create({ builder, result });
193
- const maybePromise = builder.modelClass().afterInsert(args);
194
-
195
- return after(maybePromise, (maybeResult) => {
196
- if (maybeResult === undefined) {
197
- return result;
198
- } else {
199
- return maybeResult;
157
+ if (!hasStaticHook(builder.modelClass(), 'afterInsert')) {
158
+ return result;
200
159
  }
201
- });
160
+ const args = StaticHookArguments.create({ builder, result });
161
+ const maybePromise = builder.modelClass().afterInsert(args);
162
+ return after(maybePromise, (maybeResult) => {
163
+ if (maybeResult === undefined) {
164
+ return result;
165
+ }
166
+ else {
167
+ return maybeResult;
168
+ }
169
+ });
202
170
  }
203
-
204
171
  module.exports = {
205
- InsertOperation,
172
+ InsertOperation,
206
173
  };
@@ -1,46 +1,37 @@
1
1
  'use strict';
2
-
3
2
  const { withWhereScope } = require('../whereScopes');
4
3
  const { DeleteOperation } = require('./DeleteOperation');
5
4
  const { InstanceFindOperation } = require('./InstanceFindOperation');
6
5
  const { assertHasId } = require('../../utils/assert');
7
-
8
6
  class InstanceDeleteOperation extends DeleteOperation {
9
- constructor(name, opt) {
10
- super(name, opt);
11
- this.instance = opt.instance;
12
- }
13
-
14
- async onBefore2(builder, result) {
15
- await this.instance.$beforeDelete(builder.context());
16
- await super.onBefore2(builder, result);
17
- return result;
18
- }
19
-
20
- onBuild(builder) {
21
- super.onBuild(builder);
22
-
23
- assertHasId(this.instance);
24
- withWhereScope(builder, () => builder.findById(this.instance.$id()));
25
- }
26
-
27
- async onAfter2(builder, result) {
28
- // The result may be an object if `returning` was used.
29
- if (Array.isArray(result)) {
30
- result = result[0];
7
+ constructor(name, opt) {
8
+ super(name, opt);
9
+ this.instance = opt.instance;
10
+ }
11
+ async onBefore2(builder, result) {
12
+ await this.instance.$beforeDelete(builder.context());
13
+ await super.onBefore2(builder, result);
14
+ return result;
15
+ }
16
+ onBuild(builder) {
17
+ super.onBuild(builder);
18
+ assertHasId(this.instance);
19
+ withWhereScope(builder, () => builder.findById(this.instance.$id()));
20
+ }
21
+ async onAfter2(builder, result) {
22
+ // The result may be an object if `returning` was used.
23
+ if (Array.isArray(result)) {
24
+ result = result[0];
25
+ }
26
+ await this.instance.$afterDelete(builder.context());
27
+ return super.onAfter2(builder, result);
28
+ }
29
+ toFindOperation() {
30
+ return new InstanceFindOperation('find', {
31
+ instance: this.instance,
32
+ });
31
33
  }
32
-
33
- await this.instance.$afterDelete(builder.context());
34
- return super.onAfter2(builder, result);
35
- }
36
-
37
- toFindOperation() {
38
- return new InstanceFindOperation('find', {
39
- instance: this.instance,
40
- });
41
- }
42
34
  }
43
-
44
35
  module.exports = {
45
- InstanceDeleteOperation,
36
+ InstanceDeleteOperation,
46
37
  };
@@ -1,21 +1,17 @@
1
1
  'use strict';
2
-
3
2
  const { withWhereScope } = require('../whereScopes');
4
3
  const { FindOperation } = require('./FindOperation');
5
4
  const { assertHasId } = require('../../utils/assert');
6
-
7
5
  class InstanceFindOperation extends FindOperation {
8
- constructor(name, opt) {
9
- super(name, opt);
10
- this.instance = opt.instance;
11
- }
12
-
13
- onBuild(builder) {
14
- assertHasId(this.instance);
15
- withWhereScope(builder, () => builder.findById(this.instance.$id()));
16
- }
6
+ constructor(name, opt) {
7
+ super(name, opt);
8
+ this.instance = opt.instance;
9
+ }
10
+ onBuild(builder) {
11
+ assertHasId(this.instance);
12
+ withWhereScope(builder, () => builder.findById(this.instance.$id()));
13
+ }
17
14
  }
18
-
19
15
  module.exports = {
20
- InstanceFindOperation,
16
+ InstanceFindOperation,
21
17
  };
@@ -1,24 +1,20 @@
1
1
  'use strict';
2
-
3
2
  const { InsertOperation } = require('./InsertOperation');
4
-
5
3
  class InstanceInsertOperation extends InsertOperation {
6
- constructor(name, opt) {
7
- super(name, opt);
8
- this.instance = opt.instance;
9
- }
10
-
11
- onAdd(builder, args) {
12
- if (!args || args.length === 0) {
13
- args = [this.instance];
14
- } else {
15
- args[0] = this.instance;
4
+ constructor(name, opt) {
5
+ super(name, opt);
6
+ this.instance = opt.instance;
7
+ }
8
+ onAdd(builder, args) {
9
+ if (!args || args.length === 0) {
10
+ args = [this.instance];
11
+ }
12
+ else {
13
+ args[0] = this.instance;
14
+ }
15
+ return super.onAdd(builder, args);
16
16
  }
17
-
18
- return super.onAdd(builder, args);
19
- }
20
17
  }
21
-
22
18
  module.exports = {
23
- InstanceInsertOperation,
19
+ InstanceInsertOperation,
24
20
  };