@dbml/connector 3.7.4 → 3.8.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/__tests__/connector.test.ts +2 -2
- package/__tests__/connectors/postgres/expect-out-files/schema.json +208 -0
- package/dist/connectors/bigqueryConnector.d.ts +3 -0
- package/dist/connectors/bigqueryConnector.js +276 -0
- package/dist/connectors/connector.d.ts +1 -1
- package/dist/connectors/connector.js +9 -3
- package/dist/connectors/mssqlConnector.d.ts +1 -1
- package/dist/connectors/mssqlConnector.js +100 -70
- package/dist/connectors/postgresConnector.d.ts +1 -1
- package/dist/connectors/postgresConnector.js +28 -20
- package/dist/connectors/snowflakeConnector.d.ts +3 -0
- package/dist/connectors/snowflakeConnector.js +292 -0
- package/dist/connectors/types.d.ts +11 -1
- package/dist/utils/credential-loader.d.ts +3 -0
- package/dist/utils/credential-loader.js +53 -0
- package/dist/utils/helpers.d.ts +7 -0
- package/dist/utils/helpers.js +50 -0
- package/dist/utils/parseSchema.d.ts +10 -0
- package/dist/utils/parseSchema.js +59 -0
- package/package.json +5 -3
- package/src/connectors/bigqueryConnector.ts +389 -0
- package/src/connectors/connector.ts +9 -3
- package/src/connectors/mssqlConnector.ts +107 -77
- package/src/connectors/postgresConnector.ts +29 -21
- package/src/connectors/snowflakeConnector.ts +370 -0
- package/src/connectors/types.ts +12 -0
- package/src/ddl_samples/bigquery.sql +71 -0
- package/src/ddl_samples/snowflake.sql +131 -0
- package/src/utils/credential-loader.ts +64 -0
- package/src/utils/helpers.ts +73 -0
- package/src/utils/parseSchema.ts +60 -0
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.fetchSchemaJson = void 0;
|
|
7
7
|
/* eslint-disable camelcase */
|
|
8
8
|
const mssql_1 = __importDefault(require("mssql"));
|
|
9
|
+
const parseSchema_1 = require("../utils/parseSchema");
|
|
9
10
|
const MSSQL_DATE_TYPES = [
|
|
10
11
|
'date',
|
|
11
12
|
'datetime',
|
|
@@ -101,79 +102,103 @@ const generateField = (row) => {
|
|
|
101
102
|
note: column_comment ? { value: column_comment } : { value: '' },
|
|
102
103
|
};
|
|
103
104
|
};
|
|
104
|
-
const generateTablesFieldsAndEnums = async (client) => {
|
|
105
|
+
const generateTablesFieldsAndEnums = async (client, schemas) => {
|
|
105
106
|
const fields = {};
|
|
106
107
|
const enums = [];
|
|
107
108
|
const tablesAndFieldsSql = `
|
|
108
109
|
WITH tables_and_fields AS (
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
110
|
+
SELECT
|
|
111
|
+
s.name AS table_schema,
|
|
112
|
+
t.name AS table_name,
|
|
113
|
+
c.name AS column_name,
|
|
114
|
+
ty.name AS data_type,
|
|
115
|
+
c.max_length AS character_maximum_length,
|
|
116
|
+
c.precision AS numeric_precision,
|
|
117
|
+
c.scale AS numeric_scale,
|
|
118
|
+
c.is_identity AS identity_increment,
|
|
119
|
+
CASE
|
|
120
|
+
WHEN c.is_nullable = 1 THEN 'YES'
|
|
121
|
+
ELSE 'NO'
|
|
122
|
+
END AS is_nullable,
|
|
123
|
+
CASE
|
|
124
|
+
WHEN c.default_object_id = 0 THEN NULL
|
|
125
|
+
ELSE OBJECT_DEFINITION(c.default_object_id)
|
|
126
|
+
END AS column_default,
|
|
127
|
+
-- Fetching table comments
|
|
128
|
+
p.value AS table_comment,
|
|
129
|
+
ep.value AS column_comment
|
|
130
|
+
FROM
|
|
131
|
+
sys.tables t
|
|
132
|
+
JOIN sys.schemas s ON t.schema_id = s.schema_id
|
|
133
|
+
JOIN sys.columns c ON t.object_id = c.object_id
|
|
134
|
+
JOIN sys.types ty ON c.user_type_id = ty.user_type_id
|
|
135
|
+
LEFT JOIN sys.extended_properties p ON p.major_id = t.object_id
|
|
136
|
+
AND p.name = 'MS_Description'
|
|
137
|
+
AND p.minor_id = 0 -- Ensure minor_id is 0 for table comments
|
|
138
|
+
LEFT JOIN sys.extended_properties ep ON ep.major_id = c.object_id
|
|
139
|
+
AND ep.minor_id = c.column_id
|
|
140
|
+
AND ep.name = 'MS_Description'
|
|
141
|
+
WHERE
|
|
142
|
+
t.type = 'U' -- User-defined tables
|
|
143
|
+
),
|
|
144
|
+
constraints_with_nulls AS (
|
|
145
|
+
SELECT
|
|
146
|
+
tf.*,
|
|
147
|
+
cc.name AS check_constraint_name,
|
|
148
|
+
CASE
|
|
149
|
+
WHEN cc.definition LIKE '%[' + tf.column_name + ']%=''%' THEN cc.definition
|
|
150
|
+
ELSE NULL
|
|
151
|
+
END AS check_constraint_definition
|
|
152
|
+
FROM
|
|
153
|
+
tables_and_fields AS tf
|
|
154
|
+
LEFT JOIN sys.check_constraints cc
|
|
155
|
+
ON cc.parent_object_id = OBJECT_ID(tf.table_schema + '.' + tf.table_name)
|
|
156
|
+
AND cc.definition LIKE '%' + tf.column_name + '%' -- Ensure the constraint references the column
|
|
157
|
+
),
|
|
158
|
+
constraints_with_row_number AS (
|
|
159
|
+
SELECT
|
|
160
|
+
*,
|
|
161
|
+
ROW_NUMBER() OVER (
|
|
162
|
+
PARTITION BY table_schema, table_name, column_name
|
|
163
|
+
ORDER BY
|
|
122
164
|
CASE
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
END
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
sys.tables t
|
|
131
|
-
JOIN
|
|
132
|
-
sys.schemas s ON t.schema_id = s.schema_id
|
|
133
|
-
JOIN
|
|
134
|
-
sys.columns c ON t.object_id = c.object_id
|
|
135
|
-
JOIN
|
|
136
|
-
sys.types ty ON c.user_type_id = ty.user_type_id
|
|
137
|
-
LEFT JOIN
|
|
138
|
-
sys.extended_properties p ON p.major_id = t.object_id
|
|
139
|
-
AND p.name = 'MS_Description'
|
|
140
|
-
AND p.minor_id = 0 -- Ensure minor_id is 0 for table comments
|
|
141
|
-
LEFT JOIN
|
|
142
|
-
sys.extended_properties ep ON ep.major_id = c.object_id
|
|
143
|
-
AND ep.minor_id = c.column_id
|
|
144
|
-
AND ep.name = 'MS_Description'
|
|
145
|
-
WHERE
|
|
146
|
-
t.type = 'U' -- User-defined tables
|
|
165
|
+
WHEN check_constraint_definition IS NOT NULL THEN 1
|
|
166
|
+
ELSE 2
|
|
167
|
+
END,
|
|
168
|
+
check_constraint_name
|
|
169
|
+
) AS rn
|
|
170
|
+
FROM
|
|
171
|
+
constraints_with_nulls
|
|
147
172
|
)
|
|
148
173
|
SELECT
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
174
|
+
table_schema,
|
|
175
|
+
table_name,
|
|
176
|
+
column_name,
|
|
177
|
+
data_type,
|
|
178
|
+
character_maximum_length,
|
|
179
|
+
numeric_precision,
|
|
180
|
+
numeric_scale,
|
|
181
|
+
identity_increment,
|
|
182
|
+
is_nullable,
|
|
183
|
+
column_default,
|
|
184
|
+
table_comment,
|
|
185
|
+
column_comment,
|
|
186
|
+
check_constraint_name,
|
|
187
|
+
check_constraint_definition,
|
|
188
|
+
CASE
|
|
189
|
+
WHEN column_default LIKE '((%))' THEN 'number'
|
|
190
|
+
WHEN column_default LIKE '(''%'')' THEN 'string'
|
|
191
|
+
ELSE 'expression'
|
|
192
|
+
END AS default_type
|
|
168
193
|
FROM
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
194
|
+
constraints_with_row_number
|
|
195
|
+
WHERE
|
|
196
|
+
rn = 1
|
|
197
|
+
${(0, parseSchema_1.buildSchemaQuery)('table_schema', schemas, 'WHERE')}
|
|
173
198
|
ORDER BY
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
199
|
+
table_schema,
|
|
200
|
+
table_name,
|
|
201
|
+
column_name;
|
|
177
202
|
`;
|
|
178
203
|
const tablesAndFieldsResult = await client.query(tablesAndFieldsSql);
|
|
179
204
|
const tables = tablesAndFieldsResult.recordset.reduce((acc, row) => {
|
|
@@ -212,7 +237,7 @@ const generateTablesFieldsAndEnums = async (client) => {
|
|
|
212
237
|
enums,
|
|
213
238
|
};
|
|
214
239
|
};
|
|
215
|
-
const generateRefs = async (client) => {
|
|
240
|
+
const generateRefs = async (client, schemas) => {
|
|
216
241
|
const refs = [];
|
|
217
242
|
const refsListSql = `
|
|
218
243
|
SELECT
|
|
@@ -242,6 +267,7 @@ const generateRefs = async (client) => {
|
|
|
242
267
|
JOIN sys.tables AS t2 ON fk.referenced_object_id = t2.object_id
|
|
243
268
|
JOIN sys.schemas AS s2 ON t2.schema_id = s2.schema_id
|
|
244
269
|
WHERE s.name NOT IN ('sys', 'information_schema')
|
|
270
|
+
${(0, parseSchema_1.buildSchemaQuery)('s.name', schemas)}
|
|
245
271
|
ORDER BY
|
|
246
272
|
s.name,
|
|
247
273
|
t.name;
|
|
@@ -270,7 +296,7 @@ const generateRefs = async (client) => {
|
|
|
270
296
|
});
|
|
271
297
|
return refs;
|
|
272
298
|
};
|
|
273
|
-
const generateIndexes = async (client) => {
|
|
299
|
+
const generateIndexes = async (client, schemas) => {
|
|
274
300
|
const indexListSql = `
|
|
275
301
|
WITH user_tables AS (
|
|
276
302
|
SELECT
|
|
@@ -288,6 +314,7 @@ const generateIndexes = async (client) => {
|
|
|
288
314
|
),
|
|
289
315
|
index_info AS (
|
|
290
316
|
SELECT
|
|
317
|
+
SCHEMA_NAME(t.schema_id) AS table_schema, -- Add schema information
|
|
291
318
|
OBJECT_NAME(i.object_id) AS table_name,
|
|
292
319
|
i.name AS index_name,
|
|
293
320
|
i.is_unique,
|
|
@@ -335,8 +362,10 @@ const generateIndexes = async (client) => {
|
|
|
335
362
|
user_tables ut
|
|
336
363
|
LEFT JOIN
|
|
337
364
|
index_info ii ON ut.TABLE_NAME = ii.table_name
|
|
365
|
+
AND ut.TABLE_SCHEMA = ii.table_schema
|
|
338
366
|
WHERE
|
|
339
367
|
ii.columns IS NOT NULL
|
|
368
|
+
${(0, parseSchema_1.buildSchemaQuery)('ut.TABLE_SCHEMA', schemas)}
|
|
340
369
|
ORDER BY
|
|
341
370
|
ut.TABLE_NAME,
|
|
342
371
|
ii.constraint_type,
|
|
@@ -410,10 +439,11 @@ const generateIndexes = async (client) => {
|
|
|
410
439
|
};
|
|
411
440
|
};
|
|
412
441
|
const fetchSchemaJson = async (connection) => {
|
|
413
|
-
const
|
|
414
|
-
const
|
|
415
|
-
const
|
|
416
|
-
const
|
|
442
|
+
const { connectionString, schemas } = (0, parseSchema_1.parseConnectionString)(connection, 'odbc');
|
|
443
|
+
const client = await getValidatedClient(connectionString);
|
|
444
|
+
const tablesFieldsAndEnumsRes = generateTablesFieldsAndEnums(client, schemas);
|
|
445
|
+
const indexesRes = generateIndexes(client, schemas);
|
|
446
|
+
const refsRes = generateRefs(client, schemas);
|
|
417
447
|
const res = await Promise.all([
|
|
418
448
|
tablesFieldsAndEnumsRes,
|
|
419
449
|
indexesRes,
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.fetchSchemaJson = void 0;
|
|
4
4
|
/* eslint-disable camelcase */
|
|
5
5
|
const pg_1 = require("pg");
|
|
6
|
+
const parseSchema_1 = require("../utils/parseSchema");
|
|
6
7
|
const getValidatedClient = async (connection) => {
|
|
7
8
|
const client = new pg_1.Client(connection);
|
|
8
9
|
try {
|
|
@@ -78,11 +79,11 @@ const generateField = (row) => {
|
|
|
78
79
|
note: column_comment ? { value: column_comment } : { value: '' },
|
|
79
80
|
};
|
|
80
81
|
};
|
|
81
|
-
const generateTablesAndFields = async (client) => {
|
|
82
|
+
const generateTablesAndFields = async (client, schemas) => {
|
|
82
83
|
const fields = {};
|
|
83
84
|
const tablesAndFieldsSql = `
|
|
84
85
|
WITH comments AS (
|
|
85
|
-
SELECT
|
|
86
|
+
SELECT DISTINCT ON (pc.relname, pn.nspname, pa.attname)
|
|
86
87
|
pc.relname AS table_name,
|
|
87
88
|
pn.nspname AS table_schema,
|
|
88
89
|
pa.attname AS column_name,
|
|
@@ -112,6 +113,7 @@ const generateTablesAndFields = async (client) => {
|
|
|
112
113
|
c.identity_increment,
|
|
113
114
|
c.is_nullable,
|
|
114
115
|
c.column_default,
|
|
116
|
+
c.ordinal_position,
|
|
115
117
|
CASE
|
|
116
118
|
WHEN c.column_default IS NULL THEN NULL
|
|
117
119
|
WHEN c.column_default LIKE 'nextval(%' THEN 'increment'
|
|
@@ -120,8 +122,8 @@ const generateTablesAndFields = async (client) => {
|
|
|
120
122
|
WHEN c.column_default ~ '^-?[0-9]+(.[0-9]+)?$' THEN 'number'
|
|
121
123
|
ELSE 'expression'
|
|
122
124
|
END AS default_type,
|
|
123
|
-
(SELECT description FROM comments WHERE table_name = t.table_name AND table_schema = t.table_schema AND column_name IS NULL) AS table_comment,
|
|
124
|
-
(SELECT description FROM comments WHERE table_name = t.table_name AND table_schema = t.table_schema AND column_name = c.column_name) AS column_comment
|
|
125
|
+
(SELECT description FROM comments WHERE table_name = t.table_name AND table_schema = t.table_schema AND column_name IS NULL LIMIT 1) AS table_comment,
|
|
126
|
+
(SELECT description FROM comments WHERE table_name = t.table_name AND table_schema = t.table_schema AND column_name = c.column_name LIMIT 1) AS column_comment
|
|
125
127
|
FROM
|
|
126
128
|
information_schema.columns c
|
|
127
129
|
JOIN
|
|
@@ -129,6 +131,7 @@ const generateTablesAndFields = async (client) => {
|
|
|
129
131
|
WHERE
|
|
130
132
|
t.table_type = 'BASE TABLE'
|
|
131
133
|
AND t.table_schema NOT IN ('pg_catalog', 'information_schema')
|
|
134
|
+
${(0, parseSchema_1.buildSchemaQuery)('t.table_schema', schemas)}
|
|
132
135
|
ORDER BY
|
|
133
136
|
t.table_schema,
|
|
134
137
|
t.table_name,
|
|
@@ -157,7 +160,7 @@ const generateTablesAndFields = async (client) => {
|
|
|
157
160
|
fields,
|
|
158
161
|
};
|
|
159
162
|
};
|
|
160
|
-
const generateRawRefs = async (client) => {
|
|
163
|
+
const generateRawRefs = async (client, schemas) => {
|
|
161
164
|
const refs = [];
|
|
162
165
|
const refsListSql = `
|
|
163
166
|
SELECT
|
|
@@ -182,6 +185,7 @@ const generateRawRefs = async (client) => {
|
|
|
182
185
|
AND tc.table_schema = rc.constraint_schema
|
|
183
186
|
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
184
187
|
AND tc.table_schema NOT IN ('pg_catalog', 'information_schema')
|
|
188
|
+
${(0, parseSchema_1.buildSchemaQuery)('tc.table_schema', schemas)}
|
|
185
189
|
GROUP BY
|
|
186
190
|
tc.table_schema,
|
|
187
191
|
tc.table_name,
|
|
@@ -219,8 +223,7 @@ const generateRawRefs = async (client) => {
|
|
|
219
223
|
});
|
|
220
224
|
return refs;
|
|
221
225
|
};
|
|
222
|
-
const generateIndexes = async (client) => {
|
|
223
|
-
// const tableConstraints = {};
|
|
226
|
+
const generateIndexes = async (client, schemas) => {
|
|
224
227
|
const indexListSql = `
|
|
225
228
|
WITH user_tables AS (
|
|
226
229
|
SELECT
|
|
@@ -233,6 +236,7 @@ const generateIndexes = async (client) => {
|
|
|
233
236
|
),
|
|
234
237
|
index_info AS (
|
|
235
238
|
SELECT
|
|
239
|
+
t.relnamespace::regnamespace::text AS table_schema,
|
|
236
240
|
t.relname AS table_name,
|
|
237
241
|
i.relname AS index_name,
|
|
238
242
|
ix.indisunique AS is_unique,
|
|
@@ -257,7 +261,7 @@ const generateIndexes = async (client) => {
|
|
|
257
261
|
AND t.relname NOT LIKE 'pg_%'
|
|
258
262
|
AND t.relname NOT LIKE 'sql_%'
|
|
259
263
|
GROUP BY
|
|
260
|
-
t.relname, i.relname, ix.indisunique, ix.indisprimary, am.amname, ix.indexprs, ix.indrelid
|
|
264
|
+
t.relnamespace, t.relname, i.relname, ix.indisunique, ix.indisprimary, am.amname, ix.indexprs, ix.indrelid
|
|
261
265
|
)
|
|
262
266
|
SELECT
|
|
263
267
|
ut.tableschema AS table_schema,
|
|
@@ -268,12 +272,13 @@ const generateIndexes = async (client) => {
|
|
|
268
272
|
ii.index_type,
|
|
269
273
|
ii.columns,
|
|
270
274
|
ii.expressions,
|
|
271
|
-
ii.constraint_type --
|
|
275
|
+
ii.constraint_type -- Retained constraint type here
|
|
272
276
|
FROM
|
|
273
277
|
user_tables ut
|
|
274
278
|
LEFT JOIN
|
|
275
|
-
index_info ii ON ut.tablename = ii.table_name
|
|
279
|
+
index_info ii ON ut.tableschema = ii.table_schema AND ut.tablename = ii.table_name
|
|
276
280
|
WHERE ii.columns IS NOT NULL
|
|
281
|
+
${(0, parseSchema_1.buildSchemaQuery)('ut.tableschema', schemas)}
|
|
277
282
|
ORDER BY
|
|
278
283
|
ut.tablename,
|
|
279
284
|
ii.constraint_type,
|
|
@@ -349,9 +354,9 @@ const generateIndexes = async (client) => {
|
|
|
349
354
|
tableConstraints,
|
|
350
355
|
};
|
|
351
356
|
};
|
|
352
|
-
const generateRawEnums = async (client) => {
|
|
357
|
+
const generateRawEnums = async (client, schemas) => {
|
|
353
358
|
const enumListSql = `
|
|
354
|
-
SELECT
|
|
359
|
+
SELECT DISTINCT
|
|
355
360
|
n.nspname AS schema_name,
|
|
356
361
|
t.typname AS enum_type,
|
|
357
362
|
e.enumlabel AS enum_value,
|
|
@@ -362,6 +367,7 @@ const generateRawEnums = async (client) => {
|
|
|
362
367
|
pg_type t ON e.enumtypid = t.oid
|
|
363
368
|
JOIN
|
|
364
369
|
pg_namespace n ON t.typnamespace = n.oid
|
|
370
|
+
${(0, parseSchema_1.buildSchemaQuery)('n.nspname', schemas, 'WHERE')}
|
|
365
371
|
ORDER BY
|
|
366
372
|
schema_name,
|
|
367
373
|
enum_type,
|
|
@@ -371,14 +377,15 @@ const generateRawEnums = async (client) => {
|
|
|
371
377
|
const enumListResult = await client.query(enumListSql);
|
|
372
378
|
const enums = enumListResult.rows.reduce((acc, row) => {
|
|
373
379
|
const { schema_name, enum_type, enum_value } = row;
|
|
374
|
-
|
|
375
|
-
|
|
380
|
+
const key = `${schema_name}.${enum_type}`;
|
|
381
|
+
if (!acc[key]) {
|
|
382
|
+
acc[key] = {
|
|
376
383
|
name: enum_type,
|
|
377
384
|
schemaName: schema_name,
|
|
378
385
|
values: [],
|
|
379
386
|
};
|
|
380
387
|
}
|
|
381
|
-
acc[
|
|
388
|
+
acc[key].values.push({
|
|
382
389
|
name: enum_value,
|
|
383
390
|
});
|
|
384
391
|
return acc;
|
|
@@ -386,11 +393,12 @@ const generateRawEnums = async (client) => {
|
|
|
386
393
|
return Object.values(enums);
|
|
387
394
|
};
|
|
388
395
|
const fetchSchemaJson = async (connection) => {
|
|
389
|
-
const
|
|
390
|
-
const
|
|
391
|
-
const
|
|
392
|
-
const
|
|
393
|
-
const
|
|
396
|
+
const { connectionString, schemas } = (0, parseSchema_1.parseConnectionString)(connection, 'jdbc');
|
|
397
|
+
const client = await getValidatedClient(connectionString);
|
|
398
|
+
const tablesAndFieldsRes = generateTablesAndFields(client, schemas);
|
|
399
|
+
const indexesRes = generateIndexes(client, schemas);
|
|
400
|
+
const refsRes = generateRawRefs(client, schemas);
|
|
401
|
+
const enumsRes = generateRawEnums(client, schemas);
|
|
394
402
|
const res = await Promise.all([
|
|
395
403
|
tablesAndFieldsRes,
|
|
396
404
|
indexesRes,
|