@dbml/connector 3.7.3 → 3.8.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.
@@ -0,0 +1,276 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchSchemaJson = fetchSchemaJson;
4
+ const bigquery_1 = require("@google-cloud/bigquery");
5
+ const credential_loader_1 = require("../utils/credential-loader");
6
+ const helpers_1 = require("../utils/helpers");
7
+ async function connectBigQuery(credential) {
8
+ const client = new bigquery_1.BigQuery({
9
+ projectId: credential.projectId,
10
+ credentials: {
11
+ private_key: credential.credentials.privateKey,
12
+ client_email: credential.credentials.clientEmail,
13
+ },
14
+ });
15
+ try {
16
+ const query = `SELECT CURRENT_DATE() as today`;
17
+ await client.query(query);
18
+ return client;
19
+ }
20
+ catch (error) {
21
+ if (error instanceof Error) {
22
+ throw new Error(`BigQuery connection error: ${error.message}`);
23
+ }
24
+ throw error;
25
+ }
26
+ }
27
+ function getDbDefault(columnDefault, defaultValueType) {
28
+ if (defaultValueType === null) {
29
+ return null;
30
+ }
31
+ if (defaultValueType === 'string') {
32
+ // bigquery store the double qoutes and quotes at the end and the beginning of the string: "string" or 'string'
33
+ return { value: columnDefault.slice(1, -1).replaceAll("'", "\'"), type: defaultValueType };
34
+ }
35
+ return { value: columnDefault, type: defaultValueType };
36
+ }
37
+ function generateField(row) {
38
+ const { columnName, isNullable, dataType, columnDefault, columnDefaultType, columnDescription, } = row;
39
+ const fieldDefaultValue = getDbDefault(columnDefault, columnDefaultType);
40
+ const field = {
41
+ name: columnName,
42
+ not_null: isNullable === 'NO',
43
+ type: {
44
+ type_name: dataType,
45
+ schemaName: null,
46
+ },
47
+ note: {
48
+ value: columnDescription || '',
49
+ },
50
+ dbdefault: fieldDefaultValue,
51
+ increment: false, // bigquery does not support native auto-increment
52
+ };
53
+ return field;
54
+ }
55
+ async function generateTablesAndFields(client, projectId, datasetId) {
56
+ const tableName = `${projectId}.${datasetId}`;
57
+ const query = `
58
+ with
59
+ table_comments as (
60
+ select table_schema, table_name, option_value as description
61
+ from ${tableName}.INFORMATION_SCHEMA.TABLE_OPTIONS
62
+ where option_name = 'description'
63
+ ),
64
+ column_comments as (
65
+ select column_name, table_schema, table_name, description
66
+ from ${tableName}.INFORMATION_SCHEMA.COLUMN_FIELD_PATHS
67
+ where column_name = field_path
68
+ )
69
+ select
70
+ t.table_schema as tableSchema,
71
+ t.table_name as tableName,
72
+ (select description from table_comments tc where tc.table_name = t.table_name and tc.table_schema = t.table_schema) as tableDescription,
73
+ (
74
+ select description
75
+ from column_comments cc
76
+ where cc.table_name = c.table_name and cc.table_schema = c.table_schema and cc.column_name = c.column_name
77
+ ) as columnDescription,
78
+ c.column_name as columnName,
79
+ c.is_nullable as isNullable,
80
+ c.data_type as dataType,
81
+ c.column_default as columnDefault,
82
+ CASE
83
+ WHEN SAFE_CAST(c.column_default AS FLOAT64) IS NOT NULL THEN 'number'
84
+ WHEN SAFE_CAST(c.column_default AS BOOLEAN) IS NOT NULL THEN 'boolean'
85
+ -- string value is enclosed in single quotes, double quotes
86
+ WHEN REGEXP_CONTAINS(c.column_default, r"^['\\"].*['\\"]$") THEN 'string'
87
+ WHEN c.column_default = "NULL" THEN NULL
88
+ ELSE 'expression'
89
+ END AS columnDefaultType
90
+ from ${tableName}.INFORMATION_SCHEMA.TABLES t
91
+ join ${tableName}.INFORMATION_SCHEMA.COLUMNS c
92
+ on
93
+ t.table_schema = c.table_schema
94
+ and t.table_name = c.table_name
95
+ where t.table_type = 'BASE TABLE'
96
+ order by t.table_name, c.ordinal_position;
97
+ `;
98
+ const [queryResult] = await client.query({
99
+ query,
100
+ params: {
101
+ // stringRegex: STRING_REGEX,
102
+ },
103
+ });
104
+ const tableMap = {};
105
+ const fieldMap = {};
106
+ queryResult.forEach((row) => {
107
+ const { tableSchema, tableName, tableComment } = row;
108
+ const key = (0, helpers_1.getTableSchemaKey)(tableSchema, tableName);
109
+ if (!tableMap[key]) {
110
+ tableMap[key] = {
111
+ name: tableName,
112
+ note: { value: tableComment || '' },
113
+ schemaName: tableSchema,
114
+ };
115
+ }
116
+ if (!fieldMap[key]) {
117
+ fieldMap[key] = [];
118
+ }
119
+ const field = generateField(row);
120
+ fieldMap[key].push(field);
121
+ });
122
+ return {
123
+ tables: Object.values(tableMap),
124
+ fieldMap,
125
+ };
126
+ }
127
+ async function generateIndexes(client, projectId, datasetId) {
128
+ const tableName = `${projectId}.${datasetId}`;
129
+ const query = `
130
+ select
131
+ s.index_schema as indexSchema,
132
+ s.table_name as tableName,
133
+ s.index_name as indexName,
134
+ string_agg(sc.index_column_name, ', ') as indexColumnNames
135
+ from ${tableName}.INFORMATION_SCHEMA.SEARCH_INDEXES s
136
+ join ${tableName}.INFORMATION_SCHEMA.SEARCH_INDEX_COLUMNS sc
137
+ on
138
+ s.index_schema = sc.index_schema
139
+ and s.table_name = sc.table_name
140
+ and s.index_name = sc.index_name
141
+ where sc.index_column_name = sc.index_field_path
142
+ group by s.index_schema, s.table_name, s.index_name
143
+ order by s.table_name, s.index_name;
144
+ `;
145
+ const [queryResult] = await client.query(query);
146
+ const indexMap = {};
147
+ queryResult.forEach((row) => {
148
+ const { indexSchema, tableName, indexName, indexColumnNames } = row;
149
+ const indexColumns = indexColumnNames.split(', ').map((column) => {
150
+ return {
151
+ type: 'column',
152
+ value: column,
153
+ };
154
+ });
155
+ const index = {
156
+ name: indexName,
157
+ type: '',
158
+ columns: [...indexColumns],
159
+ };
160
+ const key = (0, helpers_1.getTableSchemaKey)(indexSchema, tableName);
161
+ if (indexMap[key]) {
162
+ indexMap[key].push(index);
163
+ }
164
+ else {
165
+ indexMap[key] = [index];
166
+ }
167
+ });
168
+ return indexMap;
169
+ }
170
+ async function generateTableConstraints(client, projectId, datasetId) {
171
+ const tableName = `${projectId}.${datasetId}`;
172
+ const query = `
173
+ select
174
+ tc.table_schema as tableSchema,
175
+ tc.table_name as tableName,
176
+ tc.constraint_name as constraintName,
177
+ string_agg(kcu.column_name, ', ') as columnNames,
178
+ count(kcu.column_name) as columnCount,
179
+ from ${tableName}.INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
180
+ join ${tableName}.INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
181
+ on
182
+ tc.table_schema = kcu.table_schema
183
+ and tc.table_name = kcu.table_name
184
+ and tc.constraint_name = kcu.constraint_name
185
+ where tc.constraint_type = 'PRIMARY KEY'
186
+ group by tc.table_schema, tc.table_name, tc.constraint_name
187
+ order by tc.table_name, tc.constraint_name;
188
+ `;
189
+ const [queryResult] = await client.query(query);
190
+ const inlinePrimaryKeyList = queryResult.filter((row) => row.columnCount && row.columnCount === 1);
191
+ const compositePrimaryKeyList = queryResult.filter((row) => row.columnCount && row.columnCount > 1);
192
+ const inlinePrimaryKeyMap = {};
193
+ inlinePrimaryKeyList.forEach((inlineKey) => {
194
+ const { tableSchema, tableName, columnNames } = inlineKey;
195
+ const key = (0, helpers_1.getTableSchemaKey)(tableSchema, tableName);
196
+ if (!inlinePrimaryKeyMap[key]) {
197
+ inlinePrimaryKeyMap[key] = {};
198
+ }
199
+ if (!inlinePrimaryKeyMap[key][columnNames]) {
200
+ inlinePrimaryKeyMap[key][columnNames] = {};
201
+ }
202
+ inlinePrimaryKeyMap[key][columnNames].pk = true;
203
+ });
204
+ const compositePrimaryKeyMap = {};
205
+ compositePrimaryKeyList.forEach((compositeKey) => {
206
+ const { tableSchema, tableName, constraintName, columnNames } = compositeKey;
207
+ const indexColumns = columnNames.split(', ').map((column) => {
208
+ return {
209
+ type: 'column',
210
+ value: column,
211
+ };
212
+ });
213
+ const index = {
214
+ name: constraintName,
215
+ type: '',
216
+ columns: [...indexColumns],
217
+ pk: true,
218
+ };
219
+ const key = (0, helpers_1.getTableSchemaKey)(tableSchema, tableName);
220
+ if (compositePrimaryKeyMap[key]) {
221
+ compositePrimaryKeyMap[key].push(index);
222
+ }
223
+ else {
224
+ compositePrimaryKeyMap[key] = [index];
225
+ }
226
+ });
227
+ return {
228
+ inlinePrimaryKeyMap,
229
+ compositePrimaryKeyMap,
230
+ };
231
+ }
232
+ async function validateDatasetIdList(client, datasetIdList) {
233
+ const [datasets] = await client.getDatasets();
234
+ const rawDatasetIdList = datasets.map((dataset) => dataset.id).filter((id) => id);
235
+ // If user does not specify which datasets to be fetched, we will fetch all datasets
236
+ if (datasetIdList.length === 0) {
237
+ return rawDatasetIdList;
238
+ }
239
+ return (0, helpers_1.getIntersection)(datasetIdList, rawDatasetIdList);
240
+ }
241
+ async function fetchSchemaJsonByDataset(client, projectId, datasetId) {
242
+ const res = await Promise.all([
243
+ generateTablesAndFields(client, projectId, datasetId),
244
+ generateIndexes(client, projectId, datasetId),
245
+ generateTableConstraints(client, projectId, datasetId),
246
+ ]);
247
+ const { tables, fieldMap } = res[0];
248
+ const indexMap = res[1];
249
+ const { inlinePrimaryKeyMap, compositePrimaryKeyMap } = res[2];
250
+ return {
251
+ tables,
252
+ fields: fieldMap,
253
+ refs: [],
254
+ enums: [],
255
+ indexes: (0, helpers_1.mergeIndexDictionary)(indexMap, compositePrimaryKeyMap),
256
+ tableConstraints: inlinePrimaryKeyMap,
257
+ };
258
+ }
259
+ async function fetchSchemaJson(keyFilename) {
260
+ const rawCredential = await (0, credential_loader_1.loadCredentialFromFile)(keyFilename);
261
+ const credentialJson = (0, credential_loader_1.parseBigQueryCredential)(rawCredential);
262
+ const client = await connectBigQuery(credentialJson);
263
+ const projectId = await client.getProjectId();
264
+ const datasetIdList = await validateDatasetIdList(client, credentialJson.datasets);
265
+ const querySchemaPromises = datasetIdList.map((dataset) => fetchSchemaJsonByDataset(client, projectId, dataset));
266
+ const databaseSchemaRes = await Promise.all(querySchemaPromises);
267
+ const res = databaseSchemaRes.reduce((acc, dbSchema) => {
268
+ const { tables, fields, indexes, tableConstraints } = dbSchema;
269
+ acc.tables = (0, helpers_1.mergeTables)(acc.tables, tables);
270
+ acc.fields = (0, helpers_1.mergeFieldDictionary)(acc.fields, fields);
271
+ acc.indexes = (0, helpers_1.mergeIndexDictionary)(acc.indexes, indexes);
272
+ acc.tableConstraints = (0, helpers_1.mergeTableConstraintDictionary)(acc.tableConstraints, tableConstraints);
273
+ return acc;
274
+ }, { tables: [], fields: {}, tableConstraints: {}, indexes: {}, refs: [], enums: [] });
275
+ return res;
276
+ }
@@ -1,3 +1,3 @@
1
1
  import { DatabaseSchema } from './types';
2
- declare const fetchSchemaJson: (connection: string, format: string) => Promise<DatabaseSchema>;
2
+ declare const fetchSchemaJson: (connection: string, databaseType: string) => Promise<DatabaseSchema>;
3
3
  export { fetchSchemaJson, };
@@ -4,16 +4,22 @@ exports.fetchSchemaJson = void 0;
4
4
  const postgresConnector_1 = require("./postgresConnector");
5
5
  const mssqlConnector_1 = require("./mssqlConnector");
6
6
  const mysqlConnector_1 = require("./mysqlConnector");
7
- const fetchSchemaJson = async (connection, format) => {
8
- switch (format) {
7
+ const snowflakeConnector_1 = require("./snowflakeConnector");
8
+ const bigqueryConnector_1 = require("./bigqueryConnector");
9
+ const fetchSchemaJson = async (connection, databaseType) => {
10
+ switch (databaseType) {
9
11
  case 'postgres':
10
12
  return (0, postgresConnector_1.fetchSchemaJson)(connection);
11
13
  case 'mssql':
12
14
  return (0, mssqlConnector_1.fetchSchemaJson)(connection);
13
15
  case 'mysql':
14
16
  return (0, mysqlConnector_1.fetchSchemaJson)(connection);
17
+ case 'snowflake':
18
+ return (0, snowflakeConnector_1.fetchSchemaJson)(connection);
19
+ case 'bigquery':
20
+ return (0, bigqueryConnector_1.fetchSchemaJson)(connection);
15
21
  default:
16
- throw new Error(`Unsupported connection format: ${format}`);
22
+ throw new Error(`Unsupported database type: ${databaseType}`);
17
23
  }
18
24
  };
19
25
  exports.fetchSchemaJson = fetchSchemaJson;
@@ -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,75 @@ 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
- 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,
122
- 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
147
- )
109
+ WITH tables_and_fields AS (
148
110
  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
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
168
130
  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
173
- ORDER BY
174
- tf.table_schema,
175
- tf.table_name,
176
- tf.column_name;
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
+ SELECT
145
+ tf.table_schema,
146
+ tf.table_name,
147
+ tf.column_name,
148
+ tf.data_type,
149
+ tf.character_maximum_length,
150
+ tf.numeric_precision,
151
+ tf.numeric_scale,
152
+ tf.identity_increment,
153
+ tf.is_nullable,
154
+ tf.column_default,
155
+ tf.table_comment,
156
+ tf.column_comment,
157
+ cc.name AS check_constraint_name, -- Adding CHECK constraint name
158
+ cc.definition AS check_constraint_definition, -- Adding CHECK constraint definition
159
+ CASE
160
+ WHEN tf.column_default LIKE '((%))' THEN 'number'
161
+ WHEN tf.column_default LIKE '(''%'')' THEN 'string'
162
+ ELSE 'expression'
163
+ END AS default_type
164
+ FROM
165
+ tables_and_fields AS tf
166
+ LEFT JOIN sys.check_constraints cc
167
+ ON cc.parent_object_id = OBJECT_ID(tf.table_schema + '.' + tf.table_name)
168
+ AND cc.definition LIKE '%' + tf.column_name + '%' -- Ensure the constraint references the column
169
+ ${(0, parseSchema_1.buildSchemaQuery)('tf.table_schema', schemas, 'WHERE')}
170
+ ORDER BY
171
+ tf.table_schema,
172
+ tf.table_name,
173
+ tf.column_name;
177
174
  `;
178
175
  const tablesAndFieldsResult = await client.query(tablesAndFieldsSql);
179
176
  const tables = tablesAndFieldsResult.recordset.reduce((acc, row) => {
@@ -212,7 +209,7 @@ const generateTablesFieldsAndEnums = async (client) => {
212
209
  enums,
213
210
  };
214
211
  };
215
- const generateRefs = async (client) => {
212
+ const generateRefs = async (client, schemas) => {
216
213
  const refs = [];
217
214
  const refsListSql = `
218
215
  SELECT
@@ -242,6 +239,7 @@ const generateRefs = async (client) => {
242
239
  JOIN sys.tables AS t2 ON fk.referenced_object_id = t2.object_id
243
240
  JOIN sys.schemas AS s2 ON t2.schema_id = s2.schema_id
244
241
  WHERE s.name NOT IN ('sys', 'information_schema')
242
+ ${(0, parseSchema_1.buildSchemaQuery)('s.name', schemas)}
245
243
  ORDER BY
246
244
  s.name,
247
245
  t.name;
@@ -270,7 +268,7 @@ const generateRefs = async (client) => {
270
268
  });
271
269
  return refs;
272
270
  };
273
- const generateIndexes = async (client) => {
271
+ const generateIndexes = async (client, schemas) => {
274
272
  const indexListSql = `
275
273
  WITH user_tables AS (
276
274
  SELECT
@@ -288,6 +286,7 @@ const generateIndexes = async (client) => {
288
286
  ),
289
287
  index_info AS (
290
288
  SELECT
289
+ SCHEMA_NAME(t.schema_id) AS table_schema, -- Add schema information
291
290
  OBJECT_NAME(i.object_id) AS table_name,
292
291
  i.name AS index_name,
293
292
  i.is_unique,
@@ -335,8 +334,10 @@ const generateIndexes = async (client) => {
335
334
  user_tables ut
336
335
  LEFT JOIN
337
336
  index_info ii ON ut.TABLE_NAME = ii.table_name
337
+ AND ut.TABLE_SCHEMA = ii.table_schema
338
338
  WHERE
339
339
  ii.columns IS NOT NULL
340
+ ${(0, parseSchema_1.buildSchemaQuery)('ut.TABLE_SCHEMA', schemas)}
340
341
  ORDER BY
341
342
  ut.TABLE_NAME,
342
343
  ii.constraint_type,
@@ -410,10 +411,11 @@ const generateIndexes = async (client) => {
410
411
  };
411
412
  };
412
413
  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);
414
+ const { connectionString, schemas } = (0, parseSchema_1.parseConnectionString)(connection, 'odbc');
415
+ const client = await getValidatedClient(connectionString);
416
+ const tablesFieldsAndEnumsRes = generateTablesFieldsAndEnums(client, schemas);
417
+ const indexesRes = generateIndexes(client, schemas);
418
+ const refsRes = generateRefs(client, schemas);
417
419
  const res = await Promise.all([
418
420
  tablesFieldsAndEnumsRes,
419
421
  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,7 +79,7 @@ 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 (
@@ -129,6 +130,7 @@ const generateTablesAndFields = async (client) => {
129
130
  WHERE
130
131
  t.table_type = 'BASE TABLE'
131
132
  AND t.table_schema NOT IN ('pg_catalog', 'information_schema')
133
+ ${(0, parseSchema_1.buildSchemaQuery)('t.table_schema', schemas)}
132
134
  ORDER BY
133
135
  t.table_schema,
134
136
  t.table_name,
@@ -157,7 +159,7 @@ const generateTablesAndFields = async (client) => {
157
159
  fields,
158
160
  };
159
161
  };
160
- const generateRawRefs = async (client) => {
162
+ const generateRawRefs = async (client, schemas) => {
161
163
  const refs = [];
162
164
  const refsListSql = `
163
165
  SELECT
@@ -182,6 +184,7 @@ const generateRawRefs = async (client) => {
182
184
  AND tc.table_schema = rc.constraint_schema
183
185
  WHERE tc.constraint_type = 'FOREIGN KEY'
184
186
  AND tc.table_schema NOT IN ('pg_catalog', 'information_schema')
187
+ ${(0, parseSchema_1.buildSchemaQuery)('tc.table_schema', schemas)}
185
188
  GROUP BY
186
189
  tc.table_schema,
187
190
  tc.table_name,
@@ -219,8 +222,7 @@ const generateRawRefs = async (client) => {
219
222
  });
220
223
  return refs;
221
224
  };
222
- const generateIndexes = async (client) => {
223
- // const tableConstraints = {};
225
+ const generateIndexes = async (client, schemas) => {
224
226
  const indexListSql = `
225
227
  WITH user_tables AS (
226
228
  SELECT
@@ -233,6 +235,7 @@ const generateIndexes = async (client) => {
233
235
  ),
234
236
  index_info AS (
235
237
  SELECT
238
+ t.relnamespace::regnamespace::text AS table_schema,
236
239
  t.relname AS table_name,
237
240
  i.relname AS index_name,
238
241
  ix.indisunique AS is_unique,
@@ -257,7 +260,7 @@ const generateIndexes = async (client) => {
257
260
  AND t.relname NOT LIKE 'pg_%'
258
261
  AND t.relname NOT LIKE 'sql_%'
259
262
  GROUP BY
260
- t.relname, i.relname, ix.indisunique, ix.indisprimary, am.amname, ix.indexprs, ix.indrelid
263
+ t.relnamespace, t.relname, i.relname, ix.indisunique, ix.indisprimary, am.amname, ix.indexprs, ix.indrelid
261
264
  )
262
265
  SELECT
263
266
  ut.tableschema AS table_schema,
@@ -268,12 +271,13 @@ const generateIndexes = async (client) => {
268
271
  ii.index_type,
269
272
  ii.columns,
270
273
  ii.expressions,
271
- ii.constraint_type -- Added constraint type
274
+ ii.constraint_type -- Retained constraint type here
272
275
  FROM
273
276
  user_tables ut
274
277
  LEFT JOIN
275
- index_info ii ON ut.tablename = ii.table_name
278
+ index_info ii ON ut.tableschema = ii.table_schema AND ut.tablename = ii.table_name
276
279
  WHERE ii.columns IS NOT NULL
280
+ ${(0, parseSchema_1.buildSchemaQuery)('ut.tableschema', schemas)}
277
281
  ORDER BY
278
282
  ut.tablename,
279
283
  ii.constraint_type,
@@ -349,7 +353,7 @@ const generateIndexes = async (client) => {
349
353
  tableConstraints,
350
354
  };
351
355
  };
352
- const generateRawEnums = async (client) => {
356
+ const generateRawEnums = async (client, schemas) => {
353
357
  const enumListSql = `
354
358
  SELECT
355
359
  n.nspname AS schema_name,
@@ -362,6 +366,7 @@ const generateRawEnums = async (client) => {
362
366
  pg_type t ON e.enumtypid = t.oid
363
367
  JOIN
364
368
  pg_namespace n ON t.typnamespace = n.oid
369
+ ${(0, parseSchema_1.buildSchemaQuery)('n.nspname', schemas, 'WHERE')}
365
370
  ORDER BY
366
371
  schema_name,
367
372
  enum_type,
@@ -386,11 +391,12 @@ const generateRawEnums = async (client) => {
386
391
  return Object.values(enums);
387
392
  };
388
393
  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);
394
+ const { connectionString, schemas } = (0, parseSchema_1.parseConnectionString)(connection, 'jdbc');
395
+ const client = await getValidatedClient(connectionString);
396
+ const tablesAndFieldsRes = generateTablesAndFields(client, schemas);
397
+ const indexesRes = generateIndexes(client, schemas);
398
+ const refsRes = generateRawRefs(client, schemas);
399
+ const enumsRes = generateRawEnums(client, schemas);
394
400
  const res = await Promise.all([
395
401
  tablesAndFieldsRes,
396
402
  indexesRes,
@@ -0,0 +1,3 @@
1
+ import { DatabaseSchema } from './types';
2
+ declare const fetchSchemaJson: (connection: string) => Promise<DatabaseSchema>;
3
+ export { fetchSchemaJson, };