diff --git a/packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts b/packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts index e36ed59f2c..ef3820ba76 100644 --- a/packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts +++ b/packages/nocodb/src/db/formulav2/formulaQueryBuilderv2.ts @@ -873,6 +873,32 @@ async function _formulaQueryBuilder( ); } + // if operator is == or !=, then handle comparison with BLANK which should accept NULL and empty string + if (pt.operator === '==' || pt.operator === '!=') { + if (pt.left.callee?.name !== pt.left.callee?.name) { + // if left/right is BLANK, accept both NULL and empty string + ['left', 'right'].forEach((operand) => { + if ( + pt[operand].type === 'CallExpression' && + pt[operand].callee.name === 'BLANK' + ) { + return fn( + { + type: 'CallExpression', + arguments: [operand === 'left' ? pt.right : pt.left], + callee: { + type: 'Identifier', + name: 'ISBLANK', + }, + }, + alias, + prevBinaryOp, + ); + } + }); + } + } + if (pt.operator === '==') { pt.operator = '='; // if left/right is of different type, convert to string and compare diff --git a/packages/nocodb/src/db/functionMappings/commonFns.ts b/packages/nocodb/src/db/functionMappings/commonFns.ts index e2ab573a91..3f9af3e777 100644 --- a/packages/nocodb/src/db/functionMappings/commonFns.ts +++ b/packages/nocodb/src/db/functionMappings/commonFns.ts @@ -321,4 +321,22 @@ export default { ), }; }, + ISBLANK: async ({ fn, knex, pt, colAlias }: MapFnArgs) => { + const { builder: valueBuilder } = await fn(pt.arguments[0]); + + return { + builder: knex.raw( + `(${valueBuilder} IS NULL OR ${valueBuilder} = '')${colAlias}`, + ), + }; + }, + ISNOTBLANK: async ({ fn, knex, pt, colAlias }: MapFnArgs) => { + const { builder: valueBuilder } = await fn(pt.arguments[0]); + + return { + builder: knex.raw( + `(${valueBuilder} IS NOT NULL AND ${valueBuilder} != '')${colAlias}`, + ), + }; + }, };