Browse Source

Merge pull request #3570 from nocodb/chore/upgrade-knex

feat: upgrade knex
pull/4296/head
Pranav C 2 years ago committed by GitHub
parent
commit
a7c55a8430
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      .github/workflows/release-executables.yml
  2. 16
      .github/workflows/release-timely-executables.yml
  3. 4
      packages/nc-gui/lib/constants.ts
  4. 9
      packages/nocodb/Dockerfile
  5. 3210
      packages/nocodb/package-lock.json
  6. 6
      packages/nocodb/package.json
  7. 2
      packages/nocodb/src/interface/config.ts
  8. 3
      packages/nocodb/src/lib/db/sql-client/lib/KnexClient.ts
  9. 177
      packages/nocodb/src/lib/db/sql-client/lib/mssql/MssqlClient.ts
  10. 6
      packages/nocodb/src/lib/db/sql-client/lib/pg/PgClient.ts
  11. 34
      packages/nocodb/src/lib/db/sql-client/lib/sqlite/SqliteClient.ts
  12. 21
      packages/nocodb/src/lib/db/sql-data-mapper/lib/BaseModel.ts
  13. 23
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSql.ts
  14. 187
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts
  15. 130
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/CustomKnex.ts
  16. 18
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/conditionV2.ts
  17. 2
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/genRollupSelect.ts
  18. 4
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/genRollupSelectv2.ts
  19. 4
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/mapFunctionName.ts
  20. 4
      packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/sortV2.ts
  21. 4
      packages/nocodb/src/lib/db/sql-mgr/v2/SqlMgrv2Trans.ts
  22. 2
      packages/nocodb/src/lib/meta/api/dataApis/dataAliasApis.ts
  23. 2
      packages/nocodb/src/lib/meta/api/publicApis/publicDataApis.ts
  24. 2
      packages/nocodb/src/lib/migrations/v1/nc_002_add_m2m.ts
  25. 2
      packages/nocodb/src/lib/migrations/v1/nc_003_add_fkn_column.ts
  26. 2
      packages/nocodb/src/lib/migrations/v1/nc_004_add_view_type_column.ts
  27. 2
      packages/nocodb/src/lib/migrations/v1/nc_005_add_view_name_column.ts
  28. 2
      packages/nocodb/src/lib/migrations/v1/nc_006_alter_nc_shared_views.ts
  29. 2
      packages/nocodb/src/lib/migrations/v1/nc_007_alter_nc_shared_views_1.ts
  30. 2
      packages/nocodb/src/lib/migrations/v1/nc_008_add_nc_shared_bases.ts
  31. 2
      packages/nocodb/src/lib/migrations/v1/nc_009_add_model_order.ts
  32. 2
      packages/nocodb/src/lib/migrations/v1/nc_010_add_parent_title_column.ts
  33. 2
      packages/nocodb/src/lib/migrations/v1/nc_011_remove_old_ses_plugin.ts
  34. 2
      packages/nocodb/src/lib/migrations/v2/nc_012_alter_column_data_types.ts
  35. 2
      packages/nocodb/src/lib/migrations/v2/nc_013_sync_source.ts
  36. 2
      packages/nocodb/src/lib/migrations/v2/nc_014_alter_column_data_types.ts
  37. 2
      packages/nocodb/src/lib/migrations/v2/nc_015_add_meta_col_in_column_table.ts
  38. 2
      packages/nocodb/src/lib/migrations/v2/nc_016_alter_hooklog_payload_types.ts
  39. 2
      packages/nocodb/src/lib/migrations/v2/nc_017_add_user_token_version_column.ts
  40. 2
      packages/nocodb/src/lib/migrations/v2/nc_018_add_meta_in_view.ts
  41. 2
      packages/nocodb/src/lib/migrations/v2/nc_019_add_meta_in_meta_tables.ts
  42. 2
      packages/nocodb/src/lib/migrations/v2/nc_020_kanban_view.ts
  43. 2
      packages/nocodb/src/lib/services/test/TestResetService/index.ts
  44. 2
      packages/nocodb/src/lib/services/test/TestResetService/resetMetaSakilaSqliteProject.ts
  45. 16
      packages/nocodb/src/lib/services/test/TestResetService/resetMysqlSakilaProject.ts
  46. 8
      packages/nocodb/src/lib/services/test/TestResetService/resetPgSakilaProject.ts
  47. 2
      packages/nocodb/src/lib/utils/common/NcConnectionMgr.ts
  48. 6
      packages/nocodb/tests/unit/TestDbMngr.ts

11
.github/workflows/release-executables.yml

@ -84,8 +84,15 @@ jobs:
# install npm dependendencies # install npm dependendencies
npm i npm i
# Copy sqlite binaries # Build sqlite binaries for all platforms
rsync -rvzhP ./binaries/binding/ ./node_modules/sqlite3/lib/binding/ ./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=win32 --fallback-to-build --target_arch=x64 --target_libc=unknown
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=win32 --fallback-to-build --target_arch=ia32 --target_libc=unknown
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=darwin --fallback-to-build --target_arch=x64 --target_libc=unknown
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=darwin --fallback-to-build --target_arch=arm64 --target_libc=unknown
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=x64 --target_libc=glibc
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=arm64 --target_libc=glibc
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=x64 --target_libc=musl
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=arm64 --target_libc=musl
# clean up code to optimize size # clean up code to optimize size
npx modclean --patterns="default:*" --ignore="nc-lib-gui/**,dayjs/**,express-status-monitor/**,sqlite3/**" --run npx modclean --patterns="default:*" --ignore="nc-lib-gui/**,dayjs/**,express-status-monitor/**,sqlite3/**" --run

16
.github/workflows/release-timely-executables.yml

@ -86,7 +86,21 @@ jobs:
npm i npm i
# Copy sqlite binaries # Copy sqlite binaries
rsync -rvzhP ./binaries/binding/ ./node_modules/sqlite3/lib/binding/ # rsync -rvzhP ./binaries/binding/ ./node_modules/sqlite3/lib/binding/
# Build sqlite binaries for all platforms
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=win32 --fallback-to-build --target_arch=x64 --target_libc=unknown
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=win32 --fallback-to-build --target_arch=ia32 --target_libc=unknown
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=darwin --fallback-to-build --target_arch=x64 --target_libc=unknown
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=darwin --fallback-to-build --target_arch=arm64 --target_libc=unknown
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=x64 --target_libc=glibc
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=arm64 --target_libc=glibc
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=x64 --target_libc=musl
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=arm64 --target_libc=musl
# ./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=armv6 --target_libc=unknown
# ./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=armv7 --target_libc=unknown
# clean up code to optimize size # clean up code to optimize size
npx modclean --patterns="default:*" --ignore="nc-lib-gui-daily/**,dayjs/**,express-status-monitor/**,sqlite3/**" --run npx modclean --patterns="default:*" --ignore="nc-lib-gui-daily/**,dayjs/**,express-status-monitor/**,sqlite3/**" --run

4
packages/nc-gui/lib/constants.ts

@ -4,9 +4,7 @@ export const NOCO = 'noco'
export const SYSTEM_COLUMNS = ['id', 'title', 'created_at', 'updated_at'] export const SYSTEM_COLUMNS = ['id', 'title', 'created_at', 'updated_at']
export const BASE_URL = export const BASE_URL = import.meta.env.NC_BACKEND_URL || (process.env.NODE_ENV === 'production' ? '..' : 'http://localhost:8080')
import.meta.env.NC_BACKEND_URL || (import.meta.env.NODE_ENV === 'production' ? '..' : 'http://localhost:8080')
/** /**
* Each permission value means the following * Each permission value means the following
* `*` - which is wildcard, means all permissions are allowed * `*` - which is wildcard, means all permissions are allowed

9
packages/nocodb/Dockerfile

@ -18,9 +18,12 @@ RUN cp $GOPATH/bin/litestream /usr/src/lt
########### ###########
# Builder # Builder
########### ###########
FROM node:12 as builder FROM node:16.17.0-alpine3.15 as builder
WORKDIR /usr/src/app WORKDIR /usr/src/app
# install node-gyp dependencies
RUN apk add --no-cache python3 make g++
# Copy application dependency manifests to the container image. # Copy application dependency manifests to the container image.
# A wildcard is used to ensure both package.json AND package-lock.json are copied. # A wildcard is used to ensure both package.json AND package-lock.json are copied.
# Copying this separately prevents re-running npm ci on every code change. # Copying this separately prevents re-running npm ci on every code change.
@ -32,7 +35,7 @@ COPY ./docker/start-litestream.sh /usr/src/appEntry/start.sh
# install production dependencies, # install production dependencies,
# reduce node_module size with modclean & removing sqlite deps, # reduce node_module size with modclean & removing sqlite deps,
# package built code into app.tar.gz & add execute permission to start.sh # package built code into app.tar.gz & add execute permission to start.sh
RUN npm ci --production --quiet \ RUN npm ci --omit=dev --quiet \
&& npx modclean --patterns="default:*" --ignore="nc-lib-gui/**,dayjs/**,express-status-monitor/**" --run \ && npx modclean --patterns="default:*" --ignore="nc-lib-gui/**,dayjs/**,express-status-monitor/**" --run \
&& rm -rf ./node_modules/sqlite3/deps \ && rm -rf ./node_modules/sqlite3/deps \
&& tar -czf ../appEntry/app.tar.gz ./* \ && tar -czf ../appEntry/app.tar.gz ./* \
@ -41,7 +44,7 @@ RUN npm ci --production --quiet \
########## ##########
# Runner # Runner
########## ##########
FROM alpine:3.12 FROM alpine:3.15
WORKDIR /usr/src/app WORKDIR /usr/src/app
ENV NC_DOCKER 0.6 ENV NC_DOCKER 0.6

3210
packages/nocodb/package-lock.json generated

File diff suppressed because it is too large Load Diff

6
packages/nocodb/package.json

@ -95,7 +95,7 @@
"jsep": "^1.3.6", "jsep": "^1.3.6",
"jsonfile": "^6.1.0", "jsonfile": "^6.1.0",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"knex": "^0.21.2", "knex": "^2.2.0",
"lodash": "^4.17.19", "lodash": "^4.17.19",
"lru-cache": "^6.0.0", "lru-cache": "^6.0.0",
"mailersend": "^1.1.0", "mailersend": "^1.1.0",
@ -124,11 +124,13 @@
"passport-jwt": "^4.0.0", "passport-jwt": "^4.0.0",
"passport-local": "^1.0.0", "passport-local": "^1.0.0",
"pg": "^8.3.0", "pg": "^8.3.0",
"request": "^2.88.2",
"request-ip": "^2.1.3", "request-ip": "^2.1.3",
"rmdir": "^1.2.0", "rmdir": "^1.2.0",
"slash": "^3.0.0", "slash": "^3.0.0",
"socket.io": "^4.4.1", "socket.io": "^4.4.1",
"sqlite3": "5.0.0", "sqlite3": "5.1.2",
"tedious": "^15.0.0",
"tinycolor2": "^1.4.2", "tinycolor2": "^1.4.2",
"twilio": "^3.55.1", "twilio": "^3.55.1",
"unique-names-generator": "^4.3.1", "unique-names-generator": "^4.3.1",

2
packages/nocodb/src/interface/config.ts

@ -1,6 +1,6 @@
import { Handler } from 'express'; import { Handler } from 'express';
import * as e from 'express'; import * as e from 'express';
import Knex from 'knex'; import { Knex } from 'knex';
export interface Route { export interface Route {
path: string; path: string;

3
packages/nocodb/src/lib/db/sql-client/lib/KnexClient.ts

@ -1,10 +1,9 @@
/* eslint-disable no-constant-condition */ /* eslint-disable no-constant-condition */
import Knex from 'knex'; import { knex, Knex } from 'knex'
import Debug from '../../util/Debug'; import Debug from '../../util/Debug';
import Emit from '../../util/emit'; import Emit from '../../util/emit';
import Result from '../../util/Result'; import Result from '../../util/Result';
import knex from 'knex';
import lodash from 'lodash'; import lodash from 'lodash';
import fs from 'fs'; import fs from 'fs';
import { promisify } from 'util'; import { promisify } from 'util';

177
packages/nocodb/src/lib/db/sql-client/lib/mssql/MssqlClient.ts

@ -356,13 +356,11 @@ class MssqlClient extends KnexClient {
try { try {
/** ************** START : create _evolution table if not exists *************** */ /** ************** START : create _evolution table if not exists *************** */
const exists = await this.sqlClient.schema.hasTable( const exists = await this.sqlClient.schema.withSchema(this.schema).hasTable(args.tn);
this.getTnPath(args.tn)
);
if (!exists) { if (!exists) {
await this.sqlClient.schema.createTable( await this.sqlClient.schema.withSchema(this.schema).createTable(
this.getTnPath(args.tn), args.tn,
function (table) { function (table) {
table.increments(); table.increments();
table.string('title').notNullable(); table.string('title').notNullable();
@ -396,9 +394,7 @@ class MssqlClient extends KnexClient {
log.api(`${_func}:args:`, args); log.api(`${_func}:args:`, args);
try { try {
result.data.value = await this.sqlClient.schema.hasTable( result.data.value = await this.sqlClient.schema.withSchema(this.schema).hasTable(args.tn);
this.getTnPath(args.tn)
);
} catch (e) { } catch (e) {
log.ppe(e, _func); log.ppe(e, _func);
throw e; throw e;
@ -1599,9 +1595,10 @@ class MssqlClient extends KnexClient {
const result = new Result(); const result = new Result();
log.api(`${func}:args:`, args); log.api(`${func}:args:`, args);
try { try {
const query = `CREATE TRIGGER ${args.trigger_name} on ${this.getTnPath( const query = this.genQuery(
args.tn `CREATE TRIGGER ?? on ?? \n${args.timing} ${args.event}\n as\n${args.statement}`,
)} \n${args.timing} ${args.event}\n as\n${args.statement}`; [args.trigger_name, this.getTnPath(args.tn)]
);
await this.sqlClient.raw(query); await this.sqlClient.raw(query);
result.data.object = { result.data.object = {
upStatement: [{ sql: this.querySeparator() + query }], upStatement: [{ sql: this.querySeparator() + query }],
@ -1817,7 +1814,7 @@ class MssqlClient extends KnexClient {
const downStatement = const downStatement =
this.querySeparator() + this.querySeparator() +
this.sqlClient.schema.dropTable(args.table).toString(); this.sqlClient.schema.withSchema(this.schema).dropTable(args.table).toString();
this.emit(`Success : ${upQuery}`); this.emit(`Success : ${upQuery}`);
@ -1850,15 +1847,17 @@ class MssqlClient extends KnexClient {
for (let i = 0; i < args.columns.length; i++) { for (let i = 0; i < args.columns.length; i++) {
const column = args.columns[i]; const column = args.columns[i];
if (column.au) { if (column.au) {
const triggerName = `xc_trigger_${args.table_name}_${column.column_name}`; const triggerName = `[${this.schema}].[xc_trigger_${args.table_name}_${column.column_name}]`;
const triggerCreateQuery = const triggerCreateQuery =
this.querySeparator() + this.querySeparator() +
`CREATE TRIGGER ${this.schema}.${triggerName} ON ${this.schema}.${args.table_name} AFTER UPDATE this.genQuery(
`CREATE TRIGGER ?? ON ?? AFTER UPDATE
AS AS
BEGIN BEGIN
SET NOCOUNT ON; SET NOCOUNT ON;
UPDATE ${this.schema}.${args.table_name} Set ${column.column_name} = GetDate() where ${pk.column_name} in (SELECT ${pk.column_name} FROM Inserted) UPDATE ?? Set ?? = GetDate() where ?? in (SELECT ?? FROM Inserted)
END;`; END;`, [triggerName, this.getTnPath(args.table_name), this.getTnPath(args.table_name), column.column_name, pk.column_name, pk.column_name]
);
upQuery += triggerCreateQuery; upQuery += triggerCreateQuery;
@ -1888,11 +1887,11 @@ class MssqlClient extends KnexClient {
const triggerName = `xc_trigger_${args.table_name}_${column.column_name}`; const triggerName = `xc_trigger_${args.table_name}_${column.column_name}`;
const triggerCreateQuery = const triggerCreateQuery =
this.querySeparator() + this.querySeparator() +
`CREATE TRIGGER ${this.schema}.${triggerName} ON ${this.schema}.${args.table_name} AFTER UPDATE `CREATE TRIGGER [${this.schema}].[${triggerName}] ON [${this.schema}].[${args.table_name}] AFTER UPDATE
AS AS
BEGIN BEGIN
SET NOCOUNT ON; SET NOCOUNT ON;
UPDATE ${this.schema}.${args.table_name} Set ${column.column_name} = GetDate() where ${pk.column_name} in (SELECT ${pk.column_name} FROM Inserted) UPDATE [${this.schema}].[${args.table_name}] Set [${column.column_name}] = GetDate() where [${pk.column_name}] in (SELECT [${pk.column_name}] FROM Inserted)
END;`; END;`;
upQuery += triggerCreateQuery; upQuery += triggerCreateQuery;
@ -1901,7 +1900,7 @@ class MssqlClient extends KnexClient {
downQuery += downQuery +=
this.querySeparator() + this.querySeparator() +
`DROP TRIGGER IF EXISTS ${this.schema}.${triggerName};`; `DROP TRIGGER IF EXISTS [${this.schema}].[${triggerName}];`;
} }
} }
result.upStatement[0] = { sql: upQuery }; result.upStatement[0] = { sql: upQuery };
@ -2059,13 +2058,13 @@ class MssqlClient extends KnexClient {
/** ************** create up & down statements *************** */ /** ************** create up & down statements *************** */
const upStatement = const upStatement =
this.querySeparator() + this.querySeparator() +
this.sqlClient.schema.dropTable(this.getTnPath(args.tn)).toString(); this.sqlClient.schema.withSchema(this.schema).dropTable(args.tn).toString();
let downQuery = this.querySeparator() + this.createTable(args.tn, args); let downQuery = this.querySeparator() + this.createTable(args.tn, args);
this.emit(`Success : ${upStatement}`); this.emit(`Success : ${upStatement}`);
let relationsList: any = await this.relationList({ let relationsList: any = await this.relationList({
tn: this.getTnPath(args.tn), tn: args.tn,
}); });
relationsList = relationsList.data.list; relationsList = relationsList.data.list;
@ -2073,12 +2072,12 @@ class MssqlClient extends KnexClient {
for (const relation of relationsList) { for (const relation of relationsList) {
downQuery += downQuery +=
this.querySeparator() + this.querySeparator() +
(await this.sqlClient.schema (await this.sqlClient.withSchema(this.schema).schema
.table(this.getTnPath(relation.tn), function (table) { .table(relation.tn, (table) => {
table = table table = table
.foreign(relation.cn, null) .foreign(relation.cn, null)
.references(relation.rcn) .references(relation.rcn)
.on(relation.rtn); .on(this.getTnPath(relation.rtn));
if (relation.ur) { if (relation.ur) {
table = table.onUpdate(relation.ur); table = table.onUpdate(relation.ur);
@ -2117,7 +2116,7 @@ class MssqlClient extends KnexClient {
)) { )) {
downQuery += downQuery +=
this.querySeparator() + this.querySeparator() +
this.sqlClient.schema this.sqlClient.schema.withSchema(this.schema)
.table(tn, function (table) { .table(tn, function (table) {
if (non_unique) { if (non_unique) {
table.index(columns, key_name); table.index(columns, key_name);
@ -2129,7 +2128,7 @@ class MssqlClient extends KnexClient {
} }
/** ************** drop tn *************** */ /** ************** drop tn *************** */
await this.sqlClient.schema.dropTable(this.getTnPath(args.tn)); await this.sqlClient.schema.withSchema(this.schema).dropTable(args.tn);
/** ************** return files *************** */ /** ************** return files *************** */
result.data.object = { result.data.object = {
@ -2144,6 +2143,132 @@ class MssqlClient extends KnexClient {
return result; return result;
} }
/**
*
* @param {Object} - args
* @param {String} - args.parentTable
* @param {String} - args.parentColumn
* @param {String} - args.childColumn
* @param {String} - args.childTable
* @returns {Promise<{upStatement, downStatement}>}
*/
async relationCreate(args) {
const _func = this.relationCreate.name;
const result = new Result();
log.api(`${_func}:args:`, args);
const foreignKeyName = args.foreignKeyName || null;
try {
const self = this;
await this.sqlClient.schema.table(this.getTnPath(args.childTable), function (table) {
table = table
.foreign(args.childColumn, foreignKeyName)
.references(args.parentColumn)
.on(self.getTnPath(args.parentTable));
if (args.onUpdate) {
table = table.onUpdate(args.onUpdate);
}
if (args.onDelete) {
table = table.onDelete(args.onDelete);
}
});
const upStatement =
this.querySeparator() +
(await this.sqlClient.schema
.table(this.getTnPath(args.childTable), function (table) {
table = table
.foreign(args.childColumn, foreignKeyName)
.references(args.parentColumn)
.on(self.getTnPath(args.parentTable));
if (args.onUpdate) {
table = table.onUpdate(args.onUpdate);
}
if (args.onDelete) {
table = table.onDelete(args.onDelete);
}
})
.toQuery());
this.emit(`Success : ${upStatement}`);
const downStatement =
this.querySeparator() +
this.sqlClient.schema
.table(this.getTnPath(args.childTable), function (table) {
table = table.dropForeign(args.childColumn, foreignKeyName);
})
.toQuery();
result.data.object = {
upStatement: [{ sql: upStatement }],
downStatement: [{ sql: downStatement }],
};
} catch (e) {
log.ppe(e, _func);
throw e;
}
return result;
}
/**
*
* @param {Object} - args
* @param {String} - args.parentTable
* @param {String} - args.parentColumn
* @param {String} - args.childColumn
* @param {String} - args.childTable
* @param {String} - args.foreignKeyName
* @returns {Promise<{upStatement, downStatement}>}
*/
async relationDelete(args) {
const _func = this.relationDelete.name;
const result = new Result();
log.api(`${_func}:args:`, args);
const foreignKeyName = args.foreignKeyName || null;
try {
const self = this;
await this.sqlClient.schema.table(this.getTnPath(args.childTable), function (table) {
table.dropForeign(args.childColumn, foreignKeyName);
});
const upStatement =
this.querySeparator() +
this.sqlClient.schema
.table(this.getTnPath(args.childTable), function (table) {
table.dropForeign(args.childColumn, foreignKeyName);
})
.toQuery();
const downStatement =
this.querySeparator() +
(await this.sqlClient.schema
.table(this.getTnPath(args.childTable), function (table) {
table
.foreign(args.childColumn, foreignKeyName)
.references(args.parentColumn)
.on(self.getTnPath(args.parentTable));
})
.toQuery());
result.data.object = {
upStatement: [{ sql: upStatement }],
downStatement: [{ sql: downStatement }],
};
} catch (e) {
log.ppe(e, _func);
throw e;
}
return result;
}
/** /**
* *
* @param args * @param args

6
packages/nocodb/src/lib/db/sql-client/lib/pg/PgClient.ts

@ -2102,7 +2102,7 @@ class PGClient extends KnexClient {
this.genQuery(`DROP FUNCTION IF EXISTS ??()`, [triggerFnName]); this.genQuery(`DROP FUNCTION IF EXISTS ??()`, [triggerFnName]);
} }
} }
await this.sqlClient.raw(upQuery); if (upQuery !== '') await this.sqlClient.raw(upQuery);
result.upStatement[0] = { sql: upQuery }; result.upStatement[0] = { sql: upQuery };
result.downStatement[0] = { sql: downQuery }; result.downStatement[0] = { sql: downQuery };
@ -2153,7 +2153,7 @@ class PGClient extends KnexClient {
this.genQuery(`DROP FUNCTION IF EXISTS ??()`, [triggerFnName]); this.genQuery(`DROP FUNCTION IF EXISTS ??()`, [triggerFnName]);
} }
} }
await this.sqlClient.raw(upQuery); if (upQuery !== '') await this.sqlClient.raw(upQuery);
result.upStatement[0] = { sql: upQuery }; result.upStatement[0] = { sql: upQuery };
result.downStatement[0] = { sql: downQuery }; result.downStatement[0] = { sql: downQuery };
@ -2273,7 +2273,7 @@ class PGClient extends KnexClient {
//downQuery = `ALTER TABLE "${args.columns[0].tn}" ${downQuery};`; //downQuery = `ALTER TABLE "${args.columns[0].tn}" ${downQuery};`;
} }
await this.sqlClient.raw(upQuery); if (upQuery !== '') await this.sqlClient.raw(upQuery);
// console.log(upQuery); // console.log(upQuery);

34
packages/nocodb/src/lib/db/sql-client/lib/sqlite/SqliteClient.ts

@ -1497,7 +1497,7 @@ class SqliteClient extends KnexClient {
if (args.columns[i].altered & 4) { if (args.columns[i].altered & 4) {
// col remove // col remove
upQuery += await this.alterTableRemoveColumn( upQuery += this.alterTableRemoveColumn(
args.table, args.table,
args.columns[i], args.columns[i],
oldColumn, oldColumn,
@ -1552,18 +1552,7 @@ class SqliteClient extends KnexClient {
); );
//downQuery += alterTablePK(args.originalColumns, args.columns, downQuery); //downQuery += alterTablePK(args.originalColumns, args.columns, downQuery);
if (upQuery) { await this.sqlClient.raw(upQuery);
//upQuery = `ALTER TABLE ${args.columns[0].tn} ${upQuery};`;
//downQuery = `ALTER TABLE ${args.columns[0].tn} ${downQuery};`;
}
await Promise.all(
upQuery.split(';').map(async (query) => {
if (query.trim().length) await this.sqlClient.raw(query);
})
);
// await this.sqlClient.raw(upQuery);
console.log(upQuery); console.log(upQuery);
@ -1918,16 +1907,15 @@ class SqliteClient extends KnexClient {
return query; return query;
} }
async alterTableRemoveColumn(t, n, _o, _existingQuery) { alterTableRemoveColumn(t, n, _o, existingQuery) {
// let query = existingQuery ? "," : ""; const shouldSanitize = true;
// query += ` DROP COLUMN ${n.cn}`; let query = existingQuery ? ';' : '';
// query = existingQuery ? query : `ALTER TABLE "${t}" ${query};`; query += this.genQuery(
// return query; `ALTER TABLE ?? DROP COLUMN ??`,
await this.sqlClient.schema.alterTable(t, (tb) => { [t, n.cn],
tb.dropColumn(n.cn); shouldSanitize
}); );
return query;
return '';
} }
createTableColumn(t, n, o, existingQuery) { createTableColumn(t, n, o, existingQuery) {

21
packages/nocodb/src/lib/db/sql-data-mapper/lib/BaseModel.ts

@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/ban-types,prefer-const */ /* eslint-disable @typescript-eslint/ban-types,prefer-const */
import Knex from 'knex'; import { Knex } from 'knex';
import Filter from '../../../models/Filter'; import Filter from '../../../models/Filter';
import Sort from '../../../models/Sort'; import Sort from '../../../models/Sort';
@ -112,7 +112,7 @@ abstract class BaseModel {
timeout: 25000, timeout: 25000,
}; };
this.clientType = this.dbDriver.clientType(); this.clientType = this.dbDriver.client;
autoBind(this); autoBind(this);
} }
@ -221,8 +221,8 @@ abstract class BaseModel {
const query = this.$db.insert(data); const query = this.$db.insert(data);
if ( if (
this.dbDriver.clientType() === 'pg' || this.dbDriver.client === 'pg' ||
this.dbDriver.clientType() === 'mssql' this.dbDriver.client === 'mssql'
) { ) {
query.returning('*'); query.returning('*');
response = await this._run(query); response = await this._run(query);
@ -266,8 +266,8 @@ abstract class BaseModel {
const query = this.$db.insert(data); const query = this.$db.insert(data);
if ( if (
this.dbDriver.clientType() === 'pg' || this.dbDriver.client === 'pg' ||
this.dbDriver.clientType() === 'mssql' this.dbDriver.client === 'mssql'
) { ) {
query.returning('*'); query.returning('*');
response = await this._run(query); response = await this._run(query);
@ -303,9 +303,12 @@ abstract class BaseModel {
await this.validate(d); await this.validate(d);
} }
const response = await this.dbDriver const response = (this.dbDriver.client === 'pg' || this.dbDriver.client === 'mssql') ?
.batchInsert(this.tn, data, 50) this.dbDriver
.returning(this.pks?.[0]?.cn || '*'); .batchInsert(this.tn, data, 50)
.returning(this.pks?.[0]?.cn || '*') :
this.dbDriver
.batchInsert(this.tn, data, 50);
await this.afterInsertb(data); await this.afterInsertb(data);

23
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSql.ts

@ -89,7 +89,7 @@ class BaseModelSql extends BaseModel {
timeout: 25000, timeout: 25000,
}; };
this.clientType = this.dbDriver.clientType(); this.clientType = this.dbDriver.client;
this.dbModels = dbModels; this.dbModels = dbModels;
this._tn = _tn; this._tn = _tn;
autoBind(this); autoBind(this);
@ -281,7 +281,7 @@ class BaseModelSql extends BaseModel {
const query = driver(this.tnPath).insert(insertObj); const query = driver(this.tnPath).insert(insertObj);
if (this.isPg() || this.dbDriver.clientType() === 'mssql') { if (this.isPg() || this.dbDriver.client === 'mssql') {
query.returning( query.returning(
Object.entries(this.aliasToColumn).map( Object.entries(this.aliasToColumn).map(
([val, key]) => `${key} as ${val}` ([val, key]) => `${key} as ${val}`
@ -332,7 +332,7 @@ class BaseModelSql extends BaseModel {
} }
private isPg() { private isPg() {
return this.dbDriver.clientType() === 'pg'; return this.dbDriver.client === 'pg';
} }
/** /**
@ -418,8 +418,8 @@ class BaseModelSql extends BaseModel {
const query = dbDriver(this.tnPath).insert(insertObj); const query = dbDriver(this.tnPath).insert(insertObj);
if ( if (
this.dbDriver.clientType() === 'pg' || this.dbDriver.client === 'pg' ||
this.dbDriver.clientType() === 'mssql' this.dbDriver.client === 'mssql'
) { ) {
query.returning(this.selectQuery('')); query.returning(this.selectQuery(''));
response = await this._run(query); response = await this._run(query);
@ -608,9 +608,12 @@ class BaseModelSql extends BaseModel {
await this.validate(d1); await this.validate(d1);
} }
const response = await this.dbDriver const response = (this.dbDriver.client === 'pg' || this.dbDriver.client === 'mssql') ?
.batchInsert(this.tn, insertDatas, 50) await this.dbDriver
.returning(this.pks[0].cn); .batchInsert(this.tn, insertDatas, 50)
.returning(this.pks[0].cn) :
await this.dbDriver
.batchInsert(this.tn, insertDatas, 50);
await this.afterInsertb(insertDatas, null); await this.afterInsertb(insertDatas, null);
@ -1708,7 +1711,7 @@ class BaseModelSql extends BaseModel {
const query = driver(this.tnPath).insert(insertObj); const query = driver(this.tnPath).insert(insertObj);
if (this.isPg() || this.dbDriver.clientType() === 'mssql') { if (this.isPg() || this.dbDriver.client === 'mssql') {
query.returning( query.returning(
Object.entries(this.aliasToColumn).map( Object.entries(this.aliasToColumn).map(
([val, key]) => `${key} as ${val}` ([val, key]) => `${key} as ${val}`
@ -2096,7 +2099,7 @@ class BaseModelSql extends BaseModel {
} }
isMssql() { isMssql() {
return this.dbDriver.clientType() === 'mssql'; return this.dbDriver.client === 'mssql';
} }
/** /**

187
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts

@ -17,7 +17,7 @@ import Sort from '../../../../models/Sort';
import FormulaColumn from '../../../../models/FormulaColumn'; import FormulaColumn from '../../../../models/FormulaColumn';
import genRollupSelectv2 from './genRollupSelectv2'; import genRollupSelectv2 from './genRollupSelectv2';
import formulaQueryBuilderv2 from './formulav2/formulaQueryBuilderv2'; import formulaQueryBuilderv2 from './formulav2/formulaQueryBuilderv2';
import { QueryBuilder } from 'knex'; import { Knex } from 'knex';
import View from '../../../../models/View'; import View from '../../../../models/View';
import { import {
AuditOperationSubTypes, AuditOperationSubTypes,
@ -391,7 +391,10 @@ class BaseModelSqlv2 {
}); });
await parentTable.getColumns(); await parentTable.getColumns();
const qb = this.dbDriver(childTable.table_name); const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const qb = this.dbDriver(childTn);
await childModel.selectObject({ qb }); await childModel.selectObject({ qb });
await this.applySortAndFilter({ table: childTable, where, qb, sort }); await this.applySortAndFilter({ table: childTable, where, qb, sort });
@ -404,7 +407,7 @@ class BaseModelSqlv2 {
.select(this.dbDriver.raw('? as ??', [p, GROUP_COL])) .select(this.dbDriver.raw('? as ??', [p, GROUP_COL]))
.whereIn( .whereIn(
chilCol.column_name, chilCol.column_name,
this.dbDriver(parentTable.table_name) this.dbDriver(parentTn)
.select(parentCol.column_name) .select(parentCol.column_name)
// .where(parentTable.primaryKey.cn, p) // .where(parentTable.primaryKey.cn, p)
.where(_wherePk(parentTable.primaryKeys, p)) .where(_wherePk(parentTable.primaryKeys, p))
@ -477,13 +480,16 @@ class BaseModelSqlv2 {
const parentTable = await parentCol.getModel(); const parentTable = await parentCol.getModel();
await parentTable.getColumns(); await parentTable.getColumns();
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const children = await this.dbDriver.unionAll( const children = await this.dbDriver.unionAll(
ids.map((p) => { ids.map((p) => {
const query = this.dbDriver(childTable.table_name) const query = this.dbDriver(childTn)
.count(`${chilCol?.column_name} as count`) .count(`${chilCol?.column_name} as count`)
.whereIn( .whereIn(
chilCol.column_name, chilCol.column_name,
this.dbDriver(parentTable.table_name) this.dbDriver(parentTn)
.select(parentCol.column_name) .select(parentCol.column_name)
// .where(parentTable.primaryKey.cn, p) // .where(parentTable.primaryKey.cn, p)
.where(_wherePk(parentTable.primaryKeys, p)) .where(_wherePk(parentTable.primaryKeys, p))
@ -525,12 +531,15 @@ class BaseModelSqlv2 {
}); });
await parentTable.getColumns(); await parentTable.getColumns();
const qb = this.dbDriver(childTable.table_name); const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const qb = this.dbDriver(childTn);
await this.applySortAndFilter({ table: childTable, where, qb, sort }); await this.applySortAndFilter({ table: childTable, where, qb, sort });
qb.whereIn( qb.whereIn(
chilCol.column_name, chilCol.column_name,
this.dbDriver(parentTable.table_name) this.dbDriver(parentTn)
.select(parentCol.column_name) .select(parentCol.column_name)
// .where(parentTable.primaryKey.cn, p) // .where(parentTable.primaryKey.cn, p)
.where(_wherePk(parentTable.primaryKeys, id)) .where(_wherePk(parentTable.primaryKeys, id))
@ -576,11 +585,14 @@ class BaseModelSqlv2 {
const parentTable = await parentCol.getModel(); const parentTable = await parentCol.getModel();
await parentTable.getColumns(); await parentTable.getColumns();
const query = this.dbDriver(childTable.table_name) const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const query = this.dbDriver(childTn)
.count(`${chilCol?.column_name} as count`) .count(`${chilCol?.column_name} as count`)
.whereIn( .whereIn(
chilCol.column_name, chilCol.column_name,
this.dbDriver(parentTable.table_name) this.dbDriver(parentTn)
.select(parentCol.column_name) .select(parentCol.column_name)
.where(_wherePk(parentTable.primaryKeys, id)) .where(_wherePk(parentTable.primaryKeys, id))
) )
@ -607,7 +619,8 @@ class BaseModelSqlv2 {
// const tn = this.model.tn; // const tn = this.model.tn;
// const cn = (await relColOptions.getChildColumn()).title; // const cn = (await relColOptions.getChildColumn()).title;
const vtn = (await relColOptions.getMMModel()).table_name; const mmTable = await relColOptions.getMMModel();
const vtn = this.getTnPath(mmTable);
const vcn = (await relColOptions.getMMChildColumn()).column_name; const vcn = (await relColOptions.getMMChildColumn()).column_name;
const vrcn = (await relColOptions.getMMParentColumn()).column_name; const vrcn = (await relColOptions.getMMParentColumn()).column_name;
const rcn = (await relColOptions.getParentColumn()).column_name; const rcn = (await relColOptions.getParentColumn()).column_name;
@ -619,7 +632,11 @@ class BaseModelSqlv2 {
dbDriver: this.dbDriver, dbDriver: this.dbDriver,
model: childTable, model: childTable,
}); });
const rtn = childTable.table_name;
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const rtn = childTn;
const rtnId = childTable.id; const rtnId = childTable.id;
const qb = this.dbDriver(rtn).join(vtn, `${vtn}.${vrcn}`, `${rtn}.${rcn}`); const qb = this.dbDriver(rtn).join(vtn, `${vtn}.${vrcn}`, `${rtn}.${rcn}`);
@ -634,7 +651,7 @@ class BaseModelSqlv2 {
.clone() .clone()
.whereIn( .whereIn(
`${vtn}.${vcn}`, `${vtn}.${vcn}`,
this.dbDriver(parentTable.table_name) this.dbDriver(parentTn)
.select(cn) .select(cn)
// .where(parentTable.primaryKey.cn, id) // .where(parentTable.primaryKey.cn, id)
.where(_wherePk(parentTable.primaryKeys, id)) .where(_wherePk(parentTable.primaryKeys, id))
@ -680,7 +697,8 @@ class BaseModelSqlv2 {
// const tn = this.model.tn; // const tn = this.model.tn;
// const cn = (await relColOptions.getChildColumn()).title; // const cn = (await relColOptions.getChildColumn()).title;
const vtn = (await relColOptions.getMMModel()).table_name; const mmTable = await relColOptions.getMMModel();
const vtn = this.getTnPath(mmTable);
const vcn = (await relColOptions.getMMChildColumn()).column_name; const vcn = (await relColOptions.getMMChildColumn()).column_name;
const vrcn = (await relColOptions.getMMParentColumn()).column_name; const vrcn = (await relColOptions.getMMParentColumn()).column_name;
const rcn = (await relColOptions.getParentColumn()).column_name; const rcn = (await relColOptions.getParentColumn()).column_name;
@ -692,14 +710,18 @@ class BaseModelSqlv2 {
dbDriver: this.dbDriver, dbDriver: this.dbDriver,
model: childTable, model: childTable,
}); });
const rtn = childTable.table_name;
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const rtn = childTn;
const rtnId = childTable.id; const rtnId = childTable.id;
const qb = this.dbDriver(rtn) const qb = this.dbDriver(rtn)
.join(vtn, `${vtn}.${vrcn}`, `${rtn}.${rcn}`) .join(vtn, `${vtn}.${vrcn}`, `${rtn}.${rcn}`)
.whereIn( .whereIn(
`${vtn}.${vcn}`, `${vtn}.${vcn}`,
this.dbDriver(parentTable.table_name) this.dbDriver(parentTn)
.select(cn) .select(cn)
// .where(parentTable.primaryKey.cn, id) // .where(parentTable.primaryKey.cn, id)
.where(_wherePk(parentTable.primaryKeys, parentId)) .where(_wherePk(parentTable.primaryKeys, parentId))
@ -731,16 +753,21 @@ class BaseModelSqlv2 {
const relColOptions = const relColOptions =
(await relColumn.getColOptions()) as LinkToAnotherRecordColumn; (await relColumn.getColOptions()) as LinkToAnotherRecordColumn;
const vtn = (await relColOptions.getMMModel()).table_name; const mmTable = await relColOptions.getMMModel();
const vtn = this.getTnPath(mmTable);
const vcn = (await relColOptions.getMMChildColumn()).column_name; const vcn = (await relColOptions.getMMChildColumn()).column_name;
const vrcn = (await relColOptions.getMMParentColumn()).column_name; const vrcn = (await relColOptions.getMMParentColumn()).column_name;
const rcn = (await relColOptions.getParentColumn()).column_name; const rcn = (await relColOptions.getParentColumn()).column_name;
const cn = (await relColOptions.getChildColumn()).column_name; const cn = (await relColOptions.getChildColumn()).column_name;
const childTable = await (await relColOptions.getParentColumn()).getModel(); const childTable = await (await relColOptions.getParentColumn()).getModel();
const rtn = childTable.table_name;
const parentTable = await (await relColOptions.getChildColumn()).getModel(); const parentTable = await (await relColOptions.getChildColumn()).getModel();
await parentTable.getColumns(); await parentTable.getColumns();
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const rtn = childTn;
const qb = this.dbDriver(rtn) const qb = this.dbDriver(rtn)
.join(vtn, `${vtn}.${vrcn}`, `${rtn}.${rcn}`) .join(vtn, `${vtn}.${vrcn}`, `${rtn}.${rcn}`)
// .select({ // .select({
@ -755,7 +782,7 @@ class BaseModelSqlv2 {
.clone() .clone()
.whereIn( .whereIn(
`${vtn}.${vcn}`, `${vtn}.${vcn}`,
this.dbDriver(parentTable.table_name) this.dbDriver(parentTn)
.select(cn) .select(cn)
// .where(parentTable.primaryKey.cn, id) // .where(parentTable.primaryKey.cn, id)
.where(_wherePk(parentTable.primaryKeys, id)) .where(_wherePk(parentTable.primaryKeys, id))
@ -778,16 +805,21 @@ class BaseModelSqlv2 {
const relColOptions = const relColOptions =
(await relColumn.getColOptions()) as LinkToAnotherRecordColumn; (await relColumn.getColOptions()) as LinkToAnotherRecordColumn;
const vtn = (await relColOptions.getMMModel()).table_name; const mmTable = await relColOptions.getMMModel();
const vtn = this.getTnPath(mmTable);
const vcn = (await relColOptions.getMMChildColumn()).column_name; const vcn = (await relColOptions.getMMChildColumn()).column_name;
const vrcn = (await relColOptions.getMMParentColumn()).column_name; const vrcn = (await relColOptions.getMMParentColumn()).column_name;
const rcn = (await relColOptions.getParentColumn()).column_name; const rcn = (await relColOptions.getParentColumn()).column_name;
const cn = (await relColOptions.getChildColumn()).column_name; const cn = (await relColOptions.getChildColumn()).column_name;
const childTable = await (await relColOptions.getParentColumn()).getModel(); const childTable = await (await relColOptions.getParentColumn()).getModel();
const rtn = childTable.table_name;
const parentTable = await (await relColOptions.getChildColumn()).getModel(); const parentTable = await (await relColOptions.getChildColumn()).getModel();
await parentTable.getColumns(); await parentTable.getColumns();
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const rtn = childTn;
const qb = this.dbDriver(rtn) const qb = this.dbDriver(rtn)
.join(vtn, `${vtn}.${vrcn}`, `${rtn}.${rcn}`) .join(vtn, `${vtn}.${vrcn}`, `${rtn}.${rcn}`)
// .select({ // .select({
@ -796,7 +828,7 @@ class BaseModelSqlv2 {
.count(`${vtn}.${vcn}`, { as: 'count' }) .count(`${vtn}.${vcn}`, { as: 'count' })
.whereIn( .whereIn(
`${vtn}.${vcn}`, `${vtn}.${vcn}`,
this.dbDriver(parentTable.table_name) this.dbDriver(parentTn)
.select(cn) .select(cn)
// .where(parentTable.primaryKey.cn, id) // .where(parentTable.primaryKey.cn, id)
.where(_wherePk(parentTable.primaryKeys, parentId)) .where(_wherePk(parentTable.primaryKeys, parentId))
@ -820,7 +852,8 @@ class BaseModelSqlv2 {
const relColOptions = const relColOptions =
(await relColumn.getColOptions()) as LinkToAnotherRecordColumn; (await relColumn.getColOptions()) as LinkToAnotherRecordColumn;
const vtn = (await relColOptions.getMMModel()).table_name; const mmTable = await relColOptions.getMMModel();
const vtn = this.getTnPath(mmTable);
const vcn = (await relColOptions.getMMChildColumn()).column_name; const vcn = (await relColOptions.getMMChildColumn()).column_name;
const vrcn = (await relColOptions.getMMParentColumn()).column_name; const vrcn = (await relColOptions.getMMParentColumn()).column_name;
const rcn = (await relColOptions.getParentColumn()).column_name; const rcn = (await relColOptions.getParentColumn()).column_name;
@ -828,7 +861,11 @@ class BaseModelSqlv2 {
const childTable = await (await relColOptions.getParentColumn()).getModel(); const childTable = await (await relColOptions.getParentColumn()).getModel();
const parentTable = await (await relColOptions.getChildColumn()).getModel(); const parentTable = await (await relColOptions.getChildColumn()).getModel();
await parentTable.getColumns(); await parentTable.getColumns();
const rtn = childTable.table_name;
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const rtn = childTn;
const qb = this.dbDriver(rtn) const qb = this.dbDriver(rtn)
.count(`*`, { as: 'count' }) .count(`*`, { as: 'count' })
.where((qb) => { .where((qb) => {
@ -839,7 +876,7 @@ class BaseModelSqlv2 {
.join(vtn, `${rtn}.${rcn}`, `${vtn}.${vrcn}`) .join(vtn, `${rtn}.${rcn}`, `${vtn}.${vrcn}`)
.whereIn( .whereIn(
`${vtn}.${vcn}`, `${vtn}.${vcn}`,
this.dbDriver(parentTable.table_name) this.dbDriver(parentTn)
.select(cn) .select(cn)
// .where(parentTable.primaryKey.cn, pid) // .where(parentTable.primaryKey.cn, pid)
.where(_wherePk(parentTable.primaryKeys, pid)) .where(_wherePk(parentTable.primaryKeys, pid))
@ -866,7 +903,8 @@ class BaseModelSqlv2 {
const relColOptions = const relColOptions =
(await relColumn.getColOptions()) as LinkToAnotherRecordColumn; (await relColumn.getColOptions()) as LinkToAnotherRecordColumn;
const vtn = (await relColOptions.getMMModel()).table_name; const mmTable = await relColOptions.getMMModel();
const vtn = this.getTnPath(mmTable);
const vcn = (await relColOptions.getMMChildColumn()).column_name; const vcn = (await relColOptions.getMMChildColumn()).column_name;
const vrcn = (await relColOptions.getMMParentColumn()).column_name; const vrcn = (await relColOptions.getMMParentColumn()).column_name;
const rcn = (await relColOptions.getParentColumn()).column_name; const rcn = (await relColOptions.getParentColumn()).column_name;
@ -878,7 +916,11 @@ class BaseModelSqlv2 {
}); });
const parentTable = await (await relColOptions.getChildColumn()).getModel(); const parentTable = await (await relColOptions.getChildColumn()).getModel();
await parentTable.getColumns(); await parentTable.getColumns();
const rtn = childTable.table_name;
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const rtn = childTn;
const qb = this.dbDriver(rtn).where((qb) => const qb = this.dbDriver(rtn).where((qb) =>
qb qb
@ -889,7 +931,7 @@ class BaseModelSqlv2 {
.join(vtn, `${rtn}.${rcn}`, `${vtn}.${vrcn}`) .join(vtn, `${rtn}.${rcn}`, `${vtn}.${vrcn}`)
.whereIn( .whereIn(
`${vtn}.${vcn}`, `${vtn}.${vcn}`,
this.dbDriver(parentTable.table_name) this.dbDriver(parentTn)
.select(cn) .select(cn)
// .where(parentTable.primaryKey.cn, pid) // .where(parentTable.primaryKey.cn, pid)
.where(_wherePk(parentTable.primaryKeys, pid)) .where(_wherePk(parentTable.primaryKeys, pid))
@ -945,8 +987,12 @@ class BaseModelSqlv2 {
const parentTable = await ( const parentTable = await (
await relColOptions.getParentColumn() await relColOptions.getParentColumn()
).getModel(); ).getModel();
const tn = childTable.table_name;
const rtn = parentTable.table_name; const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const tn = childTn;
const rtn = parentTn;
await parentTable.getColumns(); await parentTable.getColumns();
const qb = this.dbDriver(tn) const qb = this.dbDriver(tn)
@ -993,8 +1039,11 @@ class BaseModelSqlv2 {
}); });
await parentTable.getColumns(); await parentTable.getColumns();
const tn = childTable.table_name; const childTn = this.getTnPath(childTable);
const rtn = parentTable.table_name; const parentTn = this.getTnPath(parentTable);
const tn = childTn;
const rtn = parentTn;
const qb = this.dbDriver(tn).where((qb) => { const qb = this.dbDriver(tn).where((qb) => {
qb.whereNotIn( qb.whereNotIn(
@ -1054,8 +1103,11 @@ class BaseModelSqlv2 {
const cn = (await relColOptions.getChildColumn()).column_name; const cn = (await relColOptions.getChildColumn()).column_name;
const childTable = await (await relColOptions.getChildColumn()).getModel(); const childTable = await (await relColOptions.getChildColumn()).getModel();
const rtn = parentTable.table_name; const childTn = this.getTnPath(childTable);
const tn = childTable.table_name; const parentTn = this.getTnPath(parentTable);
const rtn = parentTn;
const tn = childTn;
await childTable.getColumns(); await childTable.getColumns();
const qb = this.dbDriver(rtn) const qb = this.dbDriver(rtn)
@ -1100,8 +1152,12 @@ class BaseModelSqlv2 {
dbDriver: this.dbDriver, dbDriver: this.dbDriver,
model: parentTable, model: parentTable,
}); });
const rtn = parentTable.table_name;
const tn = childTable.table_name; const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
const rtn = parentTn;
const tn = childTn;
await childTable.getColumns(); await childTable.getColumns();
const qb = this.dbDriver(rtn).where((qb) => { const qb = this.dbDriver(rtn).where((qb) => {
@ -1336,7 +1392,7 @@ class BaseModelSqlv2 {
return obj; return obj;
} }
public async shuffle({ qb }: { qb: QueryBuilder }): Promise<void> { public async shuffle({ qb }: { qb: Knex.QueryBuilder }): Promise<void> {
if (this.isMySQL) { if (this.isMySQL) {
qb.orderByRaw('RAND()'); qb.orderByRaw('RAND()');
} else if (this.isPg || this.isSqlite) { } else if (this.isPg || this.isSqlite) {
@ -1350,7 +1406,7 @@ class BaseModelSqlv2 {
qb, qb,
columns: _columns, columns: _columns,
}: { }: {
qb: QueryBuilder; qb: Knex.QueryBuilder;
columns?: Column[]; columns?: Column[];
}): Promise<void> { }): Promise<void> {
const res = {}; const res = {};
@ -1569,15 +1625,19 @@ class BaseModelSqlv2 {
return _wherePk(this.model.primaryKeys, id); return _wherePk(this.model.primaryKeys, id);
} }
public get tnPath() { private getTnPath(tb: Model) {
const schema = (this.dbDriver as any).searchPath?.(); const schema = (this.dbDriver as any).searchPath?.();
const table = const table =
this.isMssql && schema this.isMssql && schema
? this.dbDriver.raw('??.??', [schema, this.model.table_name]) ? this.dbDriver.raw('??.??', [schema, tb.table_name])
: this.model.table_name; : tb.table_name;
return table; return table;
} }
public get tnPath() {
return this.getTnPath(this.model);
}
get isSqlite() { get isSqlite() {
return this.clientType === 'sqlite3'; return this.clientType === 'sqlite3';
} }
@ -1766,9 +1826,12 @@ class BaseModelSqlv2 {
// refer : https://www.sqlite.org/limits.html // refer : https://www.sqlite.org/limits.html
const chunkSize = this.isSqlite ? 10 : _chunkSize; const chunkSize = this.isSqlite ? 10 : _chunkSize;
const response = await this.dbDriver const response = (this.isPg || this.isMssql) ?
.batchInsert(this.model.table_name, insertDatas, chunkSize) await this.dbDriver
.returning(this.model.primaryKey?.column_name); .batchInsert(this.model.table_name, insertDatas, chunkSize)
.returning(this.model.primaryKey?.column_name) :
await this.dbDriver
.batchInsert(this.model.table_name, insertDatas, chunkSize);
await this.afterBulkInsert(insertDatas, this.dbDriver, cookie); await this.afterBulkInsert(insertDatas, this.dbDriver, cookie);
@ -2230,6 +2293,9 @@ class BaseModelSqlv2 {
await childTable.getColumns(); await childTable.getColumns();
await parentTable.getColumns(); await parentTable.getColumns();
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
switch (colOptions.type) { switch (colOptions.type) {
case RelationTypes.MANY_TO_MANY: case RelationTypes.MANY_TO_MANY:
{ {
@ -2237,12 +2303,14 @@ class BaseModelSqlv2 {
const vParentCol = await colOptions.getMMParentColumn(); const vParentCol = await colOptions.getMMParentColumn();
const vTable = await colOptions.getMMModel(); const vTable = await colOptions.getMMModel();
await this.dbDriver(vTable.table_name).insert({ const vTn = this.getTnPath(vTable);
[vParentCol.column_name]: this.dbDriver(parentTable.table_name)
await this.dbDriver(vTn).insert({
[vParentCol.column_name]: this.dbDriver(parentTn)
.select(parentColumn.column_name) .select(parentColumn.column_name)
.where(_wherePk(parentTable.primaryKeys, childId)) .where(_wherePk(parentTable.primaryKeys, childId))
.first(), .first(),
[vChildCol.column_name]: this.dbDriver(childTable.table_name) [vChildCol.column_name]: this.dbDriver(childTn)
.select(childColumn.column_name) .select(childColumn.column_name)
.where(_wherePk(childTable.primaryKeys, rowId)) .where(_wherePk(childTable.primaryKeys, rowId))
.first(), .first(),
@ -2251,10 +2319,10 @@ class BaseModelSqlv2 {
break; break;
case RelationTypes.HAS_MANY: case RelationTypes.HAS_MANY:
{ {
await this.dbDriver(childTable.table_name) await this.dbDriver(childTn)
.update({ .update({
[childColumn.column_name]: this.dbDriver.from( [childColumn.column_name]: this.dbDriver.from(
this.dbDriver(parentTable.table_name) this.dbDriver(parentTn)
.select(parentColumn.column_name) .select(parentColumn.column_name)
.where(_wherePk(parentTable.primaryKeys, rowId)) .where(_wherePk(parentTable.primaryKeys, rowId))
.first() .first()
@ -2266,10 +2334,10 @@ class BaseModelSqlv2 {
break; break;
case RelationTypes.BELONGS_TO: case RelationTypes.BELONGS_TO:
{ {
await this.dbDriver(childTable.table_name) await this.dbDriver(childTn)
.update({ .update({
[childColumn.column_name]: this.dbDriver.from( [childColumn.column_name]: this.dbDriver.from(
this.dbDriver(parentTable.table_name) this.dbDriver(parentTn)
.select(parentColumn.column_name) .select(parentColumn.column_name)
.where(_wherePk(parentTable.primaryKeys, childId)) .where(_wherePk(parentTable.primaryKeys, childId))
.first() .first()
@ -2325,6 +2393,9 @@ class BaseModelSqlv2 {
await childTable.getColumns(); await childTable.getColumns();
await parentTable.getColumns(); await parentTable.getColumns();
const childTn = this.getTnPath(childTable);
const parentTn = this.getTnPath(parentTable);
switch (colOptions.type) { switch (colOptions.type) {
case RelationTypes.MANY_TO_MANY: case RelationTypes.MANY_TO_MANY:
{ {
@ -2332,13 +2403,15 @@ class BaseModelSqlv2 {
const vParentCol = await colOptions.getMMParentColumn(); const vParentCol = await colOptions.getMMParentColumn();
const vTable = await colOptions.getMMModel(); const vTable = await colOptions.getMMModel();
await this.dbDriver(vTable.table_name) const vTn = this.getTnPath(vTable);
await this.dbDriver(vTn)
.where({ .where({
[vParentCol.column_name]: this.dbDriver(parentTable.table_name) [vParentCol.column_name]: this.dbDriver(parentTn)
.select(parentColumn.column_name) .select(parentColumn.column_name)
.where(_wherePk(parentTable.primaryKeys, childId)) .where(_wherePk(parentTable.primaryKeys, childId))
.first(), .first(),
[vChildCol.column_name]: this.dbDriver(childTable.table_name) [vChildCol.column_name]: this.dbDriver(childTn)
.select(childColumn.column_name) .select(childColumn.column_name)
.where(_wherePk(childTable.primaryKeys, rowId)) .where(_wherePk(childTable.primaryKeys, rowId))
.first(), .first(),
@ -2348,7 +2421,7 @@ class BaseModelSqlv2 {
break; break;
case RelationTypes.HAS_MANY: case RelationTypes.HAS_MANY:
{ {
await this.dbDriver(childTable.table_name) await this.dbDriver(childTn)
// .where({ // .where({
// [childColumn.cn]: this.dbDriver(parentTable.tn) // [childColumn.cn]: this.dbDriver(parentTable.tn)
// .select(parentColumn.cn) // .select(parentColumn.cn)
@ -2361,7 +2434,7 @@ class BaseModelSqlv2 {
break; break;
case RelationTypes.BELONGS_TO: case RelationTypes.BELONGS_TO:
{ {
await this.dbDriver(childTable.table_name) await this.dbDriver(childTn)
// .where({ // .where({
// [childColumn.cn]: this.dbDriver(parentTable.tn) // [childColumn.cn]: this.dbDriver(parentTable.tn)
// .select(parentColumn.cn) // .select(parentColumn.cn)
@ -2629,7 +2702,7 @@ class BaseModelSqlv2 {
return await qb; return await qb;
} }
private async extractRawQueryAndExec(qb: QueryBuilder) { private async extractRawQueryAndExec(qb: Knex.QueryBuilder) {
let query = qb.toQuery(); let query = qb.toQuery();
if (!this.isPg && !this.isMssql) { if (!this.isPg && !this.isMssql) {
query = unsanitize(qb.toQuery()); query = unsanitize(qb.toQuery());

130
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/CustomKnex.ts

@ -1,4 +1,4 @@
import Knex, { QueryBuilder } from 'knex'; import { Knex, knex } from 'knex';
const types = require('pg').types; const types = require('pg').types;
// override parsing date column to Date() // override parsing date column to Date()
@ -464,70 +464,72 @@ const appendWhereCondition = function (
}; };
declare module 'knex' { declare module 'knex' {
interface QueryInterface { namespace Knex {
clientType(): string; interface QueryInterface {
} clientType(): string;
}
export type XcConditionObjVal = {
[key in 'eq' | 'neq' | 'lt' | 'gt' | 'ge' | 'le' | 'like' | 'nlike']:
| string
| number
| any;
};
export interface XcXonditionObj {
_or: XcXonditionObj[];
_and: XcXonditionObj[];
_not: XcXonditionObj;
[key: string]: export type XcConditionObjVal = {
| XcXonditionObj [key in 'eq' | 'neq' | 'lt' | 'gt' | 'ge' | 'le' | 'like' | 'nlike']:
| XcXonditionObj[] | string
| XcConditionObjVal | number
| XcConditionObjVal[]; | any;
} };
export interface XcXonditionObj {
_or: XcXonditionObj[];
_and: XcXonditionObj[];
_not: XcXonditionObj;
[key: string]:
| XcXonditionObj
| XcXonditionObj[]
| XcConditionObjVal
| XcConditionObjVal[];
}
interface QueryBuilder { interface QueryBuilder {
xwhere<TRecord, TResult>( xwhere<TRecord, TResult>(
value: string, value: string,
columnAliases?: { columnAliases?: {
[columnAlias: string]: string; [columnAlias: string]: string;
} }
): Knex.QueryBuilder<TRecord, TResult>; ): Knex.QueryBuilder<TRecord, TResult>;
condition<TRecord, TResult>( condition<TRecord, TResult>(
conditionObj: XcXonditionObj, conditionObj: XcXonditionObj,
columnAliases?: { columnAliases?: {
[columnAlias: string]: string; [columnAlias: string]: string;
} }
): Knex.QueryBuilder<TRecord, TResult>; ): Knex.QueryBuilder<TRecord, TResult>;
conditionv2<TRecord, TResult>( conditionv2<TRecord, TResult>(
conditionObj: Filter conditionObj: Filter
): Knex.QueryBuilder<TRecord, TResult>; ): Knex.QueryBuilder<TRecord, TResult>;
concat<TRecord, TResult>( concat<TRecord, TResult>(
cn: string | any cn: string | any
): Knex.QueryBuilder<TRecord, TResult>; ): Knex.QueryBuilder<TRecord, TResult>;
conditionGraph<TRecord, TResult>(condition: { conditionGraph<TRecord, TResult>(condition: {
condition: XcXonditionObj; condition: XcXonditionObj;
models: { [key: string]: BaseModelSql }; models: { [key: string]: BaseModelSql };
}): Knex.QueryBuilder<TRecord, TResult>; }): Knex.QueryBuilder<TRecord, TResult>;
xhaving<TRecord, TResult>( xhaving<TRecord, TResult>(
value: string, value: string,
columnAliases?: { columnAliases?: {
[columnAlias: string]: string; [columnAlias: string]: string;
} }
): Knex.QueryBuilder<TRecord, TResult>; ): Knex.QueryBuilder<TRecord, TResult>;
}
} }
} }
/** /**
* Append xwhere to knex query builder * Append xwhere to knex query builder
*/ */
Knex.QueryBuilder.extend( knex.QueryBuilder.extend(
'xwhere', 'xwhere',
function ( function (
conditionString, conditionString,
@ -542,7 +544,7 @@ Knex.QueryBuilder.extend(
/** /**
* Append concat to knex query builder * Append concat to knex query builder
*/ */
Knex.QueryBuilder.extend('concat', function (cn: any) { knex.QueryBuilder.extend('concat', function (cn: any) {
switch (this?.client?.config?.client) { switch (this?.client?.config?.client) {
case 'pg': case 'pg':
this.select(this.client.raw(`STRING_AGG(?? , ',')`, [cn])); this.select(this.client.raw(`STRING_AGG(?? , ',')`, [cn]));
@ -564,7 +566,7 @@ Knex.QueryBuilder.extend('concat', function (cn: any) {
/** /**
* Append xhaving to knex query builder * Append xhaving to knex query builder
*/ */
Knex.QueryBuilder.extend( knex.QueryBuilder.extend(
'xhaving', 'xhaving',
function ( function (
conditionString, conditionString,
@ -580,7 +582,7 @@ Knex.QueryBuilder.extend(
/** /**
* Append custom where condition(nested object) to knex query builder * Append custom where condition(nested object) to knex query builder
*/ */
Knex.QueryBuilder.extend('condition', function (conditionObj, columnAliases) { knex.QueryBuilder.extend('condition', function (conditionObj, columnAliases) {
if (!conditionObj || typeof conditionObj !== 'object') { if (!conditionObj || typeof conditionObj !== 'object') {
return this; return this;
} }
@ -661,7 +663,7 @@ const parseCondition = (obj, columnAliases, qb, pKey?) => {
}; };
// todo: optimize // todo: optimize
Knex.QueryBuilder.extend( knex.QueryBuilder.extend(
'conditionGraph', 'conditionGraph',
function (args: { condition; models }) { function (args: { condition; models }) {
if (!args) { if (!args) {
@ -986,9 +988,9 @@ function parseNestedCondition(obj, qb, pKey?, table?, tableAlias?) {
type CustomKnex = Knex; type CustomKnex = Knex;
function CustomKnex(arg: string | Knex.Config<any> | any): CustomKnex { function CustomKnex(arg: string | Knex.Config<any> | any): CustomKnex {
const knex: any = Knex(arg); const kn: any = knex(arg);
const knexRaw = knex.raw; const knexRaw = kn.raw;
/** /**
* Wrapper for knex.raw * Wrapper for knex.raw
@ -1000,11 +1002,11 @@ function CustomKnex(arg: string | Knex.Config<any> | any): CustomKnex {
// return knexRaw.apply(knex, args); // return knexRaw.apply(knex, args);
// }; // };
Object.defineProperties(knex, { Object.defineProperties(kn, {
raw: { raw: {
enumerable: true, enumerable: true,
value: (...args) => { value: (...args) => {
return knexRaw.apply(knex, args); return knexRaw.apply(kn, args);
}, },
}, },
clientType: { clientType: {
@ -1032,11 +1034,11 @@ function CustomKnex(arg: string | Knex.Config<any> | any): CustomKnex {
// return typeof arg === 'string' ? arg.match(/^(\w+):/) ?? [1] : arg.client; // return typeof arg === 'string' ? arg.match(/^(\w+):/) ?? [1] : arg.client;
// }; // };
return knex; return kn;
} }
// todo: optimize // todo: optimize
Knex.QueryBuilder.extend( knex.QueryBuilder.extend(
'conditionGraphv2', 'conditionGraphv2',
function (args: { condition; models }) { function (args: { condition; models }) {
if (!args) { if (!args) {
@ -1227,14 +1229,14 @@ function parseNestedConditionv2(obj, qb, pKey?, table?, tableAlias?) {
/** /**
* Append custom where condition(nested object) to knex query builder * Append custom where condition(nested object) to knex query builder
*/ */
Knex.QueryBuilder.extend('conditionv2', function (conditionObj: Filter) { knex.QueryBuilder.extend('conditionv2', function (conditionObj: Filter) {
if (!conditionObj || typeof conditionObj !== 'object') { if (!conditionObj || typeof conditionObj !== 'object') {
return this; return this;
} }
return parseConditionv2(conditionObj, this); return parseConditionv2(conditionObj, this);
} as any); } as any);
const parseConditionv2 = (obj: Filter, qb: QueryBuilder) => { const parseConditionv2 = (obj: Filter, qb: Knex.QueryBuilder) => {
if (obj.is_group) { if (obj.is_group) {
qb = qb.where(function () { qb = qb.where(function () {
const children = obj.children; const children = obj.children;

18
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/conditionV2.ts

@ -1,6 +1,6 @@
import Filter from '../../../../models/Filter'; import Filter from '../../../../models/Filter';
import LinkToAnotherRecordColumn from '../../../../models/LinkToAnotherRecordColumn'; import LinkToAnotherRecordColumn from '../../../../models/LinkToAnotherRecordColumn';
import { QueryBuilder } from 'knex'; import { Knex } from 'knex';
import { XKnex } from '../../index'; import { XKnex } from '../../index';
import Column from '../../../../models/Column'; import Column from '../../../../models/Column';
import LookupColumn from '../../../../models/LookupColumn'; import LookupColumn from '../../../../models/LookupColumn';
@ -14,7 +14,7 @@ import { sanitize } from './helpers/sanitize';
export default async function conditionV2( export default async function conditionV2(
conditionObj: Filter | Filter[], conditionObj: Filter | Filter[],
qb: QueryBuilder, qb: Knex.QueryBuilder,
knex: XKnex knex: XKnex
) { ) {
if (!conditionObj || typeof conditionObj !== 'object') { if (!conditionObj || typeof conditionObj !== 'object') {
@ -127,7 +127,7 @@ const parseConditionV2 = async (
) )
)(selectQb); )(selectQb);
return (qbP: QueryBuilder) => { return (qbP: Knex.QueryBuilder) => {
if (filter.comparison_op in negatedMapping) if (filter.comparison_op in negatedMapping)
qbP.whereNotIn(parentColumn.column_name, selectQb); qbP.whereNotIn(parentColumn.column_name, selectQb);
else qbP.whereIn(parentColumn.column_name, selectQb); else qbP.whereIn(parentColumn.column_name, selectQb);
@ -162,7 +162,7 @@ const parseConditionV2 = async (
) )
)(selectQb); )(selectQb);
return (qbP: QueryBuilder) => { return (qbP: Knex.QueryBuilder) => {
if (filter.comparison_op in negatedMapping) if (filter.comparison_op in negatedMapping)
qbP.whereNotIn(childColumn.column_name, selectQb); qbP.whereNotIn(childColumn.column_name, selectQb);
else qbP.whereIn(childColumn.column_name, selectQb); else qbP.whereIn(childColumn.column_name, selectQb);
@ -217,7 +217,7 @@ const parseConditionV2 = async (
) )
)(selectQb); )(selectQb);
return (qbP: QueryBuilder) => { return (qbP: Knex.QueryBuilder) => {
if (filter.comparison_op in negatedMapping) if (filter.comparison_op in negatedMapping)
qbP.whereNotIn(childColumn.column_name, selectQb); qbP.whereNotIn(childColumn.column_name, selectQb);
else qbP.whereIn(childColumn.column_name, selectQb); else qbP.whereIn(childColumn.column_name, selectQb);
@ -428,7 +428,7 @@ async function generateLookupCondition(
aliasCount aliasCount
); );
return (qbP: QueryBuilder) => { return (qbP: Knex.QueryBuilder) => {
if (filter.comparison_op in negatedMapping) if (filter.comparison_op in negatedMapping)
qbP.whereNotIn(parentColumn.column_name, qb); qbP.whereNotIn(parentColumn.column_name, qb);
else qbP.whereIn(parentColumn.column_name, qb); else qbP.whereIn(parentColumn.column_name, qb);
@ -451,7 +451,7 @@ async function generateLookupCondition(
aliasCount aliasCount
); );
return (qbP: QueryBuilder) => { return (qbP: Knex.QueryBuilder) => {
if (filter.comparison_op in negatedMapping) if (filter.comparison_op in negatedMapping)
qbP.whereNotIn(childColumn.column_name, qb); qbP.whereNotIn(childColumn.column_name, qb);
else qbP.whereIn(childColumn.column_name, qb); else qbP.whereIn(childColumn.column_name, qb);
@ -485,7 +485,7 @@ async function generateLookupCondition(
aliasCount aliasCount
); );
return (qbP: QueryBuilder) => { return (qbP: Knex.QueryBuilder) => {
if (filter.comparison_op in negatedMapping) if (filter.comparison_op in negatedMapping)
qbP.whereNotIn(childColumn.column_name, qb); qbP.whereNotIn(childColumn.column_name, qb);
else qbP.whereIn(childColumn.column_name, qb); else qbP.whereIn(childColumn.column_name, qb);
@ -497,7 +497,7 @@ async function generateLookupCondition(
async function nestedConditionJoin( async function nestedConditionJoin(
filter: Filter, filter: Filter,
lookupColumn: Column, lookupColumn: Column,
qb: QueryBuilder, qb: Knex.QueryBuilder,
knex, knex,
alias: string, alias: string,
aliasCount: { count: number } aliasCount: { count: number }

2
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/genRollupSelect.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
import { RelationTypes } from 'nocodb-sdk'; import { RelationTypes } from 'nocodb-sdk';
export default function ({ export default function ({

4
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/genRollupSelectv2.ts

@ -1,7 +1,7 @@
import RollupColumn from '../../../../models/RollupColumn'; import RollupColumn from '../../../../models/RollupColumn';
import { XKnex } from '../../index'; import { XKnex } from '../../index';
import LinkToAnotherRecordColumn from '../../../../models/LinkToAnotherRecordColumn'; import LinkToAnotherRecordColumn from '../../../../models/LinkToAnotherRecordColumn';
import { QueryBuilder } from 'knex'; import { Knex } from 'knex';
import { RelationTypes } from 'nocodb-sdk'; import { RelationTypes } from 'nocodb-sdk';
export default async function ({ export default async function ({
@ -14,7 +14,7 @@ export default async function ({
knex: XKnex; knex: XKnex;
alias?: string; alias?: string;
columnOptions: RollupColumn; columnOptions: RollupColumn;
}): Promise<{ builder: QueryBuilder | any }> { }): Promise<{ builder: Knex.QueryBuilder | any }> {
const relationColumn = await columnOptions.getRelationColumn(); const relationColumn = await columnOptions.getRelationColumn();
const relationColumnOption: LinkToAnotherRecordColumn = const relationColumnOption: LinkToAnotherRecordColumn =
(await relationColumn.getColOptions()) as LinkToAnotherRecordColumn; (await relationColumn.getColOptions()) as LinkToAnotherRecordColumn;

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

@ -3,7 +3,7 @@ import mssql from './functionMappings/mssql';
import mysql from './functionMappings/mysql'; import mysql from './functionMappings/mysql';
import pg from './functionMappings/pg'; import pg from './functionMappings/pg';
import sqlite from './functionMappings/sqlite'; import sqlite from './functionMappings/sqlite';
import { QueryBuilder } from 'knex'; import { Knex } from 'knex';
export interface MapFnArgs { export interface MapFnArgs {
pt: any; pt: any;
@ -11,7 +11,7 @@ export interface MapFnArgs {
knex: XKnex; knex: XKnex;
alias: string; alias: string;
a?: string; a?: string;
fn: (...args: any) => QueryBuilder | any; fn: (...args: any) => Knex.QueryBuilder | any;
colAlias: string; colAlias: string;
prevBinaryOp?: any; prevBinaryOp?: any;
} }

4
packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/sortV2.ts

@ -1,4 +1,4 @@
import { QueryBuilder } from 'knex'; import { Knex } from 'knex';
import { XKnex } from '../../index'; import { XKnex } from '../../index';
import Sort from '../../../../models/Sort'; import Sort from '../../../../models/Sort';
import LinkToAnotherRecordColumn from '../../../../models/LinkToAnotherRecordColumn'; import LinkToAnotherRecordColumn from '../../../../models/LinkToAnotherRecordColumn';
@ -12,7 +12,7 @@ import { sanitize } from './helpers/sanitize';
export default async function sortV2( export default async function sortV2(
sortList: Sort[], sortList: Sort[],
qb: QueryBuilder, qb: Knex.QueryBuilder,
knex: XKnex knex: XKnex
) { ) {
if (!sortList?.length) { if (!sortList?.length) {

4
packages/nocodb/src/lib/db/sql-mgr/v2/SqlMgrv2Trans.ts

@ -1,13 +1,13 @@
import SqlMgrv2 from './SqlMgrv2'; import SqlMgrv2 from './SqlMgrv2';
import Base from '../../../models/Base'; import Base from '../../../models/Base';
import NcConnectionMgrv2 from '../../../utils/common/NcConnectionMgrv2'; import NcConnectionMgrv2 from '../../../utils/common/NcConnectionMgrv2';
import { Transaction } from 'knex'; import { Knex } from 'knex';
import { XKnex } from '../../sql-data-mapper'; import { XKnex } from '../../sql-data-mapper';
import NcMetaIO from '../../../meta/NcMetaIO'; import NcMetaIO from '../../../meta/NcMetaIO';
import KnexMigratorv2Tans from '../../sql-migrator/lib/KnexMigratorv2Tans'; import KnexMigratorv2Tans from '../../sql-migrator/lib/KnexMigratorv2Tans';
export default class SqlMgrv2Trans extends SqlMgrv2 { export default class SqlMgrv2Trans extends SqlMgrv2 {
protected trx: Transaction; protected trx: Knex.Transaction;
protected ncMeta: NcMetaIO; protected ncMeta: NcMetaIO;
protected projectId: string; protected projectId: string;
protected base: Base; protected base: Base;

2
packages/nocodb/src/lib/meta/api/dataApis/dataAliasApis.ts

@ -270,7 +270,7 @@ async function getGroupedDataList(model, view: View, req) {
data = data.map((item) => { data = data.map((item) => {
// todo: use map to avoid loop // todo: use map to avoid loop
const count = const count =
countArr.find((countItem) => countItem.key === item.key)?.count ?? 0; countArr.find((countItem: any) => countItem.key === item.key)?.count ?? 0;
item.value = new PagedResponseImpl(item.value, { item.value = new PagedResponseImpl(item.value, {
...req.query, ...req.query,

2
packages/nocodb/src/lib/meta/api/publicApis/publicDataApis.ts

@ -157,7 +157,7 @@ async function getGroupedDataList(model, view: View, req) {
data = data.map((item) => { data = data.map((item) => {
// todo: use map to avoid loop // todo: use map to avoid loop
const count = const count =
countArr.find((countItem) => countItem.key === item.key)?.count ?? 0; countArr.find((countItem: any) => countItem.key === item.key)?.count ?? 0;
item.value = new PagedResponseImpl(item.value, { item.value = new PagedResponseImpl(item.value, {
...req.query, ...req.query,

2
packages/nocodb/src/lib/migrations/v1/nc_002_add_m2m.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {
await knex.schema.alterTable('nc_models', (table) => { await knex.schema.alterTable('nc_models', (table) => {

2
packages/nocodb/src/lib/migrations/v1/nc_003_add_fkn_column.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {
await knex.schema.alterTable('nc_relations', (table) => { await knex.schema.alterTable('nc_relations', (table) => {

2
packages/nocodb/src/lib/migrations/v1/nc_004_add_view_type_column.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {
await knex.schema.alterTable('nc_shared_views', (table) => { await knex.schema.alterTable('nc_shared_views', (table) => {

2
packages/nocodb/src/lib/migrations/v1/nc_005_add_view_name_column.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {
await knex.schema.alterTable('nc_shared_views', (table) => { await knex.schema.alterTable('nc_shared_views', (table) => {

2
packages/nocodb/src/lib/migrations/v1/nc_006_alter_nc_shared_views.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {
await knex.schema.alterTable('nc_shared_views', (table) => { await knex.schema.alterTable('nc_shared_views', (table) => {

2
packages/nocodb/src/lib/migrations/v1/nc_007_alter_nc_shared_views_1.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {
await knex.schema.alterTable('nc_shared_views', (table) => { await knex.schema.alterTable('nc_shared_views', (table) => {

2
packages/nocodb/src/lib/migrations/v1/nc_008_add_nc_shared_bases.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {
await knex.schema.createTable('nc_shared_bases', (table) => { await knex.schema.createTable('nc_shared_bases', (table) => {

2
packages/nocodb/src/lib/migrations/v1/nc_009_add_model_order.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {
await knex.schema.alterTable('nc_models', (table) => { await knex.schema.alterTable('nc_models', (table) => {

2
packages/nocodb/src/lib/migrations/v1/nc_010_add_parent_title_column.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {
await knex.schema.alterTable('nc_disabled_models_for_role', (table) => { await knex.schema.alterTable('nc_disabled_models_for_role', (table) => {

2
packages/nocodb/src/lib/migrations/v1/nc_011_remove_old_ses_plugin.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
import ses from '../../v1-legacy/plugins/ses'; import ses from '../../v1-legacy/plugins/ses';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {

2
packages/nocodb/src/lib/migrations/v2/nc_012_alter_column_data_types.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
import { MetaTable } from '../../utils/globals'; import { MetaTable } from '../../utils/globals';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {

2
packages/nocodb/src/lib/migrations/v2/nc_013_sync_source.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
import { MetaTable } from '../../utils/globals'; import { MetaTable } from '../../utils/globals';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {

2
packages/nocodb/src/lib/migrations/v2/nc_014_alter_column_data_types.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
import { MetaTable } from '../../utils/globals'; import { MetaTable } from '../../utils/globals';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {

2
packages/nocodb/src/lib/migrations/v2/nc_015_add_meta_col_in_column_table.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
import { MetaTable } from '../../utils/globals'; import { MetaTable } from '../../utils/globals';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {

2
packages/nocodb/src/lib/migrations/v2/nc_016_alter_hooklog_payload_types.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
import { MetaTable } from '../../utils/globals'; import { MetaTable } from '../../utils/globals';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {

2
packages/nocodb/src/lib/migrations/v2/nc_017_add_user_token_version_column.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {
await knex.schema.alterTable('nc_users_v2', (table) => { await knex.schema.alterTable('nc_users_v2', (table) => {

2
packages/nocodb/src/lib/migrations/v2/nc_018_add_meta_in_view.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
import { MetaTable } from '../../utils/globals'; import { MetaTable } from '../../utils/globals';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {

2
packages/nocodb/src/lib/migrations/v2/nc_019_add_meta_in_meta_tables.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
import { MetaTable } from '../../utils/globals'; import { MetaTable } from '../../utils/globals';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {

2
packages/nocodb/src/lib/migrations/v2/nc_020_kanban_view.ts

@ -1,4 +1,4 @@
import Knex from 'knex'; import { Knex } from 'knex';
import { MetaTable } from '../../utils/globals'; import { MetaTable } from '../../utils/globals';
const up = async (knex: Knex) => { const up = async (knex: Knex) => {

2
packages/nocodb/src/lib/services/test/TestResetService/index.ts

@ -1,6 +1,6 @@
import Noco from '../../../Noco'; import Noco from '../../../Noco';
import Knex from 'knex'; import { Knex } from 'knex';
import axios from 'axios'; import axios from 'axios';
import Project from '../../../models/Project'; import Project from '../../../models/Project';
import NcConnectionMgrv2 from '../../../utils/common/NcConnectionMgrv2'; import NcConnectionMgrv2 from '../../../utils/common/NcConnectionMgrv2';

2
packages/nocodb/src/lib/services/test/TestResetService/resetMetaSakilaSqliteProject.ts

@ -1,5 +1,5 @@
import axios from 'axios'; import axios from 'axios';
import Knex from 'knex'; import { Knex } from 'knex';
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
import { sakilaTableNames } from '../../../utils/globals'; import { sakilaTableNames } from '../../../utils/globals';

16
packages/nocodb/src/lib/services/test/TestResetService/resetMysqlSakilaProject.ts

@ -1,5 +1,5 @@
import axios from 'axios'; import axios from 'axios';
import Knex from 'knex'; import { Knex, knex } from 'knex';
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
import Audit from '../../../models/Audit'; import Audit from '../../../models/Audit';
@ -119,20 +119,20 @@ const resetMysqlSakilaProject = async ({
oldProject?: Project | undefined; oldProject?: Project | undefined;
isEmptyProject: boolean; isEmptyProject: boolean;
}) => { }) => {
const knex = Knex(config); const nc_knex = knex(config);
try { try {
await knex.raw(`USE test_sakila_${parallelId}`); await nc_knex.raw(`USE test_sakila_${parallelId}`);
} catch (e) { } catch (e) {
await knex.raw(`CREATE DATABASE test_sakila_${parallelId}`); await nc_knex.raw(`CREATE DATABASE test_sakila_${parallelId}`);
await knex.raw(`USE test_sakila_${parallelId}`); await nc_knex.raw(`USE test_sakila_${parallelId}`);
} }
if ( if (
isEmptyProject || isEmptyProject ||
(await isSakilaMysqlToBeReset(knex, parallelId, oldProject)) (await isSakilaMysqlToBeReset(nc_knex, parallelId, oldProject))
) { ) {
await resetSakilaMysql(knex, parallelId, isEmptyProject); await resetSakilaMysql(nc_knex, parallelId, isEmptyProject);
} }
const response = await axios.post( const response = await axios.post(
@ -148,7 +148,7 @@ const resetMysqlSakilaProject = async ({
console.error('Error creating project', response.data); console.error('Error creating project', response.data);
} }
await knex.destroy(); await nc_knex.destroy();
}; };
export default resetMysqlSakilaProject; export default resetMysqlSakilaProject;

8
packages/nocodb/src/lib/services/test/TestResetService/resetPgSakilaProject.ts

@ -1,5 +1,5 @@
import axios from 'axios'; import axios from 'axios';
import Knex from 'knex'; import { Knex, knex } from 'knex';
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
const util = require('util'); const util = require('util');
@ -81,7 +81,7 @@ const resetSakilaPg = async (
if (isEmptyProject) return; if (isEmptyProject) return;
const sakilaKnex = Knex(sakilaKnexConfig(parallelId)); const sakilaKnex = knex(sakilaKnexConfig(parallelId));
const schemaFile = await fs.readFile( const schemaFile = await fs.readFile(
`${testsDir}/pg-sakila-db/03-postgres-sakila-schema.sql` `${testsDir}/pg-sakila-db/03-postgres-sakila-schema.sql`
@ -117,13 +117,13 @@ const resetPgSakilaProject = async ({
oldProject?: Project | undefined; oldProject?: Project | undefined;
isEmptyProject: boolean; isEmptyProject: boolean;
}) => { }) => {
const pgknex = Knex(config); const pgknex = knex(config);
try { try {
await pgknex.raw(`CREATE DATABASE sakila_${parallelId}`); await pgknex.raw(`CREATE DATABASE sakila_${parallelId}`);
} catch (e) {} } catch (e) {}
const sakilaKnex = Knex(sakilaKnexConfig(parallelId)); const sakilaKnex = knex(sakilaKnexConfig(parallelId));
if (isEmptyProject || (await isSakilaPgToBeReset(sakilaKnex, oldProject))) { if (isEmptyProject || (await isSakilaPgToBeReset(sakilaKnex, oldProject))) {
await sakilaKnex.destroy(); await sakilaKnex.destroy();

2
packages/nocodb/src/lib/utils/common/NcConnectionMgr.ts

@ -2,7 +2,7 @@ import SqlClientFactory from '../../db/sql-client/lib/SqlClientFactory';
import { XKnex } from '../../db/sql-data-mapper'; import { XKnex } from '../../db/sql-data-mapper';
import { NcConfig } from '../../../interface/config'; import { NcConfig } from '../../../interface/config';
import fs from 'fs'; import fs from 'fs';
import Knex from 'knex'; import { Knex } from 'knex';
import NcMetaIO from '../../meta/NcMetaIO'; import NcMetaIO from '../../meta/NcMetaIO';
import { defaultConnectionConfig } from '../NcConfigFactory'; import { defaultConnectionConfig } from '../NcConfigFactory';

6
packages/nocodb/tests/unit/TestDbMngr.ts

@ -2,14 +2,14 @@ import { DbConfig } from "../../src/interface/config";
import { NcConfigFactory } from "../../src/lib"; import { NcConfigFactory } from "../../src/lib";
import SqlMgrv2 from "../../src/lib/db/sql-mgr/v2/SqlMgrv2"; import SqlMgrv2 from "../../src/lib/db/sql-mgr/v2/SqlMgrv2";
import fs from 'fs'; import fs from 'fs';
import knex from "knex"; import { Knex, knex } from "knex";
import process from "process"; import process from "process";
export default class TestDbMngr { export default class TestDbMngr {
public static readonly dbName = 'test_meta'; public static readonly dbName = 'test_meta';
public static readonly sakilaDbName = 'test_sakila'; public static readonly sakilaDbName = 'test_sakila';
public static metaKnex: knex; public static metaKnex: Knex;
public static sakilaKnex: knex; public static sakilaKnex: Knex;
public static defaultConnection = { public static defaultConnection = {
user: 'root', user: 'root',

Loading…
Cancel
Save