Browse Source

fix(nocodb): handle function handler which is not returning a builder

Signed-off-by: Pranav C <pranavxc@gmail.com>
temp-5c4a2f8331a3f36534606c6dcdb34a67f95aea6d
Pranav C 1 year ago
parent
commit
5b32ec7a5d
  1. 97
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts

97
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts

@ -613,7 +613,7 @@ async function _formulaQueryBuilder(
break; break;
default: default:
{ {
const res = mapFunctionName({ const res = await mapFunctionName({
pt, pt,
knex, knex,
alias, alias,
@ -630,23 +630,25 @@ async function _formulaQueryBuilder(
return { return {
builder: knex.raw( builder: knex.raw(
`${pt.callee.name}(${pt.arguments `${pt.callee.name}(${(
.map((arg) => { await Promise.all(
const query = fn(arg).toQuery(); pt.arguments.map(async (arg) => {
if (pt.callee.name === 'CONCAT') { const query = (await fn(arg)).builder.toQuery();
if (knex.clientType() === 'mysql2') { if (pt.callee.name === 'CONCAT') {
// mysql2: CONCAT() returns NULL if any argument is NULL. if (knex.clientType() === 'mysql2') {
// adding IFNULL to convert NULL values to empty strings // mysql2: CONCAT() returns NULL if any argument is NULL.
return `IFNULL(${query}, '')`; // adding IFNULL to convert NULL values to empty strings
} else { return `IFNULL(${query}, '')`;
// do nothing } else {
// pg / mssql: Concatenate all arguments. NULL arguments are ignored. // do nothing
// sqlite3: special handling - See BinaryExpression // pg / mssql: Concatenate all arguments. NULL arguments are ignored.
// sqlite3: special handling - See BinaryExpression
}
} }
} return query;
return query; })
}) )
.join()})${colAlias}`.replace(/\?/g, '\\?') ).join()})${colAlias}`.replace(/\?/g, '\\?')
), ),
}; };
} else if (pt.type === 'Literal') { } else if (pt.type === 'Literal') {
@ -844,7 +846,7 @@ export default async function formulaQueryBuilderv2(
// dry run qb.builder to see if it will break the grid view or not // dry run qb.builder to see if it will break the grid view or not
// if so, set formula error and show empty selectQb instead // if so, set formula error and show empty selectQb instead
await knex(getTnPath(model, knex, tableAlias)) await knex(getTnPath(model, knex, tableAlias))
.select(qb.builder) .select(knex.raw(`?? as ??`, [qb.builder, '__dry_run_alias']))
.as('dry-run-only'); .as('dry-run-only');
// if column is provided, i.e. formula has been created // if column is provided, i.e. formula has been created
@ -878,62 +880,3 @@ export default async function formulaQueryBuilderv2(
} }
return qb; return qb;
} }
export async function validateFormula(
_tree,
alias,
knex: XKnex,
model: Model,
column?: Column,
aliasToColumn = {},
tableAlias?: string
) {
// register jsep curly hook once only
jsep.plugins.register(jsepCurlyHook);
// generate qb
const qb = await _formulaQueryBuilder(
_tree,
alias,
knex,
model,
aliasToColumn,
tableAlias
);
try {
// dry run qb.builder to see if it will break the grid view or not
// if so, set formula error and show empty selectQb instead
await knex(getTnPath(model, knex, tableAlias))
.select(qb.builder)
.as('dry-run-only');
// if column is provided, i.e. formula has been created
if (column) {
const formula = await column.getColOptions<FormulaColumn>();
// clean the previous formula error if the formula works this time
if (formula.error) {
await FormulaColumn.update(formula.id, {
error: null,
});
}
}
} catch (e) {
console.error(e);
if (column) {
const formula = await column.getColOptions<FormulaColumn>();
// add formula error to show in UI
await FormulaColumn.update(formula.id, {
error: e.message,
});
// update cache to reflect the error in UI
const key = `${CacheScope.COL_FORMULA}:${column.id}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o = { ...o, error: e.message };
// set cache
await NocoCache.set(key, o);
}
}
throw new Error(`Formula error: ${e.message}`);
}
}

Loading…
Cancel
Save