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.
- package/lib/dbErrors/LICENSE +21 -0
- package/lib/dbErrors/errorCodes/mssql.js +19 -0
- package/lib/dbErrors/errorCodes/mysql.js +805 -0
- package/lib/dbErrors/errorCodes/postgres.js +241 -0
- package/lib/dbErrors/errors/CheckViolationError.js +10 -0
- package/lib/dbErrors/errors/ConstraintViolationError.js +3 -0
- package/lib/dbErrors/errors/DBError.js +9 -0
- package/lib/dbErrors/errors/DataError.js +3 -0
- package/lib/dbErrors/errors/ForeignKeyViolationError.js +11 -0
- package/lib/dbErrors/errors/NotNullViolationError.js +12 -0
- package/lib/dbErrors/errors/UniqueViolationError.js +12 -0
- package/lib/dbErrors/index.js +59 -0
- package/lib/dbErrors/parsers/mssql/DBError/CheckViolationError/parser.js +28 -0
- package/lib/dbErrors/parsers/mssql/DBError/DataError/parser.js +25 -0
- package/lib/dbErrors/parsers/mssql/DBError/ForeignKeyViolationError/parser.js +39 -0
- package/lib/dbErrors/parsers/mssql/DBError/NotNullViolationError/parser.js +30 -0
- package/lib/dbErrors/parsers/mssql/DBError/UniqueViolationError/parser.js +53 -0
- package/lib/dbErrors/parsers/mssql/DBError/parser.js +51 -0
- package/lib/dbErrors/parsers/mssql/DBError/util.js +16 -0
- package/lib/dbErrors/parsers/mysql/DBError/ConstraintViolationError/ForeignKeyViolationError/parser.js +43 -0
- package/lib/dbErrors/parsers/mysql/DBError/ConstraintViolationError/NotNullViolationError/parser.js +29 -0
- package/lib/dbErrors/parsers/mysql/DBError/ConstraintViolationError/UniqueViolationError/parser.js +27 -0
- package/lib/dbErrors/parsers/mysql/DBError/ConstraintViolationError/parser.js +23 -0
- package/lib/dbErrors/parsers/mysql/DBError/DataError/parser.js +24 -0
- package/lib/dbErrors/parsers/mysql/DBError/parser.js +28 -0
- package/lib/dbErrors/parsers/postgres/DBError/ConstraintViolationError/CheckViolationError/parser.js +18 -0
- package/lib/dbErrors/parsers/postgres/DBError/ConstraintViolationError/ForeignKeyViolationError/parser.js +18 -0
- package/lib/dbErrors/parsers/postgres/DBError/ConstraintViolationError/NotNullViolationError/parser.js +18 -0
- package/lib/dbErrors/parsers/postgres/DBError/ConstraintViolationError/UniqueViolationError/parser.js +40 -0
- package/lib/dbErrors/parsers/postgres/DBError/ConstraintViolationError/parser.js +25 -0
- package/lib/dbErrors/parsers/postgres/DBError/DataError/parser.js +16 -0
- package/lib/dbErrors/parsers/postgres/DBError/parser.js +27 -0
- package/lib/dbErrors/parsers/sqlite/DBError/ConstraintViolationError/CheckViolationError/parser.js +20 -0
- package/lib/dbErrors/parsers/sqlite/DBError/ConstraintViolationError/ForeignKeyViolationError/parser.js +20 -0
- package/lib/dbErrors/parsers/sqlite/DBError/ConstraintViolationError/NotNullViolationError/parser.js +27 -0
- package/lib/dbErrors/parsers/sqlite/DBError/ConstraintViolationError/UniqueViolationError/parser.js +28 -0
- package/lib/dbErrors/parsers/sqlite/DBError/ConstraintViolationError/parser.js +24 -0
- package/lib/dbErrors/parsers/sqlite/DBError/parser.js +23 -0
- package/lib/dbErrors/utils/sqlState.js +3 -0
- package/lib/initialize.js +1 -7
- package/lib/model/AjvValidator.js +51 -117
- package/lib/model/Model.js +84 -59
- package/lib/model/ModifierNotFoundError.js +1 -7
- package/lib/model/NotFoundError.js +1 -7
- package/lib/model/RelationDoesNotExistError.js +1 -7
- package/lib/model/ValidationError.js +3 -10
- package/lib/model/Validator.js +1 -7
- package/lib/model/getModel.js +7 -6
- package/lib/model/inheritModel.js +1 -7
- package/lib/model/modelBindKnex.js +4 -10
- package/lib/model/modelClone.js +5 -11
- package/lib/model/modelColPropMap.js +3 -10
- package/lib/model/modelId.js +3 -10
- package/lib/model/modelJsonAttributes.js +35 -16
- package/lib/model/modelParseRelations.js +2 -8
- package/lib/model/modelQueryProps.js +11 -23
- package/lib/model/modelSet.js +89 -41
- package/lib/model/modelTableMetadata.js +4 -11
- package/lib/model/modelToJson.js +6 -13
- package/lib/model/modelUtils.js +14 -13
- package/lib/model/modelValidate.js +3 -9
- package/lib/model/modelValues.js +5 -14
- package/lib/model/modelVisitor.js +1 -7
- package/lib/objection.js +33 -71
- package/lib/queryBuilder/FunctionBuilder.js +4 -11
- package/lib/queryBuilder/InternalOptions.js +4 -9
- package/lib/queryBuilder/JoinBuilder.js +5 -8
- package/lib/queryBuilder/QueryBuilder.js +126 -95
- package/lib/queryBuilder/QueryBuilderBase.js +41 -123
- package/lib/queryBuilder/QueryBuilderContext.js +2 -8
- package/lib/queryBuilder/QueryBuilderContextBase.js +2 -8
- package/lib/queryBuilder/QueryBuilderOperationSupport.js +7 -21
- package/lib/queryBuilder/QueryBuilderUserContext.js +1 -7
- package/lib/queryBuilder/RawBuilder.js +5 -13
- package/lib/queryBuilder/ReferenceBuilder.js +20 -48
- package/lib/queryBuilder/RelationExpression.js +18 -16
- package/lib/queryBuilder/StaticHookArguments.js +74 -16
- package/lib/queryBuilder/ValueBuilder.js +11 -13
- package/lib/queryBuilder/getJoinBuilder.js +10 -0
- package/lib/queryBuilder/graph/GraphLoader.js +314 -0
- package/lib/queryBuilder/graph/GraphNode.js +241 -0
- package/lib/queryBuilder/graph/GraphOptions.js +55 -248
- package/lib/queryBuilder/graph/GraphPlan.js +431 -0
- package/lib/queryBuilder/graph/GraphSchedule.js +513 -0
- package/lib/queryBuilder/graph/GraphUpsert.js +519 -412
- package/lib/queryBuilder/graph/GraphWriter.js +508 -0
- package/lib/queryBuilder/graph/graphKeys.js +929 -0
- package/lib/queryBuilder/join/JoinResultColumn.js +1 -7
- package/lib/queryBuilder/join/JoinResultParser.js +6 -11
- package/lib/queryBuilder/join/RelationJoiner.js +66 -84
- package/lib/queryBuilder/join/TableNode.js +2 -8
- package/lib/queryBuilder/join/TableTree.js +3 -9
- package/lib/queryBuilder/join/utils.js +5 -15
- package/lib/queryBuilder/jsonDialects/JsonDialect.js +51 -0
- package/lib/queryBuilder/jsonDialects/MySqlJsonDialect.js +81 -0
- package/lib/queryBuilder/jsonDialects/PostgresJsonDialect.js +45 -0
- package/lib/queryBuilder/jsonDialects/SqliteJsonDialect.js +67 -0
- package/lib/queryBuilder/jsonDialects/index.js +44 -0
- package/lib/queryBuilder/operations/DelegateOperation.js +2 -8
- package/lib/queryBuilder/operations/DeleteOperation.js +10 -39
- package/lib/queryBuilder/operations/FindByIdOperation.js +7 -12
- package/lib/queryBuilder/operations/FindByIdsOperation.js +4 -8
- package/lib/queryBuilder/operations/FindOperation.js +14 -34
- package/lib/queryBuilder/operations/FirstOperation.js +6 -10
- package/lib/queryBuilder/operations/FromOperation.js +3 -9
- package/lib/queryBuilder/operations/InsertAndFetchOperation.js +13 -12
- package/lib/queryBuilder/operations/InsertGraphAndFetchOperation.js +4 -10
- package/lib/queryBuilder/operations/InsertGraphOperation.js +7 -18
- package/lib/queryBuilder/operations/InsertOperation.js +118 -45
- package/lib/queryBuilder/operations/InstanceDeleteOperation.js +5 -12
- package/lib/queryBuilder/operations/InstanceFindOperation.js +4 -11
- package/lib/queryBuilder/operations/InstanceInsertOperation.js +2 -8
- package/lib/queryBuilder/operations/InstanceUpdateOperation.js +7 -14
- package/lib/queryBuilder/operations/JoinRelatedOperation.js +5 -11
- package/lib/queryBuilder/operations/KnexOperation.js +2 -8
- package/lib/queryBuilder/operations/LimitPerParentOperation.js +7 -69
- package/lib/queryBuilder/operations/MergeOperation.js +5 -11
- package/lib/queryBuilder/operations/NoneOperation.js +2 -8
- package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +20 -49
- package/lib/queryBuilder/operations/OnBuildKnexOperation.js +2 -8
- package/lib/queryBuilder/operations/OnBuildOperation.js +2 -8
- package/lib/queryBuilder/operations/OnErrorOperation.js +2 -8
- package/lib/queryBuilder/operations/QueryBuilderOperation.js +1 -7
- package/lib/queryBuilder/operations/RangeOperation.js +11 -26
- package/lib/queryBuilder/operations/RelateOperation.js +2 -8
- package/lib/queryBuilder/operations/ReturningOperation.js +3 -9
- package/lib/queryBuilder/operations/RunAfterOperation.js +2 -12
- package/lib/queryBuilder/operations/RunBeforeOperation.js +2 -8
- package/lib/queryBuilder/operations/UnrelateOperation.js +2 -8
- package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +14 -17
- package/lib/queryBuilder/operations/UpdateOperation.js +32 -132
- package/lib/queryBuilder/operations/UpsertGraphAndFetchOperation.js +8 -11
- package/lib/queryBuilder/operations/UpsertGraphOperation.js +6 -12
- package/lib/queryBuilder/operations/WhereCompositeOperation.js +3 -9
- package/lib/queryBuilder/operations/WhereGroupOperation.js +2 -8
- package/lib/queryBuilder/operations/eager/EagerOperation.js +3 -9
- package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +72 -10
- package/lib/queryBuilder/operations/eager/NaiveEagerOperation.js +2 -8
- package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +23 -44
- package/lib/queryBuilder/operations/fieldExpressions.js +122 -0
- package/lib/queryBuilder/operations/jsonApi/WhereJsonHasOperation.js +20 -0
- package/lib/queryBuilder/operations/jsonApi/WhereJsonOperation.js +44 -0
- package/lib/queryBuilder/operations/jsonApi/WhereJsonTypeOperation.js +14 -0
- package/lib/queryBuilder/operations/select/SelectOperation.js +11 -21
- package/lib/queryBuilder/operations/select/Selection.js +19 -17
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +4 -10
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +4 -10
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +4 -10
- package/lib/queryBuilder/operations/windowOrder.js +56 -0
- package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +3 -7
- package/lib/queryBuilder/parsers/relationExpressionParser.js +42 -43
- package/lib/queryBuilder/parsers/relationExpressionParser.pegjs +39 -36
- package/lib/queryBuilder/transformations/CompositeQueryTransformation.js +2 -8
- package/lib/queryBuilder/transformations/QueryTransformation.js +1 -7
- package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +3 -9
- package/lib/queryBuilder/transformations/index.js +3 -11
- package/lib/queryBuilder/whereGroups.js +9 -24
- package/lib/queryBuilder/withoutOrder.js +4 -11
- package/lib/relations/Relation.js +47 -28
- package/lib/relations/RelationDeleteOperation.js +4 -14
- package/lib/relations/RelationFindOperation.js +119 -90
- package/lib/relations/RelationInsertOperation.js +2 -8
- package/lib/relations/RelationOwner.js +5 -11
- package/lib/relations/RelationProperty.js +4 -10
- package/lib/relations/RelationUpdateOperation.js +4 -14
- package/lib/relations/RelationWriteResultOperation.js +15 -0
- package/lib/relations/belongsToMany/BelongsToManyDeleteOperation.js +23 -0
- package/lib/relations/belongsToMany/BelongsToManyFindOperation.js +35 -0
- package/lib/relations/belongsToMany/BelongsToManyInsertOperation.js +28 -0
- package/lib/relations/belongsToMany/BelongsToManyRelateOperation.js +16 -0
- package/lib/relations/belongsToMany/BelongsToManyRelation.js +276 -0
- package/lib/relations/belongsToMany/BelongsToManyUnrelateOperation.js +11 -0
- package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +2 -8
- package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +6 -11
- package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +3 -9
- package/lib/relations/belongsToOne/BelongsToOneRelation.js +8 -19
- package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +53 -27
- package/lib/relations/hasMany/HasManyInsertOperation.js +5 -10
- package/lib/relations/hasMany/HasManyRelateOperation.js +5 -11
- package/lib/relations/hasMany/HasManyRelation.js +9 -11
- package/lib/relations/hasMany/HasManyUnrelateOperation.js +3 -9
- package/lib/relations/hasOne/HasOneRelation.js +2 -8
- package/lib/relations/hasOneThrough/HasOneThroughRelation.js +2 -8
- package/lib/relations/manyToMany/ManyToManyModifyMixin.js +10 -15
- package/lib/relations/manyToMany/ManyToManyMySqlModifyMixin.js +2 -8
- package/lib/relations/manyToMany/ManyToManyRelation.js +82 -50
- package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +2 -8
- package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +5 -9
- package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +2 -8
- package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +3 -9
- package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +20 -59
- package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +6 -11
- package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +4 -10
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateMySqlOperation.js +3 -9
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +5 -9
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +3 -9
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +3 -9
- package/lib/relations/manyToMany/update/ManyToManyUpdateMySqlOperation.js +3 -9
- package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +5 -9
- package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +64 -72
- package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +3 -9
- package/lib/transaction.js +3 -9
- package/lib/utils/assert.js +3 -11
- package/lib/utils/buildUtils.js +2 -8
- package/lib/utils/classUtils.js +1 -7
- package/lib/utils/createModifier.js +2 -8
- package/lib/utils/identifierMapping.js +23 -27
- package/lib/utils/internalPropUtils.js +1 -7
- package/lib/utils/knexUtils.js +84 -40
- package/lib/utils/mixin.js +3 -10
- package/lib/utils/normalizeIds.js +2 -8
- package/lib/utils/objectUtils.js +41 -60
- package/lib/utils/parseFieldExpression.js +16 -16
- package/lib/utils/promiseUtils/after.js +2 -8
- package/lib/utils/promiseUtils/afterReturn.js +2 -8
- package/lib/utils/promiseUtils/index.js +7 -16
- package/lib/utils/promiseUtils/isPromise.js +2 -8
- package/lib/utils/promiseUtils/map.js +2 -8
- package/lib/utils/promiseUtils/mapAfterAllReturn.js +2 -8
- package/lib/utils/promiseUtils/try.js +2 -8
- package/lib/utils/resolveModel.js +10 -17
- package/lib/utils/tmpColumnUtils.js +2 -9
- package/lib/utils/warnings.js +2 -14
- package/package.json +25 -17
- package/typings/objection/index.d.ts +3217 -2179
- package/lib/.eslintrc.json +0 -8
- package/lib/model/graph/ModelGraph.js +0 -80
- package/lib/model/graph/ModelGraphBuilder.js +0 -241
- package/lib/model/graph/ModelGraphEdge.js +0 -52
- package/lib/model/graph/ModelGraphNode.js +0 -238
- package/lib/queryBuilder/graph/GraphAction.js +0 -69
- package/lib/queryBuilder/graph/GraphData.js +0 -53
- package/lib/queryBuilder/graph/GraphFetcher.js +0 -197
- package/lib/queryBuilder/graph/GraphNodeDbExistence.js +0 -184
- package/lib/queryBuilder/graph/GraphOperation.js +0 -27
- package/lib/queryBuilder/graph/delete/GraphDelete.js +0 -73
- package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +0 -88
- package/lib/queryBuilder/graph/insert/DeferredRelationGraphInsertAction.js +0 -58
- package/lib/queryBuilder/graph/insert/GraphInsert.js +0 -296
- package/lib/queryBuilder/graph/insert/GraphInsertAction.js +0 -233
- package/lib/queryBuilder/graph/insert/JoinRowGraphInsertAction.js +0 -92
- package/lib/queryBuilder/graph/patch/GraphPatch.js +0 -20
- package/lib/queryBuilder/graph/patch/GraphPatchAction.js +0 -289
- package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsert.js +0 -31
- package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsertAction.js +0 -126
- package/lib/queryBuilder/operations/jsonApi/WhereJsonHasPostgresOperation.js +0 -30
- package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectPostgresOperation.js +0 -37
- package/lib/queryBuilder/operations/jsonApi/WhereJsonPostgresOperation.js +0 -62
- package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +0 -192
- 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
|
-
};
|