123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- const Promise = require('bluebird');
- const UpsertNode = require('../graphUpserter/UpsertNode');
- const UpsertGraph = require('../graphUpserter/UpsertGraph');
- const HasManyRelation = require('../../relations/hasMany/HasManyRelation');
- const InsertGraphOperation = require('./InsertGraphOperation');
- const transformOptionsFromPath = require('../../utils/transformOptionsFromPath');
- class UpsertGraphOperation extends InsertGraphOperation {
- constructor(name, opt) {
- super(
- name,
- Object.assign({}, opt, {
- opt: {}
- })
- );
- this.graph = null;
- this.upsertOpt = opt.opt || {};
- }
- onBefore1(builder) {
- this.graph = new UpsertGraph(this.models, this.isArray, this.upsertOpt);
- return this.graph.build(builder).then(() => this.delete(builder));
- }
-
-
-
-
- beforeGraphInserterCreated(builder) {
- for (let i = 0, l = this.graph.nodes.length; i < l; ++i) {
- const node = this.graph.nodes[i];
-
-
- if (node.hasType(UpsertNode.Type.Relate) && !(node.relation instanceof HasManyRelation)) {
- node.upsertModel[node.modelClass.dbRefProp] = node.upsertModel.$values(
- node.relation.relatedProp.props
- );
- }
- }
- }
-
-
-
- afterGraphInserterCreated(builder, graphInserter) {
- const insertNodes = graphInserter.graph.nodes;
-
-
- for (let i = 0, l = insertNodes.length; i < l; ++i) {
- const insertNode = insertNodes[i];
- const upsertNode = this.graph.nodesByUpsert.get(insertNode.model);
- if ((!upsertNode || !upsertNode.hasType(UpsertNode.Type.Insert)) && !insertNode.handled) {
-
- for (let d = 0, ld = insertNode.isNeededBy.length; d < ld; ++d) {
- insertNode.isNeededBy[d].resolve(insertNode.model);
- }
- if (insertNode.parentNode) {
- const parent = insertNode.parentNode;
-
-
- parent.manyToManyConnections = parent.manyToManyConnections.filter(
- conn => conn.node !== insertNode
- );
- }
- insertNode.markAsInserted();
- }
- }
- }
- onAfter2(builder, result) {
- return this.relate(builder)
- .then(() => this.update(builder))
- .then(() => this.upsertRecursively(builder))
- .then(() => super.onAfter2(builder, result));
- }
- delete(builder) {
- return Promise.map(
- this.graph.nodes,
- node => {
- const relNames = Object.keys(node.relations);
- return Promise.map(
- relNames,
- relName => {
- const relation = node.modelClass.getRelation(relName);
- const nodes = node.relations[relName].filter(it =>
- it.hasType(UpsertNode.Type.Delete, UpsertNode.Type.Unrelate)
- );
- const ids = nodes.map(it => it.currentModel.$id());
- if (ids.length) {
- const unrelate = nodes[0].hasType(UpsertNode.Type.Unrelate);
- const query = node.upsertModel.$relatedQuery(relName).childQueryOf(builder);
- if (!relation.isOneToOne()) {
- query.whereInComposite(builder.fullIdColumnFor(relation.relatedModelClass), ids);
- }
- if (unrelate) {
- query.unrelate();
- } else {
- query.delete();
- }
- return query;
- }
- },
- { concurrency: 1 }
- );
- },
- { concurrency: this.graph.rootModelClass.concurrency }
- );
- }
- relate(builder) {
-
-
- const relateNodes = this.graph.nodes.filter(
- it => it.hasType(UpsertNode.Type.Relate) && it.relation instanceof HasManyRelation
- );
- return Promise.map(
- relateNodes,
- node => {
- return node.parentNode.upsertModel
- .$relatedQuery(node.relationName)
- .childQueryOf(builder, true)
- .relate(node.upsertModel.$id());
- },
- { concurrency: this.graph.rootModelClass.concurrency }
- );
- }
- update(builder) {
- const updateNodes = this.graph.nodes.filter(it =>
- it.hasType(UpsertNode.Type.Update, UpsertNode.Type.Patch)
- );
- return Promise.map(
- updateNodes,
- node => {
- let query = null;
- const patch = node.hasType(UpsertNode.Type.Patch);
-
-
- node.upsertModel.$validate(node.upsertModel, {
- patch: patch,
- dataPath: node.dataPath
- });
- if (node.parentNode) {
-
-
- query = node.parentNode.upsertModel
- .$relatedQuery(node.relationName)
- .childQueryOf(builder, true)
- .findById(node.upsertModel.$id())
- [patch ? 'patch' : 'update'](node.upsertModel);
- } else {
- query = node.upsertModel
- .$query()
- .childQueryOf(builder, true)
- .patch();
- }
- return query;
- },
- { concurrency: this.graph.rootModelClass.concurrency }
- );
- }
- upsertRecursively(builder) {
- const upsertRecursivelyNodes = this.graph.nodes.filter(it =>
- it.hasType(UpsertNode.Type.UpsertRecursively)
- );
- return Promise.map(
- upsertRecursivelyNodes,
- node => {
- return node.upsertModel.constructor
- .query()
- .upsertGraph(node.upsertModel, transformOptionsFromPath(node.opt, node.relPathFromRoot))
- .childQueryOf(builder, true);
- },
- { concurrency: this.graph.rootModelClass.concurrency }
- );
- }
- }
- module.exports = UpsertGraphOperation;
|