Browse Source

refactor(nocodb): update formula functions to async and change return statement

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/5392/head
Pranav C 1 year ago
parent
commit
88349195aa
  1. 200
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/mysql.ts
  2. 40
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/pg.ts
  3. 412
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/sqlite.ts

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

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

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

@ -34,27 +34,27 @@ const pg = {
};
},
MID: 'SUBSTR',
FLOAT: ({ fn, knex, pt, colAlias }: MapFnArgs) => {
FLOAT: async ({ fn, knex, pt, colAlias }: MapFnArgs) => {
return {
builder: knex
.raw(`CAST(${fn(pt.arguments[0])} as DOUBLE PRECISION)${colAlias}`)
.raw(`CAST(${(await fn(pt.arguments[0])).builder} as DOUBLE PRECISION)${colAlias}`)
.wrap('(', ')'),
};
},
ROUND: ({ fn, knex, pt, colAlias }: MapFnArgs) => {
ROUND: async ({ fn, knex, pt, colAlias }: MapFnArgs) => {
return {
builder: knex.raw(
`ROUND((${fn(pt.arguments[0])})::numeric, ${
pt?.arguments[1] ? fn(pt.arguments[1]) : 0
`ROUND((${(await fn(pt.arguments[0])).builder})::numeric, ${
pt?.arguments[1] ? (await fn(pt.arguments[1])).builder : 0
}) ${colAlias}`
),
};
},
DATEADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => {
DATEADD: async ({ fn, knex, pt, colAlias }: MapFnArgs) => {
return {
builder: knex.raw(
`${fn(pt.arguments[0])} + (${fn(pt.arguments[1])} ||
'${String(fn(pt.arguments[2])).replace(
`${(await fn(pt.arguments[0])).builder} + (${(await fn(pt.arguments[1])).builder} ||
'${String((await fn(pt.arguments[2])).builder).replace(
/["']/g,
''
)}')::interval${colAlias}`
@ -62,8 +62,8 @@ const pg = {
};
},
DATETIME_DIFF: async ({ fn, knex, pt, colAlias }: MapFnArgs) => {
const datetime_expr1 = fn(pt.arguments[0]);
const datetime_expr2 = fn(pt.arguments[1]);
const datetime_expr1 = (await fn(pt.arguments[0])).builder;
const datetime_expr2 = (await fn(pt.arguments[1])).builder;
const rawUnit = pt.arguments[2]
? (await fn(pt.arguments[2])).builder.bindings[0]
: 'seconds';
@ -121,7 +121,7 @@ const pg = {
? `date '${dayjs((await fn(pt.arguments[0])).builder).format(
'YYYY-MM-DD'
)}'`
: fn(pt.arguments[0])
: (await fn(pt.arguments[0])).builder
}) - 1 - ${getWeekdayByText(
pt?.arguments[1]?.value
)} % 7 + 7) ::INTEGER % 7 ${colAlias}`
@ -133,10 +133,10 @@ const pg = {
builder: args.knex.raw(
`CASE WHEN ${args.knex
.raw(
`${args.pt.arguments
`${(await Promise.all(args.pt.arguments
.map(async (ar) =>
(await args.fn(ar, '', 'AND')).builder.toQuery()
)
)))
.join(' AND ')}`
)
.wrap('(', ')')
@ -160,10 +160,10 @@ const pg = {
),
};
},
SUBSTR: ({ fn, knex, pt, colAlias }: MapFnArgs) => {
const str = fn(pt.arguments[0]);
const positionFrom = fn(pt.arguments[1] ?? 1);
const numberOfCharacters = fn(pt.arguments[2] ?? '');
SUBSTR:async ({ fn, knex, pt, colAlias }: MapFnArgs) => {
const str = (await fn(pt.arguments[0])).builder;
const positionFrom = (await fn(pt.arguments[1] ?? 1)).builder;
const numberOfCharacters = (await fn(pt.arguments[2] ?? '')).builder;
return {
builder: knex.raw(
`SUBSTR(${str}::TEXT, ${positionFrom}${
@ -172,9 +172,9 @@ const pg = {
),
};
},
MOD: ({ fn, knex, pt, colAlias }: MapFnArgs) => {
const x = fn(pt.arguments[0]);
const y = fn(pt.arguments[1]);
MOD: async ({ fn, knex, pt, colAlias }: MapFnArgs) => {
const x = (await fn(pt.arguments[0])).builder;
const y = (await fn(pt.arguments[1])).builder;
return {
builder: knex.raw(`MOD((${x})::NUMERIC, (${y})::NUMERIC) ${colAlias}`),
};

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

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

Loading…
Cancel
Save