Browse Source

refactor: convert to async...await to resolve builder only if required

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/5392/head
Pranav C 2 years ago
parent
commit
33f19aa596
  1. 91
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts
  2. 56
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/commonFns.ts
  3. 104
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/mssql.ts
  4. 184
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/mysql.ts
  5. 28
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/pg.ts
  6. 382
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/sqlite.ts
  7. 9
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/mapFunctionName.ts

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

@ -53,7 +53,7 @@ async function _formulaQueryBuilder(
alias, alias,
knex: XKnex, knex: XKnex,
model: Model, model: Model,
aliasToColumn = {}, aliasToColumn: Record<string, () => Promise<{ builder: any }>> = {},
tableAlias?: string tableAlias?: string
) { ) {
// formula may include double curly brackets in previous version // formula may include double curly brackets in previous version
@ -69,21 +69,25 @@ async function _formulaQueryBuilder(
switch (col.uidt) { switch (col.uidt) {
case UITypes.Formula: case UITypes.Formula:
{ {
const formulOption = await col.getColOptions<FormulaColumn>(); aliasToColumn[col.id] = async () => {
const { builder } = await _formulaQueryBuilder( const formulOption = await col.getColOptions<FormulaColumn>();
formulOption.formula, const { builder } = await _formulaQueryBuilder(
alias, formulOption.formula,
knex, alias,
model, knex,
{ ...aliasToColumn, [col.id]: null }, model,
tableAlias { ...aliasToColumn, [col.id]: null },
); tableAlias
builder.sql = '(' + builder.sql + ')'; );
aliasToColumn[col.id] = builder; builder.sql = '(' + builder.sql + ')';
return {
builder,
};
};
} }
break; break;
case UITypes.Lookup: case UITypes.Lookup:
{ aliasToColumn[col.id] = async (): Promise<any> => {
let aliasCount = 0; let aliasCount = 0;
let selectQb; let selectQb;
let isMany = false; let isMany = false;
@ -398,25 +402,27 @@ async function _formulaQueryBuilder(
} }
if (selectQb) if (selectQb)
aliasToColumn[col.id] = return {
typeof selectQb === 'function' builder:
? selectQb typeof selectQb === 'function'
: knex.raw(selectQb as any).wrap('(', ')'); ? selectQb
: knex.raw(selectQb as any).wrap('(', ')'),
};
} }
} };
break; break;
case UITypes.Rollup: case UITypes.Rollup:
{ aliasToColumn[col.id] = async (): Promise<any> => {
const qb = await genRollupSelectv2({ const qb = await genRollupSelectv2({
knex, knex,
columnOptions: (await col.getColOptions()) as RollupColumn, columnOptions: (await col.getColOptions()) as RollupColumn,
alias: tableAlias, alias: tableAlias,
}); });
aliasToColumn[col.id] = knex.raw(qb.builder).wrap('(', ')'); return { builder: knex.raw(qb.builder).wrap('(', ')') };
} };
break; break;
case UITypes.LinkToAnotherRecord: case UITypes.LinkToAnotherRecord:
{ aliasToColumn[col.id] = async (): Promise<any> => {
const alias = `__nc_formula_ll`; const alias = `__nc_formula_ll`;
const relation = await col.getColOptions<LinkToAnotherRecordColumn>(); const relation = await col.getColOptions<LinkToAnotherRecordColumn>();
// if (relation.type !== 'bt') continue; // if (relation.type !== 'bt') continue;
@ -520,19 +526,22 @@ async function _formulaQueryBuilder(
.wrap('(', ')'); .wrap('(', ')');
} }
if (selectQb) if (selectQb)
aliasToColumn[col.id] = return {
typeof selectQb === 'function' builder:
? selectQb typeof selectQb === 'function'
: knex.raw(selectQb as any).wrap('(', ')'); ? selectQb
} : knex.raw(selectQb as any).wrap('(', ')'),
};
};
break; break;
default: default:
aliasToColumn[col.id] = col.column_name; aliasToColumn[col.id] = () =>
Promise.resolve({ builder: col.column_name });
break; break;
} }
} }
const fn = (pt, a?, prevBinaryOp?) => { const fn = async (pt, a?, prevBinaryOp?) => {
const colAlias = a ? ` as ${a}` : ''; const colAlias = a ? ` as ${a}` : '';
pt.arguments?.forEach?.((arg) => { pt.arguments?.forEach?.((arg) => {
if (arg.fnName) return; if (arg.fnName) return;
@ -558,18 +567,6 @@ async function _formulaQueryBuilder(
return fn(pt.arguments[0], a, prevBinaryOp); return fn(pt.arguments[0], a, prevBinaryOp);
} }
break; break;
// case 'AVG':
// if (pt.arguments.length > 1) {
// return fn({
// type: 'BinaryExpression',
// operator: '/',
// left: {...pt, callee: {name: 'SUM'}},
// right: {type: 'Literal', value: pt.arguments.length}
// }, a, prevBinaryOp)
// } else {
// return fn(pt.arguments[0], a, prevBinaryOp)
// }
// break;
case 'CONCAT': case 'CONCAT':
if (knex.clientType() === 'sqlite3') { if (knex.clientType() === 'sqlite3') {
if (pt.arguments.length > 1) { if (pt.arguments.length > 1) {
@ -653,8 +650,12 @@ async function _formulaQueryBuilder(
} else if (pt.type === 'Literal') { } else if (pt.type === 'Literal') {
return knex.raw(`?${colAlias}`, [pt.value]); return knex.raw(`?${colAlias}`, [pt.value]);
} else if (pt.type === 'Identifier') { } else if (pt.type === 'Identifier') {
if (typeof aliasToColumn?.[pt.name] === 'function') { const { builder } = await aliasToColumn?.[pt.name]()
return knex.raw(`??${colAlias}`, aliasToColumn?.[pt.name](pt.fnName)); if (typeof builder === 'function') {
return knex.raw(
`??${colAlias}`,
await builder(pt.fnName)
);
} }
return knex.raw(`??${colAlias}`, [aliasToColumn?.[pt.name] || pt.name]); return knex.raw(`??${colAlias}`, [aliasToColumn?.[pt.name] || pt.name]);
} else if (pt.type === 'BinaryExpression') { } else if (pt.type === 'BinaryExpression') {
@ -772,7 +773,7 @@ async function _formulaQueryBuilder(
if (prevBinaryOp && pt.operator !== prevBinaryOp) { if (prevBinaryOp && pt.operator !== prevBinaryOp) {
query.wrap('(', ')'); query.wrap('(', ')');
} }
return query; return { builder: query };
} else if (pt.type === 'UnaryExpression') { } else if (pt.type === 'UnaryExpression') {
const query = knex.raw( const query = knex.raw(
`${pt.operator}${fn( `${pt.operator}${fn(
@ -784,7 +785,7 @@ async function _formulaQueryBuilder(
if (prevBinaryOp && pt.operator !== prevBinaryOp) { if (prevBinaryOp && pt.operator !== prevBinaryOp) {
query.wrap('(', ')'); query.wrap('(', ')');
} }
return query; return { builder: query };
} }
}; };
return { builder: fn(tree, alias) }; return { builder: fn(tree, alias) };

56
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/commonFns.ts

@ -2,66 +2,80 @@ import type { MapFnArgs } from '../mapFunctionName';
export default { export default {
// todo: handle default case // todo: handle default case
SWITCH: (args: MapFnArgs) => { SWITCH: async (args: MapFnArgs) => {
const count = Math.floor((args.pt.arguments.length - 1) / 2); const count = Math.floor((args.pt.arguments.length - 1) / 2);
let query = ''; let query = '';
const switchVal = args.fn(args.pt.arguments[0]).toQuery(); const switchVal = (await args.fn(args.pt.arguments[0])).builder.toQuery();
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
query += args.knex query += args.knex
.raw( .raw(
`\n\tWHEN ${args `\n\tWHEN ${(
.fn(args.pt.arguments[i * 2 + 1]) await args.fn(args.pt.arguments[i * 2 + 1])
.toQuery()} THEN ${args.fn(args.pt.arguments[i * 2 + 2]).toQuery()}` ).builder.toQuery()} THEN ${(
await args.fn(args.pt.arguments[i * 2 + 2])
).builder.toQuery()}`
) )
.toQuery(); .toQuery();
} }
if (args.pt.arguments.length % 2 === 0) { if (args.pt.arguments.length % 2 === 0) {
query += args.knex query += args.knex
.raw( .raw(
`\n\tELSE ${args `\n\tELSE ${(
.fn(args.pt.arguments[args.pt.arguments.length - 1]) await args.fn(args.pt.arguments[args.pt.arguments.length - 1])
.toQuery()}` ).builder.toQuery()}`
) )
.toQuery(); .toQuery();
} }
return args.knex.raw(`CASE ${switchVal} ${query}\n END${args.colAlias}`); return args.knex.raw(`CASE ${switchVal} ${query}\n END${args.colAlias}`);
}, },
IF: (args: MapFnArgs) => { IF: async (args: MapFnArgs) => {
let query = args.knex let query = args.knex
.raw( .raw(
`\n\tWHEN ${args.fn(args.pt.arguments[0]).toQuery()} THEN ${args `\n\tWHEN ${(
.fn(args.pt.arguments[1]) await args.fn(args.pt.arguments[0])
.toQuery()}` ).builder.toQuery()} THEN ${(
await args.fn(args.pt.arguments[1])
).builder.toQuery()}`
) )
.toQuery(); .toQuery();
if (args.pt.arguments[2]) { if (args.pt.arguments[2]) {
query += args.knex query += args.knex
.raw(`\n\tELSE ${args.fn(args.pt.arguments[2]).toQuery()}`) .raw(`\n\tELSE ${(await args.fn(args.pt.arguments[2])).builder.toQuery()}`)
.toQuery(); .toQuery();
} }
return args.knex.raw(`CASE ${query}\n END${args.colAlias}`); return args.knex.raw(`CASE ${query}\n END${args.colAlias}`);
}, },
TRUE: (_args) => 1, TRUE: (_args) => 1,
FALSE: (_args) => 0, FALSE: (_args) => 0,
AND: (args: MapFnArgs) => { AND: async (args: MapFnArgs) => {
return args.knex.raw( return args.knex.raw(
`${args.knex `${args.knex
.raw( .raw(
`${args.pt.arguments `${(
.map((ar) => args.fn(ar).toQuery()) await Promise.all(
.join(' AND ')}` args.pt.arguments.map(async (ar) =>
(await args.fn(ar)).builder.toQuery()
)
)
).join(' AND ')}`
) )
.wrap('(', ')') .wrap('(', ')')
.toQuery()}${args.colAlias}` .toQuery()}${args.colAlias}`
); );
}, },
OR: (args: MapFnArgs) => { OR: async (args: MapFnArgs) => {
return args.knex.raw( return args.knex.raw(
`${args.knex `${args.knex
.raw( .raw(
`${args.pt.arguments.map((ar) => args.fn(ar).toQuery()).join(' OR ')}` `${(
await Promise.all(
args.pt.arguments.map(async (ar) =>
(await args.fn(ar)).builder.toQuery()
)
)
).join(' OR ')}`
) )
.wrap('(', ')') .wrap('(', ')')
.toQuery()}${args.colAlias}` .toQuery()}${args.colAlias}`
@ -83,7 +97,7 @@ export default {
return args.fn(args.pt.arguments[0], args.a, args.prevBinaryOp); return args.fn(args.pt.arguments[0], args.a, args.prevBinaryOp);
} }
}, },
FLOAT: (args: MapFnArgs) => { FLOAT: async (args: MapFnArgs) => {
return args.fn(args.pt?.arguments?.[0]).wrap('(', ')'); return (await args.fn(args.pt?.arguments?.[0])).builder.wrap('(', ')');
}, },
}; };

104
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/mssql.ts

@ -6,48 +6,61 @@ import type { MapFnArgs } from '../mapFunctionName';
const mssql = { const mssql = {
...commonFns, ...commonFns,
MIN: (args: MapFnArgs) => { MIN: async (args: MapFnArgs) => {
if (args.pt.arguments.length === 1) { if (args.pt.arguments.length === 1) {
return args.fn(args.pt.arguments[0]); return args.fn(args.pt.arguments[0]);
} }
let query = ''; let query = '';
for (const [i, arg] of Object.entries(args.pt.arguments)) { for (const [i, arg] of Object.entries(args.pt.arguments)) {
if (+i === args.pt.arguments.length - 1) { if (+i === args.pt.arguments.length - 1) {
query += args.knex.raw(`\n\tElse ${args.fn(arg).toQuery()}`).toQuery(); query += args.knex
.raw(
`\n\tElse ${(await await args.fn(arg)).builder.builder.toQuery()}`
)
.toQuery();
} else { } else {
query += args.knex query += args.knex
.raw( .raw(
`\n\tWhen ${args.pt.arguments `\n\tWhen ${(
.filter((_, j) => +i !== j) await Promise.all(
.map( args.pt.arguments
(arg1) => .filter((_, j) => +i !== j)
`${args.fn(arg).toQuery()} < ${args.fn(arg1).toQuery()}` .map(
async (arg1) =>
`${(await args.fn(arg)).builder.toQuery()} < ${(
await args.fn(arg1)
).builder.toQuery()}`
)
) )
.join(' And ')} Then ${args.fn(arg).toQuery()}` ).join(' And ')} Then ${(await args.fn(arg)).builder.toQuery()}`
) )
.toQuery(); .toQuery();
} }
} }
return args.knex.raw(`Case ${query}\n End${args.colAlias}`); return args.knex.raw(`Case ${query}\n End${args.colAlias}`);
}, },
MAX: (args: MapFnArgs) => { MAX: async (args: MapFnArgs) => {
if (args.pt.arguments.length === 1) { if (args.pt.arguments.length === 1) {
return args.fn(args.pt.arguments[0]); return args.fn(args.pt.arguments[0]);
} }
let query = ''; let query = '';
for (const [i, arg] of Object.entries(args.pt.arguments)) { for (const [i, arg] of Object.entries(args.pt.arguments)) {
if (+i === args.pt.arguments.length - 1) { if (+i === args.pt.arguments.length - 1) {
query += args.knex.raw(`\nElse ${args.fn(arg).toQuery()}`).toQuery(); query += args.knex
.raw(`\nElse ${(await args.fn(arg)).builder.toQuery()}`)
.toQuery();
} else { } else {
query += args.knex query += args.knex
.raw( .raw(
`\nWhen ${args.pt.arguments `\nWhen ${args.pt.arguments
.filter((_, j) => +i !== j) .filter((_, j) => +i !== j)
.map( .map(
(arg1) => async (arg1) =>
`${args.fn(arg).toQuery()} > ${args.fn(arg1).toQuery()}` `${(await args.fn(arg)).builder.toQuery()} > ${(
await args.fn(arg1)
).builder.toQuery()}`
) )
.join(' And ')} Then ${args.fn(arg).toQuery()}` .join(' And ')} Then ${(await args.fn(arg)).builder.toQuery()}`
) )
.toQuery(); .toQuery();
} }
@ -55,12 +68,15 @@ const mssql = {
return args.knex.raw(`Case ${query}\n End${args.colAlias}`); return args.knex.raw(`Case ${query}\n End${args.colAlias}`);
}, },
LOG: (args: MapFnArgs) => { LOG: async (args: MapFnArgs) => {
return args.knex.raw( return args.knex.raw(
`LOG(${args.pt.arguments `LOG(${(
.reverse() await Promise.all(
.map((ar) => args.fn(ar).toQuery()) args.pt.arguments
.join(',')})${args.colAlias}` .reverse()
.map(async (ar) => (await args.fn(ar)).builder.toQuery())
)
).join(',')})${args.colAlias}`
); );
}, },
MOD: (pt) => { MOD: (pt) => {
@ -73,19 +89,19 @@ const mssql = {
}, },
REPEAT: 'REPLICATE', REPEAT: 'REPLICATE',
NOW: 'getdate', NOW: 'getdate',
SEARCH: (args: MapFnArgs) => { SEARCH: async (args: MapFnArgs) => {
args.pt.callee.name = 'CHARINDEX'; args.pt.callee.name = 'CHARINDEX';
const temp = args.pt.arguments[0]; const temp = args.pt.arguments[0];
args.pt.arguments[0] = args.pt.arguments[1]; args.pt.arguments[0] = args.pt.arguments[1];
args.pt.arguments[1] = temp; args.pt.arguments[1] = temp;
}, },
INT: (args: MapFnArgs) => { INT: async (args: MapFnArgs) => {
return args.knex.raw( return args.knex.raw(
`CASE WHEN ISNUMERIC(${args `CASE WHEN ISNUMERIC(${(
.fn(args.pt.arguments[0]) await args.fn(args.pt.arguments[0])
.toQuery()}) = 1 THEN FLOOR(${args ).builder.toQuery()}) = 1 THEN FLOOR(${(
.fn(args.pt.arguments[0]) await args.fn(args.pt.arguments[0])
.toQuery()}) ELSE 0 END${args.colAlias}` ).builder.toQuery()}) ELSE 0 END${args.colAlias}`
); );
}, },
MID: 'SUBSTR', MID: 'SUBSTR',
@ -94,8 +110,8 @@ const mssql = {
.raw(`CAST(${args.fn(args.pt.arguments[0])} as FLOAT)${args.colAlias}`) .raw(`CAST(${args.fn(args.pt.arguments[0])} as FLOAT)${args.colAlias}`)
.wrap('(', ')'); .wrap('(', ')');
}, },
DATEADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => { DATEADD: async ({ fn, knex, pt, colAlias }: MapFnArgs) => {
const dateIN = fn(pt.arguments[1]); const dateIN = (await fn(pt.arguments[1])).builder;
return knex.raw( return knex.raw(
`CASE `CASE
WHEN ${fn(pt.arguments[0])} LIKE '%:%' THEN WHEN ${fn(pt.arguments[0])} LIKE '%:%' THEN
@ -111,49 +127,59 @@ const mssql = {
END${colAlias}` END${colAlias}`
); );
}, },
DATETIME_DIFF: ({ fn, knex, pt, colAlias }: MapFnArgs) => { DATETIME_DIFF: async ({ fn, knex, pt, colAlias }: MapFnArgs) => {
const datetime_expr1 = fn(pt.arguments[0]); const datetime_expr1 = fn(pt.arguments[0]);
const datetime_expr2 = fn(pt.arguments[1]); const datetime_expr2 = fn(pt.arguments[1]);
const rawUnit = pt.arguments[2] const rawUnit = pt.arguments[2]
? fn(pt.arguments[2]).bindings[0] ? (await fn(pt.arguments[2])).builder.bindings[0]
: 'seconds'; : 'seconds';
const unit = convertUnits(rawUnit, 'mssql'); const unit = convertUnits(rawUnit, 'mssql');
return knex.raw( return knex.raw(
`DATEDIFF(${unit}, ${datetime_expr2}, ${datetime_expr1}) ${colAlias}` `DATEDIFF(${unit}, ${datetime_expr2}, ${datetime_expr1}) ${colAlias}`
); );
}, },
WEEKDAY: ({ fn, knex, pt, colAlias }: MapFnArgs) => { WEEKDAY: async ({ fn, knex, pt, colAlias }: MapFnArgs) => {
// DATEPART(WEEKDAY, DATE): sunday = 1, monday = 2, ..., saturday = 7 // DATEPART(WEEKDAY, DATE): sunday = 1, monday = 2, ..., saturday = 7
// WEEKDAY() returns an index from 0 to 6 for Monday to Sunday // WEEKDAY() returns an index from 0 to 6 for Monday to Sunday
return knex.raw( return knex.raw(
`(DATEPART(WEEKDAY, ${ `(DATEPART(WEEKDAY, ${
pt.arguments[0].type === 'Literal' pt.arguments[0].type === 'Literal'
? `'${dayjs(fn(pt.arguments[0])).format('YYYY-MM-DD')}'` ? `'${dayjs((await fn(pt.arguments[0])).builder).format(
'YYYY-MM-DD'
)}'`
: fn(pt.arguments[0]) : fn(pt.arguments[0])
}) - 2 - ${getWeekdayByText( }) - 2 - ${getWeekdayByText(
pt?.arguments[1]?.value pt?.arguments[1]?.value
)} % 7 + 7) % 7 ${colAlias}` )} % 7 + 7) % 7 ${colAlias}`
); );
}, },
AND: (args: MapFnArgs) => { AND: async (args: MapFnArgs) => {
return args.knex.raw( return args.knex.raw(
`CASE WHEN ${args.knex `CASE WHEN ${args.knex
.raw( .raw(
`${args.pt.arguments `${(
.map((ar) => args.fn(ar, '', 'AND').toQuery()) await Promise.all(
.join(' AND ')}` args.pt.arguments.map(async (ar) =>
(await args.fn(ar, '', 'AND')).builder.toQuery()
)
)
).join(' AND ')}`
) )
.wrap('(', ')') .wrap('(', ')')
.toQuery()} THEN 1 ELSE 0 END ${args.colAlias}` .toQuery()} THEN 1 ELSE 0 END ${args.colAlias}`
); );
}, },
OR: (args: MapFnArgs) => { OR: async (args: MapFnArgs) => {
return args.knex.raw( return args.knex.raw(
`CASE WHEN ${args.knex `CASE WHEN ${args.knex
.raw( .raw(
`${args.pt.arguments `${(
.map((ar) => args.fn(ar, '', 'OR').toQuery()) await Promise.all(
.join(' OR ')}` args.pt.arguments.map(async (ar) =>
(await args.fn(ar, '', 'OR')).builder.toQuery()
)
)
).join(' OR ')}`
) )
.wrap('(', ')') .wrap('(', ')')
.toQuery()} THEN 1 ELSE 0 END ${args.colAlias}` .toQuery()} THEN 1 ELSE 0 END ${args.colAlias}`

184
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/mysql.ts

@ -1,99 +1,99 @@
import dayjs from 'dayjs'; // import dayjs from 'dayjs';
import { convertUnits } from '../helpers/convertUnits'; // import { convertUnits } from '../helpers/convertUnits';
import { getWeekdayByText } from '../helpers/formulaFnHelper'; // import { getWeekdayByText } from '../helpers/formulaFnHelper';
import commonFns from './commonFns'; import commonFns from './commonFns';
import type { MapFnArgs } from '../mapFunctionName'; // import type { MapFnArgs } from '../mapFunctionName';
const mysql2 = { const mysql2 = {
...commonFns, ...commonFns,
LEN: 'CHAR_LENGTH', // LEN: 'CHAR_LENGTH',
MIN: 'LEAST', // MIN: 'LEAST',
MAX: 'GREATEST', // MAX: 'GREATEST',
SEARCH: (args: MapFnArgs) => { // SEARCH: (args: MapFnArgs) => {
args.pt.callee.name = 'LOCATE'; // args.pt.callee.name = 'LOCATE';
const temp = args.pt.arguments[0]; // const temp = args.pt.arguments[0];
args.pt.arguments[0] = args.pt.arguments[1]; // args.pt.arguments[0] = args.pt.arguments[1];
args.pt.arguments[1] = temp; // args.pt.arguments[1] = temp;
}, // },
INT: (args: MapFnArgs) => { // INT: (args: MapFnArgs) => {
return args.knex.raw( // return args.knex.raw(
`CAST(${args.fn(args.pt.arguments[0])} as SIGNED)${args.colAlias}` // `CAST(${args.fn(args.pt.arguments[0])} as SIGNED)${args.colAlias}`
); // );
}, // },
LEFT: (args: MapFnArgs) => { // LEFT: (args: MapFnArgs) => {
return args.knex.raw( // return args.knex.raw(
`SUBSTR(${args.fn(args.pt.arguments[0])},1,${args.fn( // `SUBSTR(${args.fn(args.pt.arguments[0])},1,${args.fn(
args.pt.arguments[1] // args.pt.arguments[1]
)})${args.colAlias}` // )})${args.colAlias}`
); // );
}, // },
RIGHT: (args: MapFnArgs) => { // RIGHT: (args: MapFnArgs) => {
return args.knex.raw( // return args.knex.raw(
`SUBSTR(${args.fn(args.pt.arguments[0])}, -(${args.fn( // `SUBSTR(${args.fn(args.pt.arguments[0])}, -(${args.fn(
args.pt.arguments[1] // args.pt.arguments[1]
)}))${args.colAlias}` // )}))${args.colAlias}`
); // );
}, // },
MID: 'SUBSTR', // MID: 'SUBSTR',
FLOAT: (args: MapFnArgs) => { // FLOAT: (args: MapFnArgs) => {
return args.knex // return args.knex
.raw( // .raw(
`CAST(CAST(${args.fn(args.pt.arguments[0])} as CHAR) AS DOUBLE)${ // `CAST(CAST(${args.fn(args.pt.arguments[0])} as CHAR) AS DOUBLE)${
args.colAlias // args.colAlias
}` // }`
) // )
.wrap('(', ')'); // .wrap('(', ')');
}, // },
DATEADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => { // DATEADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => {
return knex.raw( // return knex.raw(
`CASE // `CASE
WHEN ${fn(pt.arguments[0])} LIKE '%:%' THEN // WHEN ${fn(pt.arguments[0])} LIKE '%:%' THEN
DATE_FORMAT(DATE_ADD(${fn(pt.arguments[0])}, INTERVAL // DATE_FORMAT(DATE_ADD(${fn(pt.arguments[0])}, INTERVAL
${fn(pt.arguments[1])} ${String(fn(pt.arguments[2])).replace( // ${fn(pt.arguments[1])} ${String(fn(pt.arguments[2])).replace(
/["']/g, // /["']/g,
'' // ''
)}), '%Y-%m-%d %H:%i') // )}), '%Y-%m-%d %H:%i')
ELSE // ELSE
DATE(DATE_ADD(${fn(pt.arguments[0])}, INTERVAL // DATE(DATE_ADD(${fn(pt.arguments[0])}, INTERVAL
${fn(pt.arguments[1])} ${String(fn(pt.arguments[2])).replace( // ${fn(pt.arguments[1])} ${String(fn(pt.arguments[2])).replace(
/["']/g, // /["']/g,
'' // ''
)})) // )}))
END${colAlias}` // END${colAlias}`
); // );
}, // },
DATETIME_DIFF: ({ fn, knex, pt, colAlias }: MapFnArgs) => { // DATETIME_DIFF: ({ fn, knex, pt, colAlias }: MapFnArgs) => {
const datetime_expr1 = fn(pt.arguments[0]); // const datetime_expr1 = fn(pt.arguments[0]);
const datetime_expr2 = fn(pt.arguments[1]); // const datetime_expr2 = fn(pt.arguments[1]);
//
const unit = convertUnits( // const unit = convertUnits(
pt.arguments[2] ? fn(pt.arguments[2]).bindings[0] : 'seconds', // pt.arguments[2] ? fn(pt.arguments[2]).bindings[0] : 'seconds',
'mysql' // 'mysql'
); // );
//
if (unit === 'MICROSECOND') { // if (unit === 'MICROSECOND') {
// MySQL doesn't support millisecond // // MySQL doesn't support millisecond
// hence change from MICROSECOND to millisecond manually // // hence change from MICROSECOND to millisecond manually
return knex.raw( // return knex.raw(
`TIMESTAMPDIFF(${unit}, ${datetime_expr2}, ${datetime_expr1}) div 1000 ${colAlias}` // `TIMESTAMPDIFF(${unit}, ${datetime_expr2}, ${datetime_expr1}) div 1000 ${colAlias}`
); // );
} // }
return knex.raw( // return knex.raw(
`TIMESTAMPDIFF(${unit}, ${datetime_expr2}, ${datetime_expr1}) ${colAlias}` // `TIMESTAMPDIFF(${unit}, ${datetime_expr2}, ${datetime_expr1}) ${colAlias}`
); // );
}, // },
WEEKDAY: ({ fn, knex, pt, colAlias }: MapFnArgs) => { // WEEKDAY: ({ fn, knex, pt, colAlias }: MapFnArgs) => {
// WEEKDAY() returns an index from 0 to 6 for Monday to Sunday // // WEEKDAY() returns an index from 0 to 6 for Monday to Sunday
return knex.raw( // return knex.raw(
`(WEEKDAY(${ // `(WEEKDAY(${
pt.arguments[0].type === 'Literal' // pt.arguments[0].type === 'Literal'
? `'${dayjs(fn(pt.arguments[0])).format('YYYY-MM-DD')}'` // ? `'${dayjs(fn(pt.arguments[0])).format('YYYY-MM-DD')}'`
: fn(pt.arguments[0]) // : fn(pt.arguments[0])
}) - ${getWeekdayByText( // }) - ${getWeekdayByText(
pt?.arguments[1]?.value // pt?.arguments[1]?.value
)} % 7 + 7) % 7 ${colAlias}` // )} % 7 + 7) % 7 ${colAlias}`
); // );
}, // },
}; };
export default mysql2; export default mysql2;

28
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/pg.ts

@ -12,13 +12,13 @@ const pg = {
CEILING: 'ceil', CEILING: 'ceil',
POWER: 'pow', POWER: 'pow',
SQRT: 'sqrt', SQRT: 'sqrt',
SEARCH: (args: MapFnArgs) => { SEARCH: async (args: MapFnArgs) => {
return args.knex.raw( return args.knex.raw(
`POSITION(${args.knex.raw( `POSITION(${args.knex.raw(
args.fn(args.pt.arguments[1]).toQuery() (await args.fn(args.pt.arguments[1])).builder.toQuery()
)} in ${args.knex.raw(args.fn(args.pt.arguments[0]).toQuery())})${ )} in ${args.knex
args.colAlias .raw((await args.fn(args.pt.arguments[0])).builder)
}` .toQuery()})${args.colAlias}`
); );
}, },
INT(args: MapFnArgs) { INT(args: MapFnArgs) {
@ -51,11 +51,11 @@ const pg = {
)}')::interval${colAlias}` )}')::interval${colAlias}`
); );
}, },
DATETIME_DIFF: ({ fn, knex, pt, colAlias }: MapFnArgs) => { DATETIME_DIFF: async ({ fn, knex, pt, colAlias }: MapFnArgs) => {
const datetime_expr1 = fn(pt.arguments[0]); const datetime_expr1 = fn(pt.arguments[0]);
const datetime_expr2 = fn(pt.arguments[1]); const datetime_expr2 = fn(pt.arguments[1]);
const rawUnit = pt.arguments[2] const rawUnit = pt.arguments[2]
? fn(pt.arguments[2]).bindings[0] ? (await fn(pt.arguments[2])).builder.bindings[0]
: 'seconds'; : 'seconds';
let sql; let sql;
const unit = convertUnits(rawUnit, 'pg'); const unit = convertUnits(rawUnit, 'pg');
@ -101,37 +101,39 @@ const pg = {
} }
return knex.raw(`${sql} ${colAlias}`); return knex.raw(`${sql} ${colAlias}`);
}, },
WEEKDAY: ({ fn, knex, pt, colAlias }: MapFnArgs) => { WEEKDAY: async ({ fn, knex, pt, colAlias }: MapFnArgs) => {
// isodow: the day of the week as Monday (1) to Sunday (7) // isodow: the day of the week as Monday (1) to Sunday (7)
// WEEKDAY() returns an index from 0 to 6 for Monday to Sunday // WEEKDAY() returns an index from 0 to 6 for Monday to Sunday
return knex.raw( return knex.raw(
`(EXTRACT(ISODOW FROM ${ `(EXTRACT(ISODOW FROM ${
pt.arguments[0].type === 'Literal' pt.arguments[0].type === 'Literal'
? `date '${dayjs(fn(pt.arguments[0])).format('YYYY-MM-DD')}'` ? `date '${dayjs((await fn(pt.arguments[0])).builder).format(
'YYYY-MM-DD'
)}'`
: fn(pt.arguments[0]) : fn(pt.arguments[0])
}) - 1 - ${getWeekdayByText( }) - 1 - ${getWeekdayByText(
pt?.arguments[1]?.value pt?.arguments[1]?.value
)} % 7 + 7) ::INTEGER % 7 ${colAlias}` )} % 7 + 7) ::INTEGER % 7 ${colAlias}`
); );
}, },
AND: (args: MapFnArgs) => { AND: async (args: MapFnArgs) => {
return args.knex.raw( return args.knex.raw(
`CASE WHEN ${args.knex `CASE WHEN ${args.knex
.raw( .raw(
`${args.pt.arguments `${args.pt.arguments
.map((ar) => args.fn(ar, '', 'AND').toQuery()) .map(async (ar) => (await args.fn(ar, '', 'AND')).builder.toQuery())
.join(' AND ')}` .join(' AND ')}`
) )
.wrap('(', ')') .wrap('(', ')')
.toQuery()} THEN TRUE ELSE FALSE END ${args.colAlias}` .toQuery()} THEN TRUE ELSE FALSE END ${args.colAlias}`
); );
}, },
OR: (args: MapFnArgs) => { OR: async (args: MapFnArgs) => {
return args.knex.raw( return args.knex.raw(
`CASE WHEN ${args.knex `CASE WHEN ${args.knex
.raw( .raw(
`${args.pt.arguments `${args.pt.arguments
.map((ar) => args.fn(ar, '', 'OR').toQuery()) .map(async (ar) => (await args.fn(ar, '', 'OR')).builder.toQuery())
.join(' OR ')}` .join(' OR ')}`
) )
.wrap('(', ')') .wrap('(', ')')

382
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/sqlite.ts

@ -1,198 +1,198 @@
import dayjs from 'dayjs'; // import dayjs from 'dayjs';
import { convertUnits } from '../helpers/convertUnits'; // import { convertUnits } from '../helpers/convertUnits';
import { getWeekdayByText } from '../helpers/formulaFnHelper'; // import { getWeekdayByText } from '../helpers/formulaFnHelper';
import { // import {
convertToTargetFormat, // convertToTargetFormat,
getDateFormat, // getDateFormat,
} from '../../../../../utils/dateTimeUtils'; // } from '../../../../../utils/dateTimeUtils';
import commonFns from './commonFns'; import commonFns from './commonFns';
import type { MapFnArgs } from '../mapFunctionName'; // import type { MapFnArgs } from '../mapFunctionName';
const sqlite3 = { const sqlite3 = {
...commonFns, ...commonFns,
LEN: 'LENGTH', // LEN: 'LENGTH',
CEILING(args) { // CEILING(args) {
return args.knex.raw( // return args.knex.raw(
`round(${args.fn(args.pt.arguments[0])} + 0.5)${args.colAlias}` // `round(${args.fn(args.pt.arguments[0])} + 0.5)${args.colAlias}`
); // );
}, // },
FLOOR(args) { // FLOOR(args) {
return args.knex.raw( // return args.knex.raw(
`round(${args.fn(args.pt.arguments[0])} - 0.5)${args.colAlias}` // `round(${args.fn(args.pt.arguments[0])} - 0.5)${args.colAlias}`
); // );
}, // },
MOD: (args: MapFnArgs) => { // MOD: (args: MapFnArgs) => {
return args.fn({ // return args.fn({
type: 'BinaryExpression', // type: 'BinaryExpression',
operator: '%', // operator: '%',
left: args.pt.arguments[0], // left: args.pt.arguments[0],
right: args.pt.arguments[1], // right: args.pt.arguments[1],
}); // });
}, // },
REPEAT(args: MapFnArgs) { // REPEAT(args: MapFnArgs) {
return args.knex.raw( // return args.knex.raw(
`replace(printf('%.' || ${args.fn( // `replace(printf('%.' || ${args.fn(
args.pt.arguments[1] // args.pt.arguments[1]
)} || 'c', '/'),'/',${args.fn(args.pt.arguments[0])})${args.colAlias}` // )} || 'c', '/'),'/',${args.fn(args.pt.arguments[0])})${args.colAlias}`
); // );
}, // },
NOW: 'DATE', // NOW: 'DATE',
SEARCH: 'INSTR', // SEARCH: 'INSTR',
INT(args: MapFnArgs) { // INT(args: MapFnArgs) {
return args.knex.raw( // return args.knex.raw(
`CAST(${args.fn(args.pt.arguments[0])} as INTEGER)${args.colAlias}` // `CAST(${args.fn(args.pt.arguments[0])} as INTEGER)${args.colAlias}`
); // );
}, // },
LEFT: (args: MapFnArgs) => { // LEFT: (args: MapFnArgs) => {
return args.knex.raw( // return args.knex.raw(
`SUBSTR(${args.fn(args.pt.arguments[0])},1,${args.fn( // `SUBSTR(${args.fn(args.pt.arguments[0])},1,${args.fn(
args.pt.arguments[1] // args.pt.arguments[1]
)})${args.colAlias}` // )})${args.colAlias}`
); // );
}, // },
RIGHT: (args: MapFnArgs) => { // RIGHT: (args: MapFnArgs) => {
return args.knex.raw( // return args.knex.raw(
`SUBSTR(${args.fn(args.pt.arguments[0])},-(${args.fn( // `SUBSTR(${args.fn(args.pt.arguments[0])},-(${args.fn(
args.pt.arguments[1] // args.pt.arguments[1]
)}))${args.colAlias}` // )}))${args.colAlias}`
); // );
}, // },
MID: 'SUBSTR', // MID: 'SUBSTR',
FLOAT: (args: MapFnArgs) => { // FLOAT: (args: MapFnArgs) => {
return args.knex // return args.knex
.raw(`CAST(${args.fn(args.pt.arguments[0])} as FLOAT)${args.colAlias}`) // .raw(`CAST(${args.fn(args.pt.arguments[0])} as FLOAT)${args.colAlias}`)
.wrap('(', ')'); // .wrap('(', ')');
}, // },
DATEADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => { // DATEADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => {
const dateIN = fn(pt.arguments[1]); // const dateIN = fn(pt.arguments[1]);
return knex.raw( // return knex.raw(
`CASE // `CASE
WHEN ${fn(pt.arguments[0])} LIKE '%:%' THEN // WHEN ${fn(pt.arguments[0])} LIKE '%:%' THEN
STRFTIME('%Y-%m-%d %H:%M', DATETIME(DATETIME(${fn( // STRFTIME('%Y-%m-%d %H:%M', DATETIME(DATETIME(${fn(
pt.arguments[0] // pt.arguments[0]
)}, 'localtime'), // )}, 'localtime'),
${dateIN > 0 ? '+' : ''}${fn(pt.arguments[1])} || ' ${String( // ${dateIN > 0 ? '+' : ''}${fn(pt.arguments[1])} || ' ${String(
fn(pt.arguments[2]) // fn(pt.arguments[2])
).replace(/["']/g, '')}')) // ).replace(/["']/g, '')}'))
ELSE // ELSE
DATE(DATETIME(${fn(pt.arguments[0])}, 'localtime'), // DATE(DATETIME(${fn(pt.arguments[0])}, 'localtime'),
${dateIN > 0 ? '+' : ''}${fn(pt.arguments[1])} || ' ${String( // ${dateIN > 0 ? '+' : ''}${fn(pt.arguments[1])} || ' ${String(
fn(pt.arguments[2]) // fn(pt.arguments[2])
).replace(/["']/g, '')}') // ).replace(/["']/g, '')}')
END${colAlias}` // END${colAlias}`
); // );
}, // },
DATETIME_DIFF: ({ fn, knex, pt, colAlias }: MapFnArgs) => { // DATETIME_DIFF: ({ fn, knex, pt, colAlias }: MapFnArgs) => {
let datetime_expr1 = fn(pt.arguments[0]); // let datetime_expr1 = fn(pt.arguments[0]);
let datetime_expr2 = fn(pt.arguments[1]); // let datetime_expr2 = fn(pt.arguments[1]);
// JULIANDAY takes YYYY-MM-DD // // JULIANDAY takes YYYY-MM-DD
if (datetime_expr1.sql === '?' && datetime_expr1.bindings?.[0]) { // if (datetime_expr1.sql === '?' && datetime_expr1.bindings?.[0]) {
datetime_expr1 = `'${convertToTargetFormat( // datetime_expr1 = `'${convertToTargetFormat(
datetime_expr1.bindings[0], // datetime_expr1.bindings[0],
getDateFormat(datetime_expr1.bindings[0]), // getDateFormat(datetime_expr1.bindings[0]),
'YYYY-MM-DD' // 'YYYY-MM-DD'
)}'`; // )}'`;
} // }
//
if (datetime_expr2.sql === '?' && datetime_expr2.bindings?.[0]) { // if (datetime_expr2.sql === '?' && datetime_expr2.bindings?.[0]) {
datetime_expr2 = `'${convertToTargetFormat( // datetime_expr2 = `'${convertToTargetFormat(
datetime_expr2.bindings[0], // datetime_expr2.bindings[0],
getDateFormat(datetime_expr2.bindings[0]), // getDateFormat(datetime_expr2.bindings[0]),
'YYYY-MM-DD' // 'YYYY-MM-DD'
)}'`; // )}'`;
} // }
//
const rawUnit = pt.arguments[2] // const rawUnit = pt.arguments[2]
? fn(pt.arguments[2]).bindings[0] // ? fn(pt.arguments[2]).bindings[0]
: 'seconds'; // : 'seconds';
let sql; // let sql;
const unit = convertUnits(rawUnit, 'sqlite'); // const unit = convertUnits(rawUnit, 'sqlite');
switch (unit) { // switch (unit) {
case 'seconds': // case 'seconds':
sql = `(strftime('%s', ${datetime_expr1}) - strftime('%s', ${datetime_expr2}))`; // sql = `(strftime('%s', ${datetime_expr1}) - strftime('%s', ${datetime_expr2}))`;
break; // break;
case 'minutes': // case 'minutes':
sql = `(strftime('%s', ${datetime_expr1}) - strftime('%s', ${datetime_expr2})) / 60`; // sql = `(strftime('%s', ${datetime_expr1}) - strftime('%s', ${datetime_expr2})) / 60`;
break; // break;
case 'hours': // case 'hours':
sql = `(strftime('%s', ${datetime_expr1}) - strftime('%s', ${datetime_expr2})) / 3600`; // sql = `(strftime('%s', ${datetime_expr1}) - strftime('%s', ${datetime_expr2})) / 3600`;
break; // break;
case 'milliseconds': // case 'milliseconds':
sql = `(strftime('%s', ${datetime_expr1}) - strftime('%s', ${datetime_expr2})) * 1000`; // sql = `(strftime('%s', ${datetime_expr1}) - strftime('%s', ${datetime_expr2})) * 1000`;
break; // break;
case 'weeks': // case 'weeks':
sql = `ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) / 7)`; // sql = `ROUND((JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})) / 7)`;
break; // break;
case 'months': // case 'months':
sql = `(strftime('%Y', ${datetime_expr1}) - strftime('%Y', ${datetime_expr2})) * 12 + (strftime('%m', ${datetime_expr1}) - strftime('%m', ${datetime_expr2})) `; // sql = `(strftime('%Y', ${datetime_expr1}) - strftime('%Y', ${datetime_expr2})) * 12 + (strftime('%m', ${datetime_expr1}) - strftime('%m', ${datetime_expr2})) `;
break; // break;
case 'quarters': // case 'quarters':
sql = `(strftime('%Y', ${datetime_expr1}) - strftime('%Y', ${datetime_expr2})) * 4 + (strftime('%m', ${datetime_expr1}) - strftime('%m', ${datetime_expr2})) / 3`; // sql = `(strftime('%Y', ${datetime_expr1}) - strftime('%Y', ${datetime_expr2})) * 4 + (strftime('%m', ${datetime_expr1}) - strftime('%m', ${datetime_expr2})) / 3`;
break; // break;
case 'years': // case 'years':
sql = `CASE // sql = `CASE
WHEN (${datetime_expr2} < ${datetime_expr1}) THEN // WHEN (${datetime_expr2} < ${datetime_expr1}) THEN
( // (
(strftime('%Y', ${datetime_expr1}) - strftime('%Y', ${datetime_expr2})) // (strftime('%Y', ${datetime_expr1}) - strftime('%Y', ${datetime_expr2}))
- (strftime('%m', ${datetime_expr1}) < strftime('%m', ${datetime_expr2}) // - (strftime('%m', ${datetime_expr1}) < strftime('%m', ${datetime_expr2})
OR (strftime('%m', ${datetime_expr1}) = strftime('%m', ${datetime_expr2}) // OR (strftime('%m', ${datetime_expr1}) = strftime('%m', ${datetime_expr2})
AND strftime('%d', ${datetime_expr1}) < strftime('%d', ${datetime_expr2}))) // AND strftime('%d', ${datetime_expr1}) < strftime('%d', ${datetime_expr2})))
) // )
WHEN (${datetime_expr2} > ${datetime_expr1}) THEN // WHEN (${datetime_expr2} > ${datetime_expr1}) THEN
-1 * ( // -1 * (
(strftime('%Y', ${datetime_expr2}) - strftime('%Y', ${datetime_expr1})) // (strftime('%Y', ${datetime_expr2}) - strftime('%Y', ${datetime_expr1}))
- (strftime('%m', ${datetime_expr2}) < strftime('%m', ${datetime_expr1}) // - (strftime('%m', ${datetime_expr2}) < strftime('%m', ${datetime_expr1})
OR (strftime('%m', ${datetime_expr2}) = strftime('%m', ${datetime_expr1}) // OR (strftime('%m', ${datetime_expr2}) = strftime('%m', ${datetime_expr1})
AND strftime('%d', ${datetime_expr2}) < strftime('%d', ${datetime_expr1}))) // AND strftime('%d', ${datetime_expr2}) < strftime('%d', ${datetime_expr1})))
) // )
ELSE 0 // ELSE 0
END`; // END`;
break; // break;
case 'days': // case 'days':
sql = `JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})`; // sql = `JULIANDAY(${datetime_expr1}) - JULIANDAY(${datetime_expr2})`;
break; // break;
default: // default:
sql = ''; // sql = '';
} // }
return knex.raw(`${sql} ${colAlias}`); // return knex.raw(`${sql} ${colAlias}`);
}, // },
WEEKDAY: ({ fn, knex, pt, colAlias }: MapFnArgs) => { // WEEKDAY: ({ fn, knex, pt, colAlias }: MapFnArgs) => {
// strftime('%w', date) - day of week 0 - 6 with Sunday == 0 // // strftime('%w', date) - day of week 0 - 6 with Sunday == 0
// WEEKDAY() returns an index from 0 to 6 for Monday to Sunday // // WEEKDAY() returns an index from 0 to 6 for Monday to Sunday
return knex.raw( // return knex.raw(
`(strftime('%w', ${ // `(strftime('%w', ${
pt.arguments[0].type === 'Literal' // pt.arguments[0].type === 'Literal'
? `'${dayjs(fn(pt.arguments[0])).format('YYYY-MM-DD')}'` // ? `'${dayjs(fn(pt.arguments[0])).format('YYYY-MM-DD')}'`
: fn(pt.arguments[0]) // : fn(pt.arguments[0])
}) - 1 - ${getWeekdayByText( // }) - 1 - ${getWeekdayByText(
pt?.arguments[1]?.value // pt?.arguments[1]?.value
)} % 7 + 7) % 7 ${colAlias}` // )} % 7 + 7) % 7 ${colAlias}`
); // );
}, // },
AND: (args: MapFnArgs) => { // AND: (args: MapFnArgs) => {
return args.knex.raw( // return args.knex.raw(
`CASE WHEN ${args.knex // `CASE WHEN ${args.knex
.raw( // .raw(
`${args.pt.arguments // `${args.pt.arguments
.map((ar) => args.fn(ar, '', 'AND').toQuery()) // .map((ar) => args.fn(ar, '', 'AND').toQuery())
.join(' AND ')}` // .join(' AND ')}`
) // )
.wrap('(', ')') // .wrap('(', ')')
.toQuery()} THEN 1 ELSE 0 END ${args.colAlias}` // .toQuery()} THEN 1 ELSE 0 END ${args.colAlias}`
); // );
}, // },
OR: (args: MapFnArgs) => { // OR: (args: MapFnArgs) => {
return args.knex.raw( // return args.knex.raw(
`CASE WHEN ${args.knex // `CASE WHEN ${args.knex
.raw( // .raw(
`${args.pt.arguments // `${args.pt.arguments
.map((ar) => args.fn(ar, '', 'OR').toQuery()) // .map((ar) => args.fn(ar, '', 'OR').toQuery())
.join(' OR ')}` // .join(' OR ')}`
) // )
.wrap('(', ')') // .wrap('(', ')')
.toQuery()} THEN 1 ELSE 0 END ${args.colAlias}` // .toQuery()} THEN 1 ELSE 0 END ${args.colAlias}`
); // );
}, // },
}; };
export default sqlite3; export default sqlite3;

9
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/mapFunctionName.ts

@ -7,16 +7,19 @@ import type { Knex } from 'knex';
export interface MapFnArgs { export interface MapFnArgs {
pt: any; pt: any;
aliasToCol: { [alias: string]: string }; aliasToCol: Record<
string,
(() => Promise<{ builder: any }>) | string | undefined
>;
knex: XKnex; knex: XKnex;
alias: string; alias: string;
a?: string; a?: string;
fn: (...args: any) => Knex.QueryBuilder | any; fn: (...args: any) => Promise<{ builder: Knex.QueryBuilder | any }>;
colAlias: string; colAlias: string;
prevBinaryOp?: any; prevBinaryOp?: any;
} }
const mapFunctionName = (args: MapFnArgs): any => { const mapFunctionName = async (args: MapFnArgs): Promise<any> => {
const name = args.pt.callee.name; const name = args.pt.callee.name;
let val; let val;

Loading…
Cancel
Save