Browse Source

refactor: migrate sqlclient from nc-help

re #336, #2504

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/2537/head
Pranav C 3 years ago
parent
commit
585b11408e
  1. 1
      packages/nocodb-sdk/src/lib/Api.ts
  2. 6
      packages/nocodb/package-lock.json
  3. 3388
      packages/nocodb/src/lib/db/sql-client/lib/KnexClient.ts
  4. 114
      packages/nocodb/src/lib/db/sql-client/lib/SqlClient.ts
  5. 40
      packages/nocodb/src/lib/db/sql-client/lib/SqlClientFactory.ts
  6. 267
      packages/nocodb/src/lib/db/sql-client/lib/data.helper.ts
  7. 2675
      packages/nocodb/src/lib/db/sql-client/lib/mssql/MssqlClient.ts
  8. 39
      packages/nocodb/src/lib/db/sql-client/lib/mssql/mssql.queries.ts
  9. 2617
      packages/nocodb/src/lib/db/sql-client/lib/mysql/MysqlClient.ts
  10. 61
      packages/nocodb/src/lib/db/sql-client/lib/mysql/TidbClient.ts
  11. 247
      packages/nocodb/src/lib/db/sql-client/lib/mysql/VitessClient.ts
  12. 898
      packages/nocodb/src/lib/db/sql-client/lib/mysql/fakerFunctionList.ts
  13. 65
      packages/nocodb/src/lib/db/sql-client/lib/mysql/findDataTypeMapping.ts
  14. 364
      packages/nocodb/src/lib/db/sql-client/lib/mysql/mysql.queries.ts
  15. 2220
      packages/nocodb/src/lib/db/sql-client/lib/oracle/OracleClient.ts
  16. 25
      packages/nocodb/src/lib/db/sql-client/lib/oracle/oracle.queries.ts
  17. 111
      packages/nocodb/src/lib/db/sql-client/lib/order.ts
  18. 2829
      packages/nocodb/src/lib/db/sql-client/lib/pg/PgClient.ts
  19. 140
      packages/nocodb/src/lib/db/sql-client/lib/pg/YugabyteClient.ts
  20. 239
      packages/nocodb/src/lib/db/sql-client/lib/pg/pg.queries.ts
  21. 2087
      packages/nocodb/src/lib/db/sql-client/lib/sqlite/SqliteClient.ts
  22. 34
      packages/nocodb/src/lib/db/sql-client/lib/sqlite/sqlite.queries.ts
  23. 6
      packages/nocodb/src/lib/db/sql-mgr/SqlMgr.ts
  24. 5
      packages/nocodb/src/lib/db/sql-mgr/code/BaseRender.ts
  25. 7
      packages/nocodb/src/lib/db/sql-mgr/v2/SqlMgrv2.ts
  26. 11
      packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigrator.ts
  27. 10
      packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2.ts
  28. 2
      packages/nocodb/src/lib/db/util/Debug.ts
  29. 0
      packages/nocodb/src/lib/db/util/DebugMgr.ts
  30. 0
      packages/nocodb/src/lib/db/util/FileCollection.ts
  31. 0
      packages/nocodb/src/lib/db/util/Result.ts
  32. 0
      packages/nocodb/src/lib/db/util/emit.ts
  33. 0
      packages/nocodb/src/lib/db/util/file.help.ts
  34. 3
      packages/nocodb/src/lib/meta/NcMetaMgr.ts
  35. 14
      packages/nocodb/src/lib/utils/Emit.ts
  36. 2
      packages/nocodb/src/lib/utils/NcConfigFactory.ts
  37. 13
      packages/nocodb/src/lib/utils/Result.js
  38. 2
      packages/nocodb/src/lib/utils/common/NcConnectionMgr.ts
  39. 2
      packages/nocodb/src/lib/utils/common/NcConnectionMgrv2.ts
  40. 3
      packages/nocodb/src/lib/v1-legacy/NcProjectBuilder.ts

1
packages/nocodb-sdk/src/lib/Api.ts

@ -724,7 +724,6 @@ export class HttpClient<SecurityDataType = unknown> {
formData.append(key, property);
} else if (typeof property === 'object' && property !== null) {
if (Array.isArray(property)) {
// eslint-disable-next-line functional/no-loop-statement
for (const prop of property) {
formData.append(`${key}[]`, prop);
}

6
packages/nocodb/package-lock.json generated

@ -159,7 +159,7 @@
}
},
"../nocodb-sdk": {
"version": "0.92.0",
"version": "0.92.3",
"license": "MIT",
"dependencies": {
"axios": "^0.21.1",
@ -187,7 +187,7 @@
"prettier": "^2.1.1",
"standard-version": "^9.0.0",
"ts-node": "^9.0.0",
"typedoc": "^0.19.0",
"typedoc": "^0.22.17",
"typescript": "^4.0.2"
},
"engines": {
@ -36813,7 +36813,7 @@
"prettier": "^2.1.1",
"standard-version": "^9.0.0",
"ts-node": "^9.0.0",
"typedoc": "^0.19.0",
"typedoc": "^0.22.17",
"typescript": "^4.0.2"
}
},

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

File diff suppressed because it is too large Load Diff

114
packages/nocodb/src/lib/db/sql-client/lib/SqlClient.ts

@ -0,0 +1,114 @@
class SqlClient {
protected connectionConfig: any;
protected sqlClient: any;
constructor(connectionConfig) {
this.connectionConfig = connectionConfig;
this.sqlClient = null;
}
async testConnection(_args): Promise<any> {}
migrationInit(_args) {}
migrationUp(_args) {}
migrationDown(_args) {}
selectAll(_tn) {}
executeSqlFiles() {}
async createDatabaseIfNotExists(_args): Promise<any> {}
async createTableIfNotExists(_args): Promise<any> {}
startTransaction() {}
commit() {}
rollback() {}
hasTable(_tn) {}
hasDatabase(_databaseName) {}
async tableCreate(_args): Promise<any> {}
async tableUpdate(_args): Promise<any> {}
async columnCreate(_args): Promise<any> {}
async columnUpdate(_args): Promise<any> {}
async columnDelete(_args): Promise<any> {}
async indexCreate(_args): Promise<any> {}
async indexUpdate(_args): Promise<any> {}
async indexDelete(_args): Promise<any> {}
async relationCreate(_args): Promise<any> {}
async relationUpdate(_args): Promise<any> {}
async relationDelete(_args): Promise<any> {}
async databaseList(_args): Promise<any> {}
async tableList(_args): Promise<any> {}
async schemaList(_args): Promise<any> {}
async tableDelete(_args): Promise<any> {}
async columnList(_args): Promise<any> {}
async indexList(_args): Promise<any> {}
async relationList(_args): Promise<any> {}
async schemaCreate(_args): Promise<any> {}
async schemaDelete(_args): Promise<any> {}
async triggerList(_args): Promise<any> {}
async triggerCreate(_args): Promise<any> {}
async triggerRead(_args): Promise<any> {}
async functionList(_args): Promise<any> {}
async functionRead(_args): Promise<any> {}
async procedureList(_args): Promise<any> {}
async procedureRead(_args): Promise<any> {}
async viewList(_args): Promise<any> {}
async viewRead(_args): Promise<any> {}
async sequenceList(_args = {}): Promise<any> {}
async sequenceCreate(_args = {}): Promise<any> {}
async sequenceUpdate(_args = {}): Promise<any> {}
async sequenceDelete(_args = {}): Promise<any> {}
async tableCreateStatement(_args): Promise<any> {}
async tableInsertStatement(_args): Promise<any> {}
async tableUpdateStatement(_args): Promise<any> {}
async tableDeleteStatement(_args): Promise<any> {}
async tableTruncateStatement(_args): Promise<any> {}
async tableSelectStatement(_args): Promise<any> {}
async totalRecords(_args): Promise<any> {}
}
export default SqlClient;

40
packages/nocodb/src/lib/db/sql-client/lib/SqlClientFactory.ts

@ -0,0 +1,40 @@
import MySqlClient from './mysql/MysqlClient';
import MssqlClient from './mssql/MssqlClient';
import OracleClient from './oracle/OracleClient';
import SqliteClient from './sqlite/SqliteClient';
import PgClient from './pg/PgClient';
import YugabyteClient from './pg/YugabyteClient';
import TidbClient from './mysql/TidbClient';
import VitessClient from './mysql/VitessClient';
class SqlClientFactory {
static create(connectionConfig) {
connectionConfig.meta = connectionConfig.meta || {};
connectionConfig.pool = connectionConfig.pool || { min: 0, max: 5 };
connectionConfig.meta.dbtype = connectionConfig.meta.dbtype || '';
if (
connectionConfig.client === 'mysql' ||
connectionConfig.client === 'mysql2'
) {
if (connectionConfig.meta.dbtype === 'tidb')
return new TidbClient(connectionConfig);
if (connectionConfig.meta.dbtype === 'vitess')
return new VitessClient(connectionConfig);
return new MySqlClient(connectionConfig);
} else if (connectionConfig.client === 'sqlite3') {
return new SqliteClient(connectionConfig);
} else if (connectionConfig.client === 'mssql') {
return new MssqlClient(connectionConfig);
} else if (connectionConfig.client === 'oracledb') {
return new OracleClient(connectionConfig);
} else if (connectionConfig.client === 'pg') {
if (connectionConfig.meta.dbtype === 'yugabyte')
return new YugabyteClient(connectionConfig);
return new PgClient(connectionConfig);
}
throw new Error('Database not supported');
}
}
export default SqlClientFactory;

267
packages/nocodb/src/lib/db/sql-client/lib/data.helper.ts

@ -0,0 +1,267 @@
export const findOrInsertObjectArrayByKey = (obj, key, array) => {
let found = 0;
let i = 0;
for (i = 0; i < array.length; ++i) {
if (key in array[i]) {
if (obj[key] === array[i][key]) {
found = 1;
break;
}
}
}
if (!found) {
array.push(obj);
}
return array[i];
};
export const findObjectInArrayByKey = (key, value, objArray) => {
for (let i = 0; i < objArray.length; ++i) {
if (objArray[i][key] === value) {
return objArray[i];
}
}
return null;
};
export const round = function(number, precision) {
const factor = Math.pow(10, precision);
const tempNumber = number * factor;
const roundedTempNumber = Math.round(tempNumber);
return roundedTempNumber / factor;
};
export const numberRound = (number, precision) => {
const factor = Math.pow(10, precision);
const tempNumber = number * factor;
const roundedTempNumber = Math.round(tempNumber);
return roundedTempNumber / factor;
};
export const numberGetLength = number => {
let n = number;
if (number < 0) {
n = n * -1;
}
return n.toString().length;
};
export const numberGetFixed = number => {
//console.log(number, typeof number);
return parseInt(number.toFixed());
};
export const getStepArraySimple = function(min, max, step) {
const arr = [];
for (let i = min; i <= max; i = i + step) {
arr.push(i);
}
return arr;
};
export const getStepArray = (min, max, stddev) => {
// console.log(' = = = = = = = ');
//console.log('original numbers', min, max, stddev);
min = numberGetFixed(min);
max = numberGetFixed(max);
stddev = numberGetFixed(stddev);
// console.log('fixed numbers', min, max, stddev);
let minMinusHalf = min - stddev / 2;
let maxMinusHalf = max + stddev / 2;
minMinusHalf = numberGetFixed(minMinusHalf);
maxMinusHalf = numberGetFixed(maxMinusHalf);
// console.log('fixed numbers + (min,max)', min, max, stddev, '(', minMinusHalf, ',', maxMinusHalf, ')');
// console.log('numbers length', 'min', numberGetLength(min), 'max', numberGetLength(max), 'stddev', numberGetLength(stddev));
const minLen = numberGetLength(minMinusHalf);
const maxLen = numberGetLength(maxMinusHalf);
const stddevLen = numberGetLength(stddev);
//
// console.log('- - - -');
// console.log('Range', 'min', numberRound(minMinusHalf, -1));
// console.log('Range', 'max', numberRound(maxMinusHalf, -1));
// console.log('Range', 'stddev', numberRound(stddev, -1));
if (minLen > 1) minMinusHalf = numberRound(minMinusHalf, -1);
if (maxLen > 2) maxMinusHalf = numberRound(maxMinusHalf, -1);
if (stddevLen !== 1) stddev = numberRound(stddev, -1);
const arr = [];
for (let step = minMinusHalf; step < maxMinusHalf; step = step + stddev) {
arr.push(step);
}
arr.push(maxMinusHalf);
// console.log(arr);
return arr;
};
export const getMysqlSchemaQuery = function() {
return (
'select ' +
'c.table_name as tn, c.column_name as cn, c.ordinal_position as cop,' +
'c.column_key as ck,c.is_nullable as nrqd, c.data_type, c.column_type as ct,c.extra as ext,c.privileges as priv, ' +
'c.cc,c.cdf as cdf,c.data_type,' +
'c.character_maximum_length as clen,c.numeric_precision as np,c.numeric_scale as ns,c.datetime_precision as dp, ' +
'k.constraint_name as cstn, k.referenced_table_name as rtn, k.referenced_column_name as rcn, ' +
's.index_name,s.seq_in_index, ' +
'v.table_name as is_view ' +
'from ' +
'information_schema.columns as c ' +
'left join ' +
'information_schema.key_column_usage as k ' +
'on ' +
'c.column_name=k.column_name and ' +
'c.table_schema = k.referenced_table_schema and ' +
'c.table_name = k.table_name ' +
'left join ' +
'information_schema.statistics as s ' +
'on ' +
'c.column_name = s.column_name and ' +
'c.table_schema = s.index_schema and ' +
'c.table_name = s.table_name ' +
'LEFT JOIN ' +
'information_schema.VIEWS as v ' +
'ON ' +
'c.table_schema = v.table_schema and ' +
'c.table_name = v.table_name ' +
'where ' +
'c.table_schema=? ' +
'order by ' +
'c.table_name, c.ordinal_position'
);
};
export const getChartQuery = function() {
return 'select ? as ??, count(*) as _count from ?? where ?? between ? and ? ';
};
export const getDataType = function(colType, typesArr) {
// console.log(colType,typesArr);
for (let i = 0; i < typesArr.length; ++i) {
if (colType.indexOf(typesArr[i]) !== -1) {
return 1;
}
}
return 0;
};
export const getColumnType = function(column) {
const strTypes = [
'varchar',
'text',
'char',
'tinytext',
'mediumtext',
'longtext',
'ntext',
'image',
'blob',
'mediumblob',
'longblob',
'binary',
'varbinary',
'character',
'character varying',
'nchar',
'nvarchar',
'clob',
'nvarchar2',
'varchar2',
'raw',
'long raw',
'bfile',
'nclob'
];
const intTypes = [
'bit',
'integer',
'int',
'smallint',
'mediumint',
'bigint',
'tinyint',
'int2',
'int4',
'int8',
'long',
'serial',
'bigserial',
'smallserial',
'bool',
'boolean',
'number'
];
const floatTypes = [
'float',
'double',
'decimal',
'numeric',
'real',
'double precision',
'real',
'money',
'smallmoney',
'dec'
];
const dateTypes = [
'date',
'datetime',
'timestamp',
'time',
'year',
'timestamp without time zone',
'timestamp with time zone',
'time without time zone',
'time with time zone',
'datetime2',
'smalldatetime',
'datetimeoffset',
'interval year',
'interval day'
];
// const rowIds = ['rowId', 'urowid'];
//console.log(column);
if (getDataType(column['data_type'], strTypes)) {
return 'string';
} else if (getDataType(column['data_type'], intTypes)) {
return 'int';
} else if (getDataType(column['data_type'], floatTypes)) {
return 'float';
} else if (getDataType(column['data_type'], dateTypes)) {
return 'date';
} else {
return 'string';
}
};
export const getType = function(colType, typesArr) {
// for (let i = 0; i < typesArr.length; ++i) {
// // if (typesArr[i].indexOf(colType) !== -1) {
// // return 1;
// // }
//
// if (colType.indexOf(typesArr[i]) !== -1) {
// return 1;
// }
// }
return typesArr.includes(colType);
//return 0;
};

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

File diff suppressed because it is too large Load Diff

39
packages/nocodb/src/lib/db/sql-client/lib/mssql/mssql.queries.ts

@ -0,0 +1,39 @@
// https://docs.microsoft.com/en-us/sql/t-sql/data-types/data-types-transact-sql?view=sql-server-2017
export default {
bigint: {},
numeric: {},
bit: {},
smallint: {},
decimal: {},
smallmoney: {},
int: {},
tinyint: {},
money: {},
float: {},
real: {},
date: {},
datetimeoffset: {},
datetime2: {},
smalldatetime: {},
datetime: {},
time: {},
char: {},
varchar: {},
text: {},
nchar: {},
nvarchar: {},
ntext: {},
binary: {},
varbinary: {},
image: {},
cursor: {},
rowversion: {},
hierarchyid: {},
uniqueidentifier: {},
sql_variant: {},
xml: {},
'Spatial Geometry Types': {},
'Spatial Geography Types': {},
table: {}
};

2617
packages/nocodb/src/lib/db/sql-client/lib/mysql/MysqlClient.ts

File diff suppressed because it is too large Load Diff

61
packages/nocodb/src/lib/db/sql-client/lib/mysql/TidbClient.ts

@ -0,0 +1,61 @@
import _ from 'lodash';
import Debug from '../../../util/Debug';
import Result from '../../../util/Result';
const log = new Debug('TidbClient');
import MysqlClient from './MysqlClient';
class Tidb extends MysqlClient {
/**
*
* @param {Object} - args - Input arguments
* @param {Object} - args.tn -
* @returns {Object[]} - indexes
* @property {String} - indexes[].cstn -
* @property {String} - indexes[].cn -
* @property {String} - indexes[].op -
* @property {String} - indexes[].puc -
* @property {String} - indexes[].cst -
*/
async constraintList(args: any = {}) {
const func = this.constraintList.name;
const result = new Result();
log.api(`${func}:args:`, args);
try {
const response = await this.sqlClient.raw(
`select *, TABLE_NAME as tn from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where CONSTRAINT_SCHEMA='${this.connectionConfig.connection.database}' and TABLE_NAME='${args.tn}'`
);
if (response.length === 2) {
const indexes = [];
for (let i = 0; i < response[0].length; ++i) {
let index = response[0][i];
index = _.mapKeys(index, function(_v, k) {
return k.toLowerCase();
});
indexes.push(index);
}
result.data.list = indexes;
} else {
log.debug(
'Unknown response for databaseList:',
result.data.list.length
);
result.data.list = [];
}
} catch (e) {
log.ppe(e, func);
throw e;
}
log.api(`${func}: result`, result);
return result;
}
}
export default Tidb;

247
packages/nocodb/src/lib/db/sql-client/lib/mysql/VitessClient.ts

@ -0,0 +1,247 @@
import _ from 'lodash';
import Debug from '../../../util/Debug';
import Result from '../../../util/Result';
const log = new Debug('VitessClient');
import MysqlClient from './MysqlClient';
class Vitess extends MysqlClient {
constructor(connectionConfig: any) {
super(connectionConfig);
}
async relationList(_args: any = {}) {
const result = new Result();
result.data.list = [];
return result;
}
async relationListAll(_args: any = {}) {
const result = new Result();
result.data.list = [];
return result;
}
/**
*
* @param {Object} - args - for future reasons
* @returns {Object[]} - databases
* @property {String} - databases[].database_name
*/
async databaseList(args: any = {}) {
const func = this.databaseList.name;
const result = new Result();
log.api(`${func}:args:`, args);
try {
const response = await this.sqlClient.raw('SHOW databases');
log.debug(response.length);
if (response.length === 2) {
for (let i = 0; i < response[0].length; ++i) {
response[0][i].database_name = response[0][i].Databases;
}
result.data.list = response[0];
} else {
log.debug(
'Unknown response for databaseList:',
result.data.list.length
);
result.data.list = [];
}
} catch (e) {
log.ppe(e, func);
throw e;
}
log.api(`${func}: result`, result.data.list.length);
return result;
}
/**
*
* @param {Object} - args - for future reasons
* @returns {Object[]} - tables
* @property {String} - tables[].tn
*/
async tableList(args: any = {}) {
const func = this.tableList.name;
const result = new Result();
log.api(`${func}:args:`, args);
try {
const response = await this.sqlClient.raw('SHOW TABLES');
const keyInResponse = `Tables_in_vt_${this.connectionConfig.connection.database}`;
if (response.length === 2) {
for (let i = 0; i < response[0].length; ++i) {
response[0][i].tn = response[0][i][keyInResponse];
}
result.data.list = response[0];
} else {
log.debug(
'Unknown response for databaseList:',
result.data.list.length
);
result.data.list = [];
}
} catch (e) {
log.ppe(e, func);
throw e;
}
log.api(`${func}: result`, result.data.list.length);
return result;
}
/**
*
* @param {Object} - args - Input arguments
* @param {Object} - args.tn -
* @returns {Object[]} - columns
* @property {String} - columns[].tn
* @property {String} - columns[].cn
* @property {String} - columns[].dt
* @property {String} - columns[].dtx
* @property {String} - columns[].np
* @property {String} - columns[].ns -
* @property {String} - columns[].clen -
* @property {String} - columns[].dp -
* @property {String} - columns[].cop -
* @property {String} - columns[].pk -
* @property {String} - columns[].nrqd -
* @property {String} - columns[].not_nullable -
* @property {String} - columns[].ct -
* @property {String} - columns[].un -
* @property {String} - columns[].ai -
* @property {String} - columns[].unique -
* @property {String} - columns[].cdf -
* @property {String} - columns[].cc -
* @property {String} - columns[].csn -
*/
async columnList(args: any = {}) {
const func = this.columnList.name;
const result = new Result();
log.api(`${func}:args:`, args);
try {
args.databaseName = this.connectionConfig.connection.database;
const response = await this.sqlClient.raw(
`select *, table_name as tn from information_schema.columns where table_name = '${args.tn}' ORDER by ordinal_position`
);
if (response.length === 2) {
const columns = [];
for (let i = 0; i < response[0].length; ++i) {
const column: any = {};
response[0][i] = _.mapKeys(response[0][i], (_v, k) =>
k.toLowerCase()
);
column.tn = args.tn;
column.cn = response[0][i].cn;
column.dt = response[0][i].dt;
column.np = response[0][i].np;
column.ns = response[0][i].ns;
column.clen = response[0][i].clen;
// column.dp = response[0][i].dp;
column.cop = response[0][i].op;
column.dtx = this.getKnexDataType(column.dt);
column.pk = response[0][i].ck === 'PRI';
column.nrqd = response[0][i].nrqd !== 'NO';
column.not_nullable = !column.nrqd;
response[0][i].ct = response[0][i].ct || '';
column.un = response[0][i].ct.indexOf('unsigned') !== -1;
column.ct = response[0][i].ct || '';
response[0][i].ext = response[0][i].ext || '';
column.ai = response[0][i].ext.indexOf('auto_increment') !== -1;
response[0][i].cst = response[0][i].cst || ' ';
column.unique = response[0][i].cst.indexOf('UNIQUE') !== -1;
column.cdf = response[0][i].cdf;
column.cc = response[0][i].cc;
column.csn = response[0][i].csn;
columns.push(column);
// column['dtx'] = response[0][i]['dt'];
}
result.data.list = columns;
} else {
log.debug('Unknown response for databaseList:', response);
result.data.list = [];
}
} catch (e) {
log.ppe(e, func);
throw e;
}
log.api(`${func}: result list length = `, result.data.list.length);
return result;
}
/**
*
* @param {Object} - args - Input arguments
* @param {Object} - args.tn -
* @returns {Object[]} - indexes
* @property {String} - indexes[].cstn -
* @property {String} - indexes[].cn -
* @property {String} - indexes[].op -
* @property {String} - indexes[].puc -
* @property {String} - indexes[].cst -
*/
async constraintList(args: any = {}) {
const func = this.constraintList.name;
const result = new Result();
log.api(`${func}:args:`, args);
try {
const response = await this.sqlClient.raw(
`select *, TABLE_NAME as tn from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where TABLE_NAME = '${args.tn}' ORDER by ordinal_position;`
);
if (response.length === 2) {
const indexes = [];
for (let i = 0; i < response[0].length; ++i) {
let index = response[0][i];
index = _.mapKeys(index, function(_v, k) {
return k.toLowerCase();
});
indexes.push(index);
}
result.data.list = indexes;
} else {
log.debug(
'Unknown response for databaseList:',
result.data.list.length
);
result.data.list = [];
}
} catch (e) {
log.ppe(e, func);
throw e;
}
log.api(`${func}: result`, result);
return result;
}
}
export default Vitess;

898
packages/nocodb/src/lib/db/sql-client/lib/mysql/fakerFunctionList.ts

@ -0,0 +1,898 @@
export default [
{
name: 'zipCode',
group: 'address',
value: 'address.zipCode',
type: 'string'
},
{
name: 'city',
group: 'address',
value: 'address.city',
type: 'string'
},
{
name: 'cityPrefix',
group: 'address',
value: 'address.cityPrefix',
type: 'string'
},
{
name: 'citySuffix',
group: 'address',
value: 'address.citySuffix',
type: 'string'
},
{
name: 'streetName',
group: 'address',
value: 'address.streetName',
type: 'string'
},
{
name: 'streetAddress',
group: 'address',
value: 'address.streetAddress',
type: 'string'
},
{
name: 'streetSuffix',
group: 'address',
value: 'address.streetSuffix',
type: 'string'
},
{
name: 'streetPrefix',
group: 'address',
value: 'address.streetPrefix',
type: 'string'
},
{
name: 'secondaryAddress',
group: 'address',
value: 'address.secondaryAddress',
type: 'string'
},
{
name: 'county',
group: 'address',
value: 'address.county',
type: 'string'
},
{
name: 'country',
group: 'address',
value: 'address.country',
type: 'string'
},
{
name: 'countryCode',
group: 'address',
value: 'address.countryCode',
type: 'string'
},
{
name: 'state',
group: 'address',
value: 'address.state',
type: 'string'
},
{
name: 'stateAbbr',
group: 'address',
value: 'address.stateAbbr',
type: 'string'
},
{
name: 'latitude',
group: 'address',
value: 'address.latitude',
type: 'number'
},
{
name: 'longitude',
group: 'address',
value: 'address.longitude',
type: 'number'
},
{
name: 'color',
group: 'commerce',
value: 'commerce.color',
type: 'string'
},
{
name: 'department',
group: 'commerce',
value: 'commerce.department',
type: 'string'
},
{
name: 'productName',
group: 'commerce',
value: 'commerce.productName',
type: 'string'
},
{
name: 'price',
group: 'commerce',
value: 'commerce.price',
type: 'number'
},
{
name: 'productAdjective',
group: 'commerce',
value: 'commerce.productAdjective',
type: 'string'
},
{
name: 'productMaterial',
group: 'commerce',
value: 'commerce.productMaterial',
type: 'string'
},
{
name: 'product',
group: 'commerce',
value: 'commerce.product',
type: 'string'
},
{
name: 'suffixes',
group: 'company',
value: 'company.suffixes',
type: 'string'
},
{
name: 'companyName',
group: 'company',
value: 'company.companyName',
type: 'string'
},
{
name: 'companySuffix',
group: 'company',
value: 'company.companySuffix',
type: 'string'
},
{
name: 'catchPhrase',
group: 'company',
value: 'company.catchPhrase',
type: 'string'
},
{
name: 'bs',
group: 'company',
value: 'company.bs',
type: 'string'
},
{
name: 'catchPhraseAdjective',
group: 'company',
value: 'company.catchPhraseAdjective',
type: 'string'
},
{
name: 'catchPhraseDescriptor',
group: 'company',
value: 'company.catchPhraseDescriptor',
type: 'string'
},
{
name: 'catchPhraseNoun',
group: 'company',
value: 'company.catchPhraseNoun',
type: 'string'
},
{
name: 'bsAdjective',
group: 'company',
value: 'company.bsAdjective',
type: 'string'
},
{
name: 'bsBuzz',
group: 'company',
value: 'company.bsBuzz',
type: 'string'
},
{
name: 'bsNoun',
group: 'company',
value: 'company.bsNoun',
type: 'string'
},
{
name: 'column',
group: 'database',
value: 'database.column',
type: 'string'
},
{
name: 'type',
group: 'database',
value: 'database.type',
type: 'string'
},
{
name: 'collation',
group: 'database',
value: 'database.collation',
type: 'string'
},
{
name: 'engine',
group: 'database',
value: 'database.engine',
type: 'string'
},
{
name: 'past',
group: 'date',
value: 'date.past',
type: 'date'
},
{
name: 'future',
group: 'date',
value: 'date.future',
type: 'date'
},
// {
// name: 'between',
// group: 'date',
// value: 'date.between',
// type: 'date'
// },
{
name: 'recent',
group: 'date',
value: 'date.recent',
type: 'date'
},
{
name: 'soon',
group: 'date',
value: 'date.soon',
type: 'date'
},
{
name: 'month',
group: 'date',
value: 'date.month',
type: 'string'
},
{
name: 'weekday',
group: 'date',
value: 'date.weekday',
type: 'string'
},
{
name: 'account',
group: 'finance',
value: 'finance.account',
type: 'string'
},
{
name: 'accountName',
group: 'finance',
value: 'finance.accountName',
type: 'string'
},
{
name: 'mask',
group: 'finance',
value: 'finance.mask',
type: 'string'
},
{
name: 'amount',
group: 'finance',
value: 'finance.amount',
type: 'number'
},
{
name: 'transactionType',
group: 'finance',
value: 'finance.transactionType',
type: 'string'
},
{
name: 'currencyCode',
group: 'finance',
value: 'finance.currencyCode',
type: 'string'
},
{
name: 'currencyName',
group: 'finance',
value: 'finance.currencyName',
type: 'string'
},
{
name: 'currencySymbol',
group: 'finance',
value: 'finance.currencySymbol',
type: 'string'
},
{
name: 'bitcoinAddress',
group: 'finance',
value: 'finance.bitcoinAddress',
type: 'string'
},
{
name: 'ethereumAddress',
group: 'finance',
value: 'finance.ethereumAddress',
type: 'string'
},
{
name: 'iban',
group: 'finance',
value: 'finance.iban',
type: 'string'
},
{
name: 'bic',
group: 'finance',
value: 'finance.bic',
type: 'string'
},
{
name: 'abbreviation',
group: 'hacker',
value: 'hacker.abbreviation',
type: 'string'
},
{
name: 'adjective',
group: 'hacker',
value: 'hacker.adjective',
type: 'string'
},
{
name: 'noun',
group: 'hacker',
value: 'hacker.noun',
type: 'string'
},
{
name: 'verb',
group: 'hacker',
value: 'hacker.verb',
type: 'string'
},
{
name: 'ingverb',
group: 'hacker',
value: 'hacker.ingverb',
type: 'string'
},
{
name: 'phrase',
group: 'hacker',
value: 'hacker.phrase',
type: 'string'
},
// {
// name: 'randomize',
// group: 'helpers',
// value: 'helpers.randomize',
// type: 'string'
// },
// {
// name: 'slugify',
// group: 'helpers',
// value: 'helpers.slugify',
// type: 'string'
// },
// {
// name: 'replaceSymbolWithNumber',
// group: 'helpers',
// value: 'helpers.replaceSymbolWithNumber',
// type: 'string'
// },
// {
// name: 'replaceSymbols',
// group: 'helpers',
// value: 'helpers.replaceSymbols',
// type: 'string'
// },
// {
// name: 'shuffle',
// group: 'helpers',
// value: 'helpers.shuffle',
// type: 'string'
// },
// {
// name: 'mustache',
// group: 'helpers',
// value: 'helpers.mustache',
// type: 'string'
// },
{
name: 'createCard',
group: 'helpers',
value: 'helpers.createCard',
type: 'string'
},
{
name: 'contextualCard',
group: 'helpers',
value: 'helpers.contextualCard',
type: 'string'
},
{
name: 'userCard',
group: 'helpers',
value: 'helpers.userCard',
type: 'string'
},
{
name: 'createTransaction',
group: 'helpers',
value: 'helpers.createTransaction',
type: 'string'
},
{
name: 'image',
group: 'image',
value: 'image.image',
type: 'string'
},
{
name: 'avatar',
group: 'image',
value: 'image.avatar',
type: 'string'
},
{
name: 'imageUrl',
group: 'image',
value: 'image.imageUrl',
type: 'string'
},
{
name: 'abstract',
group: 'image',
value: 'image.abstract',
type: 'string'
},
{
name: 'animals',
group: 'image',
value: 'image.animals',
type: 'string'
},
{
name: 'business',
group: 'image',
value: 'image.business',
type: 'string'
},
{
name: 'cats',
group: 'image',
value: 'image.cats',
type: 'string'
},
{
name: 'city',
group: 'image',
value: 'image.city',
type: 'string'
},
{
name: 'food',
group: 'image',
value: 'image.food',
type: 'string'
},
{
name: 'nightlife',
group: 'image',
value: 'image.nightlife',
type: 'string'
},
{
name: 'fashion',
group: 'image',
value: 'image.fashion',
type: 'string'
},
{
name: 'people',
group: 'image',
value: 'image.people',
type: 'string'
},
{
name: 'nature',
group: 'image',
value: 'image.nature',
type: 'string'
},
{
name: 'sports',
group: 'image',
value: 'image.sports',
type: 'string'
},
{
name: 'technics',
group: 'image',
value: 'image.technics',
type: 'string'
},
{
name: 'transport',
group: 'image',
value: 'image.transport',
type: 'string'
},
{
name: 'dataUri',
group: 'image',
value: 'image.dataUri',
type: 'string'
},
{
name: 'avatar',
group: 'internet',
value: 'internet.avatar',
type: 'string'
},
{
name: 'email',
group: 'internet',
value: 'internet.email',
type: 'string'
},
{
name: 'exampleEmail',
group: 'internet',
value: 'internet.exampleEmail',
type: 'string'
},
{
name: 'userName',
group: 'internet',
value: 'internet.userName',
type: 'string'
},
{
name: 'protocol',
group: 'internet',
value: 'internet.protocol',
type: 'string'
},
{
name: 'url',
group: 'internet',
value: 'internet.url',
type: 'string'
},
{
name: 'domainName',
group: 'internet',
value: 'internet.domainName',
type: 'string'
},
{
name: 'domainSuffix',
group: 'internet',
value: 'internet.domainSuffix',
type: 'string'
},
{
name: 'domainWord',
group: 'internet',
value: 'internet.domainWord',
type: 'string'
},
{
name: 'ip',
group: 'internet',
value: 'internet.ip',
type: 'string'
},
{
name: 'ipv6',
group: 'internet',
value: 'internet.ipv6',
type: 'string'
},
{
name: 'userAgent',
group: 'internet',
value: 'internet.userAgent',
type: 'string'
},
{
name: 'color',
group: 'internet',
value: 'internet.color',
type: 'string'
},
{
name: 'mac',
group: 'internet',
value: 'internet.mac',
type: 'string'
},
{
name: 'password',
group: 'internet',
value: 'internet.password',
type: 'string'
},
{
name: 'word',
group: 'lorem',
value: 'lorem.word',
type: 'string'
},
{
name: 'words',
group: 'lorem',
value: 'lorem.words',
type: 'string'
},
{
name: 'sentence',
group: 'lorem',
value: 'lorem.sentence',
type: 'string'
},
{
name: 'slug',
group: 'lorem',
value: 'lorem.slug',
type: 'string'
},
{
name: 'sentences',
group: 'lorem',
value: 'lorem.sentences',
type: 'string'
},
{
name: 'paragraph',
group: 'lorem',
value: 'lorem.paragraph',
type: 'string'
},
{
name: 'paragraphs',
group: 'lorem',
value: 'lorem.paragraphs',
type: 'string'
},
{
name: 'text',
group: 'lorem',
value: 'lorem.text',
type: 'string'
},
{
name: 'lines',
group: 'lorem',
value: 'lorem.lines',
type: 'string'
},
{
name: 'firstName',
group: 'name',
value: 'name.firstName',
type: 'string'
},
{
name: 'lastName',
group: 'name',
value: 'name.lastName',
type: 'string'
},
{
name: 'findName',
group: 'name',
value: 'name.findName',
type: 'string'
},
{
name: 'jobTitle',
group: 'name',
value: 'name.jobTitle',
type: 'string'
},
{
name: 'prefix',
group: 'name',
value: 'name.prefix',
type: 'string'
},
{
name: 'suffix',
group: 'name',
value: 'name.suffix',
type: 'string'
},
{
name: 'title',
group: 'name',
value: 'name.title',
type: 'string'
},
{
name: 'jobDescriptor',
group: 'name',
value: 'name.jobDescriptor',
type: 'string'
},
{
name: 'jobArea',
group: 'name',
value: 'name.jobArea',
type: 'string'
},
{
name: 'jobType',
group: 'name',
value: 'name.jobType',
type: 'string'
},
{
name: 'phoneNumber',
group: 'phone',
value: 'phone.phoneNumber',
type: 'string'
},
{
name: 'phoneNumberFormat',
group: 'phone',
value: 'phone.phoneNumberFormat',
type: 'string'
},
{
name: 'phoneFormats',
group: 'phone',
value: 'phone.phoneFormats',
type: 'string'
},
{
name: 'number',
group: 'random',
value: 'random.number',
type: 'number'
},
{
name: 'float',
group: 'random',
value: 'random.float',
type: 'number'
},
// Todo : use it for collection or enum
// {
// name: 'arrayElement',
// group: 'random',
// value: 'random.arrayElement',
// type: 'collection'
// },
// {
// name: 'objectElement',
// group: 'random',
// value: 'random.objectElement',
// type: 'string'
// },
{
name: 'uuid',
group: 'random',
value: 'random.uuid',
type: 'string'
},
{
name: 'boolean',
group: 'random',
value: 'random.boolean',
type: 'boolean'
},
{
name: 'word',
group: 'random',
value: 'random.word',
type: 'string'
},
{
name: 'words',
group: 'random',
value: 'random.words',
type: 'string'
},
{
name: 'image',
group: 'random',
value: 'random.image',
type: 'string'
},
{
name: 'locale',
group: 'random',
value: 'random.locale',
type: 'string'
},
{
name: 'alphaNumeric',
group: 'random',
value: 'random.alphaNumeric',
type: 'string'
},
{
name: 'hexaDecimal',
group: 'random',
value: 'random.hexaDecimal',
type: 'string'
},
{
name: 'fileName',
group: 'system',
value: 'system.fileName',
type: 'string'
},
{
name: 'commonFileName',
group: 'system',
value: 'system.commonFileName',
type: 'string'
},
{
name: 'mimeType',
group: 'system',
value: 'system.mimeType',
type: 'string'
},
{
name: 'commonFileType',
group: 'system',
value: 'system.commonFileType',
type: 'string'
},
{
name: 'commonFileExt',
group: 'system',
value: 'system.commonFileExt',
type: 'string'
},
{
name: 'fileType',
group: 'system',
value: 'system.fileType',
type: 'string'
},
{
name: 'fileExt',
group: 'system',
value: 'system.fileExt',
type: 'string'
},
{
name: 'directoryPath',
group: 'system',
value: 'system.directoryPath',
type: 'string'
},
{
name: 'filePath',
group: 'system',
value: 'system.filePath',
type: 'string'
},
{
name: 'semver',
group: 'system',
value: 'system.semver',
type: 'string'
}
];
// export default functionList;

65
packages/nocodb/src/lib/db/sql-client/lib/mysql/findDataTypeMapping.ts

@ -0,0 +1,65 @@
export const mapDataType = function(type) {
switch (type) {
case 'int':
case 'tinyint':
case 'smallint':
case 'mediumint':
case 'bigint':
case 'bit':
case 'boolean':
case 'float':
case 'decimal':
case 'double':
case 'serial':
return 'number';
case 'date':
case 'datetime':
case 'timestamp':
case 'time':
case 'year':
return 'date';
case 'char':
case 'varchar':
case 'nchar':
case 'text':
case 'tinytext':
case 'mediumtext':
case 'longtext':
return 'string';
case 'binary':
break;
case 'varbinary':
break;
case 'blob':
break;
case 'tinyblob':
break;
case 'mediumblob':
break;
case 'longblob':
break;
case 'enum':
case 'set':
return 'string';
break;
case 'geometry':
break;
case 'point':
break;
case 'linestring':
break;
case 'polygon':
break;
case 'multipoint':
break;
case 'multilinestring':
break;
case 'multipolygon':
break;
case 'json':
return 'string';
break;
}
return 'string';
};

364
packages/nocodb/src/lib/db/sql-client/lib/mysql/mysql.queries.ts

@ -0,0 +1,364 @@
const columnListOld = `SELECT
c.table_name as tn,
c.column_name as cn,
c.data_type as dt,
c.column_type as ct,
c.character_maximum_length as clen,
c.numeric_precision as np,
c.numeric_scale as ns,
-- c.datetime_precision as dp,
c.ordinal_position as cop,
c.column_key as ck,
c.extra as ext, -- gives ai
c.column_default as cdf,
c.is_nullable as nrqd,
c.privileges as priv,
c.column_comment as cc,
-- c.generation_expression,
c.character_set_name as csn,
c.collation_name as clnn,
ct.CONSTRAINT_TYPE as cst
FROM
information_schema.COLUMNS as c
Left join(
select
tc.CONSTRAINT_NAME,
tc.TABLE_NAME,
tc.CONSTRAINT_SCHEMA,
tc.CONSTRAINT_TYPE,
s.COLUMN_NAME
from
information_schema.TABLE_CONSTRAINTS as tc
LEFT JOIN information_schema.STATISTICS as s ON
s.table_schema = tc.CONSTRAINT_SCHEMA
and s.TABLE_NAME = tc.TABLE_NAME
and s.INDEX_NAME = tc.CONSTRAINT_NAME
where
tc.CONSTRAINT_SCHEMA = ?
and s.TABLE_NAME = ?
) ct on
c.TABLE_SCHEMA = ct.CONSTRAINT_SCHEMA
AND c.TABLE_NAME = ct.TABLE_NAME
AND c.COLUMN_NAME = ct.COLUMN_NAME
WHERE
c.table_schema = ?
and c.TABLE_NAME = ?
ORDER BY
c.table_name,
c.ordinal_position`;
export default {
columnList: {
'55': {
sql: columnListOld,
paramsHints: ['databaseName', 'tn', 'databaseName', 'tn']
},
'56': {
sql: columnListOld,
paramsHints: ['databaseName', 'tn', 'databaseName', 'tn']
},
default: {
sql: `SELECT
c.table_name as tn,
c.column_name as cn,
c.data_type as dt,
c.column_type as ct,
c.character_maximum_length as clen,
c.numeric_precision as np,
c.numeric_scale as ns,
c.datetime_precision as dp,
c.ordinal_position as cop,
c.column_key as ck,
c.extra as ext, -- gives ai
c.column_default as cdf,
c.is_nullable as nrqd,
c.privileges as priv,
c.column_comment as cc,
-- c.generation_expression,
c.character_set_name as csn,
c.collation_name as clnn,
ct.CONSTRAINT_TYPE as cst
FROM
information_schema.COLUMNS as c
Left join(
select
tc.CONSTRAINT_NAME,
tc.TABLE_NAME,
tc.CONSTRAINT_SCHEMA,
tc.CONSTRAINT_TYPE,
s.COLUMN_NAME
from
information_schema.TABLE_CONSTRAINTS as tc
LEFT JOIN information_schema.STATISTICS as s ON
s.table_schema = tc.CONSTRAINT_SCHEMA
and s.TABLE_NAME = tc.TABLE_NAME
and s.INDEX_NAME = tc.CONSTRAINT_NAME
and tc.CONSTRAINT_TYPE != 'UNIQUE'
and tc.CONSTRAINT_TYPE != 'FOREIGN KEY'
where
tc.CONSTRAINT_SCHEMA = ?
and s.TABLE_NAME = ?
) ct on
c.TABLE_SCHEMA = ct.CONSTRAINT_SCHEMA
AND c.TABLE_NAME = ct.TABLE_NAME
AND c.COLUMN_NAME = ct.COLUMN_NAME
WHERE
c.table_schema = ?
and c.TABLE_NAME = ?
ORDER BY
c.table_name,
c.ordinal_position`,
paramsHints: ['databaseName', 'tn', 'databaseName', 'tn']
}
},
constraintList: {
default: {
sql: `SELECT
k.constraint_name as cstn,
k.column_name as cn,
k.ordinal_position as op,
k.position_in_unique_constraint as puc,
t.constraint_type as cst
FROM information_schema.table_constraints t
LEFT JOIN information_schema.key_column_usage k
USING(constraint_name,table_schema,table_name)
WHERE
t.table_schema=?
AND t.table_name=?;`,
paramsHints: ['database', 'tn']
}
},
createDatabaseIfNotExists: {
default: {
sql: `create database if not exists ??`,
paramsHints: ['database']
}
},
createTableIfNotExists: {
default: {
sql: ``,
paramsHints: []
}
},
dropDatabase: {
default: {
sql: `drop database ??`,
paramsHints: ['database']
}
},
databaseList: {
default: {
sql: `SHOW databases`,
paramsHints: []
}
},
hasDatabase: {
default: {
sql: `SHOW DATABASES LIKE ?`,
paramsHints: ['databaseName']
}
},
indexList: {
default: {
sql: `show index from ??`,
paramsHints: ['tn']
}
},
functionList: {
default: {
sql: `show function status where db=?`,
paramsHints: ['databaseName']
}
},
functionRead: {
default: {
sql: `SHOW CREATE FUNCTION ??`,
paramsHints: ['function_name']
}
},
functionDelete: {
default: {
sql: `DROP FUNCTION IF EXISTS ??`,
paramsHints: ['function_name']
}
},
procedureList: {
default: {
sql: `show procedure status where db=?`,
paramsHints: ['databaseName']
}
},
procedureRead: {
default: {
sql: `show create procedure ??`,
paramsHints: ['procedure_name']
}
},
procedureDelete: {
default: {
sql: `DROP PROCEDURE IF EXISTS ??`,
paramsHints: ['procedure_name']
}
},
relationList: {
default: {
sql: `SELECT
kcu.CONSTRAINT_NAME as cstn,
kcu.TABLE_NAME as tn,
kcu.COLUMN_NAME as cn,
kcu.POSITION_IN_UNIQUE_CONSTRAINT as puc,
kcu.REFERENCED_TABLE_NAME as rtn,
kcu.REFERENCED_COLUMN_NAME as rcn,
rc.MATCH_OPTION as mo,
rc.UPDATE_RULE as ur,
rc.DELETE_RULE as dr,
kcu.table_schema as ts
FROM
information_schema.KEY_COLUMN_USAGE AS kcu
INNER JOIN information_schema.REFERENTIAL_CONSTRAINTS AS rc ON
kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
Group by kcu.CONSTRAINT_NAME,
kcu.TABLE_NAME,
kcu.COLUMN_NAME,
kcu.POSITION_IN_UNIQUE_CONSTRAINT,
kcu.REFERENCED_TABLE_NAME,
kcu.REFERENCED_COLUMN_NAME,
rc.MATCH_OPTION,
rc.UPDATE_RULE,
rc.DELETE_RULE ,kcu.table_schema
Having
kcu.table_schema = ?
AND kcu.referenced_column_name IS NOT NULL
AND kcu.table_name=?`,
paramsHints: ['database', 'tn']
}
},
relationListAll: {
default: {
sql: `
SELECT
kcu.CONSTRAINT_NAME AS cstn,
kcu.TABLE_NAME AS tn,
kcu.COLUMN_NAME AS cn,
kcu.POSITION_IN_UNIQUE_CONSTRAINT AS puc,
kcu.REFERENCED_TABLE_NAME AS rtn,
kcu.REFERENCED_COLUMN_NAME AS rcn,
rc.MATCH_OPTION AS mo,
rc.UPDATE_RULE AS ur,
rc.DELETE_RULE AS dr,
kcu.table_schema AS ts
FROM
(SELECT
table_schema,
CONSTRAINT_NAME,
TABLE_NAME,
COLUMN_NAME,
POSITION_IN_UNIQUE_CONSTRAINT,
REFERENCED_TABLE_NAME,
REFERENCED_COLUMN_NAME
FROM
information_schema.KEY_COLUMN_USAGE
WHERE
table_schema = :databaseName) AS kcu
INNER JOIN
(SELECT
CONSTRAINT_SCHEMA,
MATCH_OPTION,
UPDATE_RULE,
DELETE_RULE,
CONSTRAINT_NAME
FROM
information_schema.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = :databaseName) AS rc ON kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
AND kcu.table_schema = rc.CONSTRAINT_SCHEMA
INNER JOIN
(SELECT
table_schema, TABLE_NAME, COLUMN_NAME
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
table_schema = :databaseName AND TABLE_NAME IN (SELECT
TABLE_NAME
FROM
INFORMATION_SCHEMA.TABLES
WHERE
table_schema = :databaseName
AND LOWER(TABLE_TYPE) = 'base table')) AS col ON col.table_schema = kcu.table_schema
AND col.table_name = kcu.TABLE_NAME
AND kcu.REFERENCED_COLUMN_NAME IS NOT NULL
GROUP BY cstn , tn , rcn , cn , puc , rtn ,cn, mo , ur , dr , ts`,
paramsHints: ['database']
}
},
schemaCreate: {
default: {
sql: `create database ??`,
paramsHints: ['database_name']
}
},
schemaDelete: {
default: {
sql: `drop database ??`,
paramsHints: ['database_name']
}
},
triggerList: {
default: {
sql: `SHOW TRIGGERS like ?`,
paramsHints: ['tn']
}
},
tableList: {
default: {
sql: ``,
paramsHints: []
}
},
testConnection: {
default: {
sql: ``,
paramsHints: []
}
},
triggerRead: {
default: {
sql: `SHOW FULL TABLES IN ?? WHERE TABLE_TYPE LIKE 'VIEW';`,
paramsHints: ['databaseName']
}
},
triggerDelete: {
default: {
sql: `DROP TRIGGER ??`,
paramsHints: ['trigger_name']
}
},
version: {
default: {
sql: ``,
paramsHints: []
}
},
viewRead: {
default: {
sql: `select * FROM INFORMATION_SCHEMA.VIEWS WHERE
TABLE_SCHEMA = ? AND TABLE_NAME = ?`,
paramsHints: ['databaseName', 'view_name']
}
},
//
viewList: {
default: {
sql: `SHOW FULL TABLES WHERE TABLE_TYPE LIKE 'VIEW'`,
paramsHints: []
}
}
};

2220
packages/nocodb/src/lib/db/sql-client/lib/oracle/OracleClient.ts

File diff suppressed because it is too large Load Diff

25
packages/nocodb/src/lib/db/sql-client/lib/oracle/oracle.queries.ts

@ -0,0 +1,25 @@
// https://docs.oracle.com/cd/E11882_01/appdev.112/e10646/oci03typ.htm#LNOCI16276
const oracleQueries = {
varchar2: {},
number: {},
integer: {},
float: {},
string: {},
varnum: {},
decimal: {},
long: {},
varchar: {},
date: {},
varraw: {},
raw: {},
'long raw': {},
un: {},
'long varchar': {},
'long varraw': {},
char: {},
charz: {},
rowiddescriptor: {}
};
export default oracleQueries;

111
packages/nocodb/src/lib/db/sql-client/lib/order.ts

@ -0,0 +1,111 @@
//define class
class Order {
private matrix: any;
private squareLen: any;
constructor(squareMatrix) {
if (squareMatrix) {
this.matrix = squareMatrix;
this.squareLen = this.matrix.length;
}
}
_hasColumnZeroes(index) {
for (let i = 0; i < this.matrix.length; ++i) {
if (this.matrix[i][index] !== 0) {
return false;
}
}
return true;
}
_makeAllElementsInRowAsZero(index) {
for (let i = 0; i < this.matrix.length; ++i) {
this.matrix[index][i] = 0;
}
}
_selfPointing() {
const self = {};
for (let i = 0; i < this.matrix.length; ++i) {
if (this.matrix[i][i] === 1) {
this.matrix[i][i] = 0;
self[i] = i;
}
}
return self;
}
_CycleBetweenNodes() {
const two = [];
for (let i = 0; i < this.matrix.length; ++i) {
for (let j = i + 1; j < this.matrix.length; ++j) {
if (i !== j && this.matrix[i][j] === 1 && this.matrix[j][i] === 1) {
two.push([i, j]);
console.log(i, j);
}
}
}
return two;
}
/***
*
* @returns {order:[],one:{},two:[],cycle:{}}
*/
getOrder() {
console.time('getOrder');
const visited = {};
const cycle = {};
const order = [];
const one = this._selfPointing();
const two = this._CycleBetweenNodes();
for (let i = 0; i < this.squareLen; ++i) {
cycle[i] = i;
}
for (let i = 0; i < this.squareLen; ++i) {
for (let j = 0; j < this.squareLen; ++j) {
//console.log('- - - - - - - - - - - -- ');
if (j in visited) {
//console.log('Already visited',j);
} else if (this._hasColumnZeroes(j)) {
//console.log('Inserting to visit order --> ',j);
visited[j] = j;
delete cycle[j];
order.push(j);
this._makeAllElementsInRowAsZero(j);
} else {
//console.log('Column does not have zeroes',j);
}
if (order.length === this.squareLen) {
console.timeEnd('getOrder');
return { order, one, cycle };
}
}
}
console.timeEnd('getOrder');
return { order, one, cycle, two };
}
setIndex(i, j) {
if (i < this.matrix.length && j < this.matrix.length) {
this.matrix[i][j] = 1;
}
}
resetIndex(i, j) {
if (i < this.matrix.length && j < this.matrix.length) {
this.matrix[i][j] = 0;
}
}
}
export default Order;

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

File diff suppressed because it is too large Load Diff

140
packages/nocodb/src/lib/db/sql-client/lib/pg/YugabyteClient.ts

@ -0,0 +1,140 @@
import PGClient from './PgClient';
import Debug from '../../../util/Debug';
import Result from '../../../util/Result';
const log = new Debug('YBClient');
class YBClient extends PGClient {
constructor(connectionConfig) {
super(connectionConfig);
}
/**
*
* @param {Object} - args - for future reasons
* @returns {Object[]} - tables
* @property {String} - tables[].tn
*/
async tableList(args: any = {}) {
const _func = this.tableList.name;
const result = new Result();
log.api(`${_func}:args:`, args);
try {
const { rows } = await this.raw(
`select tablename as tn, * from pg_catalog.pg_tables where schemaname != 'information_schema' and schemaname != 'pg_catalog'`
);
result.data.list = rows;
} catch (e) {
log.ppe(e, _func);
throw e;
}
log.api(`${_func}: result`, result);
return result;
}
/**
*
* @param {Object} - args - Input arguments
* @param {Object} - args.tn -
* @returns {Object[]} - columns
* @property {String} - columns[].tn
* @property {String} - columns[].cn
* @property {String} - columns[].dt
* @property {String} - columns[].dtx
* @property {String} - columns[].np
* @property {String} - columns[].ns -
* @property {String} - columns[].clen -
* @property {String} - columns[].dp -
* @property {String} - columns[].cop -
* @property {String} - columns[].pk -
* @property {String} - columns[].nrqd -
* @property {String} - columns[].not_nullable -
* @property {String} - columns[].ct -
* @property {String} - columns[].un -
* @property {String} - columns[].ai -
* @property {String} - columns[].unique -
* @property {String} - columns[].cdf -
* @property {String} - columns[].cc -
* @property {String} - columns[].csn -
*/
async columnList(args: any = {}) {
const _func = this.columnList.name;
const result = new Result();
log.api(`${_func}:args:`, args);
try {
args.databaseName = this.connectionConfig.connection.database;
const response = await this.raw(`
select c.relname as tn, a.attname as cn, pg_catalog.format_type(a.atttypid, a.atttypmod) as "dt",a.attnotnull as "not_nullable",
pg_catalog.pg_get_expr(ad.adbin, ad.adrelid, true) as cdf, dsc.description as comment,a.attnum as cop,
coalesce(i.indisprimary,false) as pk,
a.*,ad.oid as attr_id
FROM pg_catalog.pg_attribute a
INNER JOIN pg_catalog.pg_class c ON (a.attrelid=c.oid)
LEFT OUTER JOIN pg_catalog.pg_attrdef ad ON (a.attrelid=ad.adrelid AND a.attnum = ad.adnum)
LEFT OUTER JOIN pg_catalog.pg_description dsc ON (c.oid=dsc.objoid AND a.attnum = dsc.objsubid)
LEFT JOIN pg_index i ON (a.attnum = any(i.indkey) and a.attrelid = i.indrelid and i.indrelid = '${args.tn}'::regclass AND i.indisprimary)
WHERE NOT a.attisdropped AND c.relname = '${args.tn}' and a.attnum > 0 ORDER BY a.attnum`);
const columns = [];
for (let i = 0; i < response.rows.length; ++i) {
const column: any = {};
column.tn = args.tn;
column.cn = response.rows[i].cn;
column.dt = response.rows[i].dt;
column.np = response.rows[i].np;
column.ns = response.rows[i].ns;
column.clen = response.rows[i].clen;
column.dp = response.rows[i].dp;
column.cop = response.rows[i].cop;
// todo : there are lot of types in pg - handle them
column.dtx = this.getKnexDataType(column.dt);
column.pk = response.rows[i].pk_constraint_name !== null;
column.not_nullable = response.rows[i].not_nullable;
column.nrqd = !column.not_nullable;
// todo: there is no type of unsigned in postgres
response.rows[i].ct = response.rows[i].dt || '';
column.un = response.rows[i].ct.indexOf('unsigned') !== -1;
column.ai = false;
if (response.rows[i].cdf) {
column.ai = response.rows[i].cdf.indexOf('nextval') !== -1;
}
// todo : need to find if column is unique or not
// column['unique'] = response.rows[i]['cst'].indexOf('UNIQUE') === -1 ? false : true;
column.cdf = response.rows[i].cdf
? response.rows[i].cdf.split('::')[0].replace(/'/g, '')
: response.rows[i].cdf;
// todo : need to find column comment
column.cc = response.rows[i].comment;
column.csn = response.rows[i].csn;
columns.push(column);
}
result.data.list = columns;
} catch (e) {
log.ppe(e, _func);
throw e;
}
log.api(`${_func}: result`, result);
return result;
}
}
export default YBClient;

239
packages/nocodb/src/lib/db/sql-client/lib/pg/pg.queries.ts

@ -0,0 +1,239 @@
// https://www.postgresql.org/docs/9.5/datatype.html
const pgQueries = {
columnList: {
default: {
sql: `SELECT
c.table_name as tn,
c.column_name as cn,
c.data_type as dt,
c.column_type as ct,
c.character_maximum_length as clen,
c.numeric_precision as np,
c.numeric_scale as ns,
c.datetime_precision as dp,
c.ordinal_position as cop,
c.column_key as ck,
c.extra as ext, -- gives ai
c.column_default as cdf,
c.is_nullable as nrqd,
c.privileges as priv,
c.column_comment as cc,
c.generation_expression,
c.character_set_name as csn,
c.collation_name as clnn,
ct.CONSTRAINT_TYPE as cst
FROM
information_schema.COLUMNS as c
Left join(
select
tc.CONSTRAINT_NAME,
tc.TABLE_NAME,
tc.CONSTRAINT_SCHEMA,
tc.CONSTRAINT_TYPE,
s.COLUMN_NAME
from
information_schema.TABLE_CONSTRAINTS as tc
LEFT JOIN information_schema.STATISTICS as s ON
s.table_schema = tc.CONSTRAINT_SCHEMA
and s.TABLE_NAME = tc.TABLE_NAME
and s.INDEX_NAME = tc.CONSTRAINT_NAME
where
tc.CONSTRAINT_SCHEMA = ?
and s.TABLE_NAME = ?
) ct on
c.TABLE_SCHEMA = ct.CONSTRAINT_SCHEMA
AND c.TABLE_NAME = ct.TABLE_NAME
AND c.COLUMN_NAME = ct.COLUMN_NAME
WHERE
c.table_schema = ?
and c.TABLE_NAME = ?
ORDER BY
c.table_name,
c.ordinal_position`,
paramsHints: ['databaseName', 'tn', 'databaseName', 'tn']
}
},
constraintList: {
default: {
sql: `SELECT
k.constraint_name as cstn,
k.column_name as cn,
k.ordinal_position as op,
k.position_in_unique_constraint as puc,
t.constraint_type as cst
FROM information_schema.table_constraints t
LEFT JOIN information_schema.key_column_usage k
USING(constraint_name,table_schema,table_name)
WHERE
t.table_schema=?
AND t.table_name=?;`,
paramsHints: ['database', 'tn']
}
},
createDatabaseIfNotExists: {
default: {
sql: `create database if not exists ??`,
paramsHints: ['database']
}
},
createTableIfNotExists: {
default: {
sql: ``,
paramsHints: []
}
},
dropDatabase: {
default: {
sql: `drop database ??`,
paramsHints: ['database']
}
},
databaseList: {
default: {
sql: `SHOW databases`,
paramsHints: []
}
},
hasDatabase: {
default: {
sql: `SHOW DATABASES LIKE ??`,
paramsHints: ['databaseName']
}
},
indexList: {
default: {
sql: `show index from ??`,
paramsHints: ['tn']
}
},
functionList: {
default: {
sql: `show function status where db=?`,
paramsHints: ['databaseName']
}
},
functionRead: {
default: {
sql: `SHOW CREATE FUNCTION ??`,
paramsHints: ['function_name']
}
},
functionDelete: {
default: {
sql: `DROP FUNCTION IF EXISTS ??`,
paramsHints: ['function_name']
}
},
procedureList: {
default: {
sql: `show procedure status where db=?`,
paramsHints: ['databaseName']
}
},
procedureRead: {
default: {
sql: `show create procedure ??`,
paramsHints: ['procedure_name']
}
},
procedureDelete: {
default: {
sql: `DROP PROCEDURE IF EXISTS ??`,
paramsHints: ['procedure_name']
}
},
relationList: {
default: {
sql: `SELECT
kcu.CONSTRAINT_NAME as cstn,
kcu.TABLE_NAME as tn,
kcu.COLUMN_NAME as cn,
kcu.POSITION_IN_UNIQUE_CONSTRAINT as puc,
kcu.REFERENCED_TABLE_NAME as rtn,
kcu.REFERENCED_COLUMN_NAME as rcn,
rc.MATCH_OPTION as mo,
rc.UPDATE_RULE as ur,
rc.DELETE_RULE as dr
FROM
information_schema.\`KEY_COLUMN_USAGE\` AS kcu
INNER JOIN information_schema.REFERENTIAL_CONSTRAINTS AS rc ON
kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
WHERE
kcu.table_schema = ?
AND kcu.referenced_column_name IS NOT NULL
AND kcu.table_name=?`,
paramsHints: ['database', 'tn']
}
},
schemaCreate: {
default: {
sql: `create database ??`,
paramsHints: ['database_name']
}
},
schemaDelete: {
default: {
sql: `drop database ??`,
paramsHints: ['database_name']
}
},
triggerList: {
default: {
sql: `SHOW TRIGGERS like ?`,
paramsHints: ['tn']
}
},
tableList: {
default: {
sql: ``,
paramsHints: []
}
},
testConnection: {
default: {
sql: ``,
paramsHints: []
}
},
triggerRead: {
default: {
sql: `SHOW FULL TABLES IN ?? WHERE TABLE_TYPE LIKE 'VIEW';`,
paramsHints: ['databaseName']
}
},
triggerDelete: {
default: {
sql: `DROP TRIGGER ??`,
paramsHints: ['trigger_name']
}
},
version: {
default: {
sql: ``,
paramsHints: []
}
},
viewRead: {
default: {
sql: `select * FROM INFORMATION_SCHEMA.VIEWS WHERE
TABLE_SCHEMA = ? AND TABLE_NAME = ?`,
paramsHints: ['databaseName', 'view_name']
}
},
//
viewList: {
default: {
sql: `SHOW FULL TABLES IN ?? WHERE TABLE_TYPE LIKE 'VIEW'`,
paramsHints: ['databaseName']
}
}
};
export default pgQueries;

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

File diff suppressed because it is too large Load Diff

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

@ -0,0 +1,34 @@
// https://www.sqlite.org/datatype3.html
const sqliteQueries = {
int: {},
integer: {},
tinyint: {},
smallint: {},
mediumint: {},
bigint: {},
'unsigned big int': {},
int2: {},
int4: {},
character: {},
varchar: {},
nchar: {},
text: {},
clob: {},
'varying character': {},
'native character': {},
blob: {},
real: {},
double: {},
'double precision': {},
float: {},
numeric: {},
decimal: {},
boolean: {},
date: {},
datetime: {}
};
export default sqliteQueries;

6
packages/nocodb/src/lib/db/sql-mgr/SqlMgr.ts

@ -6,16 +6,18 @@ import { Tele } from 'nc-help';
import fsExtra from 'fs-extra';
import importFresh from 'import-fresh';
import inflection from 'inflection';
import { Debug, Result, SqlClientFactory } from 'nc-help';
import slash from 'slash';
import SqlClientFactory from '../sql-client/lib/SqlClientFactory';
// import debug from 'debug';
const log = new Debug('SqlMgr');
import KnexMigrator from '../sql-migrator/lib/KnexMigrator';
// import {XKnex} from "../sql-data-mapper";
import NcConnectionMgr from '../../utils/common/NcConnectionMgr';
import { customAlphabet } from 'nanoid';
import Debug from '../util/Debug';
import Result from '../util/Result';
const randomID = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz_', 20);
const log = new Debug('SqlMgr');
const ToolOps = {
DB_TABLE_LIST: 'tableList',

5
packages/nocodb/src/lib/db/sql-mgr/code/BaseRender.ts

@ -8,11 +8,12 @@
// import fsExtra from "fs-extra";
// import md5 from "md5";
// import dayjs from "dayjs";import Emit from "../../sql-migrator/util/emit";
import Debug from '../../sql-migrator/util/Debug';
import Emit from '../../sql-migrator/util/emit';
// const beautify = js_beautify.js;
import Debug from '../../util/Debug';
import Emit from '../../util/emit';
class BaseRender {
protected dir: any;
protected filename: any;

7
packages/nocodb/src/lib/db/sql-mgr/v2/SqlMgrv2.ts

@ -1,12 +1,13 @@
import { Debug, SqlClientFactory } from 'nc-help';
// import debug from 'debug';
const log = new Debug('SqlMgr');
// import {XKnex} from "../sql-data-mapper";
import NcConnectionMgrv2 from '../../../utils/common/NcConnectionMgrv2';
import SqlClientFactory from '../../sql-client/lib/SqlClientFactory';
import KnexMigratorv2 from '../../sql-migrator/lib/KnexMigratorv2';
import Base from '../../../models/Base';
import Debug from '../../util/Debug';
const log = new Debug('SqlMgr');
export default class SqlMgrv2 {
protected _migrator: KnexMigratorv2;

11
packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigrator.ts

@ -5,13 +5,12 @@ import { promisify } from 'util';
import glob from 'glob';
import Handlebars from 'handlebars';
import mkdirp from 'mkdirp';
import { SqlClientFactory } from 'nc-help';
import rmdir from 'rmdir';
import Debug from '../util/Debug';
import Result from '../util/Result';
import Emit from '../util/emit';
import * as fileHelp from '../util/file.help';
import SqlClientFactory from '../../sql-client/lib/SqlClientFactory';
import Debug from '../../util/Debug';
import Emit from '../../util/emit';
import Result from '../../util/Result';
import * as fileHelp from '../../util/file.help';
import SqlMigrator from './SqlMigrator';
import NcConfigFactory from '../../../utils/NcConfigFactory';

10
packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2.ts

@ -3,13 +3,12 @@ import path from 'path';
import { promisify } from 'util';
import glob from 'glob';
import SqlClientFactory from '../../sql-client/lib/SqlClientFactory';
import Debug from '../../util/Debug';
import Emit from '../../util/emit';
// import Handlebars from 'handlebars';
// import mkdirp from 'mkdirp';
import { SqlClientFactory } from 'nc-help';
import Debug from '../util/Debug';
import Result from '../util/Result';
import Emit from '../util/emit';
import * as fileHelp from '../util/file.help';
import * as fileHelp from '../../util/file.help';
// import SqlMigrator from './SqlMigrator';
// import NcConfigFactory from '../../../utils/NcConfigFactory';
@ -18,6 +17,7 @@ import { XKnex } from '../../sql-data-mapper';
import Project from '../../../models/Project';
import Base from '../../../models/Base';
import NcConnectionMgrv2 from '../../../utils/common/NcConnectionMgrv2';
import Result from '../../util/Result';
const evt = new Emit();
const log = new Debug('KnexMigrator');

2
packages/nocodb/src/lib/db/sql-migrator/util/Debug.ts → packages/nocodb/src/lib/db/util/Debug.ts

@ -45,7 +45,7 @@ export default class Debug {
return log;
}
ppe(e, func) {
ppe(e, func?) {
return this.ppException(e, func);
}
}

0
packages/nocodb/src/lib/db/sql-migrator/util/DebugMgr.ts → packages/nocodb/src/lib/db/util/DebugMgr.ts

0
packages/nocodb/src/lib/db/sql-migrator/util/FileCollection.ts → packages/nocodb/src/lib/db/util/FileCollection.ts

0
packages/nocodb/src/lib/db/sql-migrator/util/Result.ts → packages/nocodb/src/lib/db/util/Result.ts

0
packages/nocodb/src/lib/db/sql-migrator/util/emit.ts → packages/nocodb/src/lib/db/util/emit.ts

0
packages/nocodb/src/lib/db/sql-migrator/util/file.help.ts → packages/nocodb/src/lib/db/util/file.help.ts

3
packages/nocodb/src/lib/meta/NcMetaMgr.ts

@ -11,7 +11,7 @@ import extract from 'extract-zip';
import isDocker from 'is-docker';
import multer from 'multer';
import { customAlphabet, nanoid } from 'nanoid';
import { SqlClientFactory, Tele } from 'nc-help';
import { Tele } from 'nc-help';
import slash from 'slash';
import { v4 as uuidv4 } from 'uuid';
import { ncp } from 'ncp';
@ -19,6 +19,7 @@ import { ncp } from 'ncp';
import IEmailAdapter from '../../interface/IEmailAdapter';
import IStorageAdapter from '../../interface/IStorageAdapter';
import { NcConfig, Result } from '../../interface/config';
import SqlClientFactory from '../db/sql-client/lib/SqlClientFactory';
import { NcConfigFactory } from '../index';
import ProjectMgr from '../db/sql-mgr/ProjectMgr';
import ExpressXcTsRoutes from '../db/sql-mgr/code/routes/xc-ts/ExpressXcTsRoutes';

14
packages/nocodb/src/lib/utils/Emit.ts

@ -0,0 +1,14 @@
const Emittery = require('emittery');
let emitSingleton = null;
class Emit {
public readonly evt: any;
constructor() {
if (emitSingleton) return emitSingleton;
this.evt = new Emittery();
emitSingleton = this;
}
}
module.exports = Emit;

2
packages/nocodb/src/lib/utils/NcConfigFactory.ts

@ -1,4 +1,3 @@
import { SqlClientFactory } from 'nc-help';
import fs from 'fs';
import parseDbUrl from 'parse-database-url';
import { URL } from 'url';
@ -10,6 +9,7 @@ import {
NcConfig
} from '../../interface/config';
import * as path from 'path';
import SqlClientFactory from '../db/sql-client/lib/SqlClientFactory';
const {
uniqueNamesGenerator,

13
packages/nocodb/src/lib/utils/Result.js

@ -0,0 +1,13 @@
class Result {
constructor(code = 0, message = '', data = {}) {
this.code = code;
this.message = message;
this.data = data;
}
}
module.exports = Result;

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

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

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

@ -1,9 +1,9 @@
import SqlClientFactory from '../../db/sql-client/lib/SqlClientFactory';
import { XKnex } from '../../db/sql-data-mapper';
// import { NcConfig } from '../../../interface/config';
// import fs from 'fs';
// import Knex from 'knex';
import { SqlClientFactory } from 'nc-help';
// import NcMetaIO from '../meta/NcMetaIO';
import { defaultConnectionConfig } from '../NcConfigFactory';
import Base from '../../models/Base';

3
packages/nocodb/src/lib/v1-legacy/NcProjectBuilder.ts

@ -3,9 +3,10 @@ import path from 'path';
import axios from 'axios';
import { Router } from 'express';
import { SqlClientFactory, Tele } from 'nc-help';
import { Tele } from 'nc-help';
import { NcConfig } from '../../interface/config';
import SqlClientFactory from '../db/sql-client/lib/SqlClientFactory';
import Migrator from '../db/sql-migrator/lib/KnexMigrator';
import Noco from '../Noco';

Loading…
Cancel
Save