Browse Source

fix: select column edit options api (#3691)

Signed-off-by: mertmit <mertmit99@gmail.com>
pull/3701/head
mertmit 2 years ago committed by GitHub
parent
commit
5f346da0f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 248
      packages/nocodb/src/lib/meta/api/columnApis.ts

248
packages/nocodb/src/lib/meta/api/columnApis.ts

@ -554,13 +554,6 @@ export async function columnAdd(req: Request, res: Response<TableType>) {
NcError.badRequest('Empty options are not allowed!'); NcError.badRequest('Empty options are not allowed!');
} }
// Handle empty enum/set for mysql (we restrict empty user options beforehand)
if (driverType === 'mysql' || driverType === 'mysql2') {
if (!colBody.colOptions.options.length && (!colBody.dtxp || colBody.dtxp === '')) {
colBody.colOptions.options.push({ title: '' });
}
}
// Trim end of enum/set // Trim end of enum/set
if (colBody.dt === 'enum' || colBody.dt === 'set') { if (colBody.dt === 'enum' || colBody.dt === 'set') {
for (const opt of colBody.colOptions.options) { for (const opt of colBody.colOptions.options) {
@ -582,6 +575,13 @@ export async function columnAdd(req: Request, res: Response<TableType>) {
}).join(',')}` }).join(',')}`
: ''; : '';
} }
// Handle empty enum/set for mysql (we restrict empty user options beforehand)
if (driverType === 'mysql' || driverType === 'mysql2') {
if (!colBody.colOptions.options.length && (!colBody.dtxp || colBody.dtxp === '')) {
colBody.dtxp = '\'\'';
}
}
} }
@ -735,7 +735,7 @@ export async function columnUpdate(req: Request, res: Response<TableType>) {
dbDriver: NcConnectionMgrv2.get(base) dbDriver: NcConnectionMgrv2.get(base)
}); });
if (column.colOptions?.options) { if (colBody.colOptions?.options) {
const supportedDrivers = ['mysql', 'mysql2', 'pg', 'mssql', 'sqlite3']; const supportedDrivers = ['mysql', 'mysql2', 'pg', 'mssql', 'sqlite3'];
const dbDriver = NcConnectionMgrv2.get(base); const dbDriver = NcConnectionMgrv2.get(base);
const driverType = dbDriver.clientType(); const driverType = dbDriver.clientType();
@ -754,8 +754,10 @@ export async function columnUpdate(req: Request, res: Response<TableType>) {
} }
// Handle migrations // Handle migrations
for (const op of column.colOptions.options.filter(el => el.order === null)) { if (column.colOptions?.options) {
op.title = op.title.replace(/^'/, '').replace(/'$/, '') for (const op of column.colOptions.options.filter(el => el.order === null)) {
op.title = op.title.replace(/^'/, '').replace(/'$/, '')
}
} }
// Handle default values // Handle default values
@ -797,13 +799,6 @@ export async function columnUpdate(req: Request, res: Response<TableType>) {
NcError.badRequest('Empty options are not allowed!'); NcError.badRequest('Empty options are not allowed!');
} }
// Handle empty enum/set for mysql (we restrict empty user options beforehand)
if (driverType === 'mysql' || driverType === 'mysql2') {
if (!colBody.colOptions.options.length && (!colBody.dtxp || colBody.dtxp === '')) {
colBody.dtxp = '\'\'';
}
}
// Trim end of enum/set // Trim end of enum/set
if (colBody.dt === 'enum' || colBody.dt === 'set') { if (colBody.dt === 'enum' || colBody.dt === 'set') {
for (const opt of colBody.colOptions.options) { for (const opt of colBody.colOptions.options) {
@ -826,26 +821,35 @@ export async function columnUpdate(req: Request, res: Response<TableType>) {
: ''; : '';
} }
// Handle option delete // Handle empty enum/set for mysql (we restrict empty user options beforehand)
for (const option of column.colOptions.options.filter(oldOp => colBody.colOptions.options.find(newOp => newOp.id === oldOp.id) ? false : true)) { if (driverType === 'mysql' || driverType === 'mysql2') {
if (!supportedDrivers.includes(driverType) && column.uidt === UITypes.MultiSelect) { if (!colBody.colOptions.options.length && (!colBody.dtxp || colBody.dtxp === '')) {
NcError.badRequest('Your database not yet supported for this operation. Please remove option from records manually before dropping.'); colBody.dtxp = '\'\'';
} }
if (column.uidt === UITypes.SingleSelect) { }
if (driverType === 'mssql') {
await dbDriver.raw(`UPDATE ?? SET ?? = NULL WHERE ?? LIKE ?`, [table.table_name, column.column_name, column.column_name, option.title]); // Handle option delete
} else { if (column.colOptions?.options) {
await baseModel.bulkUpdateAll({ where: `(${column.column_name},eq,${option.title})` }, { [column.column_name]: null }, { cookie: req}); for (const option of column.colOptions.options.filter(oldOp => colBody.colOptions.options.find(newOp => newOp.id === oldOp.id) ? false : true)) {
if (!supportedDrivers.includes(driverType) && column.uidt === UITypes.MultiSelect) {
NcError.badRequest('Your database not yet supported for this operation. Please remove option from records manually before dropping.');
} }
} else if (column.uidt === UITypes.MultiSelect) { if (column.uidt === UITypes.SingleSelect) {
if (driverType === 'mysql' || driverType === 'mysql2') { if (driverType === 'mssql') {
await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), ',')) WHERE FIND_IN_SET(?, ??)`, [table.table_name, column.column_name, column.column_name, option.title, option.title, column.column_name]); await dbDriver.raw(`UPDATE ?? SET ?? = NULL WHERE ?? LIKE ?`, [table.table_name, column.column_name, column.column_name, option.title]);
} else if (driverType === 'pg') { } else {
await dbDriver.raw(`UPDATE ?? SET ?? = array_to_string(array_remove(string_to_array(??, ','), ?), ',')`, [table.table_name, column.column_name, column.column_name, option.title]); await baseModel.bulkUpdateAll({ where: `(${column.column_name},eq,${option.title})` }, { [column.column_name]: null }, { cookie: req});
} else if (driverType === 'mssql') { }
await dbDriver.raw(`UPDATE ?? SET ?? = substring(replace(concat(',', ??, ','), concat(',', ?, ','), ','), 2, len(replace(concat(',', ??, ','), concat(',', ?, ','), ',')) - 2)`, [table.table_name, column.column_name, column.column_name, option.title, column.column_name, option.title]); } else if (column.uidt === UITypes.MultiSelect) {
} else if (driverType === 'sqlite3') { if (driverType === 'mysql' || driverType === 'mysql2') {
await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(REPLACE(',' || ?? || ',', ',' || ? || ',', ','), ',')`, [table.table_name, column.column_name, column.column_name, option.title]); await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), ',')) WHERE FIND_IN_SET(?, ??)`, [table.table_name, column.column_name, column.column_name, option.title, option.title, column.column_name]);
} else if (driverType === 'pg') {
await dbDriver.raw(`UPDATE ?? SET ?? = array_to_string(array_remove(string_to_array(??, ','), ?), ',')`, [table.table_name, column.column_name, column.column_name, option.title]);
} else if (driverType === 'mssql') {
await dbDriver.raw(`UPDATE ?? SET ?? = substring(replace(concat(',', ??, ','), concat(',', ?, ','), ','), 2, len(replace(concat(',', ??, ','), concat(',', ?, ','), ',')) - 2)`, [table.table_name, column.column_name, column.column_name, option.title, column.column_name, option.title]);
} else if (driverType === 'sqlite3') {
await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(REPLACE(',' || ?? || ',', ',' || ? || ',', ','), ',')`, [table.table_name, column.column_name, column.column_name, option.title]);
}
} }
} }
} }
@ -853,97 +857,99 @@ export async function columnUpdate(req: Request, res: Response<TableType>) {
let interchange = []; let interchange = [];
// Handle option update // Handle option update
const old_titles = column.colOptions.options.map(el => el.title); if (column.colOptions?.options) {
for (const option of column.colOptions.options.filter(oldOp => colBody.colOptions.options.find(newOp => newOp.id === oldOp.id && newOp.title !== oldOp.title))) { const old_titles = column.colOptions.options.map(el => el.title);
if (!supportedDrivers.includes(driverType) && column.uidt === UITypes.MultiSelect) { for (const option of column.colOptions.options.filter(oldOp => colBody.colOptions.options.find(newOp => newOp.id === oldOp.id && newOp.title !== oldOp.title))) {
NcError.badRequest('Your database not yet supported for this operation. Please remove option from records manually before updating.'); if (!supportedDrivers.includes(driverType) && column.uidt === UITypes.MultiSelect) {
} NcError.badRequest('Your database not yet supported for this operation. Please remove option from records manually before updating.');
let newOp = { ...colBody.colOptions.options.find(el => option.id === el.id) };
if (old_titles.includes(newOp.title)) {
let def_option = { ...newOp };
let title_counter = 1;
while (old_titles.includes(newOp.title)) {
newOp.title = `${def_option.title}_${title_counter++}`;
}
interchange.push( {
def_option,
temp_title: newOp.title
} );
}
// Append new option before editing
if ((driverType === 'mysql' || driverType === 'mysql2') && (column.dt === 'enum' || column.dt === 'set')) {
column.colOptions.options.push({ title: newOp.title });
let temp_dtxp = '';
if (column.uidt === UITypes.SingleSelect) {
temp_dtxp = (column.colOptions?.options.length)
? `${column.colOptions.options.map(o => `'${o.title.replace(/'/gi, '\'\'')}'`).join(',')}`
: '';
} else if (column.uidt === UITypes.MultiSelect){
temp_dtxp = (column.colOptions?.options.length)
? `${column.colOptions.options.map((o) => {
if(o.title.includes(',')) {
NcError.badRequest('Illegal char(\',\') for MultiSelect');
throw new Error('');
}
return `'${o.title.replace(/'/gi, '\'\'')}'`;
}).join(',')}`
: '';
} }
const tableUpdateBody = { let newOp = { ...colBody.colOptions.options.find(el => option.id === el.id) };
...table, if (old_titles.includes(newOp.title)) {
tn: table.table_name, let def_option = { ...newOp };
originalColumns: table.columns.map((c) => ({ let title_counter = 1;
...c, while (old_titles.includes(newOp.title)) {
cn: c.column_name, newOp.title = `${def_option.title}_${title_counter++}`;
cno: c.column_name, }
})), interchange.push( {
columns: await Promise.all( def_option,
table.columns.map(async (c) => { temp_title: newOp.title
if (c.id === req.params.columnId) { } );
const res = { }
...c,
...column, // Append new option before editing
cn: column.column_name, if ((driverType === 'mysql' || driverType === 'mysql2') && (column.dt === 'enum' || column.dt === 'set')) {
cno: c.column_name, column.colOptions.options.push({ title: newOp.title });
dtxp: temp_dtxp,
altered: Altered.UPDATE_COLUMN, let temp_dtxp = '';
}; if (column.uidt === UITypes.SingleSelect) {
return Promise.resolve(res); temp_dtxp = (column.colOptions.options.length)
} else { ? `${column.colOptions.options.map(o => `'${o.title.replace(/'/gi, '\'\'')}'`).join(',')}`
(c as any).cn = c.column_name; : '';
} } else if (column.uidt === UITypes.MultiSelect){
return Promise.resolve(c); temp_dtxp = (column.colOptions.options.length)
}) ? `${column.colOptions.options.map((o) => {
), if(o.title.includes(',')) {
}; NcError.badRequest('Illegal char(\',\') for MultiSelect');
throw new Error('');
}
return `'${o.title.replace(/'/gi, '\'\'')}'`;
}).join(',')}`
: '';
}
const sqlMgr = await ProjectMgrv2.getSqlMgr({ id: base.project_id }); const tableUpdateBody = {
await sqlMgr.sqlOpPlus(base, 'tableUpdate', tableUpdateBody); ...table,
tn: table.table_name,
await Column.update(req.params.columnId, { originalColumns: table.columns.map((c) => ({
...column, ...c,
}); cn: c.column_name,
} cno: c.column_name,
})),
columns: await Promise.all(
table.columns.map(async (c) => {
if (c.id === req.params.columnId) {
const res = {
...c,
...column,
cn: column.column_name,
cno: c.column_name,
dtxp: temp_dtxp,
altered: Altered.UPDATE_COLUMN,
};
return Promise.resolve(res);
} else {
(c as any).cn = c.column_name;
}
return Promise.resolve(c);
})
),
};
if (column.uidt === UITypes.SingleSelect) { const sqlMgr = await ProjectMgrv2.getSqlMgr({ id: base.project_id });
if (driverType === 'mssql') { await sqlMgr.sqlOpPlus(base, 'tableUpdate', tableUpdateBody);
await dbDriver.raw(`UPDATE ?? SET ?? = ? WHERE ?? LIKE ?`, [table.table_name, column.column_name, newOp.title, column.column_name, option.title]);
} else { await Column.update(req.params.columnId, {
await baseModel.bulkUpdateAll({ where: `(${column.column_name},eq,${option.title})` }, { [column.column_name]: newOp.title }, { cookie: req}); ...column,
});
} }
} else if (column.uidt === UITypes.MultiSelect) {
if (driverType === 'mysql' || driverType === 'mysql2') { if (column.uidt === UITypes.SingleSelect) {
await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), CONCAT(',', ?, ','))) WHERE FIND_IN_SET(?, ??)`, [table.table_name, column.column_name, column.column_name, option.title, newOp.title, option.title, column.column_name]); if (driverType === 'mssql') {
} else if (driverType === 'pg') { await dbDriver.raw(`UPDATE ?? SET ?? = ? WHERE ?? LIKE ?`, [table.table_name, column.column_name, newOp.title, column.column_name, option.title]);
await dbDriver.raw(`UPDATE ?? SET ?? = array_to_string(array_replace(string_to_array(??, ','), ?, ?), ',')`, [table.table_name, column.column_name, column.column_name, option.title, newOp.title]); } else {
} else if (driverType === 'mssql') { await baseModel.bulkUpdateAll({ where: `(${column.column_name},eq,${option.title})` }, { [column.column_name]: newOp.title }, { cookie: req});
await dbDriver.raw(`UPDATE ?? SET ?? = substring(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ',')), 2, len(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ','))) - 2)`, [table.table_name, column.column_name, column.column_name, option.title, newOp.title, column.column_name, option.title, newOp.title]); }
} else if (driverType === 'sqlite3') { } else if (column.uidt === UITypes.MultiSelect) {
await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(REPLACE(',' || ?? || ',', ',' || ? || ',', ',' || ? || ','), ',')`, [table.table_name, column.column_name, column.column_name, option.title, newOp.title]); if (driverType === 'mysql' || driverType === 'mysql2') {
await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), CONCAT(',', ?, ','))) WHERE FIND_IN_SET(?, ??)`, [table.table_name, column.column_name, column.column_name, option.title, newOp.title, option.title, column.column_name]);
} else if (driverType === 'pg') {
await dbDriver.raw(`UPDATE ?? SET ?? = array_to_string(array_replace(string_to_array(??, ','), ?, ?), ',')`, [table.table_name, column.column_name, column.column_name, option.title, newOp.title]);
} else if (driverType === 'mssql') {
await dbDriver.raw(`UPDATE ?? SET ?? = substring(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ',')), 2, len(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ','))) - 2)`, [table.table_name, column.column_name, column.column_name, option.title, newOp.title, column.column_name, option.title, newOp.title]);
} else if (driverType === 'sqlite3') {
await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(REPLACE(',' || ?? || ',', ',' || ? || ',', ',' || ? || ','), ',')`, [table.table_name, column.column_name, column.column_name, option.title, newOp.title]);
}
} }
} }
} }

Loading…
Cancel
Save