diff --git a/packages/nc-gui/utils/dateTimeUtils.ts b/packages/nc-gui/utils/dateTimeUtils.ts index 9b28637e9f..803936ebdb 100644 --- a/packages/nc-gui/utils/dateTimeUtils.ts +++ b/packages/nc-gui/utils/dateTimeUtils.ts @@ -19,7 +19,7 @@ export const dateFormats = [ export const timeFormats = ['HH:mm', 'HH:mm:ss'] export const handleTZ = (val: any) => { - if (!val) { + if (val === undefined || val === null) { return } if (typeof val !== 'string') { diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts index d0c60e1a7e..b9a47522d1 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts @@ -709,6 +709,47 @@ export default async function formulaQueryBuilderv2( sql = `COALESCE(${left}, '') ${pt.operator} COALESCE(${right},'')${colAlias}`; } + if (knex.clientType() === 'mysql2') { + sql = `IFNULL(${left} ${pt.operator} ${right}, ${ + pt.operator === '=' + ? pt.left.type === 'Literal' + ? pt.left.value === '' + : pt.right.value === '' + : pt.operator === '!=' + ? pt.left.type !== 'Literal' + ? pt.left.value === '' + : pt.right.value === '' + : 0 + }) ${colAlias}`; + } else if ( + knex.clientType() === 'sqlite3' || + knex.clientType() === 'pg' || + knex.clientType() === 'mssql' + ) { + if (pt.operator === '=') { + if (pt.left.type === 'Literal' && pt.left.value === '') { + sql = `${right} IS NULL OR CAST(${right} AS TEXT) = ''`; + } else if (pt.right.type === 'Literal' && pt.right.value === '') { + sql = `${left} IS NULL OR CAST(${left} AS TEXT) = ''`; + } + } else if (pt.operator === '!=') { + if (pt.left.type === 'Literal' && pt.left.value === '') { + sql = `${right} IS NOT NULL AND CAST(${right} AS TEXT) != ''`; + } else if (pt.right.type === 'Literal' && pt.right.value === '') { + sql = `${left} IS NOT NULL AND CAST(${left} AS TEXT) != ''`; + } + } + + if ( + (pt.operator === '=' || pt.operator === '!=') && + prevBinaryOp !== 'AND' && + prevBinaryOp !== 'OR' + ) { + sql = `(CASE WHEN ${sql} THEN true ELSE false END ${colAlias})`; + } else { + sql = `${sql} ${colAlias}`; + } + } const query = knex.raw(sql); if (prevBinaryOp && pt.operator !== prevBinaryOp) { query.wrap('(', ')'); diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/mssql.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/mssql.ts index b666957176..58068e6c79 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/mssql.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/mssql.ts @@ -135,6 +135,30 @@ const mssql = { )} % 7 + 7) % 7 ${colAlias}` ); }, + AND: (args: MapFnArgs) => { + return args.knex.raw( + `CASE WHEN ${args.knex + .raw( + `${args.pt.arguments + .map((ar) => args.fn(ar, '', 'AND').toQuery()) + .join(' AND ')}` + ) + .wrap('(', ')') + .toQuery()} THEN 1 ELSE 0 END ${args.colAlias}` + ); + }, + OR: (args: MapFnArgs) => { + return args.knex.raw( + `CASE WHEN ${args.knex + .raw( + `${args.pt.arguments + .map((ar) => args.fn(ar, '', 'OR').toQuery()) + .join(' OR ')}` + ) + .wrap('(', ')') + .toQuery()} THEN 1 ELSE 0 END ${args.colAlias}` + ); + }, }; export default mssql; diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/pg.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/pg.ts index 72ee49bcfa..1157d853cf 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/pg.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/pg.ts @@ -114,6 +114,30 @@ const pg = { )} % 7 + 7) ::INTEGER % 7 ${colAlias}` ); }, + AND: (args: MapFnArgs) => { + return args.knex.raw( + `CASE WHEN ${args.knex + .raw( + `${args.pt.arguments + .map((ar) => args.fn(ar, '', 'AND').toQuery()) + .join(' AND ')}` + ) + .wrap('(', ')') + .toQuery()} THEN 1 ELSE 0 END ${args.colAlias}` + ); + }, + OR: (args: MapFnArgs) => { + return args.knex.raw( + `CASE WHEN ${args.knex + .raw( + `${args.pt.arguments + .map((ar) => args.fn(ar, '', 'OR').toQuery()) + .join(' OR ')}` + ) + .wrap('(', ')') + .toQuery()} THEN 1 ELSE 0 END ${args.colAlias}` + ); + }, }; export default pg; diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/sqlite.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/sqlite.ts index ad384aeedf..9c5f500431 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/sqlite.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/sqlite.ts @@ -152,6 +152,30 @@ const sqlite3 = { )} % 7 + 7) % 7 ${colAlias}` ); }, + AND: (args: MapFnArgs) => { + return args.knex.raw( + `CASE WHEN ${args.knex + .raw( + `${args.pt.arguments + .map((ar) => args.fn(ar, '', 'AND').toQuery()) + .join(' AND ')}` + ) + .wrap('(', ')') + .toQuery()} THEN 1 ELSE 0 END ${args.colAlias}` + ); + }, + OR: (args: MapFnArgs) => { + return args.knex.raw( + `CASE WHEN ${args.knex + .raw( + `${args.pt.arguments + .map((ar) => args.fn(ar, '', 'OR').toQuery()) + .join(' OR ')}` + ) + .wrap('(', ')') + .toQuery()} THEN 1 ELSE 0 END ${args.colAlias}` + ); + }, }; export default sqlite3;