@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,36 +1,29 @@
1
1
  'use strict';
2
-
3
2
  const { ManyToManyModifyMixin } = require('./ManyToManyModifyMixin');
4
3
  const SQLITE_BUILTIN_ROW_ID = '_rowid_';
5
-
6
4
  // We need to override this mixin for sqlite because sqlite doesn't support
7
5
  // multi-column where in statements with subqueries. We need to use the
8
6
  // internal _rowid_ column instead.
9
7
  const ManyToManySqliteModifyMixin = (Operation) => {
10
- return class extends ManyToManyModifyMixin(Operation) {
11
- applyModifyFilterForRelatedTable(builder) {
12
- const tableRef = builder.tableRefFor(this.relation.relatedModelClass);
13
- const rowIdRef = `${tableRef}.${SQLITE_BUILTIN_ROW_ID}`;
14
- const subquery = this.modifyFilterSubquery.clone().select(rowIdRef);
15
-
16
- return builder.whereInComposite(rowIdRef, subquery);
17
- }
18
-
19
- applyModifyFilterForJoinTable(builder) {
20
- const joinTableOwnerRefs = this.relation.joinTableOwnerProp.refs(builder);
21
- const tableRef = builder.tableRefFor(this.relation.getJoinModelClass(builder));
22
- const rowIdRef = `${tableRef}.${SQLITE_BUILTIN_ROW_ID}`;
23
-
24
- const ownerValues = this.owner.getProps(this.relation);
25
- const subquery = this.modifyFilterSubquery.clone().select(rowIdRef);
26
-
27
- return builder
28
- .whereInComposite(rowIdRef, subquery)
29
- .whereInComposite(joinTableOwnerRefs, ownerValues);
30
- }
31
- };
8
+ return class extends ManyToManyModifyMixin(Operation) {
9
+ applyModifyFilterForRelatedTable(builder) {
10
+ const tableRef = builder.tableRefFor(this.relation.relatedModelClass);
11
+ const rowIdRef = `${tableRef}.${SQLITE_BUILTIN_ROW_ID}`;
12
+ const subquery = this.modifyFilterSubquery.clone().select(rowIdRef);
13
+ return builder.whereInComposite(rowIdRef, subquery);
14
+ }
15
+ applyModifyFilterForJoinTable(builder) {
16
+ const joinTableOwnerRefs = this.relation.joinTableOwnerProp.refs(builder);
17
+ const tableRef = builder.tableRefFor(this.relation.getJoinModelClass(builder));
18
+ const rowIdRef = `${tableRef}.${SQLITE_BUILTIN_ROW_ID}`;
19
+ const ownerValues = this.owner.getProps(this.relation);
20
+ const subquery = this.modifyFilterSubquery.clone().select(rowIdRef);
21
+ return builder
22
+ .whereInComposite(rowIdRef, subquery)
23
+ .whereInComposite(joinTableOwnerRefs, ownerValues);
24
+ }
25
+ };
32
26
  };
33
-
34
27
  module.exports = {
35
- ManyToManySqliteModifyMixin,
28
+ ManyToManySqliteModifyMixin,
36
29
  };
@@ -1,10 +1,8 @@
1
1
  'use strict';
2
-
3
2
  const { ManyToManyDeleteOperationBase } = require('./ManyToManyDeleteOperationBase');
4
3
  const { ManyToManyModifyMixin } = require('../ManyToManyModifyMixin');
5
-
6
- class ManyToManyDeleteOperation extends ManyToManyModifyMixin(ManyToManyDeleteOperationBase) {}
7
-
4
+ class ManyToManyDeleteOperation extends ManyToManyModifyMixin(ManyToManyDeleteOperationBase) {
5
+ }
8
6
  module.exports = {
9
- ManyToManyDeleteOperation,
7
+ ManyToManyDeleteOperation,
10
8
  };
@@ -1,26 +1,20 @@
1
1
  'use strict';
2
-
3
2
  const { DeleteOperation } = require('../../../queryBuilder/operations/DeleteOperation');
4
-
5
3
  class ManyToManyDeleteOperationBase extends DeleteOperation {
6
- constructor(name, opt) {
7
- super(name, opt);
8
-
9
- this.relation = opt.relation;
10
- this.owner = opt.owner;
11
- }
12
-
13
- /* istanbul ignore next */
14
- applyModifyFilterForRelatedTable(builder) {
15
- throw new Error('not implemented');
16
- }
17
-
18
- /* istanbul ignore next */
19
- applyModifyFilterForJoinTable(builder) {
20
- throw new Error('not implemented');
21
- }
4
+ constructor(name, opt) {
5
+ super(name, opt);
6
+ this.relation = opt.relation;
7
+ this.owner = opt.owner;
8
+ }
9
+ /* istanbul ignore next */
10
+ applyModifyFilterForRelatedTable(builder) {
11
+ throw new Error('not implemented');
12
+ }
13
+ /* istanbul ignore next */
14
+ applyModifyFilterForJoinTable(builder) {
15
+ throw new Error('not implemented');
16
+ }
22
17
  }
23
-
24
18
  module.exports = {
25
- ManyToManyDeleteOperationBase,
19
+ ManyToManyDeleteOperationBase,
26
20
  };
@@ -1,12 +1,8 @@
1
1
  'use strict';
2
-
3
2
  const { ManyToManyDeleteOperationBase } = require('./ManyToManyDeleteOperationBase');
4
3
  const { ManyToManySqliteModifyMixin } = require('../ManyToManySqliteModifyMixin');
5
-
6
- class ManyToManyDeleteSqliteOperation extends ManyToManySqliteModifyMixin(
7
- ManyToManyDeleteOperationBase,
8
- ) {}
9
-
4
+ class ManyToManyDeleteSqliteOperation extends ManyToManySqliteModifyMixin(ManyToManyDeleteOperationBase) {
5
+ }
10
6
  module.exports = {
11
- ManyToManyDeleteSqliteOperation,
7
+ ManyToManyDeleteSqliteOperation,
12
8
  };
@@ -1,105 +1,82 @@
1
1
  'use strict';
2
-
3
2
  const { RelationFindOperation } = require('../../RelationFindOperation');
4
3
  const { getTempColumn } = require('../../../utils/tmpColumnUtils');
5
-
6
4
  class ManyToManyFindOperation extends RelationFindOperation {
7
- constructor(name, opt) {
8
- super(name, opt);
9
-
10
- this.ownerJoinColumnAlias = new Array(this.relation.joinTableOwnerProp.size);
11
-
12
- for (let i = 0, l = this.ownerJoinColumnAlias.length; i < l; ++i) {
13
- this.ownerJoinColumnAlias[i] = getTempColumn(i);
14
- }
15
- }
16
-
17
- onBuild(builder) {
18
- const relatedModelClass = this.relation.relatedModelClass;
19
-
20
- this.maybeApplyAlias(builder);
21
- this.relation.findQuery(builder, this.owner);
22
-
23
- if (!builder.hasSelects()) {
24
- const table = builder.tableRefFor(relatedModelClass);
25
-
26
- // If the user hasn't specified a select clause, select the related model's columns.
27
- // If we don't do this we also get the join table's columns.
28
- builder.select(`${table}.*`);
29
-
30
- // Also select all extra columns.
31
- for (const extra of this.relation.joinTableExtras) {
32
- const joinTable = builder.tableRefFor(this.relation.joinTable);
33
- builder.select(`${joinTable}.${extra.joinTableCol} as ${extra.aliasCol}`);
34
- }
35
- }
36
-
37
- if (this.assignResultToOwner && this.owner.isModels) {
38
- this.selectMissingJoinColumns(builder);
5
+ constructor(name, opt) {
6
+ super(name, opt);
7
+ this.ownerJoinColumnAlias = new Array(this.relation.joinTableOwnerProp.size);
8
+ for (let i = 0, l = this.ownerJoinColumnAlias.length; i < l; ++i) {
9
+ this.ownerJoinColumnAlias[i] = getTempColumn(i);
10
+ }
39
11
  }
40
- }
41
-
42
- onAfter2(_, related) {
43
- const isOneToOne = this.relation.isOneToOne();
44
-
45
- if (this.assignResultToOwner && this.owner.isModels) {
46
- const owners = this.owner.modelArray;
47
- const ownerProp = this.relation.ownerProp;
48
- const relatedByOwnerId = new Map();
49
-
50
- for (let i = 0, l = related.length; i < l; ++i) {
51
- const rel = related[i];
52
- const key = rel.$propKey(this.ownerJoinColumnAlias);
53
- let arr = relatedByOwnerId.get(key);
54
-
55
- if (!arr) {
56
- arr = [];
57
- relatedByOwnerId.set(key, arr);
12
+ onBuild(builder) {
13
+ const relatedModelClass = this.relation.relatedModelClass;
14
+ this.maybeApplyAlias(builder);
15
+ this.relation.findQuery(builder, this.owner);
16
+ if (!builder.hasSelects()) {
17
+ const table = builder.tableRefFor(relatedModelClass);
18
+ // If the user hasn't specified a select clause, select the related model's columns.
19
+ // If we don't do this we also get the join table's columns.
20
+ builder.select(`${table}.*`);
21
+ // Also select all extra columns.
22
+ for (const extra of this.relation.joinTableExtras) {
23
+ const joinTable = builder.tableRefFor(this.relation.joinTable);
24
+ builder.select(`${joinTable}.${extra.joinTableCol} as ${extra.aliasCol}`);
25
+ }
58
26
  }
59
-
60
- arr.push(rel);
61
- }
62
-
63
- for (let i = 0, l = owners.length; i < l; ++i) {
64
- const own = owners[i];
65
- const key = ownerProp.propKey(own);
66
- const related = relatedByOwnerId.get(key);
67
-
68
- if (isOneToOne) {
69
- own[this.relationProperty] = (related && related[0]) || null;
70
- } else {
71
- own[this.relationProperty] = related || [];
27
+ if (this.assignResultToOwner && this.owner.isModels) {
28
+ this.selectMissingJoinColumns(builder);
72
29
  }
73
- }
74
30
  }
75
-
76
- return related;
77
- }
78
-
79
- clone() {
80
- const clone = super.clone();
81
- clone.ownerJoinColumnAlias = this.ownerJoinColumnAlias.slice();
82
- return clone;
83
- }
84
-
85
- selectMissingJoinColumns(builder) {
86
- const { relatedModelClass, joinTableOwnerProp } = this.relation;
87
-
88
- // We must select the owner join columns so that we know for which owner model the related
89
- // models belong to after the requests.
90
- joinTableOwnerProp.forEach((i) => {
91
- const joinTableOwnerRef = joinTableOwnerProp.ref(builder, i);
92
- const propName = relatedModelClass.columnNameToPropertyName(this.ownerJoinColumnAlias[i]);
93
-
94
- builder.select(joinTableOwnerRef.as(this.ownerJoinColumnAlias[i]));
95
- // Mark them to be omitted later.
96
- this.omitProps.push(propName);
97
- });
98
-
99
- super.selectMissingJoinColumns(builder);
100
- }
31
+ onAfter2(_, related) {
32
+ const isOneToOne = this.relation.isOneToOne();
33
+ if (this.assignResultToOwner && this.owner.isModels) {
34
+ const owners = this.owner.modelArray;
35
+ const ownerProp = this.relation.ownerProp;
36
+ const relatedByOwnerId = new Map();
37
+ for (let i = 0, l = related.length; i < l; ++i) {
38
+ const rel = related[i];
39
+ const key = rel.$propKey(this.ownerJoinColumnAlias);
40
+ let arr = relatedByOwnerId.get(key);
41
+ if (!arr) {
42
+ arr = [];
43
+ relatedByOwnerId.set(key, arr);
44
+ }
45
+ arr.push(rel);
46
+ }
47
+ for (let i = 0, l = owners.length; i < l; ++i) {
48
+ const own = owners[i];
49
+ const key = ownerProp.propKey(own);
50
+ const related = relatedByOwnerId.get(key);
51
+ if (isOneToOne) {
52
+ own[this.relationProperty] = (related && related[0]) || null;
53
+ }
54
+ else {
55
+ own[this.relationProperty] = related || [];
56
+ }
57
+ }
58
+ }
59
+ return related;
60
+ }
61
+ clone() {
62
+ const clone = super.clone();
63
+ clone.ownerJoinColumnAlias = this.ownerJoinColumnAlias.slice();
64
+ return clone;
65
+ }
66
+ selectMissingJoinColumns(builder) {
67
+ const { relatedModelClass, joinTableOwnerProp } = this.relation;
68
+ // We must select the owner join columns so that we know for which owner model the related
69
+ // models belong to after the requests.
70
+ joinTableOwnerProp.forEach((i) => {
71
+ const joinTableOwnerRef = joinTableOwnerProp.ref(builder, i);
72
+ const propName = relatedModelClass.columnNameToPropertyName(this.ownerJoinColumnAlias[i]);
73
+ builder.select(joinTableOwnerRef.as(this.ownerJoinColumnAlias[i]));
74
+ // Mark them to be omitted later.
75
+ this.omitProps.push(propName);
76
+ });
77
+ super.selectMissingJoinColumns(builder);
78
+ }
101
79
  }
102
-
103
80
  module.exports = {
104
- ManyToManyFindOperation,
81
+ ManyToManyFindOperation,
105
82
  };
@@ -1,52 +1,40 @@
1
1
  'use strict';
2
-
3
2
  const { RelationInsertOperation } = require('../../RelationInsertOperation');
4
3
  const { ManyToManyRelateOperation } = require('../relate/ManyToManyRelateOperation');
5
-
6
4
  class ManyToManyInsertOperation extends RelationInsertOperation {
7
- onAdd(builder, args) {
8
- const retVal = super.onAdd(builder, args);
9
-
10
- // Omit extra properties so that we don't try to insert
11
- // them to the related table. We don't actually remove them
12
- // from the objects, but simply mark them to be removed
13
- // from the inserted row.
14
- this.relation.omitExtraProps(this.models);
15
-
16
- return retVal;
17
- }
18
-
19
- async onAfter1(builder, ret) {
20
- const inserted = await super.onAfter1(builder, ret);
21
-
22
- const relateOp = new ManyToManyRelateOperation('relate', {
23
- dontCopyReturning: true,
24
- dontCopyOnConflict: true,
25
- relation: this.relation,
26
- owner: this.owner,
27
- });
28
-
29
- const modelsToRelate = inserted.filter((it) => {
30
- return this.relation.relatedProp.hasProps(it);
31
- });
32
-
33
- if (this.assignResultToOwner && this.owner.isModels) {
34
- for (const owner of this.owner.modelArray) {
35
- owner.$appendRelated(this.relation, inserted);
36
- }
5
+ onAdd(builder, args) {
6
+ const retVal = super.onAdd(builder, args);
7
+ // Omit extra properties so that we don't try to insert
8
+ // them to the related table. We don't actually remove them
9
+ // from the objects, but simply mark them to be removed
10
+ // from the inserted row.
11
+ this.relation.omitExtraProps(this.models);
12
+ return retVal;
37
13
  }
38
-
39
- if (modelsToRelate.length === 0) {
40
- return inserted;
14
+ async onAfter1(builder, ret) {
15
+ const inserted = await super.onAfter1(builder, ret);
16
+ const relateOp = new ManyToManyRelateOperation('relate', {
17
+ dontCopyReturning: true,
18
+ dontCopyOnConflict: true,
19
+ relation: this.relation,
20
+ owner: this.owner,
21
+ });
22
+ const modelsToRelate = inserted.filter((it) => {
23
+ return this.relation.relatedProp.hasProps(it);
24
+ });
25
+ if (this.assignResultToOwner && this.owner.isModels) {
26
+ for (const owner of this.owner.modelArray) {
27
+ owner.$appendRelated(this.relation, inserted);
28
+ }
29
+ }
30
+ if (modelsToRelate.length === 0) {
31
+ return inserted;
32
+ }
33
+ relateOp.onAdd(builder, [modelsToRelate]);
34
+ await relateOp.queryExecutor(builder);
35
+ return inserted;
41
36
  }
42
-
43
- relateOp.onAdd(builder, [modelsToRelate]);
44
- await relateOp.queryExecutor(builder);
45
-
46
- return inserted;
47
- }
48
37
  }
49
-
50
38
  module.exports = {
51
- ManyToManyInsertOperation,
39
+ ManyToManyInsertOperation,
52
40
  };
@@ -1,81 +1,64 @@
1
1
  'use strict';
2
-
3
2
  const { isPostgres } = require('../../../utils/knexUtils');
4
3
  const { normalizeIds } = require('../../../utils/normalizeIds');
5
4
  const { RelateOperation } = require('../../../queryBuilder/operations/RelateOperation');
6
-
7
5
  class ManyToManyRelateOperation extends RelateOperation {
8
- onAdd(builder, args) {
9
- this.input = args[0];
10
- this.ids = normalizeIds(args[0], this.relation.relatedProp);
11
-
12
- assertOwnerIsSingleItem(builder, this.owner, this.relation);
13
- return true;
14
- }
15
-
16
- queryExecutor(builder) {
17
- const joinModelClass = this.relation.getJoinModelClass(builder.knex());
18
- const ownerValues = this.owner.getSplitProps(builder, this.relation);
19
- const joinModels = [];
20
-
21
- for (const ownerValue of ownerValues) {
22
- for (const relatedValue of this.ids) {
23
- joinModels.push(
24
- joinModelClass.fromJson(this.relation.createJoinModel(ownerValue, relatedValue)),
25
- );
26
- }
6
+ onAdd(builder, args) {
7
+ this.input = args[0];
8
+ this.ids = normalizeIds(args[0], this.relation.relatedProp);
9
+ assertOwnerIsSingleItem(builder, this.owner, this.relation);
10
+ return true;
27
11
  }
28
-
29
- return joinModelClass
30
- .query()
31
- .childQueryOf(builder)
32
- .modify((query) => {
33
- if (!this.opt.dontCopyReturning) {
34
- query.copyFrom(builder, /returning/);
12
+ queryExecutor(builder) {
13
+ const joinModelClass = this.relation.getJoinModelClass(builder.knex());
14
+ const ownerValues = this.owner.getSplitProps(builder, this.relation);
15
+ const joinModels = [];
16
+ for (const ownerValue of ownerValues) {
17
+ for (const relatedValue of this.ids) {
18
+ joinModels.push(joinModelClass.fromJson(this.relation.createJoinModel(ownerValue, relatedValue)));
19
+ }
35
20
  }
36
-
37
- if (!this.opt.dontCopyOnConflict) {
38
- query.copyFrom(builder, /onConflict|ignore|merge/);
39
- }
40
- })
41
- .runBefore((_, builder) => {
42
- return this.relation.executeJoinTableBeforeInsert(joinModels, builder.context(), null);
43
- })
44
- .insert(joinModels)
45
- .runAfter((models) => {
46
- return Array.isArray(models) ? models.length : 1;
47
- });
48
- }
21
+ return joinModelClass
22
+ .query()
23
+ .childQueryOf(builder)
24
+ .modify((query) => {
25
+ if (!this.opt.dontCopyReturning) {
26
+ query.copyFrom(builder, /returning/);
27
+ }
28
+ if (!this.opt.dontCopyOnConflict) {
29
+ query.copyFrom(builder, /onConflict|ignore|merge/);
30
+ }
31
+ })
32
+ .runBefore((_, builder) => {
33
+ return this.relation.executeJoinTableBeforeInsert(joinModels, builder.context(), null);
34
+ })
35
+ .insert(joinModels)
36
+ .runAfter((models) => {
37
+ return Array.isArray(models) ? models.length : 1;
38
+ });
39
+ }
49
40
  }
50
-
51
41
  function assertOwnerIsSingleItem(builder, owner, relation) {
52
- const { isModels, isIdentifiers, isQueryBuilder } = owner;
53
- const { ownerProp } = relation;
54
-
55
- const singleModel = isModels && owner.modelArray.length === 1;
56
- const singleId = isIdentifiers && owner.getNormalizedIdentifiers(ownerProp).length === 1;
57
-
58
- if (isPostgres(builder.unsafeKnex())) {
59
- if (!isModels && !isIdentifiers && !isQueryBuilder) {
60
- throw new Error(
61
- 'Parent must be a list of identifiers or a list of models when relating a ManyToManyRelation',
62
- );
42
+ const { isModels, isIdentifiers, isQueryBuilder } = owner;
43
+ const { ownerProp } = relation;
44
+ const singleModel = isModels && owner.modelArray.length === 1;
45
+ const singleId = isIdentifiers && owner.getNormalizedIdentifiers(ownerProp).length === 1;
46
+ if (isPostgres(builder.unsafeKnex())) {
47
+ if (!isModels && !isIdentifiers && !isQueryBuilder) {
48
+ throw new Error('Parent must be a list of identifiers or a list of models when relating a ManyToManyRelation');
49
+ }
63
50
  }
64
- } else {
65
- if (!singleModel && !singleId && !isQueryBuilder) {
66
- throw new Error(
67
- [
68
- 'Can only relate items for one parent at a time in case of ManyToManyRelation.',
69
- 'Otherwise multiple insert queries would need to be created.',
70
-
71
- 'If you need to relate items for multiple parents, simply loop through them.',
72
- `That's the most performant way.`,
73
- ].join(' '),
74
- );
51
+ else {
52
+ if (!singleModel && !singleId && !isQueryBuilder) {
53
+ throw new Error([
54
+ 'Can only relate items for one parent at a time in case of ManyToManyRelation.',
55
+ 'Otherwise multiple insert queries would need to be created.',
56
+ 'If you need to relate items for multiple parents, simply loop through them.',
57
+ `That's the most performant way.`,
58
+ ].join(' '));
59
+ }
75
60
  }
76
- }
77
61
  }
78
-
79
62
  module.exports = {
80
- ManyToManyRelateOperation,
63
+ ManyToManyRelateOperation,
81
64
  };
@@ -1,14 +1,11 @@
1
1
  'use strict';
2
-
3
2
  const { ManyToManyUnrelateOperationBase } = require('./ManyToManyUnrelateOperationBase');
4
3
  const { ManyToManyModifyMixin } = require('../ManyToManyModifyMixin');
5
-
6
4
  class ManyToManyUnrelateOperation extends ManyToManyModifyMixin(ManyToManyUnrelateOperationBase) {
7
- get modifyMainQuery() {
8
- return false;
9
- }
5
+ get modifyMainQuery() {
6
+ return false;
7
+ }
10
8
  }
11
-
12
9
  module.exports = {
13
- ManyToManyUnrelateOperation,
10
+ ManyToManyUnrelateOperation,
14
11
  };
@@ -1,34 +1,27 @@
1
1
  'use strict';
2
-
3
2
  const { withWhereScope } = require('../../../queryBuilder/whereScopes');
4
3
  const { UnrelateOperation } = require('../../../queryBuilder/operations/UnrelateOperation');
5
-
6
4
  class ManyToManyUnrelateOperationBase extends UnrelateOperation {
7
- queryExecutor(builder) {
8
- const unrelateQuery = this.relation
9
- .getJoinModelClass(builder.knex())
10
- .query()
11
- .childQueryOf(builder)
12
- .delete();
13
-
14
- withWhereScope(unrelateQuery, () => {
15
- this.applyModifyFilterForJoinTable(unrelateQuery);
16
- });
17
-
18
- return unrelateQuery.modify(this.relation.joinTableModify);
19
- }
20
-
21
- /* istanbul ignore next */
22
- applyModifyFilterForRelatedTable(builder) {
23
- throw new Error('not implemented');
24
- }
25
-
26
- /* istanbul ignore next */
27
- applyModifyFilterForJoinTable(builder) {
28
- throw new Error('not implemented');
29
- }
5
+ queryExecutor(builder) {
6
+ const unrelateQuery = this.relation
7
+ .getJoinModelClass(builder.knex())
8
+ .query()
9
+ .childQueryOf(builder)
10
+ .delete();
11
+ withWhereScope(unrelateQuery, () => {
12
+ this.applyModifyFilterForJoinTable(unrelateQuery);
13
+ });
14
+ return unrelateQuery.modify(this.relation.joinTableModify);
15
+ }
16
+ /* istanbul ignore next */
17
+ applyModifyFilterForRelatedTable(builder) {
18
+ throw new Error('not implemented');
19
+ }
20
+ /* istanbul ignore next */
21
+ applyModifyFilterForJoinTable(builder) {
22
+ throw new Error('not implemented');
23
+ }
30
24
  }
31
-
32
25
  module.exports = {
33
- ManyToManyUnrelateOperationBase,
26
+ ManyToManyUnrelateOperationBase,
34
27
  };
@@ -1,16 +1,11 @@
1
1
  'use strict';
2
-
3
2
  const { ManyToManyUnrelateOperationBase } = require('./ManyToManyUnrelateOperationBase');
4
3
  const { ManyToManySqliteModifyMixin } = require('../ManyToManySqliteModifyMixin');
5
-
6
- class ManyToManyUnrelateSqliteOperation extends ManyToManySqliteModifyMixin(
7
- ManyToManyUnrelateOperationBase,
8
- ) {
9
- get modifyMainQuery() {
10
- return false;
11
- }
4
+ class ManyToManyUnrelateSqliteOperation extends ManyToManySqliteModifyMixin(ManyToManyUnrelateOperationBase) {
5
+ get modifyMainQuery() {
6
+ return false;
7
+ }
12
8
  }
13
-
14
9
  module.exports = {
15
- ManyToManyUnrelateSqliteOperation,
10
+ ManyToManyUnrelateSqliteOperation,
16
11
  };
@@ -1,10 +1,8 @@
1
1
  'use strict';
2
-
3
2
  const { ManyToManyUpdateOperationBase } = require('./ManyToManyUpdateOperationBase');
4
3
  const { ManyToManyModifyMixin } = require('../ManyToManyModifyMixin');
5
-
6
- class ManyToManyUpdateOperation extends ManyToManyModifyMixin(ManyToManyUpdateOperationBase) {}
7
-
4
+ class ManyToManyUpdateOperation extends ManyToManyModifyMixin(ManyToManyUpdateOperationBase) {
5
+ }
8
6
  module.exports = {
9
- ManyToManyUpdateOperation,
7
+ ManyToManyUpdateOperation,
10
8
  };