From ad638355396dbbac1fdb7d421caa7bcbd08129b4 Mon Sep 17 00:00:00 2001 From: Pranav C Date: Wed, 7 Feb 2024 14:08:20 +0000 Subject: [PATCH] fix: filter correction with formula and rollup(gt,lt,gte,etc) --- packages/nocodb/src/db/BaseModelSqlv2.ts | 1 - packages/nocodb/src/db/conditionV2.ts | 72 ++++++++++++++---------- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/packages/nocodb/src/db/BaseModelSqlv2.ts b/packages/nocodb/src/db/BaseModelSqlv2.ts index 9b40981e02..b29fd2239a 100644 --- a/packages/nocodb/src/db/BaseModelSqlv2.ts +++ b/packages/nocodb/src/db/BaseModelSqlv2.ts @@ -427,7 +427,6 @@ class BaseModelSqlv2 { const proto = await this.getProto(); let data; - try { data = await this.execAndParse(qb); } catch (e) { diff --git a/packages/nocodb/src/db/conditionV2.ts b/packages/nocodb/src/db/conditionV2.ts index 66e08c3ad5..d1670525c6 100644 --- a/packages/nocodb/src/db/conditionV2.ts +++ b/packages/nocodb/src/db/conditionV2.ts @@ -569,6 +569,9 @@ const parseConditionV2 = async ( return (qb: Knex.QueryBuilder) => { let [field, val] = [_field, _val]; + // based on custom where clause(builder), we need to change the field and val + // todo: refactor this to use a better approach to make it more readable and clean + let genVal = customWhereClause ? field : val; const dateFormat = qb?.client?.config?.client === 'mysql2' ? 'YYYY-MM-DD HH:mm:ss' @@ -576,7 +579,7 @@ const parseConditionV2 = async ( if ( (column.uidt === UITypes.Formula && - getEquivalentUIType({ formulaColumn: column.colOptions }) == + getEquivalentUIType({ formulaColumn: column }) == UITypes.DateTime) || [ UITypes.Date, @@ -590,91 +593,97 @@ const parseConditionV2 = async ( if (dateFormatFromMeta && isDateMonthFormat(dateFormatFromMeta)) { // reset to 1st now = dayjs(now).date(1); - if (val) val = dayjs(val).date(1); + if (val) genVal = dayjs(val).date(1); } // handle sub operation switch (filter.comparison_sub_op) { case 'today': - val = now; + genVal = now; break; case 'tomorrow': - val = now.add(1, 'day'); + genVal = now.add(1, 'day'); break; case 'yesterday': - val = now.add(-1, 'day'); + genVal = now.add(-1, 'day'); break; case 'oneWeekAgo': - val = now.add(-1, 'week'); + genVal = now.add(-1, 'week'); break; case 'oneWeekFromNow': - val = now.add(1, 'week'); + genVal = now.add(1, 'week'); break; case 'oneMonthAgo': - val = now.add(-1, 'month'); + genVal = now.add(-1, 'month'); break; case 'oneMonthFromNow': - val = now.add(1, 'month'); + genVal = now.add(1, 'month'); break; case 'daysAgo': if (!val) return; - val = now.add(-val, 'day'); + genVal = now.add(-genVal, 'day'); break; case 'daysFromNow': if (!val) return; - val = now.add(val, 'day'); + genVal = now.add(genVal, 'day'); break; case 'exactDate': - if (!val) return; + if (!genVal) return; break; // sub-ops for `isWithin` comparison case 'pastWeek': - val = now.add(-1, 'week'); + genVal = now.add(-1, 'week'); break; case 'pastMonth': - val = now.add(-1, 'month'); + genVal = now.add(-1, 'month'); break; case 'pastYear': - val = now.add(-1, 'year'); + genVal = now.add(-1, 'year'); break; case 'nextWeek': - val = now.add(1, 'week'); + genVal = now.add(1, 'week'); break; case 'nextMonth': - val = now.add(1, 'month'); + genVal = now.add(1, 'month'); break; case 'nextYear': - val = now.add(1, 'year'); + genVal = now.add(1, 'year'); break; case 'pastNumberOfDays': if (!val) return; - val = now.add(-val, 'day'); + genVal = now.add(-genVal, 'day'); break; case 'nextNumberOfDays': - if (!val) return; - val = now.add(val, 'day'); + if (!genVal) return; + genVal = now.add(genVal, 'day'); break; } - if (dayjs.isDayjs(val)) { + if (dayjs.isDayjs(genVal)) { // turn `val` in dayjs object format to string - val = val.format(dateFormat).toString(); + genVal = genVal.format(dateFormat).toString(); // keep YYYY-MM-DD only for date - val = column.uidt === UITypes.Date ? val.substring(0, 10) : val; + genVal = + column.uidt === UITypes.Date ? val.substring(0, 10) : genVal; } } - if (isNumericCol(column.uidt) && typeof val === 'string') { + if (isNumericCol(column.uidt) && typeof genVal === 'string') { // convert to number - val = +val; + genVal = +genVal; + } + + // if customWhereClause(builder) is provided, replace field with raw value + // or assign value to val + if (customWhereClause) { + field = knex.raw('?', [genVal]); + } else { + val = genVal; } switch (filter.comparison_op) { case 'eq': if (qb?.client?.config?.client === 'mysql2') { if ( - (column.uidt === UITypes.Formula && - getEquivalentUIType({ formulaColumn: column.colOptions }) == - UITypes.DateTime) || [ UITypes.Duration, UITypes.Currency, @@ -688,6 +697,9 @@ const parseConditionV2 = async ( ) { qb = qb.where(field, val); } else if ( + (column.uidt === UITypes.Formula && + getEquivalentUIType({ formulaColumn: column }) == + UITypes.DateTime) || column.ct === 'timestamp' || column.ct === 'date' || column.ct === 'datetime' @@ -700,7 +712,7 @@ const parseConditionV2 = async ( } else { if ( (column.uidt === UITypes.Formula && - getEquivalentUIType({ formulaColumn: column.colOptions }) == + getEquivalentUIType({ formulaColumn: column }) == UITypes.DateTime) || [ UITypes.DateTime,