diff --git a/packages/nc-gui/components/project/spreadsheet/components/virtualCell.vue b/packages/nc-gui/components/project/spreadsheet/components/virtualCell.vue index 341530f955..7f9ad805d0 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/virtualCell.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/virtualCell.vue @@ -85,6 +85,7 @@ v-else-if="formula" :row="row" :column="column" + :client="nodes.dbConnection.client" />
- {{ row[column.title] }} + {{ result }}
diff --git a/packages/noco-docs/content/en/setup-and-usages/formulas.md b/packages/noco-docs/content/en/setup-and-usages/formulas.md index 9d59873a45..a20b49a477 100644 --- a/packages/noco-docs/content/en/setup-and-usages/formulas.md +++ b/packages/noco-docs/content/en/setup-and-usages/formulas.md @@ -81,12 +81,12 @@ Example: (column1 + (column2 * column3) / (3 - column4 )) ### Date Functions -| Name | Syntax | Sample | Output | -|-------------|-----------------------------------------------------------|-------------------------------------------------------|-------------------------------------------------------------------------------------------------------| -| **DATEADD** | `DATEADD(DATE_COL, 1, 'day')` | `DATEADD(date, 1, 'day')` | Supposing the DATE_COL is 2022-03-14. The result is 2022-03-15. | -| | `DATEADD(DATE_TIME_COL, 2, 'month')` | `DATEADD(datetime, 2, 'month')` | Supposing the DATE_COL is 2022-03-14 03:14. The result is 2022-05-14 03:14. | -| | `IF(NOW() < DATE_COL, "true", "false")` | `IF(NOW() < date, "true", "false")` | If current date is less than DATE_COL, it returns true. Otherwise, it returns false. | -| | `IF(NOW() < DATEADD(DATE_COL,10,'day'), "true", "false")` | `IF(NOW() < DATEADD(date,10,'day'), "true", "false")` | If the current date is less than DATE_COL plus 10 days, it returns true. Otherwise, it returns false. | +| Name | Syntax | Sample | Output | Remark | +|---|---|---|---|---| +| **DATEADD** | `DATEADD(DATE_COL, 1, 'day')` | `DATEADD(date, 1, 'day')` | Supposing the DATE_COL is 2022-03-14. The result is 2022-03-15. | DateTime columns and negative values are supported. Example: `DATEADD(DATE_TIME_COL, -1, 'day')` | +| | `DATEADD(DATE_COL, 2, 'month')` | `DATEADD(date, 2, 'month')` | Supposing the DATE_COL is 2022-03-14 03:14. The result is 2022-05-14 03:14. | DateTime columns and negative values are supported. Example: `DATEADD(DATE_TIME_COL, -2, 'month')` | +| | `IF(NOW() < DATE_COL, "true", "false")` | `IF(NOW() < date, "true", "false")` | If current date is less than DATE_COL, it returns true. Otherwise, it returns false. | DateTime columns and negative values are supported. | +| | `IF(NOW() < DATEADD(DATE_COL,10,'day'), "true", "false")` | `IF(NOW() < DATEADD(date,10,'day'), "true", "false")` | If the current date is less than DATE_COL plus 10 days, it returns true. Otherwise, it returns false. | DateTime columns and negative values are supported. | ### Logical Operators diff --git a/packages/nocodb/src/lib/dataMapper/lib/sql/formulav2/formulaQueryBuilderv2.ts b/packages/nocodb/src/lib/dataMapper/lib/sql/formulav2/formulaQueryBuilderv2.ts index 56f0d8227a..7bc9327ab5 100644 --- a/packages/nocodb/src/lib/dataMapper/lib/sql/formulav2/formulaQueryBuilderv2.ts +++ b/packages/nocodb/src/lib/dataMapper/lib/sql/formulav2/formulaQueryBuilderv2.ts @@ -564,15 +564,6 @@ export default async function formulaQueryBuilderv2( } } break; - case 'DATEADD': - if (pt.arguments[1].value) { - pt.callee.name = 'DATE_ADD'; - return fn(pt, alias, prevBinaryOp); - } else if (pt.arguments[1].operator == '-') { - pt.callee.name = 'DATE_SUB'; - return fn(pt, alias, prevBinaryOp); - } - break; case 'URL': return fn( { @@ -654,6 +645,14 @@ export default async function formulaQueryBuilderv2( query.wrap('(', ')'); } return query; + } else if (pt.type === 'UnaryExpression') { + const query = knex.raw( + `${pt.operator}${fn(pt.argument, null, pt.operator).toQuery()}${colAlias}` + ); + if (prevBinaryOp && pt.operator !== prevBinaryOp) { + query.wrap('(', ')'); + } + return query; } }; return { builder: fn(tree, alias) }; diff --git a/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/mssql.ts b/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/mssql.ts index fc45fc4b9e..2a9bb14d6c 100644 --- a/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/mssql.ts +++ b/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/mssql.ts @@ -89,31 +89,16 @@ const mssql = { .raw(`CAST(${args.fn(args.pt.arguments[0])} as FLOAT)${args.colAlias}`) .wrap('(', ')'); }, - DATE_ADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => { + DATEADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => { + const dateIN = fn(pt.arguments[1]); return knex.raw( `CASE WHEN ${fn(pt.arguments[0])} LIKE '%:%' THEN FORMAT(DATEADD(${String(fn(pt.arguments[2])).replace(/["']/g, '')}, - +${fn(pt.arguments[1])}, ${fn(pt.arguments[0])}), 'yyyy-MM-dd HH:mm') + ${dateIN > 0 ? '+' : ''}${fn(pt.arguments[1])}, ${fn(pt.arguments[0])}), 'yyyy-MM-dd HH:mm') ELSE FORMAT(DATEADD(${String(fn(pt.arguments[2])).replace(/["']/g, '')}, - +${fn(pt.arguments[1])}, ${fn(pt.arguments[0])}), 'yyyy-MM-dd') - END${colAlias}` - ); - }, - DATE_SUB: ({ fn, knex, pt, colAlias }: MapFnArgs) => { - return knex.raw( - `CASE - WHEN ${fn(pt.arguments[0])} LIKE '%:%' THEN - FORMAT(DATEADD(${String(fn(pt.arguments[2])).replace(/["']/g, '')}, - -${fn(pt.arguments[1])}.argument.value, ${fn( - pt.arguments[0] - )}), 'yyyy-MM-dd HH:mm') - ELSE - FORMAT(DATEADD(${String(fn(pt.arguments[2])).replace(/["']/g, '')}, - -${fn(pt.arguments[1])}.argument.value, ${fn( - pt.arguments[0] - )}), 'yyyy-MM-dd') + ${dateIN > 0 ? '+' : ''}${fn(pt.arguments[1])}, ${fn(pt.arguments[0])}), 'yyyy-MM-dd') END${colAlias}` ); } diff --git a/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/mysql.ts b/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/mysql.ts index c1602330bb..442914abd8 100644 --- a/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/mysql.ts +++ b/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/mysql.ts @@ -37,7 +37,7 @@ const mysql2 = { .raw(`CAST(${args.fn(args.pt.arguments[0])} as DOUBLE)${args.colAlias}`) .wrap('(', ')'); }, - DATE_ADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => { + DATEADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => { return knex.raw( `CASE WHEN ${fn(pt.arguments[0])} LIKE '%:%' THEN @@ -54,20 +54,6 @@ const mysql2 = { )})) END${colAlias}` ); - }, - DATE_SUB: ({ fn, knex, pt, colAlias }: MapFnArgs) => { - return knex.raw( - `CASE - WHEN ${fn(pt.arguments[0])} LIKE '%:%' THEN - DATE_FORMAT(DATE_ADD(${fn(pt.arguments[0])}, INTERVAL - ${fn(pt.arguments[1])}.argument.value - ${String(fn(pt.arguments[2])).replace(/["']/g, '')}), '%Y-%m-%d %H:%i') - ELSE - DATE(DATE_ADD(${fn(pt.arguments[0])}, INTERVAL - ${fn(pt.arguments[1])}.argument.value - ${String(fn(pt.arguments[2])).replace(/["']/g, '')})) - END${colAlias}` - ); } }; diff --git a/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/pg.ts b/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/pg.ts index 6623937741..ffc5d03d0e 100644 --- a/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/pg.ts +++ b/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/pg.ts @@ -33,37 +33,18 @@ const pg = { .raw(`CAST(${fn(pt.arguments[0])} as DOUBLE PRECISION)${colAlias}`) .wrap('(', ')'); }, - DATE_ADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => { + DATEADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => { return knex.raw( `CASE WHEN CAST(${fn(pt.arguments[0])} AS text) LIKE '%:%' THEN - to_char(${fn(pt.arguments[0])} + INTERVAL '${fn(pt.arguments[1])} + ${fn(pt.arguments[0])} + INTERVAL '${fn(pt.arguments[1])} ${String(fn(pt.arguments[2])).replace( /["']/g, '' - )}', 'YYYY-MM-DD HH24:MI') + )}' ELSE - to_char(${fn(pt.arguments[0])} + INTERVAL '${fn(pt.arguments[1])} - ${String(fn(pt.arguments[2])).replace(/["']/g, '')}', 'YYYY-MM-DD') - END${colAlias}` - ); - }, - DATE_SUB: ({ fn, knex, pt, colAlias }: MapFnArgs) => { - return knex.raw( - `CASE - WHEN CAST(${fn(pt.arguments[0])} AS text) LIKE '%:%' THEN - to_char(${fn(pt.arguments[0])} - INTERVAL '${ - fn(pt.arguments[1]).argument.value - } - ${String(fn(pt.arguments[2])).replace( - /["']/g, - '' - )}', 'YYYY-MM-DD HH24:MI') - ELSE - to_char(${fn(pt.arguments[0])} - INTERVAL '${ - fn(pt.arguments[1]).argument.value - } - ${String(fn(pt.arguments[2])).replace(/["']/g, '')}', 'YYYY-MM-DD') + ${fn(pt.arguments[0])} + INTERVAL '${fn(pt.arguments[1])} + ${String(fn(pt.arguments[2])).replace(/["']/g, '')}' END${colAlias}` ); } diff --git a/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/sqlite.ts b/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/sqlite.ts index 72b6e52c2f..67bfe7e88b 100644 --- a/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/sqlite.ts +++ b/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/sqlite.ts @@ -56,43 +56,26 @@ const sqlite3 = { .raw(`CAST(${args.fn(args.pt.arguments[0])} as FLOAT)${args.colAlias}`) .wrap('(', ')'); }, - DATE_ADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => { + DATEADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => { + const dateIN = fn(pt.arguments[1]); return knex.raw( `CASE WHEN ${fn(pt.arguments[0])} LIKE '%:%' THEN STRFTIME('%Y-%m-%d %H:%M', DATETIME(DATETIME(${fn( pt.arguments[0] )}, 'localtime'), - '+${fn(pt.arguments[1])} ${String(fn(pt.arguments[2])).replace( + '${dateIN > 0 ? '+' : ''}${fn(pt.arguments[1])} ${String(fn(pt.arguments[2])).replace( /["']/g, '' )}')) ELSE DATE(DATETIME(${fn(pt.arguments[0])}, 'localtime'), - '+${fn(pt.arguments[1])} ${String(fn(pt.arguments[2])).replace( + '${dateIN > 0 ? '+' : ''}${fn(pt.arguments[1])} ${String(fn(pt.arguments[2])).replace( /["']/g, '' )}') END${colAlias}` ); - }, - DATE_SUB: ({ fn, knex, pt, colAlias }: MapFnArgs) => { - return knex.raw( - `CASE - WHEN ${fn(pt.arguments[0])} LIKE '%:%' THEN - STRFTIME('%Y-%m-%d %H:%M', DATETIME(DATETIME(${fn( - pt.arguments[0] - )}, 'localtime'), - '-${fn(pt.arguments[1]).argument.value} ${String( - fn(pt.arguments[2]) - ).replace(/["']/g, '')}')) - ELSE - DATE(DATETIME(${fn(pt.arguments[0])}, 'localtime'), - '-${fn(pt.arguments[1]).argument.value} ${String( - fn(pt.arguments[2]) - ).replace(/["']/g, '')}') - END${colAlias}` - ); } };