Browse Source

Merge pull request #5463 from nocodb/fix/formula-concat

fix: formula concat
pull/5472/head
Raju Udava 1 year ago committed by GitHub
parent
commit
786d0d396d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 40
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts
  2. 23
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/convertDateFormat.ts
  3. 45
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/formulaFnHelper.ts

40
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts

@ -3,11 +3,14 @@ import { jsepCurlyHook, UITypes } from 'nocodb-sdk';
import mapFunctionName from '../mapFunctionName';
import genRollupSelectv2 from '../genRollupSelectv2';
import FormulaColumn from '../../../../../models/FormulaColumn';
import { validateDateWithUnknownFormat } from '../helpers/formulaFnHelper';
import {
convertDateFormatForConcat,
validateDateWithUnknownFormat,
} from '../helpers/formulaFnHelper';
import { CacheGetType, CacheScope } from '../../../../../utils/globals';
import NocoCache from '../../../../../cache/NocoCache';
import type Model from '../../../../../models/Model';
import type Column from '../../../../../models/Column';
import type Model from '../../../../../models/Model';
import type RollupColumn from '../../../../../models/RollupColumn';
import type { XKnex } from '../../../index';
import type LinkToAnotherRecordColumn from '../../../../../models/LinkToAnotherRecordColumn';
@ -633,8 +636,19 @@ async function _formulaQueryBuilder(
`${pt.callee.name}(${(
await Promise.all(
pt.arguments.map(async (arg) => {
const query = (await fn(arg)).builder.toQuery();
let query = (await fn(arg)).builder.toQuery();
if (pt.callee.name === 'CONCAT') {
if (knex.clientType() !== 'sqlite3') {
query = await convertDateFormatForConcat(
arg,
columnIdToUidt,
query,
knex.clientType()
);
} else {
// sqlite3: special handling - See BinaryExpression
}
if (knex.clientType() === 'mysql2') {
// mysql2: CONCAT() returns NULL if any argument is NULL.
// adding IFNULL to convert NULL values to empty strings
@ -679,8 +693,8 @@ async function _formulaQueryBuilder(
pt.left.fnName = pt.left.fnName || 'ARITH';
pt.right.fnName = pt.right.fnName || 'ARITH';
const left = (await fn(pt.left, null, pt.operator)).builder.toQuery();
const right = (await fn(pt.right, null, pt.operator)).builder.toQuery();
let left = (await fn(pt.left, null, pt.operator)).builder.toQuery();
let right = (await fn(pt.right, null, pt.operator)).builder.toQuery();
let sql = `${left} ${pt.operator} ${right}${colAlias}`;
// comparing a date with empty string would throw
@ -724,8 +738,22 @@ async function _formulaQueryBuilder(
}
}
// handle NULL values when calling CONCAT for sqlite3
if (pt.left.fnName === 'CONCAT' && knex.clientType() === 'sqlite3') {
// handle date format
left = await convertDateFormatForConcat(
pt.left?.arguments?.[0],
columnIdToUidt,
left,
knex.clientType()
);
right = await convertDateFormatForConcat(
pt.right?.arguments?.[0],
columnIdToUidt,
right,
knex.clientType()
);
// handle NULL values when calling CONCAT for sqlite3
sql = `COALESCE(${left}, '') ${pt.operator} COALESCE(${right},'')${colAlias}`;
}

23
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/convertDateFormat.ts

@ -0,0 +1,23 @@
export function convertDateFormat(date_format: string, type: string) {
if (date_format === 'YYYY-MM-DD') {
if (type === 'mysql2' || type === 'sqlite3') return '%Y-%m-%d';
} else if (date_format === 'YYYY/MM/DD') {
if (type === 'mysql2' || type === 'sqlite3') return '%Y/%m/%d';
} else if (date_format === 'DD-MM-YYYY') {
if (type === 'mysql2' || type === 'sqlite3') return '%d/%m/%Y';
} else if (date_format === 'MM-DD-YYYY') {
if (type === 'mysql2' || type === 'sqlite3') return '%d-%m-%Y';
} else if (date_format === 'DD/MM/YYYY') {
if (type === 'mysql2' || type === 'sqlite3') return '%d/%m/%Y';
} else if (date_format === 'MM/DD/YYYY') {
if (type === 'mysql2' || type === 'sqlite3') return '%m-%d-%Y';
} else if (date_format === 'DD MM YYYY') {
if (type === 'mysql2' || type === 'sqlite3') return '%d %m %Y';
} else if (date_format === 'MM DD YYYY') {
if (type === 'mysql2' || type === 'sqlite3') return '%m %d %Y';
} else if (date_format === 'YYYY MM DD') {
if (type === 'mysql2' || type === 'sqlite3') return '%Y %m %d';
}
// pg / mssql
return date_format;
}

45
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/formulaFnHelper.ts

@ -1,5 +1,8 @@
import dayjs, { extend } from 'dayjs';
import customParseFormat from 'dayjs/plugin/customParseFormat.js';
import { UITypes } from 'nocodb-sdk';
import Column from '../../../../../models/Column';
import { convertDateFormat } from './convertDateFormat';
extend(customParseFormat);
export function getWeekdayByText(v: string) {
@ -50,3 +53,45 @@ export function validateDateWithUnknownFormat(v: string) {
}
return false;
}
export async function convertDateFormatForConcat(
o,
columnIdToUidt,
query,
clientType
) {
if (
o?.type === 'Identifier' &&
o?.name in columnIdToUidt &&
columnIdToUidt[o.name] === UITypes.Date
) {
const meta = (
await Column.get({
colId: o.name,
})
).meta;
if (clientType === 'mysql2') {
query = `DATE_FORMAT(${query}, '${convertDateFormat(
meta.date_format,
clientType
)}')`;
} else if (clientType === 'pg') {
query = `TO_CHAR(${query}, '${convertDateFormat(
meta.date_format,
clientType
)}')`;
} else if (clientType === 'sqlite3') {
query = `strftime('${convertDateFormat(
meta.date_format,
clientType
)}', ${query})`;
} else if (clientType === 'mssql') {
query = `FORMAT(${query}, '${convertDateFormat(
meta.date_format,
clientType
)}')`;
}
}
return query;
}

Loading…
Cancel
Save