|
|
|
@ -1107,7 +1107,7 @@ class BaseModelSql extends BaseModel {
|
|
|
|
|
* @private |
|
|
|
|
*/ |
|
|
|
|
async _getChildListInParent({parent, child}, rest = {}, index) { |
|
|
|
|
let {fields, where, limit, offset, sort} = this._getChildListArgs(rest, index); |
|
|
|
|
let {fields, where, limit, offset, sort} = this._getChildListArgs(rest, index, child); |
|
|
|
|
const {cn} = this.hasManyRelations.find(({tn}) => tn === child) || {}; |
|
|
|
|
const _cn = this.dbModels[child].columnToAlias?.[cn]; |
|
|
|
|
|
|
|
|
@ -1125,7 +1125,7 @@ class BaseModelSql extends BaseModel {
|
|
|
|
|
.xwhere(where, this.dbModels[child].selectQuery('')) |
|
|
|
|
.select(this.dbModels[child].selectQuery(fields)) // ...fields.split(','));
|
|
|
|
|
|
|
|
|
|
this._paginateAndSort(query, {sort, limit, offset}, null,true); |
|
|
|
|
this._paginateAndSort(query, {sort, limit, offset}, null, true); |
|
|
|
|
return this.isSqlite() ? this.dbDriver.select().from(query) : query; |
|
|
|
|
}), !this.isSqlite() |
|
|
|
|
)); |
|
|
|
@ -1136,6 +1136,49 @@ class BaseModelSql extends BaseModel {
|
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Get child list and map to input parent |
|
|
|
|
* |
|
|
|
|
* @param {Object[]} parent - parent list array |
|
|
|
|
* @param {String} child - child table name |
|
|
|
|
* @param {Object} rest - index suffixed fields, limit, offset, where and sort |
|
|
|
|
* @param index - child table index |
|
|
|
|
* @returns {Promise<void>} |
|
|
|
|
* @private |
|
|
|
|
*/ |
|
|
|
|
async _getManyToManyList({parent, child}, rest = {}, index) { |
|
|
|
|
|
|
|
|
|
let {fields, where, limit, offset, sort} = this._getChildListArgs(rest, index, child); |
|
|
|
|
const {tn, cn, vtn, vcn, vrcn, rtn, rcn} = this.manyToManyRelations.find(({rtn}) => rtn === child) || {}; |
|
|
|
|
const _cn = this.dbModels[tn].columnToAlias?.[cn]; |
|
|
|
|
|
|
|
|
|
if (fields !== '*' && fields.split(',').indexOf(cn) === -1) { |
|
|
|
|
fields += ',' + cn; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const childs = await this._run(this.dbDriver.union( |
|
|
|
|
parent.map(p => { |
|
|
|
|
const query = |
|
|
|
|
this |
|
|
|
|
.dbDriver(child) |
|
|
|
|
.join(vtn, `${vtn}.${vrcn}`, `${rtn}.${rcn}`) |
|
|
|
|
.where(`${vtn}.${vcn}`, p[this.columnToAlias?.[this.pks[0].cn] || this.pks[0].cn]) |
|
|
|
|
.xwhere(where, this.dbModels[child].selectQuery('')) |
|
|
|
|
.select({[_cn]: `${vtn}.${cn}`, ...this.dbModels[child].selectQuery(fields)}) // ...fields.split(','));
|
|
|
|
|
|
|
|
|
|
this._paginateAndSort(query, {sort, limit, offset}, null, true); |
|
|
|
|
return this.isSqlite() ? this.dbDriver.select().from(query) : query; |
|
|
|
|
}), !this.isSqlite() |
|
|
|
|
)); |
|
|
|
|
|
|
|
|
|
let gs = _.groupBy(childs, _cn); |
|
|
|
|
parent.forEach(row => { |
|
|
|
|
row[this.dbModels?.[child]?._tn || child] = gs[row[this.pks[0]._cn]] || []; |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Gets child rows for a parent row in this table |
|
|
|
|
* |
|
|
|
@ -1192,7 +1235,7 @@ class BaseModelSql extends BaseModel {
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
// todo : add conditionGraph
|
|
|
|
|
async hasManyList({childs, where, fields, f, ...rest}) { |
|
|
|
|
async hasManyList({childs = '', where, fields, f, ...rest}) { |
|
|
|
|
fields = fields || f || '*'; |
|
|
|
|
try { |
|
|
|
|
|
|
|
|
@ -1202,7 +1245,7 @@ class BaseModelSql extends BaseModel {
|
|
|
|
|
|
|
|
|
|
const parent = await this.list({childs, where, fields, ...rest}); |
|
|
|
|
if (parent && parent.length) { |
|
|
|
|
await Promise.all([...new Set(childs.split('.'))].map((child, index) => this._getChildListInParent({ |
|
|
|
|
await Promise.all([...new Set(childs.split('.'))].map((child, index) => child && this._getChildListInParent({ |
|
|
|
|
parent, |
|
|
|
|
child |
|
|
|
|
}, rest, index))); |
|
|
|
@ -1214,6 +1257,75 @@ class BaseModelSql extends BaseModel {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Gets parent list along with children list and parent |
|
|
|
|
* |
|
|
|
|
* @param {Object} args |
|
|
|
|
* @param {String} args.childs - comma separated child table names |
|
|
|
|
* @param {String} [args.fields=*] - commas separated column names of this table |
|
|
|
|
* @param {String} [args.fields*=*] - commas separated column names of child table(* is a natural number 'i' where i is index of child table in comma separated list) |
|
|
|
|
* @param {String} [args.where] - where clause with conditions within () |
|
|
|
|
* @param {String} [args.where*] - where clause with conditions within ()(* is a natural number 'i' where i is index of child table in comma separated list) |
|
|
|
|
* @param {String} [args.limit] - number of rows to be limited (has default,min,max values in config) |
|
|
|
|
* @param {String} [args.limit*] - number of rows to be limited of child table(* is a natural number 'i' where i is index of child table in comma separated list) |
|
|
|
|
* @param {String} [args.offset] - offset from which to get the number of rows |
|
|
|
|
* @param {String} [args.offset*] - offset from which to get the number of rows of child table(* is a natural number 'i' where i is index of child table in comma separated list) |
|
|
|
|
* @param {String} [args.sort] - comma separated column names where each column name is cn ascending and -cn is cn descending |
|
|
|
|
* @param {String} [args.sort*] - comma separated column names where each column name is cn ascending and -cn is cn descending(* is a natural number 'i' where i is index of child table in comma separated list) |
|
|
|
|
* @returns {Promise<Object[]>} |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
// todo : add conditionGraph
|
|
|
|
|
async nestedList({childs = '', parents = '', many = '', where, fields: fields1, f, ...rest}) { |
|
|
|
|
let fields = fields1 || f || '*'; |
|
|
|
|
try { |
|
|
|
|
|
|
|
|
|
if (fields !== '*' && fields.split(',').indexOf(this.pks[0].cn) === -1) { |
|
|
|
|
fields += ',' + this.pks[0].cn; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (const parent of parents.split(',')) { |
|
|
|
|
const {cn} = this.belongsToRelations.find(({rtn}) => rtn === parent) || {}; |
|
|
|
|
if (fields !== '*' && fields.split(',').indexOf(cn) === -1) { |
|
|
|
|
fields += ',' + cn; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const items = await this.list({childs, where, fields, ...rest}); |
|
|
|
|
|
|
|
|
|
if (items && items.length) { |
|
|
|
|
await Promise.all([...new Set(childs.split(','))].map((child, index) => child && this._getChildListInParent({ |
|
|
|
|
parent: items, |
|
|
|
|
child |
|
|
|
|
}, rest, index))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
await Promise.all(parents.split(',').map((parent, index): any => { |
|
|
|
|
if (!parent) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
const {cn, rcn} = this.belongsToRelations.find(({rtn}) => rtn === parent) || {}; |
|
|
|
|
const parentIds = [...new Set(items.map(c => c[cn] || c[this.columnToAlias[cn]]))]; |
|
|
|
|
return this._belongsTo({parent, rcn, parentIds, childs: items, cn, ...rest}, index); |
|
|
|
|
})) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (items && items.length) { |
|
|
|
|
await Promise.all([...new Set(many.split(','))].map((child, index) => child && this._getManyToManyList({ |
|
|
|
|
parent: items, |
|
|
|
|
child |
|
|
|
|
}, rest, index))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return items; |
|
|
|
|
} catch (e) { |
|
|
|
|
console.log(e); |
|
|
|
|
throw e; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Gets child list along with its parent |
|
|
|
|
* |
|
|
|
@ -1269,7 +1381,7 @@ class BaseModelSql extends BaseModel {
|
|
|
|
|
* @private |
|
|
|
|
*/ |
|
|
|
|
async _belongsTo({parent, rcn, parentIds, childs, cn, ...rest}, index) { |
|
|
|
|
let {fields} = this._getChildListArgs(rest, index); |
|
|
|
|
let {fields} = this._getChildListArgs(rest, index, parent); |
|
|
|
|
if (fields !== '*' && fields.split(',').indexOf(rcn) === -1) { |
|
|
|
|
fields += ',' + rcn; |
|
|
|
|
} |
|
|
|
@ -1284,7 +1396,7 @@ class BaseModelSql extends BaseModel {
|
|
|
|
|
const gs = _.groupBy(parents, this.dbModels[parent]?.columnToAlias?.[rcn] || rcn); |
|
|
|
|
|
|
|
|
|
childs.forEach(row => { |
|
|
|
|
row[this.dbModels?.[parent]?._tn || parent] = gs[row[this.dbModels[parent]?.columnToAlias?.[cn] || cn]]?.[0]; |
|
|
|
|
row[this.dbModels?.[parent]?._tn || parent] = gs[row[this.dbModels[parent]?.columnToAlias?.[cn] || cn]]?.[0] || gs[row[cn || gs[row[this.dbModels[parent]?.columnToAlias?.[cn] || cn]]?.[0]]]?.[0]; |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1392,7 +1504,7 @@ class BaseModelSql extends BaseModel {
|
|
|
|
|
* @returns {Object} query appended with paginate and sort params |
|
|
|
|
* @private |
|
|
|
|
*/ |
|
|
|
|
_paginateAndSort(query, {limit = 20, offset = 0, sort = ''}: XcFilter, table?: string, isUnion?:boolean) { |
|
|
|
|
_paginateAndSort(query, {limit = 20, offset = 0, sort = ''}: XcFilter, table?: string, isUnion?: boolean) { |
|
|
|
|
query.offset(offset) |
|
|
|
|
.limit(limit); |
|
|
|
|
|
|
|
|
@ -1465,18 +1577,24 @@ class BaseModelSql extends BaseModel {
|
|
|
|
|
* @returns {Object} consisting of fields*,where*,limit*,offset*,sort* |
|
|
|
|
* @private |
|
|
|
|
*/ |
|
|
|
|
_getChildListArgs(args: any, index?: number) { |
|
|
|
|
_getChildListArgs(args: any, index?: number, child?: string) { |
|
|
|
|
index++; |
|
|
|
|
let obj: XcFilter = {}; |
|
|
|
|
obj.where = args[`where${index}`] || args[`w${index}`] || ''; |
|
|
|
|
obj.limit = Math.max(Math.min(args[`limit${index}`] || args[`l${index}`] || this.config.limitDefault, this.config.limitMax), this.config.limitMin); |
|
|
|
|
obj.offset = args[`offset${index}`] || args[`o${index}`] || 0; |
|
|
|
|
obj.fields = args[`fields${index}`] || args[`f${index}`] || '*'; |
|
|
|
|
obj.fields = args[`fields${index}`] || args[`f${index}`] || this.getPKandPV(child); |
|
|
|
|
obj.sort = args[`sort${index}`] || args[`s${index}`]; |
|
|
|
|
return obj; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
private getPKandPV(child: string) { |
|
|
|
|
return child ? |
|
|
|
|
(this.dbModels[child]?.columns?.filter(col => col.pk || col.pv).map(col => col.cn) || ['*']).join(',') |
|
|
|
|
: '*'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
public selectQuery(fields) { |
|
|
|
|
const fieldsArr = fields.split(','); |
|
|
|
|
return this.columns?.reduce((selectObj, col) => { |
|
|
|
@ -1484,8 +1602,8 @@ class BaseModelSql extends BaseModel {
|
|
|
|
|
!fields |
|
|
|
|
|| fieldsArr.includes('*') |
|
|
|
|
|| fieldsArr.includes(`${this.tn}.*`) |
|
|
|
|
|| fields.includes(col._cn) |
|
|
|
|
|| fields.includes(col.cn) |
|
|
|
|
|| fieldsArr.includes(col._cn) |
|
|
|
|
|| fieldsArr.includes(col.cn) |
|
|
|
|
) { |
|
|
|
|
selectObj[col._cn] = `${this.tn}.${col.cn}`; |
|
|
|
|
} |
|
|
|
|