objection 3.9.1 → 4.0.0-rc.2

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 (250) 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 +11 -23
  57. package/lib/model/modelSet.js +89 -41
  58. package/lib/model/modelTableMetadata.js +4 -11
  59. package/lib/model/modelToJson.js +6 -13
  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 +314 -0
  81. package/lib/queryBuilder/graph/GraphNode.js +241 -0
  82. package/lib/queryBuilder/graph/GraphOptions.js +55 -248
  83. package/lib/queryBuilder/graph/GraphPlan.js +431 -0
  84. package/lib/queryBuilder/graph/GraphSchedule.js +513 -0
  85. package/lib/queryBuilder/graph/GraphUpsert.js +519 -412
  86. package/lib/queryBuilder/graph/GraphWriter.js +508 -0
  87. package/lib/queryBuilder/graph/graphKeys.js +929 -0
  88. package/lib/queryBuilder/join/JoinResultColumn.js +1 -7
  89. package/lib/queryBuilder/join/JoinResultParser.js +6 -11
  90. package/lib/queryBuilder/join/RelationJoiner.js +66 -84
  91. package/lib/queryBuilder/join/TableNode.js +2 -8
  92. package/lib/queryBuilder/join/TableTree.js +3 -9
  93. package/lib/queryBuilder/join/utils.js +5 -15
  94. package/lib/queryBuilder/jsonDialects/JsonDialect.js +51 -0
  95. package/lib/queryBuilder/jsonDialects/MySqlJsonDialect.js +81 -0
  96. package/lib/queryBuilder/jsonDialects/PostgresJsonDialect.js +45 -0
  97. package/lib/queryBuilder/jsonDialects/SqliteJsonDialect.js +67 -0
  98. package/lib/queryBuilder/jsonDialects/index.js +44 -0
  99. package/lib/queryBuilder/operations/DelegateOperation.js +2 -8
  100. package/lib/queryBuilder/operations/DeleteOperation.js +10 -39
  101. package/lib/queryBuilder/operations/FindByIdOperation.js +7 -12
  102. package/lib/queryBuilder/operations/FindByIdsOperation.js +4 -8
  103. package/lib/queryBuilder/operations/FindOperation.js +14 -34
  104. package/lib/queryBuilder/operations/FirstOperation.js +6 -10
  105. package/lib/queryBuilder/operations/FromOperation.js +3 -9
  106. package/lib/queryBuilder/operations/InsertAndFetchOperation.js +13 -12
  107. package/lib/queryBuilder/operations/InsertGraphAndFetchOperation.js +4 -10
  108. package/lib/queryBuilder/operations/InsertGraphOperation.js +7 -18
  109. package/lib/queryBuilder/operations/InsertOperation.js +118 -45
  110. package/lib/queryBuilder/operations/InstanceDeleteOperation.js +5 -12
  111. package/lib/queryBuilder/operations/InstanceFindOperation.js +4 -11
  112. package/lib/queryBuilder/operations/InstanceInsertOperation.js +2 -8
  113. package/lib/queryBuilder/operations/InstanceUpdateOperation.js +7 -14
  114. package/lib/queryBuilder/operations/JoinRelatedOperation.js +5 -11
  115. package/lib/queryBuilder/operations/KnexOperation.js +2 -8
  116. package/lib/queryBuilder/operations/LimitPerParentOperation.js +7 -69
  117. package/lib/queryBuilder/operations/MergeOperation.js +5 -11
  118. package/lib/queryBuilder/operations/NoneOperation.js +2 -8
  119. package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +20 -49
  120. package/lib/queryBuilder/operations/OnBuildKnexOperation.js +2 -8
  121. package/lib/queryBuilder/operations/OnBuildOperation.js +2 -8
  122. package/lib/queryBuilder/operations/OnErrorOperation.js +2 -8
  123. package/lib/queryBuilder/operations/QueryBuilderOperation.js +1 -7
  124. package/lib/queryBuilder/operations/RangeOperation.js +11 -26
  125. package/lib/queryBuilder/operations/RelateOperation.js +2 -8
  126. package/lib/queryBuilder/operations/ReturningOperation.js +3 -9
  127. package/lib/queryBuilder/operations/RunAfterOperation.js +2 -12
  128. package/lib/queryBuilder/operations/RunBeforeOperation.js +2 -8
  129. package/lib/queryBuilder/operations/UnrelateOperation.js +2 -8
  130. package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +14 -17
  131. package/lib/queryBuilder/operations/UpdateOperation.js +32 -132
  132. package/lib/queryBuilder/operations/UpsertGraphAndFetchOperation.js +8 -11
  133. package/lib/queryBuilder/operations/UpsertGraphOperation.js +6 -12
  134. package/lib/queryBuilder/operations/WhereCompositeOperation.js +3 -9
  135. package/lib/queryBuilder/operations/WhereGroupOperation.js +2 -8
  136. package/lib/queryBuilder/operations/eager/EagerOperation.js +3 -9
  137. package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +72 -10
  138. package/lib/queryBuilder/operations/eager/NaiveEagerOperation.js +2 -8
  139. package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +23 -44
  140. package/lib/queryBuilder/operations/fieldExpressions.js +122 -0
  141. package/lib/queryBuilder/operations/jsonApi/WhereJsonHasOperation.js +20 -0
  142. package/lib/queryBuilder/operations/jsonApi/WhereJsonOperation.js +44 -0
  143. package/lib/queryBuilder/operations/jsonApi/WhereJsonTypeOperation.js +14 -0
  144. package/lib/queryBuilder/operations/select/SelectOperation.js +11 -21
  145. package/lib/queryBuilder/operations/select/Selection.js +19 -17
  146. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +4 -10
  147. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +4 -10
  148. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +4 -10
  149. package/lib/queryBuilder/operations/windowOrder.js +56 -0
  150. package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +3 -7
  151. package/lib/queryBuilder/parsers/relationExpressionParser.js +42 -43
  152. package/lib/queryBuilder/parsers/relationExpressionParser.pegjs +39 -36
  153. package/lib/queryBuilder/transformations/CompositeQueryTransformation.js +2 -8
  154. package/lib/queryBuilder/transformations/QueryTransformation.js +1 -7
  155. package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +3 -9
  156. package/lib/queryBuilder/transformations/index.js +3 -11
  157. package/lib/queryBuilder/whereGroups.js +9 -24
  158. package/lib/queryBuilder/withoutOrder.js +4 -11
  159. package/lib/relations/Relation.js +47 -28
  160. package/lib/relations/RelationDeleteOperation.js +4 -14
  161. package/lib/relations/RelationFindOperation.js +119 -90
  162. package/lib/relations/RelationInsertOperation.js +2 -8
  163. package/lib/relations/RelationOwner.js +5 -11
  164. package/lib/relations/RelationProperty.js +4 -10
  165. package/lib/relations/RelationUpdateOperation.js +4 -14
  166. package/lib/relations/RelationWriteResultOperation.js +15 -0
  167. package/lib/relations/belongsToMany/BelongsToManyDeleteOperation.js +23 -0
  168. package/lib/relations/belongsToMany/BelongsToManyFindOperation.js +35 -0
  169. package/lib/relations/belongsToMany/BelongsToManyInsertOperation.js +28 -0
  170. package/lib/relations/belongsToMany/BelongsToManyRelateOperation.js +16 -0
  171. package/lib/relations/belongsToMany/BelongsToManyRelation.js +276 -0
  172. package/lib/relations/belongsToMany/BelongsToManyUnrelateOperation.js +11 -0
  173. package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +2 -8
  174. package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +6 -11
  175. package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +3 -9
  176. package/lib/relations/belongsToOne/BelongsToOneRelation.js +8 -19
  177. package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +53 -27
  178. package/lib/relations/hasMany/HasManyInsertOperation.js +5 -10
  179. package/lib/relations/hasMany/HasManyRelateOperation.js +5 -11
  180. package/lib/relations/hasMany/HasManyRelation.js +9 -11
  181. package/lib/relations/hasMany/HasManyUnrelateOperation.js +3 -9
  182. package/lib/relations/hasOne/HasOneRelation.js +2 -8
  183. package/lib/relations/hasOneThrough/HasOneThroughRelation.js +2 -8
  184. package/lib/relations/manyToMany/ManyToManyModifyMixin.js +10 -15
  185. package/lib/relations/manyToMany/ManyToManyMySqlModifyMixin.js +2 -8
  186. package/lib/relations/manyToMany/ManyToManyRelation.js +82 -50
  187. package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +2 -8
  188. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +5 -9
  189. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +2 -8
  190. package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +3 -9
  191. package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +20 -59
  192. package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +6 -11
  193. package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +4 -10
  194. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateMySqlOperation.js +3 -9
  195. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +5 -9
  196. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +3 -9
  197. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +3 -9
  198. package/lib/relations/manyToMany/update/ManyToManyUpdateMySqlOperation.js +3 -9
  199. package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +5 -9
  200. package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +64 -72
  201. package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +3 -9
  202. package/lib/transaction.js +3 -9
  203. package/lib/utils/assert.js +3 -11
  204. package/lib/utils/buildUtils.js +2 -8
  205. package/lib/utils/classUtils.js +1 -7
  206. package/lib/utils/createModifier.js +2 -8
  207. package/lib/utils/identifierMapping.js +23 -27
  208. package/lib/utils/internalPropUtils.js +1 -7
  209. package/lib/utils/knexUtils.js +84 -40
  210. package/lib/utils/mixin.js +3 -10
  211. package/lib/utils/normalizeIds.js +2 -8
  212. package/lib/utils/objectUtils.js +41 -60
  213. package/lib/utils/parseFieldExpression.js +16 -16
  214. package/lib/utils/promiseUtils/after.js +2 -8
  215. package/lib/utils/promiseUtils/afterReturn.js +2 -8
  216. package/lib/utils/promiseUtils/index.js +7 -16
  217. package/lib/utils/promiseUtils/isPromise.js +2 -8
  218. package/lib/utils/promiseUtils/map.js +2 -8
  219. package/lib/utils/promiseUtils/mapAfterAllReturn.js +2 -8
  220. package/lib/utils/promiseUtils/try.js +2 -8
  221. package/lib/utils/resolveModel.js +10 -17
  222. package/lib/utils/tmpColumnUtils.js +2 -9
  223. package/lib/utils/warnings.js +2 -14
  224. package/package.json +25 -17
  225. package/typings/objection/index.d.ts +3217 -2179
  226. package/lib/.eslintrc.json +0 -8
  227. package/lib/model/graph/ModelGraph.js +0 -80
  228. package/lib/model/graph/ModelGraphBuilder.js +0 -241
  229. package/lib/model/graph/ModelGraphEdge.js +0 -52
  230. package/lib/model/graph/ModelGraphNode.js +0 -238
  231. package/lib/queryBuilder/graph/GraphAction.js +0 -69
  232. package/lib/queryBuilder/graph/GraphData.js +0 -53
  233. package/lib/queryBuilder/graph/GraphFetcher.js +0 -197
  234. package/lib/queryBuilder/graph/GraphNodeDbExistence.js +0 -184
  235. package/lib/queryBuilder/graph/GraphOperation.js +0 -27
  236. package/lib/queryBuilder/graph/delete/GraphDelete.js +0 -73
  237. package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +0 -88
  238. package/lib/queryBuilder/graph/insert/DeferredRelationGraphInsertAction.js +0 -58
  239. package/lib/queryBuilder/graph/insert/GraphInsert.js +0 -296
  240. package/lib/queryBuilder/graph/insert/GraphInsertAction.js +0 -233
  241. package/lib/queryBuilder/graph/insert/JoinRowGraphInsertAction.js +0 -92
  242. package/lib/queryBuilder/graph/patch/GraphPatch.js +0 -20
  243. package/lib/queryBuilder/graph/patch/GraphPatchAction.js +0 -289
  244. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsert.js +0 -31
  245. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsertAction.js +0 -126
  246. package/lib/queryBuilder/operations/jsonApi/WhereJsonHasPostgresOperation.js +0 -30
  247. package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectPostgresOperation.js +0 -37
  248. package/lib/queryBuilder/operations/jsonApi/WhereJsonPostgresOperation.js +0 -62
  249. package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +0 -192
  250. package/lib/utils/wrapDbError.js +0 -64
@@ -1,53 +0,0 @@
1
- 'use strict';
2
-
3
- class GraphData {
4
- constructor({ graph, currentGraph, graphOptions, nodeDbExistence }) {
5
- this.graph = graph;
6
- this.currentGraph = currentGraph;
7
- this.graphOptions = graphOptions;
8
- this.nodeDbExistence = nodeDbExistence;
9
- // Pruning replaces `graph.nodes`, but `keptNodeForRow()` also needs the
10
- // branches below related nodes.
11
- this._unprunedNodes = graph.nodes;
12
- this._keptNodesByRowKey = null;
13
- }
14
-
15
- // Find the node that keeps the row of `currentNode` in another place of the
16
- // graph, by relating or patching it there, or by upserting it below a related
17
- // node. Only call this after pruning.
18
- keptNodeForRow(currentNode) {
19
- if (!this._keptNodesByRowKey) {
20
- this._keptNodesByRowKey = new Map();
21
- const nodes = new Set(this.graph.nodes);
22
-
23
- // Nested upserts write the pruned branches below related nodes, except
24
- // for models marked with `#unrelate` or `#delete` and their descendants:
25
- const isUpsertedBelowRelatedNode = (node) =>
26
- !node.toBeUnrelatedOrDeleted &&
27
- (nodes.has(node.parentNode)
28
- ? this.graphOptions.shouldRelate(node.parentNode, this)
29
- : isUpsertedBelowRelatedNode(node.parentNode));
30
-
31
- for (const node of this._unprunedNodes) {
32
- if (
33
- node.obj.$hasId() &&
34
- (nodes.has(node)
35
- ? this.graphOptions.shouldPatchOrUpdateIgnoreDisable(node, this)
36
- : isUpsertedBelowRelatedNode(node))
37
- ) {
38
- this._keptNodesByRowKey.set(getRowKey(node), node);
39
- }
40
- }
41
- }
42
-
43
- return this._keptNodesByRowKey.get(getRowKey(currentNode)) || null;
44
- }
45
- }
46
-
47
- function getRowKey(node) {
48
- return `${node.modelClass.getTableName()}:${node.obj.$idKey()}`;
49
- }
50
-
51
- module.exports = {
52
- GraphData,
53
- };
@@ -1,197 +0,0 @@
1
- 'use strict';
2
-
3
- const { asArray, groupBy } = require('../../utils/objectUtils');
4
- const { ModelGraph } = require('../../model/graph/ModelGraph');
5
- const { FetchStrategy } = require('./GraphOptions');
6
- const { RelationExpression } = require('../RelationExpression');
7
- const { getDeclaredColumns } = require('../operations/UpdateOperation');
8
- const { getFieldExpressionColumn } = require('../../utils/parseFieldExpression');
9
-
10
- class GraphFetcher {
11
- /**
12
- * Given a graph and options, fetches the current state of that graph
13
- * from the database and returns it as a ModelGraph instance.
14
- */
15
- static async fetchCurrentGraph({ builder, graph, graphOptions }) {
16
- const { rootObjects } = graph;
17
-
18
- const rootIds = getRootIds(rootObjects);
19
- const modelClass = builder.modelClass();
20
-
21
- if (rootIds.length === 0) {
22
- return Promise.resolve(ModelGraph.create(modelClass, []));
23
- }
24
-
25
- const eagerExpr = RelationExpression.fromModelGraph(rootObjects);
26
- const models = await modelClass
27
- .query()
28
- .childQueryOf(builder, childQueryOptions())
29
- .modify(propagateMethodCallsFromQuery(builder))
30
- .modify(buildFetchQuerySelects(graph, graphOptions, eagerExpr))
31
- .findByIds(rootIds)
32
- .withGraphFetched(eagerExpr)
33
- .internalOptions(fetchQueryInternalOptions());
34
-
35
- return ModelGraph.create(modelClass, models);
36
- }
37
- }
38
-
39
- function getRootIds(rootObjects) {
40
- return asArray(rootObjects)
41
- .filter((it) => it.$hasId())
42
- .map((root) => root.$id());
43
- }
44
-
45
- function propagateMethodCallsFromQuery(builder) {
46
- return (fetchBuilder) => {
47
- // Propagate some method calls from the root query.
48
- for (const method of ['forUpdate', 'forShare', 'forNoKeyUpdate', 'forKeyShare']) {
49
- if (builder.has(method)) {
50
- fetchBuilder[method]();
51
- }
52
- }
53
- };
54
- }
55
-
56
- function buildFetchQuerySelects(graph, graphOptions, eagerExpr) {
57
- return (builder) => {
58
- const nodesByRelationPath = groupNodesByRelationPath(graph, eagerExpr);
59
-
60
- for (const [relationPath, nodes] of nodesByRelationPath.entries()) {
61
- const selectModifier = createFetchSelectModifier(nodes, graphOptions);
62
-
63
- if (!relationPath) {
64
- builder.modify(selectModifier);
65
- } else {
66
- builder.modifyGraph(relationPath, selectModifier);
67
- }
68
- }
69
- };
70
- }
71
-
72
- function groupNodesByRelationPath(graph, eagerExpr) {
73
- const nodesByRelationPath = groupBy(graph.nodes, (node) => node.relationPathKey);
74
-
75
- // Not all relation paths have nodes. Relations with nulls or empty arrays
76
- // don't have nodes, but will still need to be fetched. Add these to the
77
- // map as empty arrays.
78
- forEachPath(eagerExpr.node, (relationPath) => {
79
- if (!nodesByRelationPath.has(relationPath)) {
80
- nodesByRelationPath.set(relationPath, []);
81
- }
82
- });
83
-
84
- return nodesByRelationPath;
85
- }
86
-
87
- function createFetchSelectModifier(nodes, graphOptions) {
88
- if (graphOptions.isFetchStrategy(FetchStrategy.OnlyIdentifiers)) {
89
- return createIdentifierSelector();
90
- } else if (graphOptions.isFetchStrategy(FetchStrategy.OnlyNeeded)) {
91
- return createInputColumnSelector(nodes);
92
- } else {
93
- return () => {};
94
- }
95
- }
96
-
97
- // Returns a function that only selects the id column.
98
- function createIdentifierSelector() {
99
- return (builder) => {
100
- builder.select(builder.fullIdColumn());
101
- };
102
- }
103
-
104
- // Returns a function that only selects the columns that exist in the input.
105
- function createInputColumnSelector(nodes) {
106
- return (builder) => {
107
- const selects = new Map();
108
-
109
- for (const node of nodes) {
110
- const databaseJson = node.obj.$toDatabaseJson(builder);
111
- const declaredColumns = getDeclaredColumns(node.modelClass);
112
-
113
- for (const key of Object.keys(databaseJson)) {
114
- // Select the json column of field expressions like `'meta:a'`:
115
- const column = getFieldExpressionColumn(key, declaredColumns) ?? key;
116
-
117
- if (!shouldSelectColumn(column, selects, node)) {
118
- continue;
119
- }
120
-
121
- const selection =
122
- createManyToManyExtraSelectionIfNeeded(builder, column, node) ||
123
- createSelection(builder, column, node);
124
-
125
- selects.set(column, selection);
126
- }
127
- }
128
-
129
- const selectArr = Array.from(selects.values());
130
- const idColumns = asArray(builder.fullIdColumn());
131
-
132
- for (const idColumn of idColumns) {
133
- if (!selectArr.includes(idColumn)) {
134
- // Always select the identifers.
135
- selectArr.push(idColumn);
136
- }
137
- }
138
-
139
- builder.select(selectArr);
140
- };
141
- }
142
-
143
- function shouldSelectColumn(column, selects, node) {
144
- const modelClass = node.modelClass;
145
-
146
- return (
147
- !selects.has(column) &&
148
- column !== modelClass.propertyNameToColumnName(modelClass.dbRefProp) &&
149
- column !== modelClass.propertyNameToColumnName(modelClass.uidRefProp) &&
150
- column !== modelClass.propertyNameToColumnName(modelClass.uidProp) &&
151
- column !== modelClass.propertyNameToColumnName(modelClass.graphUnrelateProp) &&
152
- column !== modelClass.propertyNameToColumnName(modelClass.graphDeleteProp)
153
- );
154
- }
155
-
156
- function createManyToManyExtraSelectionIfNeeded(builder, column, node) {
157
- if (node.parentEdge && node.parentEdge.relation.isObjectionManyToManyRelation) {
158
- const relation = node.parentEdge.relation;
159
- const extra = relation.joinTableExtras.find((extra) => extra.aliasCol === column);
160
-
161
- if (extra) {
162
- return `${relation.joinTableAliasFor(builder)}.${extra.joinTableCol} as ${extra.aliasCol}`;
163
- }
164
- }
165
-
166
- return null;
167
- }
168
-
169
- function createSelection(builder, column, node) {
170
- return `${builder.tableRefFor(node.modelClass)}.${column}`;
171
- }
172
-
173
- function childQueryOptions() {
174
- return {
175
- fork: true,
176
- isInternalQuery: true,
177
- };
178
- }
179
-
180
- function fetchQueryInternalOptions() {
181
- return {
182
- keepImplicitJoinProps: true,
183
- };
184
- }
185
-
186
- function forEachPath(eagerExprNode, cb, path = []) {
187
- for (const relation of eagerExprNode.$childNames) {
188
- path.push(relation);
189
- cb(path.join('.'));
190
- forEachPath(eagerExprNode[relation], cb, path);
191
- path.pop();
192
- }
193
- }
194
-
195
- module.exports = {
196
- GraphFetcher,
197
- };
@@ -1,184 +0,0 @@
1
- 'use strict';
2
-
3
- const { GraphData } = require('./GraphData');
4
- const { GraphAction } = require('./GraphAction');
5
- const promiseUtils = require('../../utils/promiseUtils');
6
-
7
- /**
8
- * This weird little class is responsible for checking (and maintaining information)
9
- * whether certain nodes exist in the database.
10
- *
11
- * Note that this information is only calculated for nodes for which `insertMissing`
12
- * option is true.
13
- */
14
- class GraphNodeDbExistence {
15
- static createEveryNodeExistsExistence() {
16
- return new GraphNodeDbExistence(new Map());
17
- }
18
-
19
- /**
20
- * Goes through the graphs and identifies nodes that may not exist in the db
21
- * (nodes that have an id, but are not found in `currentGraph`) and
22
- * creates an instance of GraphNodeDbExistence that can be used to
23
- * synchronously check if a node exist in the database.
24
- */
25
- static async create({ builder, graph, graphOptions, currentGraph }) {
26
- if (graphOptions.isInsertOnly()) {
27
- // With insertGraph, we never want to do anything but inserts.
28
- return GraphNodeDbExistence.createEveryNodeExistsExistence();
29
- }
30
-
31
- const graphData = new GraphData({
32
- graph,
33
- graphOptions,
34
- currentGraph,
35
- // We don't yet have an instance of GraphNodeDbExistence since we are
36
- // creating one. We can (and should) safely use an instance that
37
- // assumes that all nodes exist in the db for the purposes of this
38
- // method.
39
- nodeDbExistence: GraphNodeDbExistence.createEveryNodeExistsExistence(),
40
- });
41
-
42
- const { mayNotExist, mayNotExistNodes } = createMayNotExistMap(graphData);
43
-
44
- if (mayNotExist.size == 0) {
45
- // Early exit if we found no items for which we should check their
46
- // existence in the db.
47
- return GraphNodeDbExistence.createEveryNodeExistsExistence();
48
- }
49
-
50
- const dontExist = await createDontExistMap({ builder, mayNotExist, mayNotExistNodes });
51
-
52
- return new GraphNodeDbExistence(dontExist);
53
- }
54
-
55
- constructor(dontExist) {
56
- this.dontExist = dontExist;
57
- }
58
-
59
- doesNodeExistInDb(node) {
60
- const idMap = this.dontExist.get(node.modelClass);
61
-
62
- if (!idMap) {
63
- return true;
64
- }
65
-
66
- return !idMap.has(node.obj.$idKey());
67
- }
68
- }
69
-
70
- function createMayNotExistMap(graphData) {
71
- const { graph, currentGraph, graphOptions } = graphData;
72
-
73
- const mayNotExist = new Map();
74
- const mayNotExistNodes = [];
75
-
76
- for (const node of graph.nodes) {
77
- if (
78
- // As an optimization, only consider nodes for which `insertMissing` is true.
79
- // We only need the information for those nodes.
80
- graphOptions.shouldInsertMissing(node) &&
81
- // Only consider nodes that will be related. We don't consider nodes that
82
- // would get inserted with an id. Those will still result in a unique
83
- // constraint error.
84
- graphOptions.shouldRelate(node, graphData) &&
85
- // Relate nodes may not have an id if they are `#ref` nodes. Only consider
86
- // nodes that have an id so that we can check the existence.
87
- node.hasId &&
88
- // We can ignore nodes if they are found anywhere in the graph. `shouldRelate`
89
- // only checks if the node is found in the same relation.
90
- !hasNodeById(currentGraph, node)
91
- ) {
92
- if (!mayNotExist.has(node.modelClass)) {
93
- mayNotExist.set(node.modelClass, new Map());
94
- }
95
-
96
- mayNotExist.get(node.modelClass).set(node.obj.$idKey(), node.obj.$id());
97
- mayNotExistNodes.push(node);
98
- }
99
- }
100
-
101
- return {
102
- mayNotExist,
103
- mayNotExistNodes,
104
- };
105
- }
106
-
107
- function hasNodeById(currentGraph, nodeToFind) {
108
- const { modelClass } = nodeToFind;
109
-
110
- const tableToFind = modelClass.getTableName();
111
- const idProps = modelClass.getIdPropertyArray();
112
-
113
- return currentGraph.nodes.some((node) => {
114
- return (
115
- node.modelClass.getTableName() === tableToFind &&
116
- idProps.every((idProp) => node.obj[idProp] === nodeToFind.obj[idProp])
117
- );
118
- });
119
- }
120
-
121
- async function createDontExistMap({ builder, mayNotExist, mayNotExistNodes }) {
122
- const dontExist = cloneExistenceMap(mayNotExist);
123
- const existenceCheckQueries = createExistenceCheckQueries({ builder, mayNotExist });
124
-
125
- const results = await promiseUtils.map(existenceCheckQueries, (builder) => builder.execute(), {
126
- concurrency: GraphAction.getConcurrency(builder, mayNotExistNodes),
127
- });
128
-
129
- // Remove all items from the mayNotExist map that we have just proven to exist
130
- // by executing the existenceCheckQueries.
131
- for (const modelResult of results) {
132
- for (const item of modelResult) {
133
- const modelClass = item.constructor;
134
- const idMap = dontExist.get(modelClass);
135
- // Exist, remove from the map.
136
- idMap.delete(item.$idKey());
137
- }
138
- }
139
-
140
- // Now only items that don't exist in the db are left in this map.
141
- return dontExist;
142
- }
143
-
144
- function createExistenceCheckQueries({ builder, mayNotExist }) {
145
- const builders = [];
146
-
147
- for (const [modelClass, idMap] of mayNotExist.entries()) {
148
- const ids = Array.from(idMap.values());
149
-
150
- // Create one query per model class (table) to fetch the identifiers
151
- // of the nodes that may not exist. These queries should be super fast
152
- // since they come straight from the index.
153
- builders.push(
154
- modelClass
155
- .query()
156
- .childQueryOf(builder, childQueryOptions())
157
- .findByIds(ids)
158
- .select(modelClass.getIdColumnArray()),
159
- );
160
- }
161
-
162
- return builders;
163
- }
164
-
165
- function childQueryOptions() {
166
- return {
167
- fork: true,
168
- isInternalQuery: true,
169
- };
170
- }
171
-
172
- function cloneExistenceMap(exixtenseMap) {
173
- const clone = new Map(exixtenseMap);
174
-
175
- for (const modelClass of clone.keys()) {
176
- clone.set(modelClass, new Map(clone.get(modelClass)));
177
- }
178
-
179
- return clone;
180
- }
181
-
182
- module.exports = {
183
- GraphNodeDbExistence,
184
- };
@@ -1,27 +0,0 @@
1
- 'use strict';
2
-
3
- class GraphOperation {
4
- constructor(graphData) {
5
- this.graphData = graphData;
6
- }
7
-
8
- get graph() {
9
- return this.graphData.graph;
10
- }
11
-
12
- get currentGraph() {
13
- return this.graphData.currentGraph;
14
- }
15
-
16
- get graphOptions() {
17
- return this.graphData.graphOptions;
18
- }
19
-
20
- createActions() {
21
- return [];
22
- }
23
- }
24
-
25
- module.exports = {
26
- GraphOperation,
27
- };
@@ -1,73 +0,0 @@
1
- 'use strict';
2
-
3
- const { GraphOperation } = require('../GraphOperation');
4
- const { GraphDeleteAction } = require('./GraphDeleteAction');
5
- const { getPropertyTypes } = require('../../../model/modelJsonAttributes');
6
-
7
- class GraphDelete extends GraphOperation {
8
- // The owner of a BelongsToOneRelation row references it until `GraphPatch`
9
- // points the owner to a new row or to null. These rows are deleted
10
- // afterwards by `GraphDereferencedBelongsToOneDelete`, all others before.
11
- get deletesDereferencedRows() {
12
- return false;
13
- }
14
-
15
- createActions() {
16
- return [
17
- new GraphDeleteAction(this.graphData, {
18
- nodes: this.currentGraph.nodes.filter(
19
- (currentNode) =>
20
- this.graphOptions.shouldDeleteOrUnrelate(currentNode, this.graphData) &&
21
- isDereferencedBelongsToOneNode(currentNode, this.graphData) ===
22
- this.deletesDereferencedRows,
23
- ),
24
- areReferenced: !this.deletesDereferencedRows,
25
- }),
26
- ];
27
- }
28
- }
29
-
30
- class GraphDereferencedBelongsToOneDelete extends GraphDelete {
31
- get deletesDereferencedRows() {
32
- return true;
33
- }
34
- }
35
-
36
- function isDereferencedBelongsToOneNode(currentNode, graphData) {
37
- const { graph, graphOptions } = graphData;
38
- const relation = currentNode.parentEdge?.relation;
39
- const parentNode = graph.nodeForNode(currentNode.parentNode);
40
-
41
- if (relation?.isObjectionBelongsToOneRelation && parentNode) {
42
- const node = graph.nodeForNode(currentNode);
43
- const isReplaced = parentNode.edges.some(
44
- (edge) =>
45
- edge.relation === relation &&
46
- edge.isOwnerNode(parentNode) &&
47
- !graphOptions.shouldIgnore(edge.relatedNode, graphData),
48
- );
49
- const isRemoved =
50
- parentNode.obj[relation.name] === null || (!!node && node.toBeUnrelatedOrDeleted);
51
-
52
- // Removing the row sets the owner's foreign key to null, but only where
53
- // its schema allows it. Otherwise we delete the row first and leave the
54
- // owner's reference to the database, as the column may be `NOT NULL`.
55
- return (
56
- isReplaced ||
57
- (isRemoved &&
58
- relation.ownerProp.props.every((prop) => isNullable(relation.ownerModelClass, prop)))
59
- );
60
- } else {
61
- return false;
62
- }
63
- }
64
-
65
- function isNullable(modelClass, prop) {
66
- const schema = modelClass.getJsonSchema()?.properties?.[prop];
67
- return !!schema && (schema.nullable === true || getPropertyTypes(schema).includes('null'));
68
- }
69
-
70
- module.exports = {
71
- GraphDelete,
72
- GraphDereferencedBelongsToOneDelete,
73
- };
@@ -1,88 +0,0 @@
1
- 'use strict';
2
-
3
- const { GraphAction } = require('../GraphAction');
4
- const { groupBy } = require('../../../utils/objectUtils');
5
- const promiseUtils = require('../../../utils/promiseUtils');
6
-
7
- class GraphDeleteAction extends GraphAction {
8
- constructor(graphData, { nodes, areReferenced = true }) {
9
- super(graphData);
10
- // Nodes to delete.
11
- this.nodes = nodes;
12
- // Whether the parents still reference the nodes. Rows of
13
- // BelongsToOneRelations can be deleted after their owners were patched to
14
- // reference new rows or null, so they can't be found through the relation.
15
- this.areReferenced = areReferenced;
16
- }
17
-
18
- run(builder) {
19
- const nodesTodelete = this._filterOutBelongsToOneRelationUnrelates(this.nodes);
20
- const builders = this._createDeleteBuilders(builder, nodesTodelete);
21
-
22
- return promiseUtils.map(builders, (builder) => builder.execute(), {
23
- concurrency: this._getConcurrency(builder, nodesTodelete),
24
- });
25
- }
26
-
27
- _filterOutBelongsToOneRelationUnrelates(nodes) {
28
- // `BelongsToOneRelation` unrelate is handled by `GraphPatch` because
29
- // unrelating a `BelongsToOneRelation` is just a matter of updating
30
- // one field of the parent node.
31
- return nodes.filter((node) => {
32
- return !(
33
- this.graphOptions.shouldUnrelate(node, this.graphData) &&
34
- node.parentEdge.relation.isObjectionBelongsToOneRelation
35
- );
36
- });
37
- }
38
-
39
- _createDeleteBuilders(parentBuilder, nodesTodelete) {
40
- const nodesByRelation = groupBy(nodesTodelete, getRelation);
41
- const builders = [];
42
-
43
- nodesByRelation.forEach((nodes, relation) => {
44
- const nodesByParent = groupBy(nodes, getParent);
45
-
46
- nodesByParent.forEach((nodes, parentNode) => {
47
- // Nodes of the same relation and parent can still require different
48
- // operations when they are marked with `#unrelate` or `#delete`.
49
- const nodesByShouldUnrelate = groupBy(nodes, (node) =>
50
- this.graphOptions.shouldUnrelate(node, this.graphData),
51
- );
52
-
53
- nodesByShouldUnrelate.forEach((nodes, shouldUnrelate) => {
54
- const builder = (
55
- this.areReferenced
56
- ? parentNode.obj.$relatedQuery(relation.name)
57
- : relation.relatedModelClass.query()
58
- ).childQueryOf(parentBuilder);
59
-
60
- if (!this.areReferenced || !relation.isObjectionBelongsToOneRelation) {
61
- // This is useless in case of a referenced BelongsToOneRelation.
62
- builder.findByIds(nodes.map((node) => node.obj.$id()));
63
- }
64
-
65
- for (const node of nodes) {
66
- node.userData.deleted = true;
67
- }
68
-
69
- builders.push(shouldUnrelate ? builder.unrelate() : builder.delete());
70
- });
71
- });
72
- });
73
-
74
- return builders;
75
- }
76
- }
77
-
78
- function getRelation(node) {
79
- return node.parentEdge.relation;
80
- }
81
-
82
- function getParent(node) {
83
- return node.parentNode;
84
- }
85
-
86
- module.exports = {
87
- GraphDeleteAction,
88
- };
@@ -1,58 +0,0 @@
1
- 'use strict';
2
-
3
- const { GraphAction } = require('../GraphAction');
4
- const { groupBy } = require('../../../utils/objectUtils');
5
- const promiseUtils = require('../../../utils/promiseUtils');
6
-
7
- /**
8
- * Patches in the foreign keys of `BelongsToOneRelation` edges that `GraphInsert`
9
- * had to defer to break a dependency cycle. The owner nodes of these edges were
10
- * inserted without the foreign keys, which are copied from the related nodes
11
- * and patched in with one query per owner.
12
- */
13
- class DeferredRelationGraphInsertAction extends GraphAction {
14
- constructor(graphData, { edges }) {
15
- super(graphData);
16
-
17
- // `BelongsToOneRelation` edges whose owner node needs to be patched.
18
- this.edges = edges;
19
- }
20
-
21
- run(builder) {
22
- const edgesByOwner = groupBy(this.edges, (edge) => edge.ownerNode);
23
- const owners = [...edgesByOwner.keys()];
24
- const concurrency = this._getConcurrency(builder, owners);
25
-
26
- return promiseUtils.map(
27
- owners,
28
- (owner) => this._patchOwner(builder, owner, edgesByOwner.get(owner)),
29
- { concurrency },
30
- );
31
- }
32
-
33
- _patchOwner(builder, ownerNode, edges) {
34
- const { modelClass } = ownerNode;
35
- const ownerIdProp = modelClass.getIdRelationProperty();
36
- const patch = {};
37
-
38
- for (const { relation, relatedNode } of edges) {
39
- const { ownerProp, relatedProp } = relation;
40
-
41
- ownerProp.forEach((i) => {
42
- const value = relatedProp.getProp(relatedNode.obj, i);
43
- ownerProp.setProp(ownerNode.obj, i, value);
44
- ownerProp.patch(patch, i, value);
45
- });
46
- }
47
-
48
- return modelClass
49
- .query()
50
- .childQueryOf(builder)
51
- .patch(patch)
52
- .whereInComposite(ownerIdProp.refs(builder), [ownerIdProp.getProps(ownerNode.obj)]);
53
- }
54
- }
55
-
56
- module.exports = {
57
- DeferredRelationGraphInsertAction,
58
- };