Browse Source

fix: formula concat

pull/5444/head
Wing-Kam Wong 1 year ago
parent
commit
4e7a543fcc
  1. 41
      packages/nocodb-nest/src/db/formulav2/formulaQueryBuilderv2.ts
  2. 23
      packages/nocodb-nest/src/helpers/convertDateFormat.ts
  3. 45
      packages/nocodb-nest/src/helpers/formulaFnHelper.ts

41
packages/nocodb-nest/src/db/formulav2/formulaQueryBuilderv2.ts

@ -3,12 +3,12 @@ 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 { XKnex } from '../CustomKnex';
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 LinkToAnotherRecordColumn from '../../models/LinkToAnotherRecordColumn';
import type LookupColumn from '../../models/LookupColumn';
@ -633,8 +633,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
@ -646,9 +657,9 @@ async function _formulaQueryBuilder(
}
}
return query;
}),
})
)
).join()})${colAlias}`.replace(/\?/g, '\\?'),
).join()})${colAlias}`.replace(/\?/g, '\\?')
),
};
} else if (pt.type === 'Literal') {
@ -679,8 +690,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 +735,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-nest/src/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-nest/src/helpers/formulaFnHelper.ts

@ -1,4 +1,7 @@
import dayjs from 'dayjs';
import { UITypes } from 'nocodb-sdk';
import Column from '../models/Column';
import { convertDateFormat } from './convertDateFormat';
// todo: tobe fixed
// import customParseFormat from 'dayjs/plugin/customParseFormat';
@ -52,3 +55,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