@dbml/connector 5.5.1 → 5.6.0-alpha.1
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/dist/index.js +3739 -38
- package/dist/index.mjs +10359 -0
- package/eslint.config.ts +2 -1
- package/package.json +8 -25
- package/src/connectors/mysql/index.ts +1 -1
- package/vite.config.ts +53 -0
- package/.babelrc +0 -13
- package/dist/connectors/bigquery/index.js +0 -291
- package/dist/connectors/connector.js +0 -28
- package/dist/connectors/mssql/index.js +0 -486
- package/dist/connectors/mysql/index.js +0 -454
- package/dist/connectors/oracle/constraints.js +0 -112
- package/dist/connectors/oracle/index.js +0 -68
- package/dist/connectors/oracle/indexes.js +0 -65
- package/dist/connectors/oracle/refs.js +0 -67
- package/dist/connectors/oracle/tables.js +0 -280
- package/dist/connectors/oracle/utils.js +0 -27
- package/dist/connectors/postgres/index.js +0 -517
- package/dist/connectors/snowflake/index.js +0 -311
- package/dist/connectors/types.js +0 -2
- package/dist/utils/credential-loader.js +0 -58
- package/dist/utils/helpers.js +0 -61
- package/dist/utils/parseSchema.js +0 -59
- package/jest.config.ts +0 -18
|
@@ -1,486 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.fetchSchemaJson = void 0;
|
|
7
|
-
/* TDD 72
|
|
8
|
-
* - In MSSQL, there's no notion of ENUM.
|
|
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`.
|
|
10
|
-
* - Since DBML 4.0.0, we have supported CHECK constraints, so we no longer extract ENUMS out from CHECK constraints but rather keep them as CHECK constraints.
|
|
11
|
-
* */
|
|
12
|
-
const mssql_1 = __importDefault(require("mssql"));
|
|
13
|
-
const parseSchema_1 = require("../../utils/parseSchema");
|
|
14
|
-
// https://learn.microsoft.com/en-us/sql/t-sql/data-types/date-and-time-types?view=sql-server-ver15
|
|
15
|
-
const MSSQL_DATE_TYPES = [
|
|
16
|
-
'date',
|
|
17
|
-
'datetime',
|
|
18
|
-
'datetime2',
|
|
19
|
-
'smalldatetime',
|
|
20
|
-
'datetimeoffset',
|
|
21
|
-
'time',
|
|
22
|
-
];
|
|
23
|
-
const getValidatedClient = async (connection) => {
|
|
24
|
-
const pool = await mssql_1.default.connect(connection);
|
|
25
|
-
try {
|
|
26
|
-
// Establish a connection pool
|
|
27
|
-
// Validate if the connection is successful by making a simple query
|
|
28
|
-
await pool.request().query('SELECT 1');
|
|
29
|
-
// If successful, return the pool
|
|
30
|
-
return pool;
|
|
31
|
-
}
|
|
32
|
-
catch (err) {
|
|
33
|
-
// Ensure to close any open pool in case of failure
|
|
34
|
-
if (pool.connected) {
|
|
35
|
-
await pool.close();
|
|
36
|
-
}
|
|
37
|
-
if (err instanceof Error) {
|
|
38
|
-
throw new Error(`SQL connection error: ${err.message}`);
|
|
39
|
-
}
|
|
40
|
-
throw err; // Rethrow error if you want the calling code to handle it
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
const convertQueryBoolean = (val) => val === 'YES';
|
|
44
|
-
const getFieldType = (data_type, character_maximum_length, numeric_precision, numeric_scale) => {
|
|
45
|
-
if (MSSQL_DATE_TYPES.includes(data_type)) {
|
|
46
|
-
return data_type;
|
|
47
|
-
}
|
|
48
|
-
// timestamp is a synonym of rowversion and we cannot specify the precision for it
|
|
49
|
-
// https://learn.microsoft.com/en-us/sql/t-sql/data-types/rowversion-transact-sql?view=sql-server-ver15
|
|
50
|
-
if (data_type === 'timestamp') {
|
|
51
|
-
return data_type;
|
|
52
|
-
}
|
|
53
|
-
// process numeric-based type
|
|
54
|
-
if (data_type === 'bit') {
|
|
55
|
-
return data_type;
|
|
56
|
-
}
|
|
57
|
-
// if precision != 0 => numeric-based column
|
|
58
|
-
if (numeric_precision) {
|
|
59
|
-
return numeric_scale
|
|
60
|
-
? `${data_type}(${numeric_precision},${numeric_scale})`
|
|
61
|
-
: `${data_type}(${numeric_precision})`;
|
|
62
|
-
}
|
|
63
|
-
// process string-based type
|
|
64
|
-
// ntext, text & image
|
|
65
|
-
if (['ntext', 'text', 'image'].includes(data_type)) {
|
|
66
|
-
return data_type;
|
|
67
|
-
}
|
|
68
|
-
// Column data type is varchar(max), nvarchar(max), varbinary(max), or xml
|
|
69
|
-
if (character_maximum_length < 0) {
|
|
70
|
-
return data_type === 'xml' ? data_type : `${data_type}(MAX)`;
|
|
71
|
-
}
|
|
72
|
-
// character_maximum_length is the lenght in bytes
|
|
73
|
-
// nchar and nvarchar store Unicode characters, each character needs 2 bytes
|
|
74
|
-
// so we have to divide it by 2 to get the correct maximum lenght in character.
|
|
75
|
-
// ref: https://learn.microsoft.com/en-us/sql/t-sql/data-types/nchar-and-nvarchar-transact-sql?view=sql-server-ver15
|
|
76
|
-
if (character_maximum_length > 0) {
|
|
77
|
-
const maximum_length_in_character = (data_type === 'nchar' || data_type === 'nvarchar')
|
|
78
|
-
? character_maximum_length / 2
|
|
79
|
-
: character_maximum_length;
|
|
80
|
-
return `${data_type}(${maximum_length_in_character})`;
|
|
81
|
-
}
|
|
82
|
-
return data_type;
|
|
83
|
-
};
|
|
84
|
-
const getDbdefault = (data_type, column_default, default_type) => {
|
|
85
|
-
// The regex below is used to extract the value from the default value
|
|
86
|
-
// \( and \) are used to escape parentheses
|
|
87
|
-
// [^()]+ is used to match any character except parentheses
|
|
88
|
-
// Example: (1) => 1, ('hello') => hello, getdate()-(1) => getdate()-1
|
|
89
|
-
const value = column_default.slice(1, -1).replace(/\(([^()]+)\)/g, '$1');
|
|
90
|
-
return {
|
|
91
|
-
type: default_type,
|
|
92
|
-
value: default_type === 'string' ? value.slice(1, -1) : value, // Remove the quotes for string values
|
|
93
|
-
};
|
|
94
|
-
};
|
|
95
|
-
const generateField = (row) => {
|
|
96
|
-
const { column_name, data_type, character_maximum_length, numeric_precision, numeric_scale, identity_increment, is_nullable, column_default, default_type, column_comment, } = row;
|
|
97
|
-
const dbdefault = column_default && default_type !== 'increment' ? getDbdefault(data_type, column_default, default_type) : null;
|
|
98
|
-
const fieldType = {
|
|
99
|
-
type_name: getFieldType(data_type, character_maximum_length, numeric_precision, numeric_scale),
|
|
100
|
-
schemaName: null,
|
|
101
|
-
};
|
|
102
|
-
return {
|
|
103
|
-
name: column_name,
|
|
104
|
-
type: fieldType,
|
|
105
|
-
dbdefault,
|
|
106
|
-
not_null: !convertQueryBoolean(is_nullable),
|
|
107
|
-
increment: !!identity_increment,
|
|
108
|
-
note: column_comment ? { value: column_comment } : { value: '' },
|
|
109
|
-
};
|
|
110
|
-
};
|
|
111
|
-
const generateTablesFields = async (client, schemas) => {
|
|
112
|
-
const fields = {};
|
|
113
|
-
const tablesAndFieldsSql = `
|
|
114
|
-
WITH tables_and_fields AS (
|
|
115
|
-
SELECT
|
|
116
|
-
t.object_id AS table_id,
|
|
117
|
-
s.name AS table_schema,
|
|
118
|
-
t.name AS table_name,
|
|
119
|
-
t.create_date as table_create_date,
|
|
120
|
-
c.name AS column_name,
|
|
121
|
-
c.column_id as column_id,
|
|
122
|
-
ty.name AS data_type,
|
|
123
|
-
c.max_length AS character_maximum_length,
|
|
124
|
-
c.precision AS numeric_precision,
|
|
125
|
-
c.scale AS numeric_scale,
|
|
126
|
-
c.is_identity AS identity_increment,
|
|
127
|
-
CASE
|
|
128
|
-
WHEN c.is_nullable = 1 THEN 'YES'
|
|
129
|
-
ELSE 'NO'
|
|
130
|
-
END AS is_nullable,
|
|
131
|
-
CASE
|
|
132
|
-
WHEN c.default_object_id = 0 THEN NULL
|
|
133
|
-
ELSE OBJECT_DEFINITION(c.default_object_id)
|
|
134
|
-
END AS column_default,
|
|
135
|
-
-- Fetching table comments
|
|
136
|
-
p.value AS table_comment,
|
|
137
|
-
ep.value AS column_comment
|
|
138
|
-
FROM
|
|
139
|
-
sys.tables t
|
|
140
|
-
JOIN sys.schemas s ON t.schema_id = s.schema_id
|
|
141
|
-
JOIN sys.columns c ON t.object_id = c.object_id
|
|
142
|
-
JOIN sys.types ty ON c.user_type_id = ty.user_type_id
|
|
143
|
-
LEFT JOIN sys.extended_properties p ON p.major_id = t.object_id
|
|
144
|
-
AND p.name like '%description%'
|
|
145
|
-
AND p.minor_id = 0 -- Ensure minor_id is 0 for table comments
|
|
146
|
-
LEFT JOIN sys.extended_properties ep ON ep.major_id = c.object_id
|
|
147
|
-
AND ep.minor_id = c.column_id
|
|
148
|
-
AND ep.name like '%description%'
|
|
149
|
-
WHERE
|
|
150
|
-
t.type = 'U' -- User-defined tables
|
|
151
|
-
)
|
|
152
|
-
SELECT
|
|
153
|
-
table_schema,
|
|
154
|
-
table_name,
|
|
155
|
-
column_name,
|
|
156
|
-
data_type,
|
|
157
|
-
character_maximum_length,
|
|
158
|
-
numeric_precision,
|
|
159
|
-
numeric_scale,
|
|
160
|
-
identity_increment,
|
|
161
|
-
is_nullable,
|
|
162
|
-
column_default,
|
|
163
|
-
table_comment,
|
|
164
|
-
column_comment,
|
|
165
|
-
CASE
|
|
166
|
-
WHEN column_default LIKE '((%))' THEN 'number'
|
|
167
|
-
WHEN column_default LIKE '(''%'')' THEN 'string'
|
|
168
|
-
ELSE 'expression'
|
|
169
|
-
END AS default_type
|
|
170
|
-
FROM
|
|
171
|
-
tables_and_fields
|
|
172
|
-
WHERE
|
|
173
|
-
1 = 1
|
|
174
|
-
${(0, parseSchema_1.buildSchemaQuery)('table_schema', schemas)}
|
|
175
|
-
ORDER BY
|
|
176
|
-
table_schema,
|
|
177
|
-
table_create_date,
|
|
178
|
-
table_id,
|
|
179
|
-
column_id;
|
|
180
|
-
`;
|
|
181
|
-
const tablesAndFieldsResult = await client.query(tablesAndFieldsSql);
|
|
182
|
-
const tables = tablesAndFieldsResult.recordset.reduce((acc, row) => {
|
|
183
|
-
const { table_schema, table_name, table_comment, } = row;
|
|
184
|
-
const key = `${table_schema}.${table_name}`;
|
|
185
|
-
if (!acc[key]) {
|
|
186
|
-
acc[key] = {
|
|
187
|
-
name: table_name,
|
|
188
|
-
schemaName: table_schema,
|
|
189
|
-
note: table_comment ? { value: table_comment } : { value: '' },
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
if (!fields[key])
|
|
193
|
-
fields[key] = [];
|
|
194
|
-
const field = generateField(row);
|
|
195
|
-
fields[key].push(field);
|
|
196
|
-
return acc;
|
|
197
|
-
}, {});
|
|
198
|
-
return {
|
|
199
|
-
tables: Object.values(tables),
|
|
200
|
-
fields,
|
|
201
|
-
};
|
|
202
|
-
};
|
|
203
|
-
const generateRefs = async (client, schemas) => {
|
|
204
|
-
const refs = [];
|
|
205
|
-
const refsListSql = `
|
|
206
|
-
SELECT
|
|
207
|
-
s.name AS table_schema,
|
|
208
|
-
t.name AS table_name,
|
|
209
|
-
fk.name AS fk_constraint_name,
|
|
210
|
-
STUFF((
|
|
211
|
-
SELECT ',' + c1.name
|
|
212
|
-
FROM sys.foreign_key_columns AS fkc
|
|
213
|
-
JOIN sys.columns AS c1 ON fkc.parent_object_id = c1.object_id AND fkc.parent_column_id = c1.column_id
|
|
214
|
-
WHERE fkc.constraint_object_id = fk.object_id
|
|
215
|
-
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS column_names,
|
|
216
|
-
s2.name AS foreign_table_schema,
|
|
217
|
-
t2.name AS foreign_table_name,
|
|
218
|
-
STUFF((
|
|
219
|
-
SELECT ',' + c2.name
|
|
220
|
-
FROM sys.foreign_key_columns AS fkc
|
|
221
|
-
JOIN sys.columns AS c2 ON fkc.referenced_object_id = c2.object_id AND fkc.referenced_column_id = c2.column_id
|
|
222
|
-
WHERE fkc.constraint_object_id = fk.object_id
|
|
223
|
-
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS foreign_column_names,
|
|
224
|
-
fk.type_desc AS constraint_type,
|
|
225
|
-
fk.delete_referential_action_desc AS on_delete,
|
|
226
|
-
fk.update_referential_action_desc AS on_update
|
|
227
|
-
FROM sys.foreign_keys AS fk
|
|
228
|
-
JOIN sys.tables AS t ON fk.parent_object_id = t.object_id
|
|
229
|
-
JOIN sys.schemas AS s ON t.schema_id = s.schema_id
|
|
230
|
-
JOIN sys.tables AS t2 ON fk.referenced_object_id = t2.object_id
|
|
231
|
-
JOIN sys.schemas AS s2 ON t2.schema_id = s2.schema_id
|
|
232
|
-
WHERE s.name NOT IN ('sys', 'information_schema')
|
|
233
|
-
${(0, parseSchema_1.buildSchemaQuery)('s.name', schemas)}
|
|
234
|
-
ORDER BY
|
|
235
|
-
s.name,
|
|
236
|
-
t.name;
|
|
237
|
-
`;
|
|
238
|
-
const refsQueryResult = await client.query(refsListSql);
|
|
239
|
-
const endpointsEqual = (ep1, ep2) => {
|
|
240
|
-
if (ep1.length !== ep2.length)
|
|
241
|
-
return false;
|
|
242
|
-
return ep1.every((endpoint, index) => endpoint.tableName === ep2[index].tableName
|
|
243
|
-
&& endpoint.schemaName === ep2[index].schemaName
|
|
244
|
-
&& endpoint.fieldNames.length === ep2[index].fieldNames.length
|
|
245
|
-
&& endpoint.fieldNames.every((field, fieldIndex) => field === ep2[index].fieldNames[fieldIndex]));
|
|
246
|
-
};
|
|
247
|
-
refsQueryResult.recordset.forEach((refRow) => {
|
|
248
|
-
const { table_schema, fk_constraint_name, table_name, column_names, foreign_table_schema, foreign_table_name, foreign_column_names, on_delete, on_update, } = refRow;
|
|
249
|
-
const ep1 = {
|
|
250
|
-
tableName: table_name,
|
|
251
|
-
schemaName: table_schema,
|
|
252
|
-
fieldNames: column_names.split(','),
|
|
253
|
-
relation: '*',
|
|
254
|
-
};
|
|
255
|
-
const ep2 = {
|
|
256
|
-
tableName: foreign_table_name,
|
|
257
|
-
schemaName: foreign_table_schema,
|
|
258
|
-
fieldNames: foreign_column_names.split(','),
|
|
259
|
-
relation: '1',
|
|
260
|
-
};
|
|
261
|
-
const newRef = {
|
|
262
|
-
name: fk_constraint_name,
|
|
263
|
-
endpoints: [ep1, ep2],
|
|
264
|
-
onDelete: on_delete === 'NO_ACTION' ? null : on_delete,
|
|
265
|
-
onUpdate: on_update === 'NO_ACTION' ? null : on_update,
|
|
266
|
-
};
|
|
267
|
-
const isDuplicate = refs.some((ref) => endpointsEqual(ref.endpoints, newRef.endpoints));
|
|
268
|
-
if (!isDuplicate) {
|
|
269
|
-
refs.push(newRef);
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
return refs;
|
|
273
|
-
};
|
|
274
|
-
const generateIndexesAndConstraints = async (client, schemas) => {
|
|
275
|
-
const indexListSql = `
|
|
276
|
-
WITH user_tables AS (
|
|
277
|
-
SELECT
|
|
278
|
-
TABLE_SCHEMA,
|
|
279
|
-
TABLE_NAME
|
|
280
|
-
FROM
|
|
281
|
-
INFORMATION_SCHEMA.TABLES
|
|
282
|
-
WHERE
|
|
283
|
-
TABLE_TYPE = 'BASE TABLE' -- Ensure we are only getting base tables
|
|
284
|
-
AND TABLE_NAME NOT LIKE 'dt%'
|
|
285
|
-
AND TABLE_NAME NOT LIKE 'syscs%'
|
|
286
|
-
AND TABLE_NAME NOT LIKE 'sysss%'
|
|
287
|
-
AND TABLE_NAME NOT LIKE 'sysrs%'
|
|
288
|
-
AND TABLE_NAME NOT LIKE 'sysxlgc%'
|
|
289
|
-
),
|
|
290
|
-
index_info AS (
|
|
291
|
-
SELECT
|
|
292
|
-
SCHEMA_NAME(t.schema_id) AS table_schema, -- Add schema information
|
|
293
|
-
OBJECT_NAME(i.object_id) AS table_name,
|
|
294
|
-
i.name AS index_name,
|
|
295
|
-
i.is_unique,
|
|
296
|
-
CASE
|
|
297
|
-
WHEN i.type = 1 THEN 1
|
|
298
|
-
ELSE 0
|
|
299
|
-
END AS is_primary,
|
|
300
|
-
i.type_desc AS index_type,
|
|
301
|
-
STUFF((
|
|
302
|
-
SELECT
|
|
303
|
-
', ' + c.name
|
|
304
|
-
FROM
|
|
305
|
-
sys.index_columns ic
|
|
306
|
-
JOIN sys.columns c ON ic.column_id = c.column_id AND ic.object_id = c.object_id
|
|
307
|
-
WHERE
|
|
308
|
-
ic.index_id = i.index_id
|
|
309
|
-
AND ic.object_id = i.object_id
|
|
310
|
-
AND OBJECT_NAME(ic.object_id) IN (SELECT TABLE_NAME FROM user_tables) -- Filter for user tables
|
|
311
|
-
ORDER BY
|
|
312
|
-
ic.key_ordinal
|
|
313
|
-
FOR XML PATH('')
|
|
314
|
-
), 1, 2, '') AS columns,
|
|
315
|
-
CASE
|
|
316
|
-
WHEN i.type = 1 THEN 'PRIMARY KEY'
|
|
317
|
-
WHEN i.is_unique = 1 THEN 'UNIQUE'
|
|
318
|
-
ELSE NULL
|
|
319
|
-
END AS constraint_type
|
|
320
|
-
FROM
|
|
321
|
-
sys.indexes i
|
|
322
|
-
JOIN sys.tables t ON i.object_id = t.object_id
|
|
323
|
-
WHERE
|
|
324
|
-
t.is_ms_shipped = 0
|
|
325
|
-
AND i.type <> 0
|
|
326
|
-
)
|
|
327
|
-
SELECT
|
|
328
|
-
ut.TABLE_SCHEMA AS table_schema,
|
|
329
|
-
ut.TABLE_NAME AS table_name,
|
|
330
|
-
ii.index_name,
|
|
331
|
-
ii.is_unique,
|
|
332
|
-
ii.is_primary,
|
|
333
|
-
ii.index_type,
|
|
334
|
-
ii.columns,
|
|
335
|
-
ii.constraint_type
|
|
336
|
-
FROM
|
|
337
|
-
user_tables ut
|
|
338
|
-
LEFT JOIN
|
|
339
|
-
index_info ii ON ut.TABLE_NAME = ii.table_name
|
|
340
|
-
AND ut.TABLE_SCHEMA = ii.table_schema
|
|
341
|
-
WHERE
|
|
342
|
-
ii.columns IS NOT NULL
|
|
343
|
-
${(0, parseSchema_1.buildSchemaQuery)('ut.TABLE_SCHEMA', schemas)}
|
|
344
|
-
ORDER BY
|
|
345
|
-
ut.TABLE_NAME,
|
|
346
|
-
ii.constraint_type,
|
|
347
|
-
ii.index_name;
|
|
348
|
-
`;
|
|
349
|
-
const indexListResult = await client.query(indexListSql);
|
|
350
|
-
const { outOfLineIndexes, inlineIndexes } = indexListResult.recordset.reduce((acc, row) => {
|
|
351
|
-
const { constraint_type, columns } = row;
|
|
352
|
-
if (columns === 'null' || columns.trim() === '')
|
|
353
|
-
return acc;
|
|
354
|
-
if (constraint_type === 'PRIMARY KEY' || constraint_type === 'UNIQUE') {
|
|
355
|
-
acc.inlineIndexes.push(row);
|
|
356
|
-
}
|
|
357
|
-
else {
|
|
358
|
-
acc.outOfLineIndexes.push(row);
|
|
359
|
-
}
|
|
360
|
-
return acc;
|
|
361
|
-
}, { inlineIndexes: [], outOfLineIndexes: [] });
|
|
362
|
-
const indexes = outOfLineIndexes.reduce((acc, indexRow) => {
|
|
363
|
-
const { table_schema, table_name, index_name, index_type, columns, expressions, is_unique, is_primary, } = indexRow;
|
|
364
|
-
const indexColumns = columns.split(',').map((column) => {
|
|
365
|
-
return {
|
|
366
|
-
type: 'column',
|
|
367
|
-
value: column.trim(),
|
|
368
|
-
};
|
|
369
|
-
});
|
|
370
|
-
const indexExpressions = expressions
|
|
371
|
-
? expressions.split(',').map((expression) => {
|
|
372
|
-
return {
|
|
373
|
-
type: 'expression',
|
|
374
|
-
value: expression,
|
|
375
|
-
};
|
|
376
|
-
})
|
|
377
|
-
: [];
|
|
378
|
-
const index = {
|
|
379
|
-
name: index_name,
|
|
380
|
-
type: index_type,
|
|
381
|
-
columns: [
|
|
382
|
-
...indexColumns,
|
|
383
|
-
...indexExpressions,
|
|
384
|
-
],
|
|
385
|
-
pk: !!is_primary,
|
|
386
|
-
unique: !is_primary && !!is_unique,
|
|
387
|
-
};
|
|
388
|
-
const key = `${table_schema}.${table_name}`;
|
|
389
|
-
if (acc[key]) {
|
|
390
|
-
acc[key].push(index);
|
|
391
|
-
}
|
|
392
|
-
else {
|
|
393
|
-
acc[key] = [index];
|
|
394
|
-
}
|
|
395
|
-
return acc;
|
|
396
|
-
}, {});
|
|
397
|
-
const tableConstraints = {};
|
|
398
|
-
inlineIndexes.forEach((row) => {
|
|
399
|
-
const { table_schema, table_name, columns, constraint_type, } = row;
|
|
400
|
-
const key = `${table_schema}.${table_name}`;
|
|
401
|
-
if (!tableConstraints[key])
|
|
402
|
-
tableConstraints[key] = {};
|
|
403
|
-
const columnNames = columns.split(',').map((column) => column.trim());
|
|
404
|
-
columnNames.forEach((columnName) => {
|
|
405
|
-
if (!tableConstraints[key][columnName])
|
|
406
|
-
tableConstraints[key][columnName] = { checks: [] };
|
|
407
|
-
if (constraint_type === 'PRIMARY KEY') {
|
|
408
|
-
tableConstraints[key][columnName].pk = true;
|
|
409
|
-
}
|
|
410
|
-
if (constraint_type === 'UNIQUE' && !tableConstraints[key][columnName].pk) {
|
|
411
|
-
tableConstraints[key][columnName].unique = true;
|
|
412
|
-
}
|
|
413
|
-
});
|
|
414
|
-
});
|
|
415
|
-
const checkListSql = `
|
|
416
|
-
SELECT
|
|
417
|
-
OBJECT_SCHEMA_NAME(cc.parent_object_id) AS table_schema,
|
|
418
|
-
OBJECT_NAME(cc.parent_object_id) AS table_name,
|
|
419
|
-
c.name AS column_name,
|
|
420
|
-
cc.name AS check_name,
|
|
421
|
-
cc.definition AS check_expression
|
|
422
|
-
FROM
|
|
423
|
-
sys.check_constraints cc
|
|
424
|
-
LEFT JOIN
|
|
425
|
-
sys.columns c ON cc.parent_object_id = c.object_id AND cc.parent_column_id = c.column_id
|
|
426
|
-
WHERE 1 = 1
|
|
427
|
-
${(0, parseSchema_1.buildSchemaQuery)('OBJECT_SCHEMA_NAME(cc.parent_object_id)', schemas)}
|
|
428
|
-
`;
|
|
429
|
-
const checkListResult = await client.query(checkListSql);
|
|
430
|
-
const checks = {};
|
|
431
|
-
checkListResult.recordset.forEach((row) => {
|
|
432
|
-
const { table_schema, table_name, column_name, check_name, check_expression, } = row;
|
|
433
|
-
const key = `${table_schema}.${table_name}`;
|
|
434
|
-
if (column_name) {
|
|
435
|
-
if (!tableConstraints[key])
|
|
436
|
-
tableConstraints[key] = {};
|
|
437
|
-
if (!tableConstraints[key][column_name])
|
|
438
|
-
tableConstraints[key][column_name] = { checks: [] };
|
|
439
|
-
// The check definition has the form: `(expr)`
|
|
440
|
-
// The expression starts at 1 and ends at -1
|
|
441
|
-
tableConstraints[key][column_name].checks.push({ name: check_name, expression: check_expression.slice(1, -1) });
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
|
-
if (!checks[key])
|
|
445
|
-
checks[key] = [];
|
|
446
|
-
// The check definition has the form: `(expr)`
|
|
447
|
-
// The expression starts at 1 and ends at -1
|
|
448
|
-
checks[key].push({ name: check_name, expression: check_expression.slice(1, -1) });
|
|
449
|
-
});
|
|
450
|
-
return {
|
|
451
|
-
indexes,
|
|
452
|
-
tableConstraints,
|
|
453
|
-
checks,
|
|
454
|
-
};
|
|
455
|
-
};
|
|
456
|
-
const fetchSchemaJson = async (connection) => {
|
|
457
|
-
const { connectionString, schemas } = (0, parseSchema_1.parseConnectionString)(connection, 'odbc');
|
|
458
|
-
const client = await getValidatedClient(connectionString);
|
|
459
|
-
try {
|
|
460
|
-
const tablesRes = generateTablesFields(client, schemas);
|
|
461
|
-
const indexesAndConstraintsRes = generateIndexesAndConstraints(client, schemas);
|
|
462
|
-
const refsRes = generateRefs(client, schemas);
|
|
463
|
-
const res = await Promise.all([
|
|
464
|
-
tablesRes,
|
|
465
|
-
indexesAndConstraintsRes,
|
|
466
|
-
refsRes,
|
|
467
|
-
]);
|
|
468
|
-
const { tables, fields } = res[0];
|
|
469
|
-
const { indexes, tableConstraints, checks } = res[1];
|
|
470
|
-
const refs = res[2];
|
|
471
|
-
return {
|
|
472
|
-
tables,
|
|
473
|
-
fields,
|
|
474
|
-
// MSSQL doesn't support the notion of enums
|
|
475
|
-
enums: [],
|
|
476
|
-
refs,
|
|
477
|
-
indexes,
|
|
478
|
-
tableConstraints,
|
|
479
|
-
checks,
|
|
480
|
-
};
|
|
481
|
-
}
|
|
482
|
-
finally {
|
|
483
|
-
await client.close();
|
|
484
|
-
}
|
|
485
|
-
};
|
|
486
|
-
exports.fetchSchemaJson = fetchSchemaJson;
|