@abedmurrar/objection 0.0.0-stage → 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.
- package/LICENSE +23 -0
- package/README.md +105 -2
- package/lib/index.mjs +6 -0
- package/lib/initialize.js +11 -0
- package/lib/model/AjvValidator.js +278 -0
- package/lib/model/Model.js +772 -0
- package/lib/model/ModifierNotFoundError.js +10 -0
- package/lib/model/NotFoundError.js +19 -0
- package/lib/model/RelationDoesNotExistError.js +11 -0
- package/lib/model/ValidationError.js +46 -0
- package/lib/model/Validator.js +20 -0
- package/lib/model/getModel.js +7 -0
- package/lib/model/graph/ModelGraph.js +60 -0
- package/lib/model/graph/ModelGraphBuilder.js +188 -0
- package/lib/model/graph/ModelGraphEdge.js +40 -0
- package/lib/model/graph/ModelGraphNode.js +201 -0
- package/lib/model/inheritModel.js +19 -0
- package/lib/model/modelBindKnex.js +69 -0
- package/lib/model/modelClone.js +102 -0
- package/lib/model/modelColPropMap.js +24 -0
- package/lib/model/modelConcurrency.js +24 -0
- package/lib/model/modelId.js +57 -0
- package/lib/model/modelJsonAttributes.js +72 -0
- package/lib/model/modelParseRelations.js +83 -0
- package/lib/model/modelQueryProps.js +116 -0
- package/lib/model/modelSet.js +116 -0
- package/lib/model/modelTableMetadata.js +71 -0
- package/lib/model/modelToJson.js +157 -0
- package/lib/model/modelUtils.js +40 -0
- package/lib/model/modelValidate.js +40 -0
- package/lib/model/modelValues.js +113 -0
- package/lib/model/modelVisitor.js +34 -0
- package/lib/objection.js +89 -0
- package/lib/queryBuilder/FunctionBuilder.js +291 -0
- package/lib/queryBuilder/InternalOptions.js +24 -0
- package/lib/queryBuilder/JoinBuilder.js +124 -0
- package/lib/queryBuilder/QueryBuilder.js +1136 -0
- package/lib/queryBuilder/QueryBuilderBase.js +666 -0
- package/lib/queryBuilder/QueryBuilderContext.js +20 -0
- package/lib/queryBuilder/QueryBuilderContextBase.js +26 -0
- package/lib/queryBuilder/QueryBuilderOperationSupport.js +484 -0
- package/lib/queryBuilder/QueryBuilderUserContext.js +25 -0
- package/lib/queryBuilder/RawBuilder.js +78 -0
- package/lib/queryBuilder/ReferenceBuilder.js +246 -0
- package/lib/queryBuilder/RelationExpression.js +373 -0
- package/lib/queryBuilder/StaticHookArguments.js +122 -0
- package/lib/queryBuilder/ValueBuilder.js +115 -0
- package/lib/queryBuilder/expressions.js +121 -0
- package/lib/queryBuilder/functions/mysql.js +762 -0
- package/lib/queryBuilder/graph/GraphAction.js +54 -0
- package/lib/queryBuilder/graph/GraphData.js +12 -0
- package/lib/queryBuilder/graph/GraphFetcher.js +155 -0
- package/lib/queryBuilder/graph/GraphNodeDbExistence.js +146 -0
- package/lib/queryBuilder/graph/GraphOperation.js +21 -0
- package/lib/queryBuilder/graph/GraphOptions.js +165 -0
- package/lib/queryBuilder/graph/GraphUpsert.js +231 -0
- package/lib/queryBuilder/graph/delete/GraphDelete.js +15 -0
- package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +56 -0
- package/lib/queryBuilder/graph/insert/GraphInsert.js +116 -0
- package/lib/queryBuilder/graph/insert/GraphInsertAction.js +183 -0
- package/lib/queryBuilder/graph/insert/JoinRowGraphInsertAction.js +70 -0
- package/lib/queryBuilder/graph/patch/GraphPatch.js +15 -0
- package/lib/queryBuilder/graph/patch/GraphPatchAction.js +205 -0
- package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsert.js +26 -0
- package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsertAction.js +96 -0
- package/lib/queryBuilder/join/JoinResultColumn.js +19 -0
- package/lib/queryBuilder/join/JoinResultParser.js +106 -0
- package/lib/queryBuilder/join/RelationJoiner.js +258 -0
- package/lib/queryBuilder/join/TableNode.js +136 -0
- package/lib/queryBuilder/join/TableTree.js +69 -0
- package/lib/queryBuilder/join/utils.js +19 -0
- package/lib/queryBuilder/operations/DelegateOperation.js +101 -0
- package/lib/queryBuilder/operations/DeleteOperation.js +47 -0
- package/lib/queryBuilder/operations/FindByIdOperation.js +29 -0
- package/lib/queryBuilder/operations/FindByIdsOperation.js +23 -0
- package/lib/queryBuilder/operations/FindOperation.js +147 -0
- package/lib/queryBuilder/operations/FirstOperation.js +22 -0
- package/lib/queryBuilder/operations/FromOperation.js +91 -0
- package/lib/queryBuilder/operations/InsertAndFetchOperation.js +38 -0
- package/lib/queryBuilder/operations/InsertGraphAndFetchOperation.js +35 -0
- package/lib/queryBuilder/operations/InsertGraphOperation.js +87 -0
- package/lib/queryBuilder/operations/InsertOperation.js +173 -0
- package/lib/queryBuilder/operations/InstanceDeleteOperation.js +37 -0
- package/lib/queryBuilder/operations/InstanceFindOperation.js +17 -0
- package/lib/queryBuilder/operations/InstanceInsertOperation.js +20 -0
- package/lib/queryBuilder/operations/InstanceUpdateOperation.js +45 -0
- package/lib/queryBuilder/operations/JoinRelatedOperation.js +83 -0
- package/lib/queryBuilder/operations/KnexOperation.js +11 -0
- package/lib/queryBuilder/operations/MergeOperation.js +43 -0
- package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +173 -0
- package/lib/queryBuilder/operations/OnBuildKnexOperation.js +23 -0
- package/lib/queryBuilder/operations/OnBuildOperation.js +23 -0
- package/lib/queryBuilder/operations/OnErrorOperation.js +23 -0
- package/lib/queryBuilder/operations/QueryBuilderOperation.js +258 -0
- package/lib/queryBuilder/operations/RangeOperation.js +37 -0
- package/lib/queryBuilder/operations/RelateOperation.js +20 -0
- package/lib/queryBuilder/operations/ReturningOperation.js +24 -0
- package/lib/queryBuilder/operations/RunAfterOperation.js +23 -0
- package/lib/queryBuilder/operations/RunBeforeOperation.js +23 -0
- package/lib/queryBuilder/operations/UnrelateOperation.js +18 -0
- package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +63 -0
- package/lib/queryBuilder/operations/UpdateOperation.js +130 -0
- package/lib/queryBuilder/operations/UpsertGraphAndFetchOperation.js +35 -0
- package/lib/queryBuilder/operations/UpsertGraphOperation.js +47 -0
- package/lib/queryBuilder/operations/WhereCompositeOperation.js +48 -0
- package/lib/queryBuilder/operations/WhereInOperation.js +46 -0
- package/lib/queryBuilder/operations/eager/EagerOperation.js +46 -0
- package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +41 -0
- package/lib/queryBuilder/operations/eager/NaiveEagerOperation.js +10 -0
- package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +227 -0
- package/lib/queryBuilder/operations/jsonApi/WhereJsonHasOperation.js +29 -0
- package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectOperation.js +37 -0
- package/lib/queryBuilder/operations/jsonApi/WhereJsonOperation.js +30 -0
- package/lib/queryBuilder/operations/jsonApi/WhereJsonOverlapsOperation.js +33 -0
- package/lib/queryBuilder/operations/jsonApi/mysqlJsonApi.js +155 -0
- package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +135 -0
- package/lib/queryBuilder/operations/select/SelectOperation.js +50 -0
- package/lib/queryBuilder/operations/select/Selection.js +112 -0
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +84 -0
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +90 -0
- package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +95 -0
- package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +787 -0
- package/lib/queryBuilder/parsers/relationExpressionParser.js +930 -0
- package/lib/queryBuilder/transformations/CompositeQueryTransformation.js +17 -0
- package/lib/queryBuilder/transformations/QueryTransformation.js +9 -0
- package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +57 -0
- package/lib/queryBuilder/transformations/index.js +9 -0
- package/lib/queryBuilder/whereScopes.js +199 -0
- package/lib/relations/Relation.js +317 -0
- package/lib/relations/RelationDeleteOperation.js +23 -0
- package/lib/relations/RelationFindOperation.js +116 -0
- package/lib/relations/RelationInsertOperation.js +25 -0
- package/lib/relations/RelationOwner.js +199 -0
- package/lib/relations/RelationProperty.js +207 -0
- package/lib/relations/RelationUpdateOperation.js +23 -0
- package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +18 -0
- package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +33 -0
- package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +39 -0
- package/lib/relations/belongsToOne/BelongsToOneRelation.js +45 -0
- package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +46 -0
- package/lib/relations/hasMany/HasManyInsertOperation.js +45 -0
- package/lib/relations/hasMany/HasManyRelateOperation.js +48 -0
- package/lib/relations/hasMany/HasManyRelation.js +41 -0
- package/lib/relations/hasMany/HasManyUnrelateOperation.js +26 -0
- package/lib/relations/hasOne/HasOneRelation.js +10 -0
- package/lib/relations/hasOneThrough/HasOneThroughRelation.js +10 -0
- package/lib/relations/manyToMany/ManyToManyModifyMixin.js +82 -0
- package/lib/relations/manyToMany/ManyToManyRelation.js +405 -0
- package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +29 -0
- package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +8 -0
- package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +20 -0
- package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +8 -0
- package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +82 -0
- package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +40 -0
- package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +64 -0
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +11 -0
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +27 -0
- package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +11 -0
- package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +8 -0
- package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +65 -0
- package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +8 -0
- package/lib/transaction.js +66 -0
- package/lib/utils/assert.js +19 -0
- package/lib/utils/buildUtils.js +19 -0
- package/lib/utils/classUtils.js +9 -0
- package/lib/utils/cloneDeep.js +365 -0
- package/lib/utils/createModifier.js +37 -0
- package/lib/utils/deprecate.js +11 -0
- package/lib/utils/identifierMapping.js +188 -0
- package/lib/utils/internalPropUtils.js +7 -0
- package/lib/utils/knexUtils.js +81 -0
- package/lib/utils/mixin.js +18 -0
- package/lib/utils/mysqlJsonPath.js +70 -0
- package/lib/utils/normalizeIds.js +127 -0
- package/lib/utils/objectUtils.js +314 -0
- package/lib/utils/parseFieldExpression.js +73 -0
- package/lib/utils/postgresJsonPath.js +96 -0
- package/lib/utils/promiseUtils/after.js +14 -0
- package/lib/utils/promiseUtils/afterReturn.js +14 -0
- package/lib/utils/promiseUtils/index.js +15 -0
- package/lib/utils/promiseUtils/isPromise.js +8 -0
- package/lib/utils/promiseUtils/map.js +96 -0
- package/lib/utils/promiseUtils/mapAfterAllReturn.js +23 -0
- package/lib/utils/promiseUtils/try.js +19 -0
- package/lib/utils/resolveModel.js +104 -0
- package/lib/utils/tmpColumnUtils.js +7 -0
- package/package.json +113 -4
- package/typings/objection/index.d.mts +362 -0
- package/typings/objection/index.d.ts +4131 -0
- package/typings/objection/relation-expression.d.ts +237 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { Relation } = require('../Relation');
|
|
3
|
+
const { BelongsToOneInsertOperation } = require('./BelongsToOneInsertOperation');
|
|
4
|
+
const { BelongsToOneDeleteOperation } = require('./BelongsToOneDeleteOperation');
|
|
5
|
+
const { BelongsToOneRelateOperation } = require('./BelongsToOneRelateOperation');
|
|
6
|
+
const { BelongsToOneUnrelateOperation } = require('./BelongsToOneUnrelateOperation');
|
|
7
|
+
class BelongsToOneRelation extends Relation {
|
|
8
|
+
isOneToOne() {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
insert(_, owner) {
|
|
12
|
+
return new BelongsToOneInsertOperation('insert', {
|
|
13
|
+
relation: this,
|
|
14
|
+
owner,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
delete(_, owner) {
|
|
18
|
+
return new BelongsToOneDeleteOperation('delete', {
|
|
19
|
+
relation: this,
|
|
20
|
+
owner,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
relate(_, owner) {
|
|
24
|
+
return new BelongsToOneRelateOperation('relate', {
|
|
25
|
+
relation: this,
|
|
26
|
+
owner,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
unrelate(_, owner) {
|
|
30
|
+
return new BelongsToOneUnrelateOperation('unrelate', {
|
|
31
|
+
relation: this,
|
|
32
|
+
owner,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
Object.defineProperties(BelongsToOneRelation.prototype, {
|
|
37
|
+
isObjectionBelongsToOneRelation: {
|
|
38
|
+
enumerable: false,
|
|
39
|
+
writable: false,
|
|
40
|
+
value: true,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
module.exports = {
|
|
44
|
+
BelongsToOneRelation,
|
|
45
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { UnrelateOperation } = require('../../queryBuilder/operations/UnrelateOperation');
|
|
3
|
+
class BelongsToOneUnrelateOperation extends UnrelateOperation {
|
|
4
|
+
onAdd() {
|
|
5
|
+
const ids = new Array(this.relation.ownerProp.size);
|
|
6
|
+
this.relation.ownerProp.forEach((i) => {
|
|
7
|
+
ids[i] = null;
|
|
8
|
+
});
|
|
9
|
+
this.ids = [ids];
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
queryExecutor(builder) {
|
|
13
|
+
const patch = {};
|
|
14
|
+
const ownerProp = this.relation.ownerProp;
|
|
15
|
+
ownerProp.forEach((i) => {
|
|
16
|
+
const relatedValue = this.ids[0][i];
|
|
17
|
+
if (this.owner.isModels) {
|
|
18
|
+
for (const owner of this.owner.modelArray) {
|
|
19
|
+
ownerProp.setProp(owner, i, relatedValue);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
ownerProp.patch(patch, i, relatedValue);
|
|
23
|
+
});
|
|
24
|
+
const ownerIdProp = this.relation.ownerModelClass.getIdRelationProperty();
|
|
25
|
+
const ownerRefs = ownerIdProp.refs(builder);
|
|
26
|
+
const ownerIds = this.owner.getProps(this.relation, ownerIdProp);
|
|
27
|
+
const query = this.relation.ownerModelClass
|
|
28
|
+
.query()
|
|
29
|
+
.childQueryOf(builder)
|
|
30
|
+
.patch(patch)
|
|
31
|
+
.whereInComposite(ownerRefs, ownerIds);
|
|
32
|
+
// We are creating a query to the related items. So any `where` statements
|
|
33
|
+
// must filter the *related* items, not the root query above, which is actually
|
|
34
|
+
// for the owners.
|
|
35
|
+
if (builder.has(builder.constructor.WhereSelector)) {
|
|
36
|
+
query.whereExists(this.relation.ownerModelClass
|
|
37
|
+
.relatedQuery(this.relation.name)
|
|
38
|
+
.copyFrom(builder, builder.constructor.JoinSelector)
|
|
39
|
+
.copyFrom(builder, builder.constructor.WhereSelector));
|
|
40
|
+
}
|
|
41
|
+
return query;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
module.exports = {
|
|
45
|
+
BelongsToOneUnrelateOperation,
|
|
46
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { RelationInsertOperation } = require('../RelationInsertOperation');
|
|
3
|
+
class HasManyInsertOperation extends RelationInsertOperation {
|
|
4
|
+
onAdd(builder, args) {
|
|
5
|
+
const retVal = super.onAdd(builder, args);
|
|
6
|
+
assertOwnerIsSingleItem(this.owner, this.relation);
|
|
7
|
+
const ownerValues = this.owner.getSplitProps(builder, this.relation);
|
|
8
|
+
const relatedProp = this.relation.relatedProp;
|
|
9
|
+
for (const model of this.models) {
|
|
10
|
+
for (let j = 0, lp = relatedProp.size; j < lp; ++j) {
|
|
11
|
+
relatedProp.setProp(model, j, ownerValues[0][j]);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return retVal;
|
|
15
|
+
}
|
|
16
|
+
async onAfter1(builder, ret) {
|
|
17
|
+
const inserted = await super.onAfter1(builder, ret);
|
|
18
|
+
if (!this.assignResultToOwner) {
|
|
19
|
+
return inserted;
|
|
20
|
+
}
|
|
21
|
+
if (this.owner.isModels) {
|
|
22
|
+
for (const owner of this.owner.modelArray) {
|
|
23
|
+
owner.$appendRelated(this.relation, inserted);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return inserted;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function assertOwnerIsSingleItem(owner, relation) {
|
|
30
|
+
const { isModels, isIdentifiers, isQueryBuilder } = owner;
|
|
31
|
+
const { ownerProp } = relation;
|
|
32
|
+
const singleModel = isModels && owner.modelArray.length === 1;
|
|
33
|
+
const singleId = isIdentifiers && owner.getNormalizedIdentifiers(ownerProp).length === 1;
|
|
34
|
+
if (!singleModel && !singleId && !isQueryBuilder) {
|
|
35
|
+
throw new Error([
|
|
36
|
+
'Can only insert items for one parent at a time in case of HasManyRelation.',
|
|
37
|
+
'Otherwise multiple insert queries would need to be created.',
|
|
38
|
+
'If you need to insert items for multiple parents, simply loop through them.',
|
|
39
|
+
`That's the most performant way.`,
|
|
40
|
+
].join(' '));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
module.exports = {
|
|
44
|
+
HasManyInsertOperation,
|
|
45
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { withWhereScope } = require('../../queryBuilder/whereScopes');
|
|
3
|
+
const { normalizeIds } = require('../../utils/normalizeIds');
|
|
4
|
+
const { RelateOperation } = require('../../queryBuilder/operations/RelateOperation');
|
|
5
|
+
class HasManyRelateOperation extends RelateOperation {
|
|
6
|
+
onAdd(_, args) {
|
|
7
|
+
this.input = args[0];
|
|
8
|
+
this.ids = normalizeIds(args[0], this.relation.relatedModelClass.getIdRelationProperty(), {
|
|
9
|
+
arrayOutput: true,
|
|
10
|
+
});
|
|
11
|
+
assertOwnerIsSingleItem(this.owner, this.relation);
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
queryExecutor(builder) {
|
|
15
|
+
const patch = {};
|
|
16
|
+
const relatedProp = this.relation.relatedProp;
|
|
17
|
+
const ownerValues = this.owner.getSplitProps(builder, this.relation);
|
|
18
|
+
relatedProp.forEach((i) => {
|
|
19
|
+
relatedProp.patch(patch, i, ownerValues[0][i]);
|
|
20
|
+
});
|
|
21
|
+
const query = this.relation.relatedModelClass
|
|
22
|
+
.query()
|
|
23
|
+
.childQueryOf(builder)
|
|
24
|
+
.patch(patch)
|
|
25
|
+
.copyFrom(builder, builder.constructor.JoinSelector)
|
|
26
|
+
.copyFrom(builder, builder.constructor.WhereSelector);
|
|
27
|
+
withWhereScope(query, () => query.findByIds(this.ids));
|
|
28
|
+
withWhereScope(query, () => query.modify(this.relation.modify));
|
|
29
|
+
return query;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function assertOwnerIsSingleItem(owner, relation) {
|
|
33
|
+
const { isModels, isIdentifiers, isQueryBuilder } = owner;
|
|
34
|
+
const { ownerProp } = relation;
|
|
35
|
+
const singleModel = isModels && owner.modelArray.length === 1;
|
|
36
|
+
const singleId = isIdentifiers && owner.getNormalizedIdentifiers(ownerProp).length === 1;
|
|
37
|
+
if (!singleModel && !singleId && !isQueryBuilder) {
|
|
38
|
+
throw new Error([
|
|
39
|
+
'Can only relate items for one parent at a time in case of HasManyRelation.',
|
|
40
|
+
'Otherwise multiple update queries would need to be created.',
|
|
41
|
+
'If you need to relate items for multiple parents, simply loop through them.',
|
|
42
|
+
`That's the most performant way.`,
|
|
43
|
+
].join(' '));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
module.exports = {
|
|
47
|
+
HasManyRelateOperation,
|
|
48
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { Relation } = require('../Relation');
|
|
3
|
+
const { HasManyInsertOperation } = require('./HasManyInsertOperation');
|
|
4
|
+
const { HasManyRelateOperation } = require('./HasManyRelateOperation');
|
|
5
|
+
const { HasManyUnrelateOperation } = require('./HasManyUnrelateOperation');
|
|
6
|
+
class HasManyRelation extends Relation {
|
|
7
|
+
insert(_, owner) {
|
|
8
|
+
return new HasManyInsertOperation('insert', {
|
|
9
|
+
relation: this,
|
|
10
|
+
owner: owner,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
relate(_, owner) {
|
|
14
|
+
return new HasManyRelateOperation('relate', {
|
|
15
|
+
relation: this,
|
|
16
|
+
owner: owner,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
unrelate(_, owner) {
|
|
20
|
+
return new HasManyUnrelateOperation('unrelate', {
|
|
21
|
+
relation: this,
|
|
22
|
+
owner: owner,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
hasRelateProp(model) {
|
|
26
|
+
return model.$hasId();
|
|
27
|
+
}
|
|
28
|
+
setRelateProp(model, values) {
|
|
29
|
+
model.$id(values);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
Object.defineProperties(HasManyRelation.prototype, {
|
|
33
|
+
isObjectionHasManyRelation: {
|
|
34
|
+
enumerable: false,
|
|
35
|
+
writable: false,
|
|
36
|
+
value: true,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
module.exports = {
|
|
40
|
+
HasManyRelation,
|
|
41
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { withWhereScope } = require('../../queryBuilder/whereScopes');
|
|
3
|
+
const { UnrelateOperation } = require('../../queryBuilder/operations/UnrelateOperation');
|
|
4
|
+
class HasManyUnrelateOperation extends UnrelateOperation {
|
|
5
|
+
queryExecutor(builder) {
|
|
6
|
+
const patch = {};
|
|
7
|
+
const relatedProp = this.relation.relatedProp;
|
|
8
|
+
const ownerValues = this.owner.getProps(this.relation);
|
|
9
|
+
const relatedRefs = relatedProp.refs(builder);
|
|
10
|
+
relatedProp.forEach((i) => {
|
|
11
|
+
relatedProp.patch(patch, i, null);
|
|
12
|
+
});
|
|
13
|
+
const query = this.relation.relatedModelClass
|
|
14
|
+
.query()
|
|
15
|
+
.childQueryOf(builder)
|
|
16
|
+
.patch(patch)
|
|
17
|
+
.copyFrom(builder, builder.constructor.JoinSelector)
|
|
18
|
+
.copyFrom(builder, builder.constructor.WhereSelector);
|
|
19
|
+
withWhereScope(query, () => query.whereInComposite(relatedRefs, ownerValues));
|
|
20
|
+
withWhereScope(query, () => query.modify(this.relation.modify));
|
|
21
|
+
return query;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
module.exports = {
|
|
25
|
+
HasManyUnrelateOperation,
|
|
26
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { withWhereScope } = require('../../queryBuilder/whereScopes');
|
|
3
|
+
const { ManyToManyFindOperation } = require('./find/ManyToManyFindOperation');
|
|
4
|
+
// This mixin contains the shared code for all modify operations (update, delete, relate, unrelate)
|
|
5
|
+
// for ManyToManyRelation operations.
|
|
6
|
+
//
|
|
7
|
+
// The most important thing this mixin does is that it moves the filters from the main query
|
|
8
|
+
// into a subquery and then adds a single where clause that uses the subquery. This is done so
|
|
9
|
+
// that we are able to `innerJoin` the join table to the query. Most SQL engines don't allow
|
|
10
|
+
// joins in updates or deletes. Join table is joined so that queries can reference the join
|
|
11
|
+
// table columns.
|
|
12
|
+
const ManyToManyModifyMixin = (Operation) => {
|
|
13
|
+
return class extends Operation {
|
|
14
|
+
constructor(...args) {
|
|
15
|
+
super(...args);
|
|
16
|
+
this.modifyFilterSubquery = null;
|
|
17
|
+
}
|
|
18
|
+
get modifyMainQuery() {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
// At this point `builder` should only have the user's own wheres and joins. There can
|
|
22
|
+
// be other operations (like orderBy) too, but those are meaningless with modify operations.
|
|
23
|
+
onBuild(builder) {
|
|
24
|
+
this.modifyFilterSubquery = this.createModifyFilterSubquery(builder);
|
|
25
|
+
if (this.modifyMainQuery) {
|
|
26
|
+
// We can now remove the where and join statements from the main query.
|
|
27
|
+
this.removeFiltersFromMainQuery(builder);
|
|
28
|
+
// Add a single where clause that uses the created subquery.
|
|
29
|
+
withWhereScope(builder, () => this.applyModifyFilterForRelatedTable(builder));
|
|
30
|
+
}
|
|
31
|
+
return super.onBuild(builder);
|
|
32
|
+
}
|
|
33
|
+
createModifyFilterSubquery(builder) {
|
|
34
|
+
const relatedModelClass = this.relation.relatedModelClass;
|
|
35
|
+
const builderClass = builder.constructor;
|
|
36
|
+
// Create an empty subquery.
|
|
37
|
+
const modifyFilterSubquery = relatedModelClass.query().childQueryOf(builder);
|
|
38
|
+
// Add the necessary joins and wheres so that only rows related to
|
|
39
|
+
// `this.owner` are selected.
|
|
40
|
+
this.relation.findQuery(modifyFilterSubquery, this.owner);
|
|
41
|
+
// Copy all where and join statements from the main query to the subquery.
|
|
42
|
+
modifyFilterSubquery
|
|
43
|
+
.copyFrom(builder, builderClass.WhereSelector)
|
|
44
|
+
.copyFrom(builder, builderClass.JoinSelector);
|
|
45
|
+
return modifyFilterSubquery.clearSelect();
|
|
46
|
+
}
|
|
47
|
+
removeFiltersFromMainQuery(builder) {
|
|
48
|
+
const builderClass = builder.constructor;
|
|
49
|
+
builder.clear(builderClass.WhereSelector);
|
|
50
|
+
builder.clear(builderClass.JoinSelector);
|
|
51
|
+
}
|
|
52
|
+
applyModifyFilterForRelatedTable(builder) {
|
|
53
|
+
const idRefs = this.relation.relatedModelClass.getIdRelationProperty().refs(builder);
|
|
54
|
+
const subquery = this.modifyFilterSubquery.clone().select(idRefs);
|
|
55
|
+
return builder.whereInComposite(idRefs, subquery);
|
|
56
|
+
}
|
|
57
|
+
applyModifyFilterForJoinTable(builder) {
|
|
58
|
+
const joinTableOwnerRefs = this.relation.joinTableOwnerProp.refs(builder);
|
|
59
|
+
const joinTableRelatedRefs = this.relation.joinTableRelatedProp.refs(builder);
|
|
60
|
+
const relatedRefs = this.relation.relatedProp.refs(builder);
|
|
61
|
+
const ownerValues = this.owner.getProps(this.relation);
|
|
62
|
+
const subquery = this.modifyFilterSubquery.clone().select(relatedRefs);
|
|
63
|
+
return builder
|
|
64
|
+
.whereInComposite(joinTableRelatedRefs, subquery)
|
|
65
|
+
.whereInComposite(joinTableOwnerRefs, ownerValues);
|
|
66
|
+
}
|
|
67
|
+
toFindOperation() {
|
|
68
|
+
return new ManyToManyFindOperation('find', {
|
|
69
|
+
relation: this.relation,
|
|
70
|
+
owner: this.owner,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
clone() {
|
|
74
|
+
const clone = super.clone();
|
|
75
|
+
clone.modifyFilterSubquery = this.modifyFilterSubquery;
|
|
76
|
+
return clone;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
module.exports = {
|
|
81
|
+
ManyToManyModifyMixin,
|
|
82
|
+
};
|