From 16d26bce0ce88ef5b1faff957eb47f34d7a3a144 Mon Sep 17 00:00:00 2001 From: rijkvanzanten Date: Wed, 16 Jun 2021 18:22:24 -0400 Subject: [PATCH] Finish date retrieval abstraction for all vendors --- api/src/database/functions/base.ts | 12 ----- api/src/database/functions/dialects/mssql.ts | 42 ++++++++++++++++ api/src/database/functions/dialects/mysql.ts | 42 ++++++++++++++++ api/src/database/functions/dialects/oracle.ts | 42 ++++++++++++++++ .../database/functions/dialects/postgres.ts | 50 ++++--------------- api/src/database/functions/dialects/sqlite.ts | 42 ++++++++++++++++ api/src/database/functions/index.ts | 27 +++++----- api/src/database/functions/types.ts | 12 +++++ api/src/utils/get-column.ts | 19 ++++--- 9 files changed, 215 insertions(+), 73 deletions(-) delete mode 100644 api/src/database/functions/base.ts create mode 100644 api/src/database/functions/dialects/mssql.ts create mode 100644 api/src/database/functions/dialects/mysql.ts create mode 100644 api/src/database/functions/dialects/oracle.ts create mode 100644 api/src/database/functions/dialects/sqlite.ts create mode 100644 api/src/database/functions/types.ts diff --git a/api/src/database/functions/base.ts b/api/src/database/functions/base.ts deleted file mode 100644 index 21df8e3486..0000000000 --- a/api/src/database/functions/base.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Knex } from 'knex'; - -export interface HelperFn { - year(table: string, column: string, alias?: string): Knex.Raw; - month(table: string, column: string, alias?: string): Knex.Raw; - week(table: string, column: string, alias?: string): Knex.Raw; - day(table: string, column: string, alias?: string): Knex.Raw; - weekday(table: string, column: string, alias?: string): Knex.Raw; - hour(table: string, column: string, alias?: string): Knex.Raw; - minute(table: string, column: string, alias?: string): Knex.Raw; - second(table: string, column: string, alias?: string): Knex.Raw; -} diff --git a/api/src/database/functions/dialects/mssql.ts b/api/src/database/functions/dialects/mssql.ts new file mode 100644 index 0000000000..dfb539a7e2 --- /dev/null +++ b/api/src/database/functions/dialects/mssql.ts @@ -0,0 +1,42 @@ +import { Knex } from 'knex'; +import { HelperFn } from '../types'; + +export class HelperMSSQL implements HelperFn { + private knex: Knex; + + constructor(knex: Knex) { + this.knex = knex; + } + + year(table: string, column: string): Knex.Raw { + return this.knex.raw('DATEPART(year, ??.??)', [table, column]); + } + + month(table: string, column: string): Knex.Raw { + return this.knex.raw('DATEPART(month, ??.??)', [table, column]); + } + + week(table: string, column: string): Knex.Raw { + return this.knex.raw('DATEPART(week, ??.??)', [table, column]); + } + + day(table: string, column: string): Knex.Raw { + return this.knex.raw('DATEPART(day, ??.??)', [table, column]); + } + + weekday(table: string, column: string): Knex.Raw { + return this.knex.raw('DATEPART(weekday, ??.??)', [table, column]); + } + + hour(table: string, column: string): Knex.Raw { + return this.knex.raw('DATEPART(hour, ??.??)', [table, column]); + } + + minute(table: string, column: string): Knex.Raw { + return this.knex.raw('DATEPART(minute, ??.??)', [table, column]); + } + + second(table: string, column: string): Knex.Raw { + return this.knex.raw('DATEPART(second, ??.??)', [table, column]); + } +} diff --git a/api/src/database/functions/dialects/mysql.ts b/api/src/database/functions/dialects/mysql.ts new file mode 100644 index 0000000000..ec5ce710b7 --- /dev/null +++ b/api/src/database/functions/dialects/mysql.ts @@ -0,0 +1,42 @@ +import { Knex } from 'knex'; +import { HelperFn } from '../types'; + +export class HelperMySQL implements HelperFn { + private knex: Knex; + + constructor(knex: Knex) { + this.knex = knex; + } + + year(table: string, column: string): Knex.Raw { + return this.knex.raw('YEAR(??.??)', [table, column]); + } + + month(table: string, column: string): Knex.Raw { + return this.knex.raw('MONTH(??.??)', [table, column]); + } + + week(table: string, column: string): Knex.Raw { + return this.knex.raw('WEEK(??.??)', [table, column]); + } + + day(table: string, column: string): Knex.Raw { + return this.knex.raw('DAYOFMONTH(??.??)', [table, column]); + } + + weekday(table: string, column: string): Knex.Raw { + return this.knex.raw('DAYOFWEEK??.??)', [table, column]); + } + + hour(table: string, column: string): Knex.Raw { + return this.knex.raw('HOUR(??.??)', [table, column]); + } + + minute(table: string, column: string): Knex.Raw { + return this.knex.raw('MINUTE(??.??)', [table, column]); + } + + second(table: string, column: string): Knex.Raw { + return this.knex.raw('SECOND(??.??)', [table, column]); + } +} diff --git a/api/src/database/functions/dialects/oracle.ts b/api/src/database/functions/dialects/oracle.ts new file mode 100644 index 0000000000..34dcad2f8d --- /dev/null +++ b/api/src/database/functions/dialects/oracle.ts @@ -0,0 +1,42 @@ +import { Knex } from 'knex'; +import { HelperFn } from '../types'; + +export class HelperOracle implements HelperFn { + private knex: Knex; + + constructor(knex: Knex) { + this.knex = knex; + } + + year(table: string, column: string): Knex.Raw { + return this.knex.raw("TO_CHAR(??.??, 'IYYY')", [table, column]); + } + + month(table: string, column: string): Knex.Raw { + return this.knex.raw("TO_CHAR(??.??, 'MM')", [table, column]); + } + + week(table: string, column: string): Knex.Raw { + return this.knex.raw("TO_CHAR(??.??, 'IW')", [table, column]); + } + + day(table: string, column: string): Knex.Raw { + return this.knex.raw("TO_CHAR(??.??, 'DD')", [table, column]); + } + + weekday(table: string, column: string): Knex.Raw { + return this.knex.raw("TO_CHAR(??.??, 'D')", [table, column]); + } + + hour(table: string, column: string): Knex.Raw { + return this.knex.raw("TO_CHAR(??.??, 'HH24')", [table, column]); + } + + minute(table: string, column: string): Knex.Raw { + return this.knex.raw("TO_CHAR(??.??, 'MI')", [table, column]); + } + + second(table: string, column: string): Knex.Raw { + return this.knex.raw("TO_CHAR(??.??, 'SS')", [table, column]); + } +} diff --git a/api/src/database/functions/dialects/postgres.ts b/api/src/database/functions/dialects/postgres.ts index 464541af8e..fb3fe33aec 100644 --- a/api/src/database/functions/dialects/postgres.ts +++ b/api/src/database/functions/dialects/postgres.ts @@ -1,5 +1,5 @@ import { Knex } from 'knex'; -import { HelperFn } from '../base'; +import { HelperFn } from '../types'; export class HelperPostgres implements HelperFn { private knex: Knex; @@ -8,67 +8,35 @@ export class HelperPostgres implements HelperFn { this.knex = knex; } - year(table: string, column: string, alias?: string): Knex.Raw { - if (alias) { - return this.knex.raw('EXTRACT(YEAR FROM ??.??) as ??', [table, column, alias]); - } - + year(table: string, column: string): Knex.Raw { return this.knex.raw('EXTRACT(YEAR FROM ??.??)', [table, column]); } - month(table: string, column: string, alias?: string): Knex.Raw { - if (alias) { - return this.knex.raw('EXTRACT(MONTH FROM ??.??) as ??', [table, column, alias]); - } - + month(table: string, column: string): Knex.Raw { return this.knex.raw('EXTRACT(MONTH FROM ??.??)', [table, column]); } - week(table: string, column: string, alias?: string): Knex.Raw { - if (alias) { - return this.knex.raw('EXTRACT(WEEK FROM ??.??) as ??', [table, column, alias]); - } - + week(table: string, column: string): Knex.Raw { return this.knex.raw('EXTRACT(WEEK FROM ??.??)', [table, column]); } - day(table: string, column: string, alias?: string): Knex.Raw { - if (alias) { - return this.knex.raw('EXTRACT(DAY FROM ??.??) as ??', [table, column, alias]); - } - + day(table: string, column: string): Knex.Raw { return this.knex.raw('EXTRACT(DAY FROM ??.??)', [table, column]); } - weekday(table: string, column: string, alias?: string): Knex.Raw { - if (alias) { - return this.knex.raw('EXTRACT(DOW FROM ??.??) as ??', [table, column, alias]); - } - + weekday(table: string, column: string): Knex.Raw { return this.knex.raw('EXTRACT(DOW FROM ??.??)', [table, column]); } - hour(table: string, column: string, alias?: string): Knex.Raw { - if (alias) { - return this.knex.raw('EXTRACT(HOUR FROM ??.??) as ??', [table, column, alias]); - } - + hour(table: string, column: string): Knex.Raw { return this.knex.raw('EXTRACT(HOUR FROM ??.??)', [table, column]); } - minute(table: string, column: string, alias?: string): Knex.Raw { - if (alias) { - return this.knex.raw('EXTRACT(MINUTE FROM ??.??) as ??', [table, column, alias]); - } - + minute(table: string, column: string): Knex.Raw { return this.knex.raw('EXTRACT(MINUTE FROM ??.??)', [table, column]); } - second(table: string, column: string, alias?: string): Knex.Raw { - if (alias) { - return this.knex.raw('EXTRACT(SECOND FROM ??.??) as ??', [table, column, alias]); - } - + second(table: string, column: string): Knex.Raw { return this.knex.raw('EXTRACT(SECOND FROM ??.??)', [table, column]); } } diff --git a/api/src/database/functions/dialects/sqlite.ts b/api/src/database/functions/dialects/sqlite.ts new file mode 100644 index 0000000000..6bfdaea473 --- /dev/null +++ b/api/src/database/functions/dialects/sqlite.ts @@ -0,0 +1,42 @@ +import { Knex } from 'knex'; +import { HelperFn } from '../types'; + +export class HelperSQLite implements HelperFn { + private knex: Knex; + + constructor(knex: Knex) { + this.knex = knex; + } + + year(table: string, column: string): Knex.Raw { + return this.knex.raw("strftime('%Y', ??.??)", [table, column]); + } + + month(table: string, column: string): Knex.Raw { + return this.knex.raw("strftime('%m', ??.??)", [table, column]); + } + + week(table: string, column: string): Knex.Raw { + return this.knex.raw("strftime('%W', ??.??)", [table, column]); + } + + day(table: string, column: string): Knex.Raw { + return this.knex.raw("strftime('%d', ??.??)", [table, column]); + } + + weekday(table: string, column: string): Knex.Raw { + return this.knex.raw("strftime('%w', ??.??)", [table, column]); + } + + hour(table: string, column: string): Knex.Raw { + return this.knex.raw("strftime('%H', ??.??)", [table, column]); + } + + minute(table: string, column: string): Knex.Raw { + return this.knex.raw("strftime('%M', ??.??)", [table, column]); + } + + second(table: string, column: string): Knex.Raw { + return this.knex.raw("strftime('%S', ??.??)", [table, column]); + } +} diff --git a/api/src/database/functions/index.ts b/api/src/database/functions/index.ts index 4662f7ac54..3b0c785a27 100644 --- a/api/src/database/functions/index.ts +++ b/api/src/database/functions/index.ts @@ -1,25 +1,24 @@ import { Knex } from 'knex'; import { HelperPostgres } from './dialects/postgres'; +import { HelperMySQL } from './dialects/mysql'; +import { HelperMSSQL } from './dialects/mssql'; +import { HelperSQLite } from './dialects/sqlite'; +import { HelperOracle } from './dialects/oracle'; export function FunctionsHelper(knex: Knex) { switch (knex.client.constructor.name) { - // case 'Client_MySQL': - // constructor = require('./dialects/mysql').default; - // break; + case 'Client_MySQL': + return new HelperMySQL(knex); case 'Client_PG': return new HelperPostgres(knex); - // case 'Client_SQLite3': - // constructor = require('./dialects/sqlite').default; - // break; - // case 'Client_Oracledb': - // case 'Client_Oracle': - // constructor = require('./dialects/oracledb').default; - // break; - // case 'Client_MSSQL': - // constructor = require('./dialects/mssql').default; - // break; - + case 'Client_SQLite3': + return new HelperSQLite(knex); + case 'Client_Oracledb': + case 'Client_Oracle': + return new HelperOracle(knex); + case 'Client_MSSQL': + return new HelperMSSQL(knex); default: throw Error('Unsupported driver used: ' + knex.client.constructor.name); } diff --git a/api/src/database/functions/types.ts b/api/src/database/functions/types.ts new file mode 100644 index 0000000000..302ba629c8 --- /dev/null +++ b/api/src/database/functions/types.ts @@ -0,0 +1,12 @@ +import { Knex } from 'knex'; + +export interface HelperFn { + year(table: string, column: string): Knex.Raw; + month(table: string, column: string): Knex.Raw; + week(table: string, column: string): Knex.Raw; + day(table: string, column: string): Knex.Raw; + weekday(table: string, column: string): Knex.Raw; + hour(table: string, column: string): Knex.Raw; + minute(table: string, column: string): Knex.Raw; + second(table: string, column: string): Knex.Raw; +} diff --git a/api/src/utils/get-column.ts b/api/src/utils/get-column.ts index 4292b9f3ce..1829330450 100644 --- a/api/src/utils/get-column.ts +++ b/api/src/utils/get-column.ts @@ -13,7 +13,12 @@ import { applyFunctionToColumnName } from './apply-function-to-column-name'; * @param alias Whether or not to add a SQL AS statement * @returns Knex raw instance */ -export function getColumn(knex: Knex, table: string, column: string, alias = true): Knex.Raw { +export function getColumn( + knex: Knex, + table: string, + column: string, + alias = applyFunctionToColumnName(column) +): Knex.Raw { const fn = FunctionsHelper(knex); if (column.includes('(') && column.includes(')')) { @@ -21,11 +26,13 @@ export function getColumn(knex: Knex, table: string, column: string, alias = tru const columnName = column.match(REGEX_BETWEEN_PARENS)![1]; if (functionName in fn) { - return fn[functionName as keyof typeof fn]( - table, - columnName, - alias ? applyFunctionToColumnName(column) : undefined - ); + const result = fn[functionName as keyof typeof fn](table, columnName); + + if (alias) { + return knex.raw(result + ' AS ??', [alias]); + } + + return result; } else { throw new Error(`Invalid function specified "${functionName}"`); }