|
|
@ -1897,7 +1897,7 @@ class BaseModelSqlv2 { |
|
|
|
// .where(childTable.primaryKey.cn, cid)
|
|
|
|
// .where(childTable.primaryKey.cn, cid)
|
|
|
|
.where(_wherePk(childTable.primaryKeys, cid)) |
|
|
|
.where(_wherePk(childTable.primaryKeys, cid)) |
|
|
|
.whereNotNull(cn), |
|
|
|
.whereNotNull(cn), |
|
|
|
).orWhereNull(rcn); |
|
|
|
); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
if (+rest?.shuffle) { |
|
|
|
if (+rest?.shuffle) { |
|
|
@ -2107,7 +2107,7 @@ class BaseModelSqlv2 { |
|
|
|
] = async function (args): Promise<any> { |
|
|
|
] = async function (args): Promise<any> { |
|
|
|
(listLoader as any).args = args; |
|
|
|
(listLoader as any).args = args; |
|
|
|
return listLoader.load( |
|
|
|
return listLoader.load( |
|
|
|
getCompositePk(self.model.primaryKeys, this), |
|
|
|
getCompositePkValue(self.model.primaryKeys, this), |
|
|
|
); |
|
|
|
); |
|
|
|
}; |
|
|
|
}; |
|
|
|
} else if (colOptions.type === 'mm') { |
|
|
|
} else if (colOptions.type === 'mm') { |
|
|
@ -2148,7 +2148,7 @@ class BaseModelSqlv2 { |
|
|
|
] = async function (args): Promise<any> { |
|
|
|
] = async function (args): Promise<any> { |
|
|
|
(listLoader as any).args = args; |
|
|
|
(listLoader as any).args = args; |
|
|
|
return await listLoader.load( |
|
|
|
return await listLoader.load( |
|
|
|
getCompositePk(self.model.primaryKeys, this), |
|
|
|
getCompositePkValue(self.model.primaryKeys, this), |
|
|
|
); |
|
|
|
); |
|
|
|
}; |
|
|
|
}; |
|
|
|
} else if (colOptions.type === 'bt') { |
|
|
|
} else if (colOptions.type === 'bt') { |
|
|
@ -2370,7 +2370,7 @@ class BaseModelSqlv2 { |
|
|
|
] = async function (args): Promise<any> { |
|
|
|
] = async function (args): Promise<any> { |
|
|
|
(listLoader as any).args = args; |
|
|
|
(listLoader as any).args = args; |
|
|
|
return listLoader.load( |
|
|
|
return listLoader.load( |
|
|
|
getCompositePk(self.model.primaryKeys, this), |
|
|
|
getCompositePkValue(self.model.primaryKeys, this), |
|
|
|
); |
|
|
|
); |
|
|
|
}; |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
@ -3124,7 +3124,7 @@ class BaseModelSqlv2 { |
|
|
|
|
|
|
|
|
|
|
|
await this.prepareNocoData(insertObj, true, cookie); |
|
|
|
await this.prepareNocoData(insertObj, true, cookie); |
|
|
|
|
|
|
|
|
|
|
|
await Promise.all(preInsertOps.map((f) => f(this.dbDriver))); |
|
|
|
await this.runOps(preInsertOps.map((f) => f())); |
|
|
|
|
|
|
|
|
|
|
|
let response; |
|
|
|
let response; |
|
|
|
const query = this.dbDriver(this.tnPath).insert(insertObj); |
|
|
|
const query = this.dbDriver(this.tnPath).insert(insertObj); |
|
|
@ -3206,7 +3206,7 @@ class BaseModelSqlv2 { |
|
|
|
} |
|
|
|
} |
|
|
|
rowId = this.extractCompositePK({ ai, ag, rowId, insertObj }); |
|
|
|
rowId = this.extractCompositePK({ ai, ag, rowId, insertObj }); |
|
|
|
|
|
|
|
|
|
|
|
await Promise.all(postInsertOps.map((f) => f(rowId))); |
|
|
|
await this.runOps(postInsertOps.map((f) => f(rowId))); |
|
|
|
|
|
|
|
|
|
|
|
if (rowId !== null && rowId !== undefined) { |
|
|
|
if (rowId !== null && rowId !== undefined) { |
|
|
|
response = await this.readRecord({ |
|
|
|
response = await this.readRecord({ |
|
|
@ -3254,7 +3254,20 @@ class BaseModelSqlv2 { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
rowId = pkObj; |
|
|
|
rowId = pkObj; |
|
|
|
|
|
|
|
} else if ( |
|
|
|
|
|
|
|
!ai && |
|
|
|
|
|
|
|
!ag && |
|
|
|
|
|
|
|
(force || this.model.primaryKeys?.length > 1 || this.isSnowflake) |
|
|
|
|
|
|
|
) { |
|
|
|
|
|
|
|
// handle if primary key is not ai or ag
|
|
|
|
|
|
|
|
const pkObj = {}; |
|
|
|
|
|
|
|
for (const pk of this.model.primaryKeys) { |
|
|
|
|
|
|
|
const key = pk.title; |
|
|
|
|
|
|
|
pkObj[key] = insertObj[pk.column_name] ?? null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
rowId = pkObj; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return rowId; |
|
|
|
return rowId; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3267,8 +3280,8 @@ class BaseModelSqlv2 { |
|
|
|
data: Record<string, any>; |
|
|
|
data: Record<string, any>; |
|
|
|
insertObj: Record<string, any>; |
|
|
|
insertObj: Record<string, any>; |
|
|
|
}) { |
|
|
|
}) { |
|
|
|
const postInsertOps: ((rowId: any, trx?: any) => Promise<void>)[] = []; |
|
|
|
const postInsertOps: ((rowId: any) => Promise<string>)[] = []; |
|
|
|
const preInsertOps: ((trx?: any) => Promise<void>)[] = []; |
|
|
|
const preInsertOps: (() => Promise<string>)[] = []; |
|
|
|
for (const col of nestedCols) { |
|
|
|
for (const col of nestedCols) { |
|
|
|
if (col.title in data) { |
|
|
|
if (col.title in data) { |
|
|
|
const colOptions = await col.getColOptions<LinkToAnotherRecordColumn>(); |
|
|
|
const colOptions = await col.getColOptions<LinkToAnotherRecordColumn>(); |
|
|
@ -3302,15 +3315,16 @@ class BaseModelSqlv2 { |
|
|
|
|
|
|
|
|
|
|
|
if (isBt) { |
|
|
|
if (isBt) { |
|
|
|
// todo: unlink the ref record
|
|
|
|
// todo: unlink the ref record
|
|
|
|
preInsertOps.push(async (trx: any = this.dbDriver) => { |
|
|
|
preInsertOps.push(async () => { |
|
|
|
await trx(this.getTnPath(childModel.table_name)) |
|
|
|
return this.dbDriver(this.getTnPath(childModel.table_name)) |
|
|
|
.update({ |
|
|
|
.update({ |
|
|
|
[childCol.column_name]: null, |
|
|
|
[childCol.column_name]: null, |
|
|
|
}) |
|
|
|
}) |
|
|
|
.where( |
|
|
|
.where( |
|
|
|
childCol.column_name, |
|
|
|
childCol.column_name, |
|
|
|
nestedData[childModel.primaryKey.title], |
|
|
|
nestedData[childModel.primaryKey.title], |
|
|
|
); |
|
|
|
) |
|
|
|
|
|
|
|
.toQuery(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
if (typeof nestedData !== 'object') continue; |
|
|
|
if (typeof nestedData !== 'object') continue; |
|
|
@ -3318,15 +3332,16 @@ class BaseModelSqlv2 { |
|
|
|
const parentCol = await colOptions.getParentColumn(); |
|
|
|
const parentCol = await colOptions.getParentColumn(); |
|
|
|
insertObj[childCol.column_name] = nestedData?.[parentCol.title]; |
|
|
|
insertObj[childCol.column_name] = nestedData?.[parentCol.title]; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
postInsertOps.push(async (rowId, trx: any = this.dbDriver) => { |
|
|
|
postInsertOps.push(async (rowId) => { |
|
|
|
await trx(this.getTnPath(childModel.table_name)) |
|
|
|
return this.dbDriver(this.getTnPath(childModel.table_name)) |
|
|
|
.update({ |
|
|
|
.update({ |
|
|
|
[childCol.column_name]: rowId, |
|
|
|
[childCol.column_name]: rowId, |
|
|
|
}) |
|
|
|
}) |
|
|
|
.where( |
|
|
|
.where( |
|
|
|
childModel.primaryKey.column_name, |
|
|
|
childModel.primaryKey.column_name, |
|
|
|
nestedData[childModel.primaryKey.title], |
|
|
|
nestedData[childModel.primaryKey.title], |
|
|
|
); |
|
|
|
) |
|
|
|
|
|
|
|
.toQuery(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -3338,47 +3353,38 @@ class BaseModelSqlv2 { |
|
|
|
const childModel = await childCol.getModel(); |
|
|
|
const childModel = await childCol.getModel(); |
|
|
|
await childModel.getColumns(); |
|
|
|
await childModel.getColumns(); |
|
|
|
|
|
|
|
|
|
|
|
postInsertOps.push( |
|
|
|
postInsertOps.push(async (rowId) => { |
|
|
|
async ( |
|
|
|
return this.dbDriver(this.getTnPath(childModel.table_name)) |
|
|
|
rowId, |
|
|
|
.update({ |
|
|
|
// todo: use transaction type
|
|
|
|
[childCol.column_name]: rowId, |
|
|
|
trx: any = this.dbDriver, |
|
|
|
}) |
|
|
|
) => { |
|
|
|
.whereIn( |
|
|
|
await trx(this.getTnPath(childModel.table_name)) |
|
|
|
childModel.primaryKey.column_name, |
|
|
|
.update({ |
|
|
|
nestedData?.map((r) => r[childModel.primaryKey.title]), |
|
|
|
[childCol.column_name]: rowId, |
|
|
|
) |
|
|
|
}) |
|
|
|
.toQuery(); |
|
|
|
.whereIn( |
|
|
|
}); |
|
|
|
childModel.primaryKey.column_name, |
|
|
|
|
|
|
|
nestedData?.map((r) => r[childModel.primaryKey.title]), |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
case RelationTypes.MANY_TO_MANY: { |
|
|
|
case RelationTypes.MANY_TO_MANY: { |
|
|
|
if (!Array.isArray(nestedData)) continue; |
|
|
|
if (!Array.isArray(nestedData)) continue; |
|
|
|
postInsertOps.push( |
|
|
|
postInsertOps.push(async (rowId) => { |
|
|
|
async ( |
|
|
|
const parentModel = await colOptions |
|
|
|
rowId, |
|
|
|
.getParentColumn() |
|
|
|
// todo: use transaction type
|
|
|
|
.then((c) => c.getModel()); |
|
|
|
trx: any = this.dbDriver, |
|
|
|
await parentModel.getColumns(); |
|
|
|
) => { |
|
|
|
const parentMMCol = await colOptions.getMMParentColumn(); |
|
|
|
const parentModel = await colOptions |
|
|
|
const childMMCol = await colOptions.getMMChildColumn(); |
|
|
|
.getParentColumn() |
|
|
|
const mmModel = await colOptions.getMMModel(); |
|
|
|
.then((c) => c.getModel()); |
|
|
|
|
|
|
|
await parentModel.getColumns(); |
|
|
|
const rows = nestedData.map((r) => ({ |
|
|
|
const parentMMCol = await colOptions.getMMParentColumn(); |
|
|
|
[parentMMCol.column_name]: r[parentModel.primaryKey.title], |
|
|
|
const childMMCol = await colOptions.getMMChildColumn(); |
|
|
|
[childMMCol.column_name]: rowId, |
|
|
|
const mmModel = await colOptions.getMMModel(); |
|
|
|
})); |
|
|
|
|
|
|
|
return this.dbDriver(this.getTnPath(mmModel.table_name)) |
|
|
|
const rows = nestedData.map((r) => ({ |
|
|
|
.insert(rows) |
|
|
|
[parentMMCol.column_name]: r[parentModel.primaryKey.title], |
|
|
|
.toQuery(); |
|
|
|
[childMMCol.column_name]: rowId, |
|
|
|
}); |
|
|
|
})); |
|
|
|
|
|
|
|
await trx(this.getTnPath(mmModel.table_name)).insert(rows); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -3410,8 +3416,8 @@ class BaseModelSqlv2 { |
|
|
|
try { |
|
|
|
try { |
|
|
|
// TODO: ag column handling for raw bulk insert
|
|
|
|
// TODO: ag column handling for raw bulk insert
|
|
|
|
const insertDatas = raw ? datas : []; |
|
|
|
const insertDatas = raw ? datas : []; |
|
|
|
let postInsertOps: ((rowId: any, trx?: any) => Promise<void>)[] = []; |
|
|
|
let postInsertOps: ((rowId: any) => Promise<string>)[] = []; |
|
|
|
let preInsertOps: ((trx?: any) => Promise<void>)[] = []; |
|
|
|
let preInsertOps: (() => Promise<string>)[] = []; |
|
|
|
let aiPkCol: Column; |
|
|
|
let aiPkCol: Column; |
|
|
|
let agPkCol: Column; |
|
|
|
let agPkCol: Column; |
|
|
|
|
|
|
|
|
|
|
@ -3596,7 +3602,10 @@ class BaseModelSqlv2 { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
await Promise.all(preInsertOps.map((f) => f(trx))); |
|
|
|
await this.runOps( |
|
|
|
|
|
|
|
preInsertOps.map((f) => f()), |
|
|
|
|
|
|
|
trx, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
let responses; |
|
|
|
let responses; |
|
|
|
|
|
|
|
|
|
|
@ -3661,7 +3670,10 @@ class BaseModelSqlv2 { |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
await Promise.all(postInsertOps.map((f) => f(rowId, trx))); |
|
|
|
await this.runOps( |
|
|
|
|
|
|
|
postInsertOps.map((f) => f(rowId)), |
|
|
|
|
|
|
|
trx, |
|
|
|
|
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
await trx.commit(); |
|
|
|
await trx.commit(); |
|
|
@ -3728,7 +3740,10 @@ class BaseModelSqlv2 { |
|
|
|
const pkAndData: { pk: any; data: any }[] = []; |
|
|
|
const pkAndData: { pk: any; data: any }[] = []; |
|
|
|
const readChunkSize = 100; |
|
|
|
const readChunkSize = 100; |
|
|
|
for (const [i, d] of updateDatas.entries()) { |
|
|
|
for (const [i, d] of updateDatas.entries()) { |
|
|
|
const pkValues = this._extractPksValues(d); |
|
|
|
const pkValues = getCompositePkValue( |
|
|
|
|
|
|
|
this.model.primaryKeys, |
|
|
|
|
|
|
|
this._extractPksValues(d), |
|
|
|
|
|
|
|
); |
|
|
|
if (!pkValues) { |
|
|
|
if (!pkValues) { |
|
|
|
// throw or skip if no pk provided
|
|
|
|
// throw or skip if no pk provided
|
|
|
|
if (throwExceptionIfNotExist) { |
|
|
|
if (throwExceptionIfNotExist) { |
|
|
@ -3954,7 +3969,10 @@ class BaseModelSqlv2 { |
|
|
|
const pkAndData: { pk: any; data: any }[] = []; |
|
|
|
const pkAndData: { pk: any; data: any }[] = []; |
|
|
|
const readChunkSize = 100; |
|
|
|
const readChunkSize = 100; |
|
|
|
for (const [i, d] of deleteIds.entries()) { |
|
|
|
for (const [i, d] of deleteIds.entries()) { |
|
|
|
const pkValues = this._extractPksValues(d); |
|
|
|
const pkValues = getCompositePkValue( |
|
|
|
|
|
|
|
this.model.primaryKeys, |
|
|
|
|
|
|
|
this._extractPksValues(d), |
|
|
|
|
|
|
|
); |
|
|
|
if (!pkValues) { |
|
|
|
if (!pkValues) { |
|
|
|
// throw or skip if no pk provided
|
|
|
|
// throw or skip if no pk provided
|
|
|
|
if (throwExceptionIfNotExist) { |
|
|
|
if (throwExceptionIfNotExist) { |
|
|
@ -5248,6 +5266,13 @@ class BaseModelSqlv2 { |
|
|
|
return data; |
|
|
|
return data; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async runOps(ops: Promise<string>[], trx = this.dbDriver) { |
|
|
|
|
|
|
|
const queries = await Promise.all(ops); |
|
|
|
|
|
|
|
for (const query of queries) { |
|
|
|
|
|
|
|
await trx.raw(query); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected async substituteColumnIdsWithColumnTitles( |
|
|
|
protected async substituteColumnIdsWithColumnTitles( |
|
|
|
data: Record<string, any>[], |
|
|
|
data: Record<string, any>[], |
|
|
|
dependencyColumns?: Column[], |
|
|
|
dependencyColumns?: Column[], |
|
|
@ -6863,8 +6888,9 @@ export function _wherePk(primaryKeys: Column[], id: unknown | unknown[]) { |
|
|
|
return where; |
|
|
|
return where; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function getCompositePk(primaryKeys: Column[], row) { |
|
|
|
export function getCompositePkValue(primaryKeys: Column[], row) { |
|
|
|
return primaryKeys.map((c) => row[c.title]).join('___'); |
|
|
|
if (typeof row !== 'object') return row; |
|
|
|
|
|
|
|
return primaryKeys.map((c) => row[c.title] ?? row[c.column_name]).join('___'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function haveFormulaColumn(columns: Column[]) { |
|
|
|
export function haveFormulaColumn(columns: Column[]) { |
|
|
|