From 06039686cff63230b5caa792158f9d5aae35e2ad Mon Sep 17 00:00:00 2001 From: Fendy Heryanto Date: Thu, 8 Jan 2026 13:46:28 +0000 Subject: [PATCH] 1st work --- packages/nocodb/src/dbQueryClient/index.ts | 20 +++++++++ packages/nocodb/src/dbQueryClient/mysql.ts | 47 +++++++++++++++++++++ packages/nocodb/src/dbQueryClient/pg.ts | 47 +++++++++++++++++++++ packages/nocodb/src/dbQueryClient/sqlite.ts | 46 ++++++++++++++++++++ packages/nocodb/src/dbQueryClient/types.ts | 14 ++++++ 5 files changed, 174 insertions(+) create mode 100644 packages/nocodb/src/dbQueryClient/index.ts create mode 100644 packages/nocodb/src/dbQueryClient/mysql.ts create mode 100644 packages/nocodb/src/dbQueryClient/pg.ts create mode 100644 packages/nocodb/src/dbQueryClient/sqlite.ts create mode 100644 packages/nocodb/src/dbQueryClient/types.ts diff --git a/packages/nocodb/src/dbQueryClient/index.ts b/packages/nocodb/src/dbQueryClient/index.ts new file mode 100644 index 0000000000..1fa22329a4 --- /dev/null +++ b/packages/nocodb/src/dbQueryClient/index.ts @@ -0,0 +1,20 @@ +import { ClientType } from 'nocodb-sdk'; +import { PGDBQueryClient } from '~/dbQueryClient/pg'; +import { MySqlDBQueryClient } from '~/dbQueryClient/mysql'; +import { SqliteDBQueryClient } from '~/dbQueryClient/sqlite'; + +export class DBQueryClient { + static get(clientType: ClientType) { + switch (clientType) { + case ClientType.PG: { + return new PGDBQueryClient(); + } + case ClientType.MYSQL: { + return new MySqlDBQueryClient(); + } + case ClientType.SQLITE: { + return new SqliteDBQueryClient(); + } + } + } +} diff --git a/packages/nocodb/src/dbQueryClient/mysql.ts b/packages/nocodb/src/dbQueryClient/mysql.ts new file mode 100644 index 0000000000..d6c6a52a32 --- /dev/null +++ b/packages/nocodb/src/dbQueryClient/mysql.ts @@ -0,0 +1,47 @@ +import { arrFlatMap } from 'nocodb-sdk'; +import type { DBQueryClient } from '~/dbQueryClient/types'; +import type { XKnex } from '~/db/CustomKnex'; + +export class MySqlDBQueryClient implements DBQueryClient { + temporaryTable({ + knex, + data, + fields, + alias, + asKnexFrom = true, + }: { + data: Record[]; + fields: string[]; + alias: string; + knex: XKnex; + asKnexFrom?: boolean; + }) { + const fieldsValuePlaceholder = `(${fields.map(() => '?').join(',')})`; + const valuesPlaceholder = data.map(() => fieldsValuePlaceholder).join(', '); + const fieldsPlaceholder = fields.map(() => '??').join(','); + const query = knex.raw( + `(VALUES ${valuesPlaceholder}) AS ?? (${fieldsPlaceholder})`, + [ + ...arrFlatMap( + data.map((row) => + fields.reduce((acc, field) => { + acc.push(row[field]); + return acc; + }, []), + ), + ), + alias, + ...fields, + ], + ); + return asKnexFrom ? knex.from(query) : query; + } + + concat(fields: string[]) { + return `CONCAT(${fields.join(', ')})`; + } + simpleCast(field: string, asType: string) { + const useAsType = asType.toUpperCase() === 'TEXT' ? 'CHAR' : asType; + return `CAST(${field} as ${useAsType})`; + } +} diff --git a/packages/nocodb/src/dbQueryClient/pg.ts b/packages/nocodb/src/dbQueryClient/pg.ts new file mode 100644 index 0000000000..66af6d7860 --- /dev/null +++ b/packages/nocodb/src/dbQueryClient/pg.ts @@ -0,0 +1,47 @@ +import { arrFlatMap } from 'nocodb-sdk'; +import type { DBQueryClient } from '~/dbQueryClient/types'; +import type { XKnex } from '~/db/CustomKnex'; + +export class PGDBQueryClient implements DBQueryClient { + temporaryTable({ + knex, + data, + fields, + alias, + asKnexFrom = true, + }: { + data: Record[]; + fields: string[]; + alias: string; + knex: XKnex; + asKnexFrom?: boolean; + }) { + const fieldsValuePlaceholder = `(${fields.map(() => '?').join(',')})`; + const valuesPlaceholder = data.map(() => fieldsValuePlaceholder).join(', '); + const fieldsPlaceholder = fields.map(() => '??').join(','); + const query = knex.raw( + `(VALUES ${valuesPlaceholder}) AS ?? (${fieldsPlaceholder})`, + [ + ...arrFlatMap( + data.map((row) => + fields.reduce((acc, field) => { + acc.push(row[field]); + return acc; + }, []), + ), + ), + alias, + ...fields, + ], + ); + return asKnexFrom ? knex.from(query) : query; + } + + concat(fields: string[]) { + return `CONCAT(${fields.join(', ')})`; + } + + simpleCast(field: string, asType: string) { + return `${field}::${asType}`; + } +} diff --git a/packages/nocodb/src/dbQueryClient/sqlite.ts b/packages/nocodb/src/dbQueryClient/sqlite.ts new file mode 100644 index 0000000000..d505544021 --- /dev/null +++ b/packages/nocodb/src/dbQueryClient/sqlite.ts @@ -0,0 +1,46 @@ +import { arrFlatMap } from 'nocodb-sdk'; +import type { DBQueryClient } from '~/dbQueryClient/types'; +import type { XKnex } from '~/db/CustomKnex'; + +export class SqliteDBQueryClient implements DBQueryClient { + temporaryTable({ + knex, + data, + fields, + alias, + asKnexFrom = true, + }: { + data: Record[]; + fields: string[]; + alias: string; + knex: XKnex; + asKnexFrom?: boolean; + }) { + const fieldsValuePlaceholder = `(${fields.map(() => '?').join(',')})`; + const valuesPlaceholder = data.map(() => fieldsValuePlaceholder).join(', '); + const fieldsPlaceholder = fields.map(() => '??').join(','); + const query = knex.raw( + `(VALUES ${valuesPlaceholder}) AS ?? (${fieldsPlaceholder})`, + [ + ...arrFlatMap( + data.map((row) => + fields.reduce((acc, field) => { + acc.push(row[field]); + return acc; + }, []), + ), + ), + alias, + ...fields, + ], + ); + return asKnexFrom ? knex.from(query) : query; + } + + concat(fields: string[]) { + return `${fields.join(' || ')}`; + } + simpleCast(field: string, asType: string) { + return `CAST(${field} as ${asType})`; + } +} diff --git a/packages/nocodb/src/dbQueryClient/types.ts b/packages/nocodb/src/dbQueryClient/types.ts new file mode 100644 index 0000000000..653992b1b0 --- /dev/null +++ b/packages/nocodb/src/dbQueryClient/types.ts @@ -0,0 +1,14 @@ +import type { XKnex } from '~/db/CustomKnex'; + +export interface DBQueryClient { + temporaryTable(payload: { + data: Record[]; + fields: string[]; + alias: string; + knex: XKnex; + asKnexFrom?: boolean; + }); + + concat(fields: string[]); + simpleCast(field: string, asType: string); +}