@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.
@@ -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
- SELECT
110
- s.name AS table_schema,
111
- t.name AS table_name,
112
- c.name AS column_name,
113
- ty.name AS data_type,
114
- c.max_length AS character_maximum_length,
115
- c.precision AS numeric_precision,
116
- c.scale AS numeric_scale,
117
- c.is_identity AS identity_increment,
118
- CASE
119
- WHEN c.is_nullable = 1 THEN 'YES'
120
- ELSE 'NO'
121
- END AS is_nullable,
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
- WHEN c.default_object_id = 0 THEN NULL
124
- ELSE OBJECT_DEFINITION(c.default_object_id)
125
- END AS column_default,
126
- -- Fetching table comments
127
- p.value AS table_comment,
128
- ep.value AS column_comment
129
- FROM
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
- tf.table_schema,
150
- tf.table_name,
151
- tf.column_name,
152
- tf.data_type,
153
- tf.character_maximum_length,
154
- tf.numeric_precision,
155
- tf.numeric_scale,
156
- tf.identity_increment,
157
- tf.is_nullable,
158
- tf.column_default,
159
- tf.table_comment,
160
- tf.column_comment,
161
- cc.name AS check_constraint_name, -- Adding CHECK constraint name
162
- cc.definition AS check_constraint_definition, -- Adding CHECK constraint definition
163
- CASE
164
- WHEN tf.column_default LIKE '((%))' THEN 'number'
165
- WHEN tf.column_default LIKE '(''%'')' THEN 'string'
166
- ELSE 'expression'
167
- END AS default_type
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
- tables_and_fields AS tf
170
- LEFT JOIN
171
- sys.check_constraints cc ON cc.parent_object_id = OBJECT_ID(tf.table_schema + '.' + tf.table_name)
172
- AND cc.definition LIKE '%' + tf.column_name + '%' -- Ensure the constraint references the column
194
+ constraints_with_row_number
195
+ WHERE
196
+ rn = 1
197
+ ${(0, parseSchema_1.buildSchemaQuery)('table_schema', schemas, 'WHERE')}
173
198
  ORDER BY
174
- tf.table_schema,
175
- tf.table_name,
176
- tf.column_name;
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 client = await getValidatedClient(connection);
414
- const tablesFieldsAndEnumsRes = generateTablesFieldsAndEnums(client);
415
- const indexesRes = generateIndexes(client);
416
- const refsRes = generateRefs(client);
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,
@@ -1,3 +1,3 @@
1
1
  import { DatabaseSchema } from './types';
2
2
  declare const fetchSchemaJson: (connection: string) => Promise<DatabaseSchema>;
3
- export { fetchSchemaJson, };
3
+ export { fetchSchemaJson };
@@ -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 -- Added 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
- if (!acc[enum_type]) {
375
- acc[enum_type] = {
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[enum_type].values.push({
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 client = await getValidatedClient(connection);
390
- const tablesAndFieldsRes = generateTablesAndFields(client);
391
- const indexesRes = generateIndexes(client);
392
- const refsRes = generateRawRefs(client);
393
- const enumsRes = generateRawEnums(client);
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,
@@ -0,0 +1,3 @@
1
+ import { DatabaseSchema } from './types';
2
+ declare const fetchSchemaJson: (connection: string) => Promise<DatabaseSchema>;
3
+ export { fetchSchemaJson, };