123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- const FindOperation = require('../queryBuilder/operations/FindOperation');
- const { uniqBy } = require('../utils/objectUtils');
- class RelationFindOperation extends FindOperation {
- constructor(name, opt) {
- super(name, opt);
- this.relation = opt.relation;
- this.owners = opt.owners;
- this.alwaysReturnArray = false;
- this.assignResultToOwner = true;
- this.relationProperty = opt.relationProperty || this.relation.name;
- this.omitProps = [];
- }
- onBuild(builder) {
- let ids = new Array(this.owners.length);
- for (let i = 0, l = this.owners.length; i < l; ++i) {
- ids[i] = this.relation.ownerProp.getProps(this.owners[i]);
- }
- this.relation.findQuery(builder, {
- ownerIds: uniqBy(ids, join)
- });
- this.selectMissingJoinColumns(builder);
- }
- onAfter2(builder, related) {
- const isOneToOne = this.relation.isOneToOne();
- if (this.assignResultToOwner) {
- const owners = this.owners;
- const relatedByOwnerId = new Map();
- for (let i = 0, l = related.length; i < l; ++i) {
- const rel = related[i];
- const key = this.relation.relatedProp.propKey(rel);
- let arr = relatedByOwnerId.get(key);
- if (!arr) {
- arr = [];
- relatedByOwnerId.set(key, arr);
- }
- arr.push(rel);
- }
- for (let i = 0, l = owners.length; i < l; ++i) {
- const own = owners[i];
- const key = this.relation.ownerProp.propKey(own);
- const related = relatedByOwnerId.get(key);
- if (isOneToOne) {
- own[this.relationProperty] = (related && related[0]) || null;
- } else {
- own[this.relationProperty] = related || [];
- }
- }
- }
- return related;
- }
- onAfter3(builder, related) {
- const isOneToOne = this.relation.isOneToOne();
- const intOpt = builder.internalOptions();
- if (!intOpt.keepImplicitJoinProps) {
- this.omitImplicitJoinProps(related);
- }
- if (!this.alwaysReturnArray && isOneToOne && related.length <= 1) {
- related = related[0] || undefined;
- }
- return super.onAfter3(builder, related);
- }
- selectMissingJoinColumns(builder) {
- const relatedProp = this.relation.relatedProp;
- const addedSelects = [];
- for (let c = 0, lc = relatedProp.size; c < lc; ++c) {
- const fullCol = relatedProp.fullCol(builder, c);
- const prop = relatedProp.props[c];
- const col = relatedProp.cols[c];
- if (!builder.hasSelectionAs(fullCol, col) && addedSelects.indexOf(fullCol) === -1) {
- this.omitProps.push(prop);
- addedSelects.push(fullCol);
- }
- }
- if (addedSelects.length) {
- builder.select(addedSelects);
- }
- }
- omitImplicitJoinProps(related) {
- const relatedModelClass = this.relation.relatedModelClass;
- if (!this.omitProps.length || !related) {
- return related;
- }
- if (!Array.isArray(related)) {
- return this.omitImplicitJoinPropsFromOne(relatedModelClass, related);
- }
- if (!related.length) {
- return related;
- }
- for (let i = 0, l = related.length; i < l; ++i) {
- this.omitImplicitJoinPropsFromOne(relatedModelClass, related[i]);
- }
- return related;
- }
- omitImplicitJoinPropsFromOne(relatedModelClass, model) {
- for (let c = 0, lc = this.omitProps.length; c < lc; ++c) {
- relatedModelClass.omitImpl(model, this.omitProps[c]);
- }
- return model;
- }
- }
- function join(arr) {
- return arr.join();
- }
- module.exports = RelationFindOperation;
|