Browse Source

fix: bulkDelete with composite keys

pull/8371/head
mertmit 5 months ago
parent
commit
5441bcb4c4
  1. 66
      packages/nc-gui/composables/useData.ts
  2. 1
      packages/nocodb-sdk/src/lib/sqlUi/SnowflakeUi.ts
  3. 21
      packages/nocodb/src/db/BaseModelSqlv2.ts
  4. 1
      packages/nocodb/src/db/sql-mgr/code/models/xc/ModelXcMetaSnowflake.ts

66
packages/nc-gui/composables/useData.ts

@ -477,8 +477,8 @@ export function useData(args: {
try {
await $api.dbTableRow.nestedAdd(
NOCO,
base.value.title as string,
metaValue?.title as string,
base.value.id as string,
metaValue?.id as string,
encodeURIComponent(rowId),
type as RelationTypes,
column.title as string,
@ -630,23 +630,25 @@ export function useData(args: {
async function deleteSelectedRows() {
let row = formattedData.value.length
let removedRowsData: Record<string, any>[] = []
const removedRowsData: Record<string, any>[] = []
let compositePrimaryKey = ''
while (row--) {
const { row: rowObj, rowMeta } = formattedData.value[row] as Record<string, any>
const { row: rowData, rowMeta } = formattedData.value[row] as Record<string, any>
if (!rowMeta.selected) {
continue
}
if (!rowMeta.new) {
const extractedPk = extractPk(meta?.value?.columns as ColumnType[])
const compositePkValue = extractPkFromRow(rowObj, meta?.value?.columns as ColumnType[])
const compositePkValue = extractPkFromRow(rowData, meta?.value?.columns as ColumnType[])
const pkData = rowPkData(rowData, meta?.value?.columns as ColumnType[])
if (extractedPk && compositePkValue) {
if (!compositePrimaryKey) compositePrimaryKey = extractedPk
removedRowsData.push({
[compositePrimaryKey]: compositePkValue as string,
pkData,
row: clone(formattedData.value[row]) as Row,
rowIndex: row as number,
})
@ -670,20 +672,7 @@ export function useData(args: {
rowObj.row = clone(fullRecord)
}
const removedRowIds: Record<string, any>[] = await bulkDeleteRows(
removedRowsData.map((row) => ({ [compositePrimaryKey]: row[compositePrimaryKey] as string })),
)
if (Array.isArray(removedRowIds)) {
const removedRowsDataSet = new Set(removedRowIds.map((row) => row[compositePrimaryKey]))
removedRowsData = removedRowsData.filter((row) => removedRowsDataSet.has(row[compositePrimaryKey] as string))
const rowIndexesSet = new Set(removedRowsData.map((row) => row.rowIndex))
formattedData.value = formattedData.value.filter((_, index) => rowIndexesSet.has(index))
} else {
removedRowsData = []
}
await bulkDeleteRows(removedRowsData.map((row) => row.pkData))
} catch (e: any) {
return message.error(`${t('msg.error.deleteRowFailed')}: ${await extractSdkResponseErrorMsg(e)}`)
}
@ -692,10 +681,8 @@ export function useData(args: {
addUndo({
redo: {
fn: async function redo(this: UndoRedoAction, removedRowsData: Record<string, any>[], compositePrimaryKey: string) {
const removedRowIds = await bulkDeleteRows(
removedRowsData.map((row) => ({ [compositePrimaryKey]: row[compositePrimaryKey] as string })),
)
fn: async function redo(this: UndoRedoAction, removedRowsData: Record<string, any>[]) {
const removedRowIds = await bulkDeleteRows(removedRowsData.map((row) => row.pkData))
if (Array.isArray(removedRowIds)) {
for (const { row } of removedRowsData) {
@ -708,7 +695,7 @@ export function useData(args: {
await callbacks?.syncPagination?.()
},
args: [removedRowsData, compositePrimaryKey],
args: [removedRowsData],
},
undo: {
fn: async function undo(
@ -764,22 +751,24 @@ export function useData(args: {
// plus one because we want to include the end row
let row = start + 1
let removedRowsData: Record<string, any>[] = []
const removedRowsData: Record<string, any>[] = []
let compositePrimaryKey = ''
while (row--) {
try {
const { row: rowObj, rowMeta } = formattedData.value[row] as Record<string, any>
const { row: rowData, rowMeta } = formattedData.value[row] as Record<string, any>
if (!rowMeta.new) {
const extractedPk = extractPk(meta?.value?.columns as ColumnType[])
const compositePkValue = extractPkFromRow(rowObj, meta?.value?.columns as ColumnType[])
const compositePkValue = extractPkFromRow(rowData, meta?.value?.columns as ColumnType[])
const pkData = rowPkData(rowData, meta?.value?.columns as ColumnType[])
if (extractedPk && compositePkValue) {
if (!compositePrimaryKey) compositePrimaryKey = extractedPk
removedRowsData.push({
[compositePrimaryKey]: compositePkValue as string,
pkData,
row: clone(formattedData.value[row]) as Row,
rowIndex: row as number,
})
@ -808,20 +797,7 @@ export function useData(args: {
rowObj.row = clone(fullRecord)
}
const removedRowIds: Record<string, any>[] = await bulkDeleteRows(
removedRowsData.map((row) => ({ [compositePrimaryKey]: row[compositePrimaryKey] as string })),
)
if (Array.isArray(removedRowIds)) {
const removedRowsDataSet = new Set(removedRowIds.map((row) => row[compositePrimaryKey]))
removedRowsData = removedRowsData.filter((row) => removedRowsDataSet.has(row[compositePrimaryKey] as string))
const rowIndexesSet = new Set(removedRowsData.map((row) => row.rowIndex))
formattedData.value = formattedData.value.filter((_, index) => rowIndexesSet.has(index))
} else {
removedRowsData = []
}
await bulkDeleteRows(removedRowsData.map((row) => row.pkData))
} catch (e: any) {
return message.error(`${t('msg.error.deleteRowFailed')}: ${await extractSdkResponseErrorMsg(e)}`)
}
@ -830,10 +806,8 @@ export function useData(args: {
addUndo({
redo: {
fn: async function redo(this: UndoRedoAction, removedRowsData: Record<string, any>[], compositePrimaryKey: string) {
const removedRowIds = await bulkDeleteRows(
removedRowsData.map((row) => ({ [compositePrimaryKey]: row[compositePrimaryKey] as string })),
)
fn: async function redo(this: UndoRedoAction, removedRowsData: Record<string, any>[]) {
const removedRowIds = await bulkDeleteRows(removedRowsData.map((row) => row.pkData))
if (Array.isArray(removedRowIds)) {
for (const { row } of removedRowsData) {
@ -846,7 +820,7 @@ export function useData(args: {
await callbacks?.syncPagination?.()
},
args: [removedRowsData, compositePrimaryKey],
args: [removedRowsData],
},
undo: {
fn: async function undo(

1
packages/nocodb-sdk/src/lib/sqlUi/SnowflakeUi.ts

@ -643,6 +643,7 @@ export class SnowflakeUi {
case 'STRING':
return 'string';
case 'TEXT':
if (col.dtxp < 1024) return 'string';
return 'text';
case 'BINARY':
case 'VARBINARY':

21
packages/nocodb/src/db/BaseModelSqlv2.ts

@ -2107,7 +2107,7 @@ class BaseModelSqlv2 {
] = async function (args): Promise<any> {
(listLoader as any).args = args;
return listLoader.load(
getCompositePk(self.model.primaryKeys, this),
getCompositePkValue(self.model.primaryKeys, this),
);
};
} else if (colOptions.type === 'mm') {
@ -2148,7 +2148,7 @@ class BaseModelSqlv2 {
] = async function (args): Promise<any> {
(listLoader as any).args = args;
return await listLoader.load(
getCompositePk(self.model.primaryKeys, this),
getCompositePkValue(self.model.primaryKeys, this),
);
};
} else if (colOptions.type === 'bt') {
@ -2370,7 +2370,7 @@ class BaseModelSqlv2 {
] = async function (args): Promise<any> {
(listLoader as any).args = args;
return listLoader.load(
getCompositePk(self.model.primaryKeys, this),
getCompositePkValue(self.model.primaryKeys, this),
);
};
}
@ -3738,7 +3738,10 @@ class BaseModelSqlv2 {
const pkAndData: { pk: any; data: any }[] = [];
const readChunkSize = 100;
for (const [i, d] of updateDatas.entries()) {
const pkValues = this._extractPksValues(d);
const pkValues = getCompositePkValue(
this.model.primaryKeys,
this._extractPksValues(d),
);
if (!pkValues) {
// throw or skip if no pk provided
if (throwExceptionIfNotExist) {
@ -3964,7 +3967,10 @@ class BaseModelSqlv2 {
const pkAndData: { pk: any; data: any }[] = [];
const readChunkSize = 100;
for (const [i, d] of deleteIds.entries()) {
const pkValues = this._extractPksValues(d);
const pkValues = getCompositePkValue(
this.model.primaryKeys,
this._extractPksValues(d),
);
if (!pkValues) {
// throw or skip if no pk provided
if (throwExceptionIfNotExist) {
@ -6880,8 +6886,9 @@ export function _wherePk(primaryKeys: Column[], id: unknown | unknown[]) {
return where;
}
function getCompositePk(primaryKeys: Column[], row) {
return primaryKeys.map((c) => row[c.title]).join('___');
export function getCompositePkValue(primaryKeys: Column[], row) {
if (typeof row !== 'object') return row;
return primaryKeys.map((c) => row[c.title] ?? row[c.column_name]).join('___');
}
export function haveFormulaColumn(columns: Column[]) {

1
packages/nocodb/src/db/sql-mgr/code/models/xc/ModelXcMetaSnowflake.ts

@ -500,6 +500,7 @@ class ModelXcMetaSnowflake extends BaseModelXcMeta {
case 'smgr':
return dt;
case 'text':
if (col.dtxp < 1024) return 'string';
return 'text';
case 'tid':
return dt;

Loading…
Cancel
Save