Browse Source

Merge pull request #2608 from nocodb/fix/delete-row-with-m2m

fix: delete rows containing m2m / hm data
pull/2646/head
աɨռɢӄաօռɢ 2 years ago committed by GitHub
parent
commit
b1a744a03b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 39
      packages/nc-gui/components/project/spreadsheet/RowsXcDataTable.vue
  2. 42
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts
  3. 6
      packages/nocodb/src/lib/meta/api/dataApis/dataAliasApis.ts

39
packages/nc-gui/components/project/spreadsheet/RowsXcDataTable.vue

@ -1124,10 +1124,10 @@ export default {
.map(c => rowObj[c.title])
.join('___');
if (!id) {
return this.$toast.info("Delete not allowed for table which doesn't have primary Key").goAway(3000);
const successfulDeletion = await this.deleteRowById(id);
if (!successfulDeletion) {
return;
}
await this.$api.dbViewRow.delete('noco', this.projectName, this.meta.id, this.selectedView.id, id);
}
this.data.splice(this.rowContextMenu.index, 1);
this.syncCount();
@ -1138,7 +1138,6 @@ export default {
},
async deleteSelectedRows() {
let row = this.rowLength;
// let success = 0
while (row--) {
try {
const { row: rowObj, rowMeta } = this.data[row];
@ -1151,10 +1150,10 @@ export default {
.map(c => rowObj[c.title])
.join('___');
if (!id) {
return this.$toast.info("Delete not allowed for table which doesn't have primary Key").goAway(3000);
const successfulDeletion = await this.deleteRowById(id);
if (!successfulDeletion) {
continue;
}
await this.$api.dbViewRow.delete('noco', this.projectName, this.meta.id, this.selectedView.id, id);
}
this.data.splice(row, 1);
} catch (e) {
@ -1164,6 +1163,32 @@ export default {
this.syncCount();
},
async deleteRowById(id) {
try {
if (!id) {
this.$toast.info("Delete not allowed for table which doesn't have primary Key").goAway(3000);
return false;
}
const res = await this.$api.dbViewRow.delete('noco', this.projectName, this.meta.id, this.selectedView.id, id);
if (res?.message) {
this.$toast
.info(
`<div style="padding:10px 4px">Unable to delete row with ID ${id} because of the following:
<br><br>${res.message.join('<br>')}<br><br>
Clear the data first & try again</div>`
)
.goAway(5000);
return false;
}
} catch (e) {
this.$toast.error(`Failed to delete row : ${e.message}`).goAway(3000);
return false;
}
return true;
},
async clearCellValue() {
const { col, colIndex, row, index } = this.rowContextMenu;
if (row[col.title] === null) {

42
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts

@ -1380,6 +1380,48 @@ class BaseModelSqlv2 {
}
}
async hasLTARData(rowId, model: Model): Promise<any> {
const res = [];
const LTARColumns = (await model.getColumns()).filter(
(c) => c.uidt === UITypes.LinkToAnotherRecord
);
let i = 0;
for (const column of LTARColumns) {
const colOptions =
(await column.getColOptions()) as LinkToAnotherRecordColumn;
const childColumn = await colOptions.getChildColumn();
const parentColumn = await colOptions.getParentColumn();
const childModel = await childColumn.getModel();
await childModel.getColumns();
const parentModel = await parentColumn.getModel();
await parentModel.getColumns();
let cnt = 0;
if (colOptions.type === RelationTypes.HAS_MANY) {
cnt = +(
await this.dbDriver(childModel.table_name)
.count(childColumn.column_name, { as: 'cnt' })
.where(childColumn.column_name, rowId)
)[0].cnt;
} else if (colOptions.type === RelationTypes.MANY_TO_MANY) {
const mmModel = await colOptions.getMMModel();
const mmChildColumn = await colOptions.getMMChildColumn();
cnt = +(
await this.dbDriver(mmModel.table_name)
.where(`${mmModel.table_name}.${mmChildColumn.column_name}`, rowId)
.count(mmChildColumn.column_name, { as: 'cnt' })
)[0].cnt;
}
if (cnt) {
res.push(
`${i++ + 1}. ${model.title}.${
column.title
} is a LinkToAnotherRecord of ${childModel.title}`
);
}
}
return res;
}
async updateByPk(id, data, trx?, cookie?) {
try {
const updateObj = await this.model.mapAliasToColumn(data);

6
packages/nocodb/src/lib/meta/api/dataApis/dataAliasApis.ts

@ -81,7 +81,11 @@ async function dataDelete(req: Request, res: Response) {
viewId: view?.id,
dbDriver: NcConnectionMgrv2.get(base),
});
const message = await baseModel.hasLTARData(req.params.rowId, model);
if (message.length) {
res.json({ message });
return;
}
res.json(await baseModel.delByPk(req.params.rowId, null, req));
}
async function getDataList(model, view: View, req) {

Loading…
Cancel
Save