From 061d27e4ba125caf07b52d4aa69c11ed63712b84 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 12 Jan 2023 12:34:09 +0800 Subject: [PATCH 1/5] fix(nocodb): revise DATETIME_DIFF logic for sqlite --- .../lib/sql/functionMappings/sqlite.ts | 54 ++++++++++--------- 1 file changed, 30 insertions(+), 24 deletions(-) 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 9c5f500431..81abddfc2c 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 @@ -83,19 +83,25 @@ const sqlite3 = { ); }, DATETIME_DIFF: ({ fn, knex, pt, colAlias }: MapFnArgs) => { - let datetime_expr1 = fn(pt.arguments[0]).bindings[0]; - let datetime_expr2 = fn(pt.arguments[1]).bindings[0]; + let datetime_expr1 = fn(pt.arguments[0]); + let datetime_expr2 = fn(pt.arguments[1]); // JULIANDAY takes YYYY-MM-DD - datetime_expr1 = convertToTargetFormat( - datetime_expr1, - getDateFormat(datetime_expr1), - 'YYYY-MM-DD' - ); - datetime_expr2 = convertToTargetFormat( - datetime_expr2, - getDateFormat(datetime_expr2), - 'YYYY-MM-DD' - ); + if (datetime_expr1.sql === '?' && datetime_expr1.bindings?.[0]) { + datetime_expr1 = `'${convertToTargetFormat( + datetime_expr1.bindings[0], + getDateFormat(datetime_expr1.bindings[0]), + 'YYYY-MM-DD' + )}'`; + } + + if (datetime_expr2.sql === '?' && datetime_expr2.bindings?.[0]) { + datetime_expr2 = `'${convertToTargetFormat( + datetime_expr2.bindings[0], + getDateFormat(datetime_expr2.bindings[0]), + 'YYYY-MM-DD' + )}'`; + } + const rawUnit = pt.arguments[2] ? fn(pt.arguments[2]).bindings[0] : 'seconds'; @@ -103,36 +109,36 @@ const sqlite3 = { const unit = convertUnits(rawUnit, 'sqlite'); switch (unit) { case 'seconds': - sql = `ROUND((JULIANDAY('${datetime_expr1}') - JULIANDAY('${datetime_expr2}')) * 86400)`; + sql = `ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) * 86400)`; break; case 'minutes': - sql = `ROUND((JULIANDAY('${datetime_expr1}') - JULIANDAY('${datetime_expr2}')) * 1440)`; + sql = `ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) * 1440)`; break; case 'hours': - sql = `ROUND((JULIANDAY('${datetime_expr1}') - JULIANDAY('${datetime_expr2}')) * 24)`; + sql = `ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) * 24)`; break; case 'milliseconds': - sql = `ROUND((JULIANDAY('${datetime_expr1}') - JULIANDAY('${datetime_expr2}')) * 86400000)`; + sql = `ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) * 86400000)`; break; case 'weeks': - sql = `ROUND((JULIANDAY('${datetime_expr1}') - JULIANDAY('${datetime_expr2}')) / 7)`; + sql = `ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) / 7)`; break; case 'months': - sql = `(ROUND((JULIANDAY('${datetime_expr1}') - JULIANDAY('${datetime_expr2}')) / 365)) - * 12 + (ROUND((JULIANDAY('${datetime_expr1}') - JULIANDAY('${datetime_expr2}')) / 365 / 12))`; + sql = `(ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) / 365)) + * 12 + (ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) / 365 / 12))`; break; case 'quarters': sql = ` - ROUND((JULIANDAY('${datetime_expr1}')) / 365 / 4) - - ROUND((JULIANDAY('${datetime_expr2}')) / 365 / 4) + - (ROUND((JULIANDAY('${datetime_expr1}') - JULIANDAY('${datetime_expr2}')) / 365)) * 4 + ROUND((JULIANDAY(${datetime_expr1})) / 365 / 4) - + ROUND((JULIANDAY(${datetime_expr2})) / 365 / 4) + + (ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) / 365)) * 4 `; break; case 'years': - sql = `ROUND((JULIANDAY('${datetime_expr1}') - JULIANDAY('${datetime_expr2}')) / 365)`; + sql = `ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) / 365)`; break; case 'days': - sql = `JULIANDAY('${datetime_expr1}') - JULIANDAY('${datetime_expr2}')`; + sql = `JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})`; break; default: sql = ''; From b65789da77fc26274ae1e04a5bf7868a7039dd6d Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 12 Jan 2023 12:34:32 +0800 Subject: [PATCH 2/5] feat(playwright): add NOW() tests for datetime diff formula --- tests/playwright/tests/columnFormula.spec.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/playwright/tests/columnFormula.spec.ts b/tests/playwright/tests/columnFormula.spec.ts index bc08da00ba..650d9501a4 100644 --- a/tests/playwright/tests/columnFormula.spec.ts +++ b/tests/playwright/tests/columnFormula.spec.ts @@ -66,10 +66,22 @@ const formulaDataByDbType = (context: NcContext) => [ formula: `DATETIME_DIFF("2022/10/14", "2023/10/14", "y")`, result: ['-1', '-1', '-1', '-1', '-1'], }, + { + formula: `DATETIME_DIFF(NOW(), "2023/10/14", "y")`, + result: ['-1', '-1', '-1', '-1', '-1'], + }, + { + formula: `DATETIME_DIFF("2022/10/14", NOW(), "y")`, + result: ['0', '0', '0', '0', '0'], + }, { formula: `DATETIME_DIFF("2022/10/14", "2023/10/14", "d")`, result: ['-365', '-365', '-365', '-365', '-365'], }, + { + formula: `DATETIME_DIFF("2022/10/14", NOW(), "d")`, + result: ['-90', '-90', '-90', '-90', '-90'], + }, { formula: `CONCAT(UPPER({City}), LOWER({City}), TRIM(' trimmed '))`, result: [ From 0a93a2c8ed8aeb92e1178e364c018835b977039b Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 12 Jan 2023 13:09:53 +0800 Subject: [PATCH 3/5] fix(playwright): correct test case result - should be all zeros --- tests/playwright/tests/columnFormula.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/playwright/tests/columnFormula.spec.ts b/tests/playwright/tests/columnFormula.spec.ts index 650d9501a4..25d6e8ede7 100644 --- a/tests/playwright/tests/columnFormula.spec.ts +++ b/tests/playwright/tests/columnFormula.spec.ts @@ -68,7 +68,7 @@ const formulaDataByDbType = (context: NcContext) => [ }, { formula: `DATETIME_DIFF(NOW(), "2023/10/14", "y")`, - result: ['-1', '-1', '-1', '-1', '-1'], + result: ['0', '0', '0', '0', '0'], }, { formula: `DATETIME_DIFF("2022/10/14", NOW(), "y")`, From 4e3b00eb01186363e5de2a5f4413fe3ab3d9268b Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 12 Jan 2023 14:19:31 +0800 Subject: [PATCH 4/5] fix(playwright): correct formula datetime year --- tests/playwright/tests/columnFormula.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/playwright/tests/columnFormula.spec.ts b/tests/playwright/tests/columnFormula.spec.ts index 25d6e8ede7..3f29a09c05 100644 --- a/tests/playwright/tests/columnFormula.spec.ts +++ b/tests/playwright/tests/columnFormula.spec.ts @@ -71,7 +71,7 @@ const formulaDataByDbType = (context: NcContext) => [ result: ['0', '0', '0', '0', '0'], }, { - formula: `DATETIME_DIFF("2022/10/14", NOW(), "y")`, + formula: `DATETIME_DIFF("2023/10/14", NOW(), "y")`, result: ['0', '0', '0', '0', '0'], }, { From c3513491863ded5509366facbb03c710142da5fb Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 12 Jan 2023 14:20:00 +0800 Subject: [PATCH 5/5] fix(nocodb): use strftime for sqlite date time sql --- .../lib/sql/functionMappings/sqlite.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) 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 81abddfc2c..d95430e26b 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 @@ -109,33 +109,28 @@ const sqlite3 = { const unit = convertUnits(rawUnit, 'sqlite'); switch (unit) { case 'seconds': - sql = `ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) * 86400)`; + sql = `(strftime('%s', ${datetime_expr1}) - strftime('%s', ${datetime_expr2}))`; break; case 'minutes': - sql = `ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) * 1440)`; + sql = `(strftime('%s', ${datetime_expr1}) - strftime('%s', ${datetime_expr2})) / 60`; break; case 'hours': - sql = `ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) * 24)`; + sql = `(strftime('%s', ${datetime_expr1}) - strftime('%s', ${datetime_expr2})) / 3600`; break; case 'milliseconds': - sql = `ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) * 86400000)`; + sql = `(strftime('%s', ${datetime_expr1}) - strftime('%s', ${datetime_expr2})) * 1000`; break; case 'weeks': sql = `ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) / 7)`; break; case 'months': - sql = `(ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) / 365)) - * 12 + (ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) / 365 / 12))`; + sql = `(strftime('%Y', ${datetime_expr1}) - strftime('%Y', ${datetime_expr2})) * 12 + (strftime('%m', ${datetime_expr1}) - strftime('%m', ${datetime_expr2})) `; break; case 'quarters': - sql = ` - ROUND((JULIANDAY(${datetime_expr1})) / 365 / 4) - - ROUND((JULIANDAY(${datetime_expr2})) / 365 / 4) + - (ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) / 365)) * 4 - `; + sql = `(strftime('%Y', ${datetime_expr1}) - strftime('%Y', ${datetime_expr2})) * 4 + (strftime('%m', ${datetime_expr1}) - strftime('%m', ${datetime_expr2})) / 3`; break; case 'years': - sql = `ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) / 365)`; + sql = `strftime('%Y', ${datetime_expr1}) - strftime('%Y', ${datetime_expr2})`; break; case 'days': sql = `JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})`;