@dbml/connector 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/connectors/mssql/expect-out-files/schema.json +98 -7
- package/__tests__/connectors/mssql/out-files/schema.json +2074 -0
- package/__tests__/connectors/mysql/expect-out-files/schema.json +98 -8
- package/__tests__/connectors/mysql/out-files/schema.json +1430 -0
- package/__tests__/connectors/postgres/expect-out-files/schema.json +119 -8
- package/__tests__/connectors/postgres/out-files/schema.json +1719 -0
- package/dist/connectors/bigqueryConnector.js +1 -2
- package/dist/connectors/mssqlConnector.js +12 -9
- package/dist/connectors/mysqlConnector.js +1 -1
- package/dist/connectors/postgresConnector.js +20 -15
- package/dist/connectors/snowflakeConnector.js +0 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +17 -7
- package/dist/utils/parseSchema.d.ts +1 -1
- package/dist/utils/parseSchema.js +13 -13
- package/eslint.config.ts +70 -0
- package/jest.config.ts +2 -2
- package/package.json +15 -6
- package/src/connectors/bigqueryConnector.ts +1 -2
- package/src/connectors/mssqlConnector.ts +18 -13
- package/src/connectors/mysqlConnector.ts +2 -2
- package/src/connectors/postgresConnector.ts +23 -16
- package/src/connectors/snowflakeConnector.ts +5 -4
- package/src/connectors/types.ts +13 -13
- package/src/index.ts +1 -1
- package/src/utils/parseSchema.ts +11 -11
- package/test-output.log +18 -0
- package/tsconfig.json +1 -1
- package/.eslintrc.json +0 -24
|
@@ -46,8 +46,7 @@ function getDbDefault(columnDefault, defaultValueType) {
|
|
|
46
46
|
}
|
|
47
47
|
if (defaultValueType === 'string') {
|
|
48
48
|
// bigquery store the double qoutes and quotes at the end and the beginning of the string: "string" or 'string'
|
|
49
|
-
|
|
50
|
-
return { value: columnDefault.slice(1, -1).replaceAll("'", "\'"), type: defaultValueType };
|
|
49
|
+
return { value: columnDefault.slice(1, -1).replaceAll('\'', '\''), type: defaultValueType };
|
|
51
50
|
}
|
|
52
51
|
return { value: columnDefault, type: defaultValueType };
|
|
53
52
|
}
|
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.fetchSchemaJson = void 0;
|
|
7
|
-
/* eslint-disable camelcase */
|
|
8
7
|
/* TDD 72
|
|
9
8
|
* - In MSSQL, there's no notion of ENUM.
|
|
10
9
|
* - MSSQL connector used to extract ENUMS from CHECK constraints, for example: `CHECK ([col]=value1 OR [col]=value2)` would be translated to an enum with 2 values, `value1` and `value2`.
|
|
@@ -265,7 +264,7 @@ const generateRefs = async (client, schemas) => {
|
|
|
265
264
|
onDelete: on_delete === 'NO_ACTION' ? null : on_delete,
|
|
266
265
|
onUpdate: on_update === 'NO_ACTION' ? null : on_update,
|
|
267
266
|
};
|
|
268
|
-
const isDuplicate = refs.some(ref => endpointsEqual(ref.endpoints, newRef.endpoints));
|
|
267
|
+
const isDuplicate = refs.some((ref) => endpointsEqual(ref.endpoints, newRef.endpoints));
|
|
269
268
|
if (!isDuplicate) {
|
|
270
269
|
refs.push(newRef);
|
|
271
270
|
}
|
|
@@ -361,19 +360,21 @@ const generateIndexesAndConstraints = async (client, schemas) => {
|
|
|
361
360
|
return acc;
|
|
362
361
|
}, { inlineIndexes: [], outOfLineIndexes: [] });
|
|
363
362
|
const indexes = outOfLineIndexes.reduce((acc, indexRow) => {
|
|
364
|
-
const { table_schema, table_name, index_name, index_type, columns, expressions, } = indexRow;
|
|
363
|
+
const { table_schema, table_name, index_name, index_type, columns, expressions, is_unique, is_primary, } = indexRow;
|
|
365
364
|
const indexColumns = columns.split(',').map((column) => {
|
|
366
365
|
return {
|
|
367
366
|
type: 'column',
|
|
368
367
|
value: column.trim(),
|
|
369
368
|
};
|
|
370
369
|
});
|
|
371
|
-
const indexExpressions = expressions
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
370
|
+
const indexExpressions = expressions
|
|
371
|
+
? expressions.split(',').map((expression) => {
|
|
372
|
+
return {
|
|
373
|
+
type: 'expression',
|
|
374
|
+
value: expression,
|
|
375
|
+
};
|
|
376
|
+
})
|
|
377
|
+
: [];
|
|
377
378
|
const index = {
|
|
378
379
|
name: index_name,
|
|
379
380
|
type: index_type,
|
|
@@ -381,6 +382,8 @@ const generateIndexesAndConstraints = async (client, schemas) => {
|
|
|
381
382
|
...indexColumns,
|
|
382
383
|
...indexExpressions,
|
|
383
384
|
],
|
|
385
|
+
pk: !!is_primary,
|
|
386
|
+
unique: !is_primary && !!is_unique,
|
|
384
387
|
};
|
|
385
388
|
const key = `${table_schema}.${table_name}`;
|
|
386
389
|
if (acc[key]) {
|
|
@@ -264,7 +264,7 @@ async function generatePrimaryAndUniqueConstraint(client, schemaName) {
|
|
|
264
264
|
};
|
|
265
265
|
}
|
|
266
266
|
if (constraintType === 'PRIMARY KEY') {
|
|
267
|
-
acc[key][constraintName].
|
|
267
|
+
acc[key][constraintName].pk = true;
|
|
268
268
|
}
|
|
269
269
|
if (constraintType === 'UNIQUE') {
|
|
270
270
|
acc[key][constraintName].unique = true;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.fetchSchemaJson = void 0;
|
|
4
|
-
/* eslint-disable camelcase */
|
|
5
4
|
const pg_1 = require("pg");
|
|
6
5
|
const parseSchema_1 = require("../utils/parseSchema");
|
|
7
6
|
const getValidatedClient = async (connection) => {
|
|
@@ -63,13 +62,15 @@ const getDbdefault = (data_type, column_default, default_type) => {
|
|
|
63
62
|
const generateField = (row) => {
|
|
64
63
|
const { column_name, data_type, character_maximum_length, numeric_precision, numeric_scale, udt_schema, udt_name, identity_increment, is_nullable, column_default, default_type, column_comment, } = row;
|
|
65
64
|
const dbdefault = column_default && default_type !== 'increment' ? getDbdefault(data_type, column_default, default_type) : null;
|
|
66
|
-
const fieldType = data_type === 'USER-DEFINED'
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
65
|
+
const fieldType = data_type === 'USER-DEFINED'
|
|
66
|
+
? {
|
|
67
|
+
type_name: udt_name,
|
|
68
|
+
schemaName: udt_schema,
|
|
69
|
+
}
|
|
70
|
+
: {
|
|
71
|
+
type_name: getFieldType(data_type, udt_name, character_maximum_length, numeric_precision, numeric_scale),
|
|
72
|
+
schemaName: null,
|
|
73
|
+
};
|
|
73
74
|
return {
|
|
74
75
|
name: column_name,
|
|
75
76
|
type: fieldType,
|
|
@@ -319,19 +320,21 @@ const generateIndexesAndConstraints = async (client, schemas) => {
|
|
|
319
320
|
return acc;
|
|
320
321
|
}, { outOfLineIndexes: [], inlineIndexes: [] });
|
|
321
322
|
const indexes = outOfLineIndexes.reduce((acc, indexRow) => {
|
|
322
|
-
const { table_schema, table_name, index_name, index_type, index_columns, index_expressions, } = indexRow;
|
|
323
|
+
const { table_schema, table_name, index_name, index_type, index_columns, index_expressions, is_primary, is_unique, } = indexRow;
|
|
323
324
|
const indexColumns = index_columns.split(',').map((column) => {
|
|
324
325
|
return {
|
|
325
326
|
type: 'column',
|
|
326
327
|
value: column.trim(),
|
|
327
328
|
};
|
|
328
329
|
});
|
|
329
|
-
const indexExpressions = index_expressions
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
330
|
+
const indexExpressions = index_expressions
|
|
331
|
+
? index_expressions.split(',').map((expression) => {
|
|
332
|
+
return {
|
|
333
|
+
type: 'expression',
|
|
334
|
+
value: expression,
|
|
335
|
+
};
|
|
336
|
+
})
|
|
337
|
+
: [];
|
|
335
338
|
const index = {
|
|
336
339
|
name: index_name,
|
|
337
340
|
type: index_type,
|
|
@@ -339,6 +342,8 @@ const generateIndexesAndConstraints = async (client, schemas) => {
|
|
|
339
342
|
...indexColumns,
|
|
340
343
|
...indexExpressions,
|
|
341
344
|
],
|
|
345
|
+
pk: !!is_primary,
|
|
346
|
+
unique: !is_primary && !!is_unique,
|
|
342
347
|
};
|
|
343
348
|
const key = `${table_schema}.${table_name}`;
|
|
344
349
|
if (acc[key]) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import * as connector from
|
|
1
|
+
import * as connector from './connectors/connector';
|
|
2
2
|
export { connector, };
|
package/dist/index.js
CHANGED
|
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
25
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
36
|
exports.connector = void 0;
|
|
27
37
|
const connector = __importStar(require("./connectors/connector"));
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const parseSchema: (schemas: string | undefined) => string[];
|
|
1
2
|
export declare const parseJdbcSchema: (connectionString: string) => {
|
|
2
3
|
connectionString: string;
|
|
3
4
|
schemas: string[];
|
|
@@ -7,4 +8,3 @@ export declare const parseConnectionString: (connectionString: string, connectio
|
|
|
7
8
|
schemas: string[];
|
|
8
9
|
};
|
|
9
10
|
export declare const buildSchemaQuery: (columnName: string, schemas: string[], prefix?: string) => string;
|
|
10
|
-
export declare const parseSchema: (schemas: string | undefined) => string[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.buildSchemaQuery = exports.parseConnectionString = exports.parseJdbcSchema = exports.parseSchema = void 0;
|
|
4
4
|
// You cannot use the "=" inside database's schema name. It will be treated as a delimiter.
|
|
5
5
|
const SCHEMAS_DELIMITER = 'schemas=';
|
|
6
6
|
const haveSchemas = (str) => {
|
|
@@ -13,6 +13,18 @@ const noSchemaResult = (connectionString) => ({
|
|
|
13
13
|
connectionString,
|
|
14
14
|
schemas: [],
|
|
15
15
|
});
|
|
16
|
+
// Inputs: schemas string -> Output: schema array string[]
|
|
17
|
+
// schema1, schema2 -> ['schema1', 'schema2']
|
|
18
|
+
// schema3,schema4 -> ['schema3", 'schema4']
|
|
19
|
+
// "schema5,gg", "schema6", schema7 -> ['schema5,gg', 'schema6', 'schema7']
|
|
20
|
+
// schema8 -> ['schema8']
|
|
21
|
+
const parseSchema = (schemas) => {
|
|
22
|
+
if (!schemas)
|
|
23
|
+
return [];
|
|
24
|
+
const schemasWithDoubleQuotes = schemas.split(/,(?=(?:[^"]*(?:"[^"]*")*)*$)/).map((s) => s.trim());
|
|
25
|
+
return schemasWithDoubleQuotes.map((s) => s.replace(/"/g, ''));
|
|
26
|
+
};
|
|
27
|
+
exports.parseSchema = parseSchema;
|
|
16
28
|
const parseOdbcSchema = (connectionString) => {
|
|
17
29
|
const connectionParts = connectionString.split(';');
|
|
18
30
|
const schemasPart = connectionParts.find((part) => haveSchemas(part));
|
|
@@ -45,15 +57,3 @@ const buildSchemaQuery = (columnName, schemas, prefix = 'AND') => {
|
|
|
45
57
|
return `${prefix} ${columnName} IN (${schemas.map((schema) => `'${schema}'`).join(', ')})`;
|
|
46
58
|
};
|
|
47
59
|
exports.buildSchemaQuery = buildSchemaQuery;
|
|
48
|
-
// Inputs: schemas string -> Output: schema array string[]
|
|
49
|
-
// schema1, schema2 -> ['schema1', 'schema2']
|
|
50
|
-
// schema3,schema4 -> ['schema3", 'schema4']
|
|
51
|
-
// "schema5,gg", "schema6", schema7 -> ['schema5,gg', 'schema6', 'schema7']
|
|
52
|
-
// schema8 -> ['schema8']
|
|
53
|
-
const parseSchema = (schemas) => {
|
|
54
|
-
if (!schemas)
|
|
55
|
-
return [];
|
|
56
|
-
const schemasWithDoubleQuotes = schemas.split(/,(?=(?:[^"]*(?:"[^"]*")*)*$)/).map((s) => s.trim());
|
|
57
|
-
return schemasWithDoubleQuotes.map((s) => s.replace(/"/g, ''));
|
|
58
|
-
};
|
|
59
|
-
exports.parseSchema = parseSchema;
|
package/eslint.config.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import eslint from '@eslint/js';
|
|
2
|
+
import { defineConfig } from 'eslint/config';
|
|
3
|
+
import tseslint from 'typescript-eslint';
|
|
4
|
+
import tsparser from '@typescript-eslint/parser';
|
|
5
|
+
import stylistic from '@stylistic/eslint-plugin';
|
|
6
|
+
|
|
7
|
+
export default defineConfig(
|
|
8
|
+
eslint.configs.recommended,
|
|
9
|
+
tseslint.configs.recommended,
|
|
10
|
+
stylistic.configs.customize({
|
|
11
|
+
indent: 2,
|
|
12
|
+
semi: true,
|
|
13
|
+
arrowParens: true,
|
|
14
|
+
braceStyle: '1tbs',
|
|
15
|
+
}),
|
|
16
|
+
[
|
|
17
|
+
{
|
|
18
|
+
ignores: [
|
|
19
|
+
'node_modules/*',
|
|
20
|
+
'dist/*',
|
|
21
|
+
'eslint.config.ts',
|
|
22
|
+
'jestHelpers.ts',
|
|
23
|
+
'jest.config.ts',
|
|
24
|
+
'**/*.test.ts',
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
files: ['**/*.ts'],
|
|
29
|
+
languageOptions: {
|
|
30
|
+
parser: tsparser,
|
|
31
|
+
parserOptions: {
|
|
32
|
+
sourceType: 'module',
|
|
33
|
+
ecmaVersion: 2020,
|
|
34
|
+
project: './tsconfig.json',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
plugins: {
|
|
38
|
+
'@stylistic': stylistic,
|
|
39
|
+
},
|
|
40
|
+
rules: {
|
|
41
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
42
|
+
'no-use-before-define': 'off',
|
|
43
|
+
'no-continue': 'off',
|
|
44
|
+
'no-useless-escape': 'warn',
|
|
45
|
+
'@stylistic/space-before-function-paren': ['error', 'always'],
|
|
46
|
+
'@typescript-eslint/no-unused-vars': [
|
|
47
|
+
'warn',
|
|
48
|
+
{
|
|
49
|
+
argsIgnorePattern: '^_',
|
|
50
|
+
varsIgnorePattern: '^_',
|
|
51
|
+
caughtErrorsIgnorePattern: '^_',
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
'consistent-return': 'off',
|
|
55
|
+
'@typescript-eslint/consistent-return': ['error'],
|
|
56
|
+
'@stylistic/quotes': ['error', 'single', { 'avoidEscape': true }],
|
|
57
|
+
'@stylistic/max-statements-per-line': 'off',
|
|
58
|
+
'@stylistic/operator-linebreak': ['error', 'before', { overrides: { '=': 'after' } }],
|
|
59
|
+
},
|
|
60
|
+
settings: {
|
|
61
|
+
'import/resolver': {
|
|
62
|
+
typescript: {
|
|
63
|
+
alwaysTryTypes: true,
|
|
64
|
+
project: 'packages/*/{ts,js}config.json',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
);
|
package/jest.config.ts
CHANGED
|
@@ -2,9 +2,9 @@ module.exports = {
|
|
|
2
2
|
preset: 'ts-jest',
|
|
3
3
|
testEnvironment: 'node',
|
|
4
4
|
transform: {
|
|
5
|
-
|
|
5
|
+
'^.+\\.[tj]sx?$': 'babel-jest',
|
|
6
6
|
},
|
|
7
7
|
moduleNameMapper: {
|
|
8
|
-
|
|
8
|
+
'\\.(css|less|scss)$': 'identity-obj-proxy',
|
|
9
9
|
},
|
|
10
10
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/package",
|
|
2
3
|
"name": "@dbml/connector",
|
|
3
|
-
"version": "5.
|
|
4
|
+
"version": "5.2.0",
|
|
4
5
|
"description": "This package was created to fetch the schema JSON from many kind of databases.",
|
|
5
6
|
"author": "huy.phung.sw@gmail.com",
|
|
6
7
|
"license": "MIT",
|
|
@@ -15,26 +16,34 @@
|
|
|
15
16
|
"@babel/preset-env": "^7.21.4",
|
|
16
17
|
"@babel/preset-typescript": "^7.24.7",
|
|
17
18
|
"@babel/runtime": "^7.21.0",
|
|
19
|
+
"@stylistic/eslint-plugin": "^5.5.0",
|
|
18
20
|
"@types/jest": "^29.5.12",
|
|
19
21
|
"@types/lodash": "^4.17.16",
|
|
20
22
|
"@types/mssql": "^9.1.5",
|
|
21
23
|
"@types/node": "^22.2.0",
|
|
22
24
|
"@types/pg": "^8.11.6",
|
|
25
|
+
"@typescript-eslint/eslint-plugin": "^8.46.3",
|
|
26
|
+
"@typescript-eslint/parser": "^8.46.3",
|
|
23
27
|
"babel-jest": "^29.5.0",
|
|
28
|
+
"eslint": "^9.39.1",
|
|
24
29
|
"jest": "^29.7.0",
|
|
25
30
|
"ts-jest": "^29.2.4",
|
|
26
31
|
"ts-node": "^10.9.2",
|
|
27
|
-
"typescript": "^5.
|
|
32
|
+
"typescript": "^5.9.3",
|
|
33
|
+
"typescript-eslint": "^8.46.3"
|
|
28
34
|
},
|
|
29
35
|
"scripts": {
|
|
30
36
|
"build": "tsc",
|
|
31
37
|
"start": "node dist/index.js",
|
|
32
|
-
"test": "jest"
|
|
38
|
+
"test": "jest",
|
|
39
|
+
"lint": "eslint .",
|
|
40
|
+
"lint:fix": "eslint --fix ."
|
|
33
41
|
},
|
|
34
42
|
"dependencies": {
|
|
35
43
|
"@google-cloud/bigquery": "^7.9.0",
|
|
36
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
37
|
-
"@typescript-eslint/parser": "^8.
|
|
44
|
+
"@typescript-eslint/eslint-plugin": "^8.46.3",
|
|
45
|
+
"@typescript-eslint/parser": "^8.46.3",
|
|
46
|
+
"eslint": "^9.39.1",
|
|
38
47
|
"lodash": "^4.17.21",
|
|
39
48
|
"mssql": "^11.0.1",
|
|
40
49
|
"mysql2": "^3.11.0",
|
|
@@ -44,5 +53,5 @@
|
|
|
44
53
|
"engines": {
|
|
45
54
|
"node": ">=18"
|
|
46
55
|
},
|
|
47
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "20d556a6e6baad8a989c730e2afd3b65dedcea89"
|
|
48
57
|
}
|
|
@@ -72,8 +72,7 @@ function getDbDefault (
|
|
|
72
72
|
|
|
73
73
|
if (defaultValueType === 'string') {
|
|
74
74
|
// bigquery store the double qoutes and quotes at the end and the beginning of the string: "string" or 'string'
|
|
75
|
-
|
|
76
|
-
return { value: columnDefault.slice(1, -1).replaceAll("'", "\'"), type: defaultValueType };
|
|
75
|
+
return { value: columnDefault.slice(1, -1).replaceAll('\'', '\''), type: defaultValueType };
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
return { value: columnDefault, type: defaultValueType };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable camelcase */
|
|
2
1
|
/* TDD 72
|
|
3
2
|
* - In MSSQL, there's no notion of ENUM.
|
|
4
3
|
* - MSSQL connector used to extract ENUMS from CHECK constraints, for example: `CHECK ([col]=value1 OR [col]=value2)` would be translated to an enum with 2 values, `value1` and `value2`.
|
|
@@ -147,8 +146,8 @@ const generateField = (row: Record<string, any>): Field => {
|
|
|
147
146
|
};
|
|
148
147
|
|
|
149
148
|
const generateTablesFields = async (client: sql.ConnectionPool, schemas: string[]): Promise<{
|
|
150
|
-
tables: Table[]
|
|
151
|
-
fields: FieldsDictionary
|
|
149
|
+
tables: Table[];
|
|
150
|
+
fields: FieldsDictionary;
|
|
152
151
|
}> => {
|
|
153
152
|
const fields: FieldsDictionary = {};
|
|
154
153
|
const tablesAndFieldsSql = `
|
|
@@ -293,9 +292,9 @@ const generateRefs = async (client: sql.ConnectionPool, schemas: string[]): Prom
|
|
|
293
292
|
if (ep1.length !== ep2.length) return false;
|
|
294
293
|
return ep1.every(
|
|
295
294
|
(endpoint, index) => endpoint.tableName === ep2[index].tableName
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
295
|
+
&& endpoint.schemaName === ep2[index].schemaName
|
|
296
|
+
&& endpoint.fieldNames.length === ep2[index].fieldNames.length
|
|
297
|
+
&& endpoint.fieldNames.every((field, fieldIndex) => field === ep2[index].fieldNames[fieldIndex]),
|
|
299
298
|
);
|
|
300
299
|
};
|
|
301
300
|
|
|
@@ -333,7 +332,7 @@ const generateRefs = async (client: sql.ConnectionPool, schemas: string[]): Prom
|
|
|
333
332
|
onUpdate: on_update === 'NO_ACTION' ? null : on_update,
|
|
334
333
|
};
|
|
335
334
|
|
|
336
|
-
const isDuplicate = refs.some(ref => endpointsEqual(ref.endpoints, newRef.endpoints));
|
|
335
|
+
const isDuplicate = refs.some((ref) => endpointsEqual(ref.endpoints, newRef.endpoints));
|
|
337
336
|
|
|
338
337
|
if (!isDuplicate) {
|
|
339
338
|
refs.push(newRef);
|
|
@@ -439,6 +438,8 @@ const generateIndexesAndConstraints = async (client: sql.ConnectionPool, schemas
|
|
|
439
438
|
index_type,
|
|
440
439
|
columns,
|
|
441
440
|
expressions,
|
|
441
|
+
is_unique,
|
|
442
|
+
is_primary,
|
|
442
443
|
} = indexRow;
|
|
443
444
|
const indexColumns = columns.split(',').map((column: string) => {
|
|
444
445
|
return {
|
|
@@ -447,12 +448,14 @@ const generateIndexesAndConstraints = async (client: sql.ConnectionPool, schemas
|
|
|
447
448
|
};
|
|
448
449
|
});
|
|
449
450
|
|
|
450
|
-
const indexExpressions = expressions
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
451
|
+
const indexExpressions = expressions
|
|
452
|
+
? expressions.split(',').map((expression: string) => {
|
|
453
|
+
return {
|
|
454
|
+
type: 'expression',
|
|
455
|
+
value: expression,
|
|
456
|
+
};
|
|
457
|
+
})
|
|
458
|
+
: [];
|
|
456
459
|
|
|
457
460
|
const index = {
|
|
458
461
|
name: index_name,
|
|
@@ -461,6 +464,8 @@ const generateIndexesAndConstraints = async (client: sql.ConnectionPool, schemas
|
|
|
461
464
|
...indexColumns,
|
|
462
465
|
...indexExpressions,
|
|
463
466
|
],
|
|
467
|
+
pk: !!is_primary,
|
|
468
|
+
unique: !is_primary && !!is_unique,
|
|
464
469
|
};
|
|
465
470
|
|
|
466
471
|
const key = `${table_schema}.${table_name}`;
|
|
@@ -342,7 +342,7 @@ async function generatePrimaryAndUniqueConstraint (client: Connection, schemaNam
|
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
if (constraintType === 'PRIMARY KEY') {
|
|
345
|
-
acc[key][constraintName].
|
|
345
|
+
acc[key][constraintName].pk = true;
|
|
346
346
|
}
|
|
347
347
|
|
|
348
348
|
if (constraintType === 'UNIQUE') {
|
|
@@ -395,7 +395,7 @@ function extractColumnsFromCheckConstraint (checkClause: string): string[] {
|
|
|
395
395
|
return [...checkClause.matchAll(/`(?:``|[^`])*`/g)].map((col) => col.toString().slice(1, -1));
|
|
396
396
|
}
|
|
397
397
|
|
|
398
|
-
async function generateCheckConstraints (client: Connection, schemaName: string): Promise<{ checks: CheckConstraintDictionary
|
|
398
|
+
async function generateCheckConstraints (client: Connection, schemaName: string): Promise<{ checks: CheckConstraintDictionary; tableConstraints: TableConstraintsDictionary }> {
|
|
399
399
|
const query = `
|
|
400
400
|
select
|
|
401
401
|
cc.constraint_name as constraintName,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable camelcase */
|
|
2
1
|
import { Client } from 'pg';
|
|
3
2
|
import { buildSchemaQuery, parseConnectionString } from '../utils/parseSchema';
|
|
4
3
|
import {
|
|
@@ -97,13 +96,15 @@ const generateField = (row: Record<string, any>): Field => {
|
|
|
97
96
|
|
|
98
97
|
const dbdefault = column_default && default_type !== 'increment' ? getDbdefault(data_type, column_default, default_type) : null;
|
|
99
98
|
|
|
100
|
-
const fieldType = data_type === 'USER-DEFINED'
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
const fieldType = data_type === 'USER-DEFINED'
|
|
100
|
+
? {
|
|
101
|
+
type_name: udt_name,
|
|
102
|
+
schemaName: udt_schema,
|
|
103
|
+
}
|
|
104
|
+
: {
|
|
105
|
+
type_name: getFieldType(data_type, udt_name, character_maximum_length, numeric_precision, numeric_scale),
|
|
106
|
+
schemaName: null,
|
|
107
|
+
};
|
|
107
108
|
|
|
108
109
|
return {
|
|
109
110
|
name: column_name,
|
|
@@ -116,8 +117,8 @@ const generateField = (row: Record<string, any>): Field => {
|
|
|
116
117
|
};
|
|
117
118
|
|
|
118
119
|
const generateTablesAndFields = async (client: Client, schemas: string[]): Promise<{
|
|
119
|
-
tables: Table[]
|
|
120
|
-
fields: FieldsDictionary
|
|
120
|
+
tables: Table[];
|
|
121
|
+
fields: FieldsDictionary;
|
|
121
122
|
}> => {
|
|
122
123
|
const fields: FieldsDictionary = {};
|
|
123
124
|
const tablesAndFieldsSql = `
|
|
@@ -388,6 +389,8 @@ const generateIndexesAndConstraints = async (client: Client, schemas: string[])
|
|
|
388
389
|
index_type,
|
|
389
390
|
index_columns,
|
|
390
391
|
index_expressions,
|
|
392
|
+
is_primary,
|
|
393
|
+
is_unique,
|
|
391
394
|
} = indexRow;
|
|
392
395
|
const indexColumns = index_columns.split(',').map((column: string) => {
|
|
393
396
|
return {
|
|
@@ -396,12 +399,14 @@ const generateIndexesAndConstraints = async (client: Client, schemas: string[])
|
|
|
396
399
|
};
|
|
397
400
|
});
|
|
398
401
|
|
|
399
|
-
const indexExpressions = index_expressions
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
402
|
+
const indexExpressions = index_expressions
|
|
403
|
+
? index_expressions.split(',').map((expression: string) => {
|
|
404
|
+
return {
|
|
405
|
+
type: 'expression',
|
|
406
|
+
value: expression,
|
|
407
|
+
};
|
|
408
|
+
})
|
|
409
|
+
: [];
|
|
405
410
|
|
|
406
411
|
const index = {
|
|
407
412
|
name: index_name,
|
|
@@ -410,6 +415,8 @@ const generateIndexesAndConstraints = async (client: Client, schemas: string[])
|
|
|
410
415
|
...indexColumns,
|
|
411
416
|
...indexExpressions,
|
|
412
417
|
],
|
|
418
|
+
pk: !!is_primary,
|
|
419
|
+
unique: !is_primary && !!is_unique,
|
|
413
420
|
};
|
|
414
421
|
|
|
415
422
|
const key = `${table_schema}.${table_name}`;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable camelcase */
|
|
2
1
|
//
|
|
3
2
|
// Description:
|
|
4
3
|
// Snowflake info schema lacks reference direction for relationships.
|
|
@@ -196,8 +195,8 @@ const generateField = (row: Record<string, any>): Field => {
|
|
|
196
195
|
};
|
|
197
196
|
|
|
198
197
|
const generateTablesAndFields = async (conn: Connection, schemas: string[]): Promise<{
|
|
199
|
-
tables: Table[]
|
|
200
|
-
fields: FieldsDictionary
|
|
198
|
+
tables: Table[];
|
|
199
|
+
fields: FieldsDictionary;
|
|
201
200
|
}> => {
|
|
202
201
|
const fields: FieldsDictionary = {};
|
|
203
202
|
const schemaSql = schemas.length > 0 ? `AND c.table_schema IN (${schemas.map((schema) => `'${schema}'`).join(',')})` : '';
|
|
@@ -269,7 +268,9 @@ const createConstraintKeysMap = (keys: Record<string, string>[], schemas: string
|
|
|
269
268
|
schema_name, table_name, column_name, constraint_name,
|
|
270
269
|
} = row;
|
|
271
270
|
const selectedSchema = schemas.length > 0 ? schemas.includes(schema_name) : true;
|
|
272
|
-
if (!selectedSchema) {
|
|
271
|
+
if (!selectedSchema) {
|
|
272
|
+
return acc;
|
|
273
|
+
}
|
|
273
274
|
|
|
274
275
|
const key = `${schema_name}.${table_name}.${constraint_name}`;
|
|
275
276
|
|
package/src/connectors/types.ts
CHANGED
|
@@ -10,7 +10,7 @@ interface TypeInfo {
|
|
|
10
10
|
type DefaultType = 'string' | 'number' | 'boolean' | 'expression';
|
|
11
11
|
|
|
12
12
|
interface DefaultInfo {
|
|
13
|
-
type: DefaultType
|
|
13
|
+
type: DefaultType;
|
|
14
14
|
value: string;
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -45,12 +45,12 @@ interface CheckConstraintDictionary {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
interface TableConstraint {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
[fieldName: string]: {
|
|
49
|
+
pk?: boolean;
|
|
50
|
+
unique?: boolean;
|
|
51
|
+
checks: CheckConstraint[];
|
|
52
52
|
};
|
|
53
|
-
|
|
53
|
+
}
|
|
54
54
|
|
|
55
55
|
interface TableConstraintsDictionary {
|
|
56
56
|
[tableIdentifier: string]: TableConstraint; // Represents constraints within tables, indexed by schemaName.tableName
|
|
@@ -88,8 +88,8 @@ interface IndexColumn {
|
|
|
88
88
|
interface Index {
|
|
89
89
|
name: string;
|
|
90
90
|
type: string;
|
|
91
|
-
unique?: boolean
|
|
92
|
-
pk?: boolean
|
|
91
|
+
unique?: boolean;
|
|
92
|
+
pk?: boolean;
|
|
93
93
|
columns: IndexColumn[];
|
|
94
94
|
}
|
|
95
95
|
|
|
@@ -108,12 +108,12 @@ interface DatabaseSchema {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
interface BigQueryCredentials {
|
|
111
|
-
projectId?: string
|
|
111
|
+
projectId?: string;
|
|
112
112
|
credentials?: {
|
|
113
|
-
clientEmail: string
|
|
114
|
-
privateKey: string
|
|
115
|
-
}
|
|
116
|
-
datasets: string[]
|
|
113
|
+
clientEmail: string;
|
|
114
|
+
privateKey: string;
|
|
115
|
+
};
|
|
116
|
+
datasets: string[];
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
export {
|
package/src/index.ts
CHANGED