From cb77f071a07e76f2eade9f89a2e7a5c4cdca3b8f Mon Sep 17 00:00:00 2001 From: Verhille Date: Sun, 22 Sep 2024 18:26:06 +0200 Subject: [PATCH] feat: implement JSON_EXTRACT for mssql, mysql, pg --- .../nocodb/src/db/functionMappings/mssql.ts | 15 +++++++++-- .../nocodb/src/db/functionMappings/mysql.ts | 11 ++++++++ packages/nocodb/src/db/functionMappings/pg.ts | 27 ++++++++++++++----- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/packages/nocodb/src/db/functionMappings/mssql.ts b/packages/nocodb/src/db/functionMappings/mssql.ts index 2b17bfde61..57fd303902 100644 --- a/packages/nocodb/src/db/functionMappings/mssql.ts +++ b/packages/nocodb/src/db/functionMappings/mssql.ts @@ -127,7 +127,7 @@ const mssql = { FORMAT(DATEADD(${String((await fn(pt.arguments[2])).builder).replace( /["']/g, '', - )}, + )}, ${dateIN > 0 ? '+' : ''}${(await fn(pt.arguments[1])).builder}, ${ (await fn(pt.arguments[0])).builder }), 'yyyy-MM-dd HH:mm:ss') @@ -135,7 +135,7 @@ const mssql = { FORMAT(DATEADD(${String((await fn(pt.arguments[2])).builder).replace( /["']/g, '', - )}, + )}, ${dateIN > 0 ? '+' : ''}${(await fn(pt.arguments[1])).builder}, ${ (await fn(pt.arguments[0])).builder }), 'yyyy-MM-dd') @@ -209,6 +209,17 @@ const mssql = { ), }; }, + JSON_EXTRACT: async ({ fn, knex, pt, colAlias }: MapFnArgs) => { + return { + builder: knex.raw( + `CASE WHEN ISJSON(${ + (await fn(pt.arguments[0])).builder + }) = 1 THEN JSON_VALUE(${(await fn(pt.arguments[0])).builder}, ${ + (await fn(pt.arguments[1])).builder + }) ELSE NULL END${colAlias}`, + ), + }; + }, }; export default mssql; diff --git a/packages/nocodb/src/db/functionMappings/mysql.ts b/packages/nocodb/src/db/functionMappings/mysql.ts index 93d798bde3..6656d41e6b 100644 --- a/packages/nocodb/src/db/functionMappings/mysql.ts +++ b/packages/nocodb/src/db/functionMappings/mysql.ts @@ -171,6 +171,17 @@ END) ${colAlias}`, ), }; }, + JSON_EXTRACT: async ({ fn, knex, pt, colAlias }: MapFnArgs) => { + return { + builder: knex.raw( + `CASE WHEN JSON_VALID(${ + (await fn(pt.arguments[0])).builder + }) = 1 THEN JSON_EXTRACT(${(await fn(pt.arguments[0])).builder}, ${ + (await fn(pt.arguments[1])).builder + }) ELSE NULL END${colAlias}`, + ), + }; + }, }; export default mysql2; diff --git a/packages/nocodb/src/db/functionMappings/pg.ts b/packages/nocodb/src/db/functionMappings/pg.ts index 3d877855c3..c6b6ccd78b 100644 --- a/packages/nocodb/src/db/functionMappings/pg.ts +++ b/packages/nocodb/src/db/functionMappings/pg.ts @@ -60,7 +60,7 @@ const pg = { builder: knex.raw( `(${(await fn(pt.arguments[0])).builder})${ pt.arguments[0].dataType !== FormulaDataTypes.DATE ? '::DATE' : '' - } + (${(await fn(pt.arguments[1])).builder} || + } + (${(await fn(pt.arguments[1])).builder} || '${String((await fn(pt.arguments[2])).builder).replace( /["']/g, '', @@ -94,17 +94,17 @@ const pg = { break; case 'month': sql = `( - DATE_PART('year', ${datetime_expr1}::TIMESTAMP) - + DATE_PART('year', ${datetime_expr1}::TIMESTAMP) - DATE_PART('year', ${datetime_expr2}::TIMESTAMP) ) * 12 + ( - DATE_PART('month', ${datetime_expr1}::TIMESTAMP) - + DATE_PART('month', ${datetime_expr1}::TIMESTAMP) - DATE_PART('month', ${datetime_expr2}::TIMESTAMP) )`; break; case 'quarter': - sql = `((EXTRACT(QUARTER FROM ${datetime_expr1}::TIMESTAMP) + - DATE_PART('year', AGE(${datetime_expr1}, '1900/01/01')) * 4) - 1) - - ((EXTRACT(QUARTER FROM ${datetime_expr2}::TIMESTAMP) + + sql = `((EXTRACT(QUARTER FROM ${datetime_expr1}::TIMESTAMP) + + DATE_PART('year', AGE(${datetime_expr1}, '1900/01/01')) * 4) - 1) - + ((EXTRACT(QUARTER FROM ${datetime_expr2}::TIMESTAMP) + DATE_PART('year', AGE(${datetime_expr2}, '1900/01/01')) * 4) - 1)`; break; case 'year': @@ -305,7 +305,7 @@ const pg = { return { builder: knex.raw( - `CASE + `CASE WHEN ${value} IS NULL OR REGEXP_REPLACE(${value}::TEXT, '[^\\d.]+', '', 'g') IN ('.', '') OR LENGTH(REGEXP_REPLACE(${value}::TEXT, '[^.]+', '', 'g')) > 1 THEN NULL WHEN LENGTH(REGEXP_REPLACE(${value}::TEXT, '[^%]', '','g')) > 0 THEN POW(-1, LENGTH(REGEXP_REPLACE(${value}::TEXT, '[^-]','', 'g'))) * (REGEXP_REPLACE(${value}::TEXT, '[^\\d.]+', '', 'g'))::NUMERIC / 100 ELSE POW(-1, LENGTH(REGEXP_REPLACE(${value}::TEXT, '[^-]', '', 'g'))) * (REGEXP_REPLACE(${value}::TEXT, '[^\\d.]+', '', 'g'))::NUMERIC @@ -359,6 +359,19 @@ END ${colAlias}`, ), }; }, + JSON_EXTRACT: async ({ fn, knex, pt, colAlias }: MapFnArgs) => { + return { + builder: knex.raw( + `CASE WHEN (${ + (await fn(pt.arguments[0])).builder + })::jsonb IS NOT NULL THEN (${ + (await fn(pt.arguments[0])).builder + })::jsonb #> ${ + (await fn(pt.arguments[1])).builder + } ELSE NULL END${colAlias}`, + ), + }; + }, }; export default pg;