|
|
@ -5,6 +5,7 @@ import { nocoExecute } from 'nc-help'; |
|
|
|
import { |
|
|
|
import { |
|
|
|
AuditOperationSubTypes, |
|
|
|
AuditOperationSubTypes, |
|
|
|
AuditOperationTypes, |
|
|
|
AuditOperationTypes, |
|
|
|
|
|
|
|
isSystemColumn, |
|
|
|
isVirtualCol, |
|
|
|
isVirtualCol, |
|
|
|
RelationTypes, |
|
|
|
RelationTypes, |
|
|
|
UITypes, |
|
|
|
UITypes, |
|
|
@ -42,6 +43,7 @@ import genRollupSelectv2 from './genRollupSelectv2'; |
|
|
|
import sortV2 from './sortV2'; |
|
|
|
import sortV2 from './sortV2'; |
|
|
|
import conditionV2 from './conditionV2'; |
|
|
|
import conditionV2 from './conditionV2'; |
|
|
|
import { sanitize, unsanitize } from './helpers/sanitize'; |
|
|
|
import { sanitize, unsanitize } from './helpers/sanitize'; |
|
|
|
|
|
|
|
import type { GridViewColumn } from '../../../../models'; |
|
|
|
import type { SortType } from 'nocodb-sdk'; |
|
|
|
import type { SortType } from 'nocodb-sdk'; |
|
|
|
import type { Knex } from 'knex'; |
|
|
|
import type { Knex } from 'knex'; |
|
|
|
import type FormulaColumn from '../../../../models/FormulaColumn'; |
|
|
|
import type FormulaColumn from '../../../../models/FormulaColumn'; |
|
|
@ -68,6 +70,21 @@ async function populatePk(model: Model, insertObj: any) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function checkColumnRequired( |
|
|
|
|
|
|
|
column: Column<any>, |
|
|
|
|
|
|
|
fields: string[], |
|
|
|
|
|
|
|
extractPkAndPv?: boolean |
|
|
|
|
|
|
|
) { |
|
|
|
|
|
|
|
// if primary key or foreign key included in fields, it's required
|
|
|
|
|
|
|
|
if (column.pk || column.uidt === UITypes.ForeignKey) return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (extractPkAndPv && column.pv) return true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// check fields defined and if not, then select all
|
|
|
|
|
|
|
|
// if defined check if it is in the fields
|
|
|
|
|
|
|
|
return !fields || fields.includes(column.title); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Base class for models |
|
|
|
* Base class for models |
|
|
|
* |
|
|
|
* |
|
|
@ -101,14 +118,23 @@ class BaseModelSqlv2 { |
|
|
|
autoBind(this); |
|
|
|
autoBind(this); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async readByPk(id?: any): Promise<any> { |
|
|
|
public async readByPk(id?: any, validateFormula = false): Promise<any> { |
|
|
|
const qb = this.dbDriver(this.tnPath); |
|
|
|
const qb = this.dbDriver(this.tnPath); |
|
|
|
|
|
|
|
|
|
|
|
await this.selectObject({ qb }); |
|
|
|
await this.selectObject({ qb, validateFormula }); |
|
|
|
|
|
|
|
|
|
|
|
qb.where(_wherePk(this.model.primaryKeys, id)); |
|
|
|
qb.where(_wherePk(this.model.primaryKeys, id)); |
|
|
|
|
|
|
|
|
|
|
|
let data = (await this.execAndParse(qb))?.[0]; |
|
|
|
let data; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
data = (await this.execAndParse(qb))?.[0]; |
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
|
|
if (validateFormula || !haveFormulaColumn(await this.model.getColumns())) |
|
|
|
|
|
|
|
throw e; |
|
|
|
|
|
|
|
console.log(e); |
|
|
|
|
|
|
|
return this.readByPk(id, true); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (data) { |
|
|
|
if (data) { |
|
|
|
const proto = await this.getProto(); |
|
|
|
const proto = await this.getProto(); |
|
|
@ -141,11 +167,12 @@ class BaseModelSqlv2 { |
|
|
|
where?: string; |
|
|
|
where?: string; |
|
|
|
filterArr?: Filter[]; |
|
|
|
filterArr?: Filter[]; |
|
|
|
sort?: string | string[]; |
|
|
|
sort?: string | string[]; |
|
|
|
} = {} |
|
|
|
} = {}, |
|
|
|
|
|
|
|
validateFormula = false |
|
|
|
): Promise<any> { |
|
|
|
): Promise<any> { |
|
|
|
const { where, ...rest } = this._getListArgs(args as any); |
|
|
|
const { where, ...rest } = this._getListArgs(args as any); |
|
|
|
const qb = this.dbDriver(this.tnPath); |
|
|
|
const qb = this.dbDriver(this.tnPath); |
|
|
|
await this.selectObject({ qb }); |
|
|
|
await this.selectObject({ qb, validateFormula }); |
|
|
|
|
|
|
|
|
|
|
|
const aliasColObjMap = await this.model.getAliasColObjMap(); |
|
|
|
const aliasColObjMap = await this.model.getAliasColObjMap(); |
|
|
|
const sorts = extractSortsObject(rest?.sort, aliasColObjMap); |
|
|
|
const sorts = extractSortsObject(rest?.sort, aliasColObjMap); |
|
|
@ -174,7 +201,16 @@ class BaseModelSqlv2 { |
|
|
|
qb.orderBy(this.model.primaryKey.column_name); |
|
|
|
qb.orderBy(this.model.primaryKey.column_name); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const data = await qb.first(); |
|
|
|
let data; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
data = await qb.first(); |
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
|
|
if (validateFormula || !haveFormulaColumn(await this.model.getColumns())) |
|
|
|
|
|
|
|
throw e; |
|
|
|
|
|
|
|
console.log(e); |
|
|
|
|
|
|
|
return this.findOne(args, true); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (data) { |
|
|
|
if (data) { |
|
|
|
const proto = await this.getProto(); |
|
|
|
const proto = await this.getProto(); |
|
|
@ -191,13 +227,21 @@ class BaseModelSqlv2 { |
|
|
|
filterArr?: Filter[]; |
|
|
|
filterArr?: Filter[]; |
|
|
|
sortArr?: Sort[]; |
|
|
|
sortArr?: Sort[]; |
|
|
|
sort?: string | string[]; |
|
|
|
sort?: string | string[]; |
|
|
|
|
|
|
|
fieldsSet?: Set<string>; |
|
|
|
} = {}, |
|
|
|
} = {}, |
|
|
|
ignoreViewFilterAndSort = false |
|
|
|
ignoreViewFilterAndSort = false, |
|
|
|
|
|
|
|
validateFormula = false |
|
|
|
): Promise<any> { |
|
|
|
): Promise<any> { |
|
|
|
const { where, ...rest } = this._getListArgs(args as any); |
|
|
|
const { where, fields, ...rest } = this._getListArgs(args as any); |
|
|
|
|
|
|
|
|
|
|
|
const qb = this.dbDriver(this.tnPath); |
|
|
|
const qb = this.dbDriver(this.tnPath); |
|
|
|
await this.selectObject({ qb }); |
|
|
|
|
|
|
|
|
|
|
|
await this.selectObject({ |
|
|
|
|
|
|
|
qb, |
|
|
|
|
|
|
|
fieldsSet: args.fieldsSet, |
|
|
|
|
|
|
|
viewId: this.viewId, |
|
|
|
|
|
|
|
validateFormula, |
|
|
|
|
|
|
|
}); |
|
|
|
if (+rest?.shuffle) { |
|
|
|
if (+rest?.shuffle) { |
|
|
|
await this.shuffle({ qb }); |
|
|
|
await this.shuffle({ qb }); |
|
|
|
} |
|
|
|
} |
|
|
@ -268,8 +312,17 @@ class BaseModelSqlv2 { |
|
|
|
|
|
|
|
|
|
|
|
if (!ignoreViewFilterAndSort) applyPaginate(qb, rest); |
|
|
|
if (!ignoreViewFilterAndSort) applyPaginate(qb, rest); |
|
|
|
const proto = await this.getProto(); |
|
|
|
const proto = await this.getProto(); |
|
|
|
const data = await this.execAndParse(qb); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let data; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
data = await this.execAndParse(qb); |
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
|
|
if (validateFormula || !haveFormulaColumn(await this.model.getColumns())) |
|
|
|
|
|
|
|
throw e; |
|
|
|
|
|
|
|
console.log(e); |
|
|
|
|
|
|
|
return this.list(args, ignoreViewFilterAndSort, true); |
|
|
|
|
|
|
|
} |
|
|
|
return data?.map((d) => { |
|
|
|
return data?.map((d) => { |
|
|
|
d.__proto__ = proto; |
|
|
|
d.__proto__ = proto; |
|
|
|
return d; |
|
|
|
return d; |
|
|
@ -391,7 +444,10 @@ class BaseModelSqlv2 { |
|
|
|
return await qb; |
|
|
|
return await qb; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async multipleHmList({ colId, ids }, args: { limit?; offset? } = {}) { |
|
|
|
async multipleHmList( |
|
|
|
|
|
|
|
{ colId, ids }, |
|
|
|
|
|
|
|
args: { limit?; offset?; fieldsSet?: Set<string> } = {} |
|
|
|
|
|
|
|
) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
const { where, sort, ...rest } = this._getListArgs(args as any); |
|
|
|
const { where, sort, ...rest } = this._getListArgs(args as any); |
|
|
|
// todo: get only required fields
|
|
|
|
// todo: get only required fields
|
|
|
@ -419,7 +475,11 @@ class BaseModelSqlv2 { |
|
|
|
const parentTn = this.getTnPath(parentTable); |
|
|
|
const parentTn = this.getTnPath(parentTable); |
|
|
|
|
|
|
|
|
|
|
|
const qb = this.dbDriver(childTn); |
|
|
|
const qb = this.dbDriver(childTn); |
|
|
|
await childModel.selectObject({ qb }); |
|
|
|
await childModel.selectObject({ |
|
|
|
|
|
|
|
qb, |
|
|
|
|
|
|
|
extractPkAndPv: true, |
|
|
|
|
|
|
|
fieldsSet: args.fieldsSet, |
|
|
|
|
|
|
|
}); |
|
|
|
await this.applySortAndFilter({ table: childTable, where, qb, sort }); |
|
|
|
await this.applySortAndFilter({ table: childTable, where, qb, sort }); |
|
|
|
|
|
|
|
|
|
|
|
const childQb = this.dbDriver.queryBuilder().from( |
|
|
|
const childQb = this.dbDriver.queryBuilder().from( |
|
|
@ -447,6 +507,8 @@ class BaseModelSqlv2 { |
|
|
|
.as('list') |
|
|
|
.as('list') |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// console.log(childQb.toQuery())
|
|
|
|
|
|
|
|
|
|
|
|
const children = await this.execAndParse(childQb, childTable); |
|
|
|
const children = await this.execAndParse(childQb, childTable); |
|
|
|
const proto = await ( |
|
|
|
const proto = await ( |
|
|
|
await Model.getBaseModelSQL({ |
|
|
|
await Model.getBaseModelSQL({ |
|
|
@ -532,7 +594,10 @@ class BaseModelSqlv2 { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async hmList({ colId, id }, args: { limit?; offset? } = {}) { |
|
|
|
async hmList( |
|
|
|
|
|
|
|
{ colId, id }, |
|
|
|
|
|
|
|
args: { limit?; offset?; fieldSet?: Set<string> } = {} |
|
|
|
|
|
|
|
) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
const { where, sort, ...rest } = this._getListArgs(args as any); |
|
|
|
const { where, sort, ...rest } = this._getListArgs(args as any); |
|
|
|
// todo: get only required fields
|
|
|
|
// todo: get only required fields
|
|
|
@ -572,7 +637,7 @@ class BaseModelSqlv2 { |
|
|
|
qb.limit(+rest?.limit || 25); |
|
|
|
qb.limit(+rest?.limit || 25); |
|
|
|
qb.offset(+rest?.offset || 0); |
|
|
|
qb.offset(+rest?.offset || 0); |
|
|
|
|
|
|
|
|
|
|
|
await childModel.selectObject({ qb }); |
|
|
|
await childModel.selectObject({ qb, fieldsSet: args.fieldSet }); |
|
|
|
|
|
|
|
|
|
|
|
const children = await this.execAndParse(qb, childTable); |
|
|
|
const children = await this.execAndParse(qb, childTable); |
|
|
|
|
|
|
|
|
|
|
@ -631,7 +696,7 @@ class BaseModelSqlv2 { |
|
|
|
|
|
|
|
|
|
|
|
public async multipleMmList( |
|
|
|
public async multipleMmList( |
|
|
|
{ colId, parentIds }, |
|
|
|
{ colId, parentIds }, |
|
|
|
args: { limit?; offset? } = {} |
|
|
|
args: { limit?; offset?; fieldsSet?: Set<string> } = {} |
|
|
|
) { |
|
|
|
) { |
|
|
|
const { where, sort, ...rest } = this._getListArgs(args as any); |
|
|
|
const { where, sort, ...rest } = this._getListArgs(args as any); |
|
|
|
const relColumn = (await this.model.getColumns()).find( |
|
|
|
const relColumn = (await this.model.getColumns()).find( |
|
|
@ -664,7 +729,7 @@ class BaseModelSqlv2 { |
|
|
|
|
|
|
|
|
|
|
|
const qb = this.dbDriver(rtn).join(vtn, `${vtn}.${vrcn}`, `${rtn}.${rcn}`); |
|
|
|
const qb = this.dbDriver(rtn).join(vtn, `${vtn}.${vrcn}`, `${rtn}.${rcn}`); |
|
|
|
|
|
|
|
|
|
|
|
await childModel.selectObject({ qb }); |
|
|
|
await childModel.selectObject({ qb, fieldsSet: args.fieldsSet }); |
|
|
|
|
|
|
|
|
|
|
|
await this.applySortAndFilter({ table: childTable, where, qb, sort }); |
|
|
|
await this.applySortAndFilter({ table: childTable, where, qb, sort }); |
|
|
|
|
|
|
|
|
|
|
@ -710,7 +775,10 @@ class BaseModelSqlv2 { |
|
|
|
return parentIds.map((id) => gs[id] || []); |
|
|
|
return parentIds.map((id) => gs[id] || []); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async mmList({ colId, parentId }, args: { limit?; offset? } = {}) { |
|
|
|
public async mmList( |
|
|
|
|
|
|
|
{ colId, parentId }, |
|
|
|
|
|
|
|
args: { limit?; offset?; fieldsSet?: Set<string> } = {} |
|
|
|
|
|
|
|
) { |
|
|
|
const { where, sort, ...rest } = this._getListArgs(args as any); |
|
|
|
const { where, sort, ...rest } = this._getListArgs(args as any); |
|
|
|
const relColumn = (await this.model.getColumns()).find( |
|
|
|
const relColumn = (await this.model.getColumns()).find( |
|
|
|
(c) => c.id === colId |
|
|
|
(c) => c.id === colId |
|
|
@ -750,7 +818,7 @@ class BaseModelSqlv2 { |
|
|
|
.where(_wherePk(parentTable.primaryKeys, parentId)) |
|
|
|
.where(_wherePk(parentTable.primaryKeys, parentId)) |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
await childModel.selectObject({ qb }); |
|
|
|
await childModel.selectObject({ qb, fieldsSet: args.fieldsSet }); |
|
|
|
|
|
|
|
|
|
|
|
await this.applySortAndFilter({ table: childTable, where, qb, sort }); |
|
|
|
await this.applySortAndFilter({ table: childTable, where, qb, sort }); |
|
|
|
|
|
|
|
|
|
|
@ -1224,7 +1292,11 @@ class BaseModelSqlv2 { |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private async getSelectQueryBuilderForFormula(column: Column<any>) { |
|
|
|
private async getSelectQueryBuilderForFormula( |
|
|
|
|
|
|
|
column: Column<any>, |
|
|
|
|
|
|
|
tableAlias?: string, |
|
|
|
|
|
|
|
validateFormula = false |
|
|
|
|
|
|
|
) { |
|
|
|
const formula = await column.getColOptions<FormulaColumn>(); |
|
|
|
const formula = await column.getColOptions<FormulaColumn>(); |
|
|
|
if (formula.error) throw new Error(`Formula error: ${formula.error}`); |
|
|
|
if (formula.error) throw new Error(`Formula error: ${formula.error}`); |
|
|
|
const qb = await formulaQueryBuilderv2( |
|
|
|
const qb = await formulaQueryBuilderv2( |
|
|
@ -1232,7 +1304,10 @@ class BaseModelSqlv2 { |
|
|
|
null, |
|
|
|
null, |
|
|
|
this.dbDriver, |
|
|
|
this.dbDriver, |
|
|
|
this.model, |
|
|
|
this.model, |
|
|
|
column |
|
|
|
column, |
|
|
|
|
|
|
|
{}, |
|
|
|
|
|
|
|
tableAlias, |
|
|
|
|
|
|
|
validateFormula |
|
|
|
); |
|
|
|
); |
|
|
|
return qb; |
|
|
|
return qb; |
|
|
|
} |
|
|
|
} |
|
|
@ -1376,6 +1451,7 @@ class BaseModelSqlv2 { |
|
|
|
{ |
|
|
|
{ |
|
|
|
// limit: ids.length,
|
|
|
|
// limit: ids.length,
|
|
|
|
where: `(${pCol.column_name},in,${ids.join(',')})`, |
|
|
|
where: `(${pCol.column_name},in,${ids.join(',')})`, |
|
|
|
|
|
|
|
fieldsSet: (readLoader as any).args?.fieldsSet, |
|
|
|
}, |
|
|
|
}, |
|
|
|
true |
|
|
|
true |
|
|
|
); |
|
|
|
); |
|
|
@ -1388,13 +1464,15 @@ class BaseModelSqlv2 { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// defining HasMany count method within GQL Type class
|
|
|
|
// defining HasMany count method within GQL Type class
|
|
|
|
proto[column.title] = async function () { |
|
|
|
proto[column.title] = async function (args?: any) { |
|
|
|
if ( |
|
|
|
if ( |
|
|
|
this?.[cCol?.title] === null || |
|
|
|
this?.[cCol?.title] === null || |
|
|
|
this?.[cCol?.title] === undefined |
|
|
|
this?.[cCol?.title] === undefined |
|
|
|
) |
|
|
|
) |
|
|
|
return null; |
|
|
|
return null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(readLoader as any).args = args; |
|
|
|
|
|
|
|
|
|
|
|
return await readLoader.load(this?.[cCol?.title]); |
|
|
|
return await readLoader.load(this?.[cCol?.title]); |
|
|
|
}; |
|
|
|
}; |
|
|
|
// todo : handle mm
|
|
|
|
// todo : handle mm
|
|
|
@ -1422,7 +1500,7 @@ class BaseModelSqlv2 { |
|
|
|
this.config.limitMin |
|
|
|
this.config.limitMin |
|
|
|
); |
|
|
|
); |
|
|
|
obj.offset = Math.max(+(args.offset || args.o) || 0, 0); |
|
|
|
obj.offset = Math.max(+(args.offset || args.o) || 0, 0); |
|
|
|
obj.fields = args.fields || args.f || '*'; |
|
|
|
obj.fields = args.fields || args.f; |
|
|
|
obj.sort = args.sort || args.s; |
|
|
|
obj.sort = args.sort || args.s; |
|
|
|
return obj; |
|
|
|
return obj; |
|
|
|
} |
|
|
|
} |
|
|
@ -1437,16 +1515,70 @@ class BaseModelSqlv2 { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// todo:
|
|
|
|
|
|
|
|
// pass view id as argument
|
|
|
|
|
|
|
|
// add option to get only pk and pv
|
|
|
|
public async selectObject({ |
|
|
|
public async selectObject({ |
|
|
|
qb, |
|
|
|
qb, |
|
|
|
columns: _columns, |
|
|
|
columns: _columns, |
|
|
|
|
|
|
|
fields: _fields, |
|
|
|
|
|
|
|
extractPkAndPv, |
|
|
|
|
|
|
|
viewId, |
|
|
|
|
|
|
|
fieldsSet, |
|
|
|
|
|
|
|
alias, |
|
|
|
|
|
|
|
validateFormula, |
|
|
|
}: { |
|
|
|
}: { |
|
|
|
|
|
|
|
fieldsSet?: Set<string>; |
|
|
|
qb: Knex.QueryBuilder; |
|
|
|
qb: Knex.QueryBuilder; |
|
|
|
columns?: Column[]; |
|
|
|
columns?: Column[]; |
|
|
|
|
|
|
|
fields?: string[] | string; |
|
|
|
|
|
|
|
extractPkAndPv?: boolean; |
|
|
|
|
|
|
|
viewId?: string; |
|
|
|
|
|
|
|
alias?: string; |
|
|
|
|
|
|
|
validateFormula?: boolean; |
|
|
|
}): Promise<void> { |
|
|
|
}): Promise<void> { |
|
|
|
|
|
|
|
let viewOrTableColumns: Column[] | { fk_column_id?: string }[]; |
|
|
|
|
|
|
|
|
|
|
|
const res = {}; |
|
|
|
const res = {}; |
|
|
|
const columns = _columns ?? (await this.model.getColumns()); |
|
|
|
let view: View; |
|
|
|
for (const column of columns) { |
|
|
|
let fields: string[]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fieldsSet?.size) { |
|
|
|
|
|
|
|
viewOrTableColumns = _columns || (await this.model.getColumns()); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
view = await View.get(viewId); |
|
|
|
|
|
|
|
const viewColumns = viewId && (await View.getColumns(viewId)); |
|
|
|
|
|
|
|
fields = Array.isArray(_fields) ? _fields : _fields?.split(','); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// const columns = _columns ?? (await this.model.getColumns());
|
|
|
|
|
|
|
|
// for (const column of columns) {
|
|
|
|
|
|
|
|
viewOrTableColumns = |
|
|
|
|
|
|
|
_columns || viewColumns || (await this.model.getColumns()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
for (const viewOrTableColumn of viewOrTableColumns) { |
|
|
|
|
|
|
|
const column = |
|
|
|
|
|
|
|
viewOrTableColumn instanceof Column |
|
|
|
|
|
|
|
? viewOrTableColumn |
|
|
|
|
|
|
|
: await Column.get({ |
|
|
|
|
|
|
|
colId: (viewOrTableColumn as GridViewColumn).fk_column_id, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
// hide if column marked as hidden in view
|
|
|
|
|
|
|
|
// of if column is system field and system field is hidden
|
|
|
|
|
|
|
|
if ( |
|
|
|
|
|
|
|
fieldsSet |
|
|
|
|
|
|
|
? !fieldsSet.has(column.title) |
|
|
|
|
|
|
|
: !extractPkAndPv && |
|
|
|
|
|
|
|
!(viewOrTableColumn instanceof Column) && |
|
|
|
|
|
|
|
(!(viewOrTableColumn as GridViewColumn)?.show || |
|
|
|
|
|
|
|
(!view?.show_system_fields && |
|
|
|
|
|
|
|
column.uidt !== UITypes.ForeignKey && |
|
|
|
|
|
|
|
!column.pk && |
|
|
|
|
|
|
|
isSystemColumn(column))) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!checkColumnRequired(column, fields, extractPkAndPv)) continue; |
|
|
|
|
|
|
|
|
|
|
|
switch (column.uidt) { |
|
|
|
switch (column.uidt) { |
|
|
|
case 'LinkToAnotherRecord': |
|
|
|
case 'LinkToAnotherRecord': |
|
|
|
case 'Lookup': |
|
|
|
case 'Lookup': |
|
|
@ -1466,7 +1598,9 @@ class BaseModelSqlv2 { |
|
|
|
case UITypes.Formula: |
|
|
|
case UITypes.Formula: |
|
|
|
try { |
|
|
|
try { |
|
|
|
const selectQb = await this.getSelectQueryBuilderForFormula( |
|
|
|
const selectQb = await this.getSelectQueryBuilderForFormula( |
|
|
|
qrValueColumn |
|
|
|
qrValueColumn, |
|
|
|
|
|
|
|
alias, |
|
|
|
|
|
|
|
validateFormula |
|
|
|
); |
|
|
|
); |
|
|
|
qb.select({ |
|
|
|
qb.select({ |
|
|
|
[column.column_name]: selectQb.builder, |
|
|
|
[column.column_name]: selectQb.builder, |
|
|
@ -1498,7 +1632,9 @@ class BaseModelSqlv2 { |
|
|
|
case UITypes.Formula: |
|
|
|
case UITypes.Formula: |
|
|
|
try { |
|
|
|
try { |
|
|
|
const selectQb = await this.getSelectQueryBuilderForFormula( |
|
|
|
const selectQb = await this.getSelectQueryBuilderForFormula( |
|
|
|
barcodeValueColumn |
|
|
|
barcodeValueColumn, |
|
|
|
|
|
|
|
alias, |
|
|
|
|
|
|
|
validateFormula |
|
|
|
); |
|
|
|
); |
|
|
|
qb.select({ |
|
|
|
qb.select({ |
|
|
|
[column.column_name]: selectQb.builder, |
|
|
|
[column.column_name]: selectQb.builder, |
|
|
@ -1521,7 +1657,9 @@ class BaseModelSqlv2 { |
|
|
|
{ |
|
|
|
{ |
|
|
|
try { |
|
|
|
try { |
|
|
|
const selectQb = await this.getSelectQueryBuilderForFormula( |
|
|
|
const selectQb = await this.getSelectQueryBuilderForFormula( |
|
|
|
column |
|
|
|
column, |
|
|
|
|
|
|
|
alias, |
|
|
|
|
|
|
|
validateFormula |
|
|
|
); |
|
|
|
); |
|
|
|
qb.select( |
|
|
|
qb.select( |
|
|
|
this.dbDriver.raw(`?? as ??`, [ |
|
|
|
this.dbDriver.raw(`?? as ??`, [ |
|
|
@ -1529,7 +1667,8 @@ class BaseModelSqlv2 { |
|
|
|
sanitize(column.title), |
|
|
|
sanitize(column.title), |
|
|
|
]) |
|
|
|
]) |
|
|
|
); |
|
|
|
); |
|
|
|
} catch { |
|
|
|
} catch (e) { |
|
|
|
|
|
|
|
console.log(e); |
|
|
|
// return dummy select
|
|
|
|
// return dummy select
|
|
|
|
qb.select( |
|
|
|
qb.select( |
|
|
|
this.dbDriver.raw(`'ERR' as ??`, [sanitize(column.title)]) |
|
|
|
this.dbDriver.raw(`'ERR' as ??`, [sanitize(column.title)]) |
|
|
@ -1544,6 +1683,7 @@ class BaseModelSqlv2 { |
|
|
|
// tn: this.title,
|
|
|
|
// tn: this.title,
|
|
|
|
knex: this.dbDriver, |
|
|
|
knex: this.dbDriver, |
|
|
|
// column,
|
|
|
|
// column,
|
|
|
|
|
|
|
|
alias, |
|
|
|
columnOptions: (await column.getColOptions()) as RollupColumn, |
|
|
|
columnOptions: (await column.getColOptions()) as RollupColumn, |
|
|
|
}) |
|
|
|
}) |
|
|
|
).builder.as(sanitize(column.title)) |
|
|
|
).builder.as(sanitize(column.title)) |
|
|
@ -1551,7 +1691,7 @@ class BaseModelSqlv2 { |
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
res[sanitize(column.title || column.column_name)] = sanitize( |
|
|
|
res[sanitize(column.title || column.column_name)] = sanitize( |
|
|
|
`${this.model.table_name}.${column.column_name}` |
|
|
|
`${alias || this.model.table_name}.${column.column_name}` |
|
|
|
); |
|
|
|
); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -2700,7 +2840,7 @@ class BaseModelSqlv2 { |
|
|
|
qb.limit(+rest?.limit || 25); |
|
|
|
qb.limit(+rest?.limit || 25); |
|
|
|
qb.offset(+rest?.offset || 0); |
|
|
|
qb.offset(+rest?.offset || 0); |
|
|
|
|
|
|
|
|
|
|
|
await this.selectObject({ qb }); |
|
|
|
await this.selectObject({ qb, extractPkAndPv: true }); |
|
|
|
|
|
|
|
|
|
|
|
// todo: refactor and move to a method (applyFilterAndSort)
|
|
|
|
// todo: refactor and move to a method (applyFilterAndSort)
|
|
|
|
const aliasColObjMap = await this.model.getAliasColObjMap(); |
|
|
|
const aliasColObjMap = await this.model.getAliasColObjMap(); |
|
|
@ -3118,4 +3258,8 @@ function getCompositePk(primaryKeys: Column[], row) { |
|
|
|
return primaryKeys.map((c) => row[c.title]).join('___'); |
|
|
|
return primaryKeys.map((c) => row[c.title]).join('___'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function haveFormulaColumn(columns: Column[]) { |
|
|
|
|
|
|
|
return columns.some((c) => c.uidt === UITypes.Formula); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export { BaseModelSqlv2 }; |
|
|
|
export { BaseModelSqlv2 }; |
|
|
|