dbgraph 0.1.3 → 0.1.5
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/README.ZH-cn.md +32 -9
- package/README.md +32 -9
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/introspect/base.d.ts.map +1 -1
- package/dist/introspect/base.js +8 -1
- package/dist/introspect/base.js.map +1 -1
- package/dist/introspect/connection.d.ts +5 -0
- package/dist/introspect/connection.d.ts.map +1 -1
- package/dist/introspect/connection.js +118 -1
- package/dist/introspect/connection.js.map +1 -1
- package/dist/introspect/index.d.ts +2 -0
- package/dist/introspect/index.d.ts.map +1 -1
- package/dist/introspect/index.js +9 -1
- package/dist/introspect/index.js.map +1 -1
- package/dist/introspect/mongodb.d.ts +51 -0
- package/dist/introspect/mongodb.d.ts.map +1 -0
- package/dist/introspect/mongodb.js +271 -0
- package/dist/introspect/mongodb.js.map +1 -0
- package/dist/introspect/mssql.d.ts +69 -0
- package/dist/introspect/mssql.d.ts.map +1 -0
- package/dist/introspect/mssql.js +409 -0
- package/dist/introspect/mssql.js.map +1 -0
- package/dist/introspect/postgres.d.ts.map +1 -1
- package/dist/introspect/postgres.js +88 -82
- package/dist/introspect/postgres.js.map +1 -1
- package/dist/mcp/tools.js +3 -3
- package/dist/mcp/tools.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MSSQL Introspector
|
|
4
|
+
*
|
|
5
|
+
* Extracts schemas, tables, columns, primary keys, foreign keys,
|
|
6
|
+
* indexes, and views from a Microsoft SQL Server database using
|
|
7
|
+
* INFORMATION_SCHEMA and sys catalog views.
|
|
8
|
+
*
|
|
9
|
+
* Connection: uses `connection.ts` which wraps the `mssql` package.
|
|
10
|
+
* The driver import is guarded so a missing `mssql` is reported at
|
|
11
|
+
* connect() time, not at module load time.
|
|
12
|
+
*
|
|
13
|
+
* MSSQL-specific metadata extracted:
|
|
14
|
+
* - Identity columns (via COLUMNPROPERTY)
|
|
15
|
+
* - Index metadata from sys.indexes / sys.index_columns / sys.columns
|
|
16
|
+
* - Schema-based organization (like PostgreSQL, unlike MySQL)
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.MSSQLIntrospector = void 0;
|
|
20
|
+
const base_1 = require("./base");
|
|
21
|
+
const connection_1 = require("./connection");
|
|
22
|
+
const utils_1 = require("../utils");
|
|
23
|
+
// =============================================================================
|
|
24
|
+
// MSSQLIntrospector
|
|
25
|
+
// =============================================================================
|
|
26
|
+
class MSSQLIntrospector extends base_1.BaseIntrospector {
|
|
27
|
+
constructor(config) {
|
|
28
|
+
super(config);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Full schema introspection pipeline.
|
|
32
|
+
*
|
|
33
|
+
* 1. Connect to the MSSQL database
|
|
34
|
+
* 2. Query schemas and filter by config.schemas if provided
|
|
35
|
+
* 3. Query all structural metadata in parallel
|
|
36
|
+
* 4. Build Node[] + Edge[]
|
|
37
|
+
* 5. Close connection and return the result
|
|
38
|
+
*/
|
|
39
|
+
async extractAll() {
|
|
40
|
+
const startTime = Date.now();
|
|
41
|
+
const errors = [];
|
|
42
|
+
const nodes = [];
|
|
43
|
+
const edges = [];
|
|
44
|
+
let conn;
|
|
45
|
+
try {
|
|
46
|
+
conn = await (0, connection_1.createConnection)(this.config);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
return {
|
|
50
|
+
nodes: [],
|
|
51
|
+
edges: [],
|
|
52
|
+
durationMs: Date.now() - startTime,
|
|
53
|
+
errors: [err.message],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
// ----- 1. Determine which schemas to introspect -----
|
|
58
|
+
// schemas: undefined → no filter (all schemas)
|
|
59
|
+
// schemas: ["*"] → explicit "all schemas" (no filter)
|
|
60
|
+
// schemas: ["public"] → filter specific schemas
|
|
61
|
+
// schemas: [] → introspect nothing
|
|
62
|
+
const hasFilter = this.config.schemas !== undefined && !this.config.schemas.includes('*');
|
|
63
|
+
const schemaFilter = new Set(this.config.schemas ?? []);
|
|
64
|
+
const schemas = await this.querySchemas(conn);
|
|
65
|
+
// Apply user-configured schema filter
|
|
66
|
+
const targetSchemas = hasFilter
|
|
67
|
+
? schemas.filter((r) => schemaFilter.has(r.schema_name))
|
|
68
|
+
: schemas;
|
|
69
|
+
if (targetSchemas.length === 0) {
|
|
70
|
+
errors.push(hasFilter
|
|
71
|
+
? (this.config.schemas.length > 0
|
|
72
|
+
? `No matching schemas found. Filter: ${this.config.schemas.join(', ')}`
|
|
73
|
+
: 'No schemas to introspect (schemas: [])')
|
|
74
|
+
: 'No non-system schemas found');
|
|
75
|
+
return { nodes, edges, durationMs: Date.now() - startTime, errors };
|
|
76
|
+
}
|
|
77
|
+
const schemaNames = targetSchemas.map((r) => r.schema_name);
|
|
78
|
+
// ----- 2. Fetch all raw metadata in parallel -----
|
|
79
|
+
const [tables, columns, pks, fks, indexes, views] = await Promise.all([
|
|
80
|
+
this.queryTables(conn, schemaNames),
|
|
81
|
+
this.queryColumns(conn, schemaNames),
|
|
82
|
+
this.queryPrimaryKeys(conn, schemaNames),
|
|
83
|
+
this.queryForeignKeys(conn, schemaNames),
|
|
84
|
+
this.queryIndexes(conn, schemaNames),
|
|
85
|
+
this.queryViews(conn, schemaNames),
|
|
86
|
+
]);
|
|
87
|
+
// ----- 3. Build schema nodes -----
|
|
88
|
+
const schemaNodeById = new Map(); // key = schema name
|
|
89
|
+
for (const s of targetSchemas) {
|
|
90
|
+
const qual = this.qn(s.schema_name);
|
|
91
|
+
const fp = this.schemaFilePath(s.schema_name);
|
|
92
|
+
const node = this.makeNode('schema', s.schema_name, qual, fp);
|
|
93
|
+
nodes.push(node);
|
|
94
|
+
schemaNodeById.set(s.schema_name, node);
|
|
95
|
+
}
|
|
96
|
+
// ----- 4. Build table nodes + contains edges (schema → table) -----
|
|
97
|
+
const tableNodeByKey = new Map(); // key = schema.table
|
|
98
|
+
for (const t of tables) {
|
|
99
|
+
const schemaNode = schemaNodeById.get(t.schema_name);
|
|
100
|
+
if (!schemaNode)
|
|
101
|
+
continue;
|
|
102
|
+
const key = this.tableKey(t.schema_name, t.table_name);
|
|
103
|
+
const kind = t.table_type === 'VIEW' ? 'view' : 'table';
|
|
104
|
+
const qual = this.qn(t.schema_name, t.table_name);
|
|
105
|
+
const fp = this.schemaFilePath(t.schema_name);
|
|
106
|
+
const node = this.makeNode(kind, t.table_name, qual, fp);
|
|
107
|
+
nodes.push(node);
|
|
108
|
+
tableNodeByKey.set(key, node);
|
|
109
|
+
edges.push(this.containEdge(schemaNode.id, node.id));
|
|
110
|
+
}
|
|
111
|
+
// ----- 5. Build column nodes + contains edges (table → column) -----
|
|
112
|
+
const columnNodeByKey = new Map(); // key = schema.table.column
|
|
113
|
+
for (const c of columns) {
|
|
114
|
+
const tableKey = this.tableKey(c.schema_name, c.table_name);
|
|
115
|
+
const tableNode = tableNodeByKey.get(tableKey);
|
|
116
|
+
if (!tableNode)
|
|
117
|
+
continue;
|
|
118
|
+
const colKey = this.columnKey(c.schema_name, c.table_name, c.column_name);
|
|
119
|
+
const qual = this.qn(c.schema_name, c.table_name, c.column_name);
|
|
120
|
+
const fp = this.schemaFilePath(c.schema_name);
|
|
121
|
+
const node = this.makeNode('column', c.column_name, qual, fp, {
|
|
122
|
+
startLine: c.ordinal_position ?? 0,
|
|
123
|
+
metadata: {
|
|
124
|
+
dataType: c.data_type,
|
|
125
|
+
isNullable: c.is_nullable === 'YES',
|
|
126
|
+
defaultValue: c.column_default ?? null,
|
|
127
|
+
maxLength: c.character_maximum_length ?? null,
|
|
128
|
+
numericPrecision: c.numeric_precision ?? null,
|
|
129
|
+
numericScale: c.numeric_scale ?? null,
|
|
130
|
+
isIdentity: c.is_identity === 1,
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
nodes.push(node);
|
|
134
|
+
columnNodeByKey.set(colKey, node);
|
|
135
|
+
edges.push(this.containEdge(tableNode.id, node.id));
|
|
136
|
+
}
|
|
137
|
+
// ----- 6. Primary key edges (table → column) -----
|
|
138
|
+
for (const pk of pks) {
|
|
139
|
+
const colKey = this.columnKey(pk.schema_name, pk.table_name, pk.column_name);
|
|
140
|
+
const colNode = columnNodeByKey.get(colKey);
|
|
141
|
+
const tableKey = this.tableKey(pk.schema_name, pk.table_name);
|
|
142
|
+
const tableNode = tableNodeByKey.get(tableKey);
|
|
143
|
+
if (colNode && tableNode) {
|
|
144
|
+
edges.push(this.makeEdge(tableNode.id, colNode.id, 'primary_key', {
|
|
145
|
+
constraintName: pk.constraint_name,
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// ----- 7. Foreign key references edges (column → referenced column) -----
|
|
150
|
+
for (const fk of fks) {
|
|
151
|
+
const fromKey = this.columnKey(fk.schema_name, fk.table_name, fk.column_name);
|
|
152
|
+
const toKey = this.columnKey(fk.ref_table_schema, fk.ref_table_name, fk.ref_column_name);
|
|
153
|
+
const fromNode = columnNodeByKey.get(fromKey);
|
|
154
|
+
const toNode = columnNodeByKey.get(toKey);
|
|
155
|
+
if (fromNode && toNode) {
|
|
156
|
+
edges.push(this.makeEdge(fromNode.id, toNode.id, 'references', {
|
|
157
|
+
constraintName: fk.constraint_name,
|
|
158
|
+
onUpdate: fk.update_rule,
|
|
159
|
+
onDelete: fk.delete_rule,
|
|
160
|
+
}));
|
|
161
|
+
}
|
|
162
|
+
else if (fromNode) {
|
|
163
|
+
// Cross-schema FK reference — emit unresolved edge
|
|
164
|
+
edges.push(this.makeEdge(fromNode.id, (0, utils_1.hashString)(`${fk.ref_table_schema}.${fk.ref_table_name}.${fk.ref_column_name}`), 'references', {
|
|
165
|
+
constraintName: fk.constraint_name,
|
|
166
|
+
onUpdate: fk.update_rule,
|
|
167
|
+
onDelete: fk.delete_rule,
|
|
168
|
+
refTableSchema: fk.ref_table_schema,
|
|
169
|
+
refTableName: fk.ref_table_name,
|
|
170
|
+
refColumn: fk.ref_column_name,
|
|
171
|
+
unresolved: true,
|
|
172
|
+
}));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// ----- 8. Index nodes + indexed_by edges -----
|
|
176
|
+
// Group index rows to collect column lists (one row per index × column)
|
|
177
|
+
const indexGroups = new Map();
|
|
178
|
+
for (const idx of indexes) {
|
|
179
|
+
const indexKey = `${idx.schema_name}.${idx.table_name}.${idx.index_name}`;
|
|
180
|
+
if (!indexGroups.has(indexKey)) {
|
|
181
|
+
indexGroups.set(indexKey, {
|
|
182
|
+
schema: idx.schema_name,
|
|
183
|
+
table: idx.table_name,
|
|
184
|
+
indexName: idx.index_name,
|
|
185
|
+
isUnique: idx.is_unique,
|
|
186
|
+
isPrimaryKey: idx.is_primary_key,
|
|
187
|
+
columns: [],
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
indexGroups.get(indexKey).columns.push(idx.column_name);
|
|
191
|
+
}
|
|
192
|
+
for (const [, grp] of indexGroups) {
|
|
193
|
+
const tableKey = this.tableKey(grp.schema, grp.table);
|
|
194
|
+
const tableNode = tableNodeByKey.get(tableKey);
|
|
195
|
+
if (!tableNode)
|
|
196
|
+
continue;
|
|
197
|
+
if (grp.isPrimaryKey)
|
|
198
|
+
continue; // PK already handled via primary_key edges
|
|
199
|
+
const qual = this.qn(grp.schema, grp.table, grp.indexName);
|
|
200
|
+
const fp = this.schemaFilePath(grp.schema);
|
|
201
|
+
const node = this.makeNode('index', grp.indexName, qual, fp, {
|
|
202
|
+
metadata: {
|
|
203
|
+
unique: grp.isUnique,
|
|
204
|
+
columns: grp.columns,
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
nodes.push(node);
|
|
208
|
+
edges.push(this.containEdge(tableNode.id, node.id));
|
|
209
|
+
edges.push(this.makeEdge(tableNode.id, node.id, 'indexed_by'));
|
|
210
|
+
}
|
|
211
|
+
// ----- 9. Attach view definitions as signatures -----
|
|
212
|
+
const viewDefMap = new Map();
|
|
213
|
+
for (const v of views) {
|
|
214
|
+
const key = this.tableKey(v.schema_name, v.table_name);
|
|
215
|
+
if (v.view_definition)
|
|
216
|
+
viewDefMap.set(key, v.view_definition);
|
|
217
|
+
}
|
|
218
|
+
for (const node of nodes) {
|
|
219
|
+
if (node.kind !== 'view')
|
|
220
|
+
continue;
|
|
221
|
+
// qualifiedName = alias.schema.viewname → extract last two parts
|
|
222
|
+
const parts = node.qualifiedName.split('.');
|
|
223
|
+
if (parts.length < 3)
|
|
224
|
+
continue;
|
|
225
|
+
const schema = parts[parts.length - 2];
|
|
226
|
+
const viewName = parts[parts.length - 1];
|
|
227
|
+
const def = viewDefMap.get(this.tableKey(schema, viewName));
|
|
228
|
+
if (def)
|
|
229
|
+
node.signature = def;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
errors.push(`Introspection error: ${err.message}`);
|
|
234
|
+
}
|
|
235
|
+
finally {
|
|
236
|
+
await conn.close();
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
nodes,
|
|
240
|
+
edges,
|
|
241
|
+
durationMs: Date.now() - startTime,
|
|
242
|
+
errors,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
// ===========================================================================
|
|
246
|
+
// Query Methods
|
|
247
|
+
//
|
|
248
|
+
// MSSQL INFORMATION_SCHEMA uses UPPERCASE column names.
|
|
249
|
+
// Each query fetches ALL data and then JS-filters by schemaNames to avoid
|
|
250
|
+
// parameter-binding complexities with the mssql driver.
|
|
251
|
+
// ===========================================================================
|
|
252
|
+
/**
|
|
253
|
+
* Query: non-system schemas.
|
|
254
|
+
*/
|
|
255
|
+
async querySchemas(conn) {
|
|
256
|
+
return (await conn.query(`SELECT SCHEMA_NAME AS schema_name
|
|
257
|
+
FROM INFORMATION_SCHEMA.SCHEMATA
|
|
258
|
+
WHERE SCHEMA_NAME NOT IN ('sys', 'INFORMATION_SCHEMA', 'guest')
|
|
259
|
+
AND SCHEMA_NAME NOT LIKE 'db_%'
|
|
260
|
+
ORDER BY SCHEMA_NAME`));
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Query: tables and views (BASE TABLE or VIEW).
|
|
264
|
+
*/
|
|
265
|
+
async queryTables(conn, schemaNames) {
|
|
266
|
+
if (schemaNames.length === 0)
|
|
267
|
+
return [];
|
|
268
|
+
const placeholders = schemaNames.map(() => '?').join(',');
|
|
269
|
+
return (await conn.query(`SELECT TABLE_SCHEMA AS schema_name,
|
|
270
|
+
TABLE_NAME AS table_name,
|
|
271
|
+
TABLE_TYPE AS table_type
|
|
272
|
+
FROM INFORMATION_SCHEMA.TABLES
|
|
273
|
+
WHERE TABLE_TYPE IN ('BASE TABLE', 'VIEW')
|
|
274
|
+
AND TABLE_SCHEMA IN (${placeholders})
|
|
275
|
+
ORDER BY TABLE_NAME`, schemaNames));
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Query: columns with identity detection via COLUMNPROPERTY.
|
|
279
|
+
*/
|
|
280
|
+
async queryColumns(conn, schemaNames) {
|
|
281
|
+
if (schemaNames.length === 0)
|
|
282
|
+
return [];
|
|
283
|
+
const placeholders = schemaNames.map(() => '?').join(',');
|
|
284
|
+
return (await conn.query(`SELECT c.TABLE_SCHEMA AS schema_name,
|
|
285
|
+
c.TABLE_NAME AS table_name,
|
|
286
|
+
c.COLUMN_NAME AS column_name,
|
|
287
|
+
c.DATA_TYPE AS data_type,
|
|
288
|
+
c.IS_NULLABLE AS is_nullable,
|
|
289
|
+
c.COLUMN_DEFAULT AS column_default,
|
|
290
|
+
c.CHARACTER_MAXIMUM_LENGTH AS character_maximum_length,
|
|
291
|
+
c.NUMERIC_PRECISION AS numeric_precision,
|
|
292
|
+
c.NUMERIC_SCALE AS numeric_scale,
|
|
293
|
+
c.ORDINAL_POSITION AS ordinal_position,
|
|
294
|
+
COLUMNPROPERTY(OBJECT_ID(QUOTENAME(c.TABLE_SCHEMA) + '.' + QUOTENAME(c.TABLE_NAME)), c.COLUMN_NAME, 'IsIdentity') AS is_identity
|
|
295
|
+
FROM INFORMATION_SCHEMA.COLUMNS c
|
|
296
|
+
WHERE c.TABLE_SCHEMA IN (${placeholders})
|
|
297
|
+
ORDER BY c.TABLE_NAME, c.ORDINAL_POSITION`, schemaNames));
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Query: columns that are part of a PRIMARY KEY constraint.
|
|
301
|
+
*/
|
|
302
|
+
async queryPrimaryKeys(conn, schemaNames) {
|
|
303
|
+
if (schemaNames.length === 0)
|
|
304
|
+
return [];
|
|
305
|
+
const placeholders = schemaNames.map(() => '?').join(',');
|
|
306
|
+
return (await conn.query(`SELECT tc.TABLE_SCHEMA AS schema_name,
|
|
307
|
+
tc.TABLE_NAME AS table_name,
|
|
308
|
+
tc.CONSTRAINT_NAME AS constraint_name,
|
|
309
|
+
kcu.COLUMN_NAME AS column_name
|
|
310
|
+
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
|
|
311
|
+
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
|
|
312
|
+
ON tc.CONSTRAINT_CATALOG = kcu.CONSTRAINT_CATALOG
|
|
313
|
+
AND tc.CONSTRAINT_SCHEMA = kcu.CONSTRAINT_SCHEMA
|
|
314
|
+
AND tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
|
|
315
|
+
AND tc.TABLE_SCHEMA = kcu.TABLE_SCHEMA
|
|
316
|
+
AND tc.TABLE_NAME = kcu.TABLE_NAME
|
|
317
|
+
WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
|
|
318
|
+
AND tc.TABLE_SCHEMA IN (${placeholders})
|
|
319
|
+
ORDER BY tc.TABLE_NAME, kcu.ORDINAL_POSITION`, schemaNames));
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Query: foreign key columns + referential actions.
|
|
323
|
+
*
|
|
324
|
+
* Uses sys.foreign_keys / sys.foreign_key_columns catalog views
|
|
325
|
+
* (faster than the INFORMATION_SCHEMA 4-table join).
|
|
326
|
+
* Referential action codes are mapped via CASE:
|
|
327
|
+
* 0 = NO ACTION, 1 = CASCADE, 2 = SET_NULL, 3 = SET_DEFAULT
|
|
328
|
+
*/
|
|
329
|
+
async queryForeignKeys(conn, schemaNames) {
|
|
330
|
+
if (schemaNames.length === 0)
|
|
331
|
+
return [];
|
|
332
|
+
const placeholders = schemaNames.map(() => '?').join(',');
|
|
333
|
+
return (await conn.query(`SELECT s.name AS schema_name,
|
|
334
|
+
OBJECT_NAME(fk.parent_object_id) AS table_name,
|
|
335
|
+
fk.name AS constraint_name,
|
|
336
|
+
COL_NAME(fkc.parent_object_id, fkc.parent_column_id) AS column_name,
|
|
337
|
+
ref_s.name AS ref_table_schema,
|
|
338
|
+
OBJECT_NAME(fk.referenced_object_id) AS ref_table_name,
|
|
339
|
+
COL_NAME(fkc.referenced_object_id, fkc.referenced_column_id) AS ref_column_name,
|
|
340
|
+
CASE fk.update_referential_action
|
|
341
|
+
WHEN 0 THEN 'NO ACTION'
|
|
342
|
+
WHEN 1 THEN 'CASCADE'
|
|
343
|
+
WHEN 2 THEN 'SET_NULL'
|
|
344
|
+
WHEN 3 THEN 'SET_DEFAULT'
|
|
345
|
+
END AS update_rule,
|
|
346
|
+
CASE fk.delete_referential_action
|
|
347
|
+
WHEN 0 THEN 'NO ACTION'
|
|
348
|
+
WHEN 1 THEN 'CASCADE'
|
|
349
|
+
WHEN 2 THEN 'SET_NULL'
|
|
350
|
+
WHEN 3 THEN 'SET_DEFAULT'
|
|
351
|
+
END AS delete_rule
|
|
352
|
+
FROM sys.foreign_keys fk
|
|
353
|
+
JOIN sys.foreign_key_columns fkc
|
|
354
|
+
ON fk.object_id = fkc.constraint_object_id
|
|
355
|
+
JOIN sys.tables pt
|
|
356
|
+
ON fk.parent_object_id = pt.object_id
|
|
357
|
+
JOIN sys.schemas s
|
|
358
|
+
ON pt.schema_id = s.schema_id
|
|
359
|
+
JOIN sys.tables rt
|
|
360
|
+
ON fk.referenced_object_id = rt.object_id
|
|
361
|
+
JOIN sys.schemas ref_s
|
|
362
|
+
ON rt.schema_id = ref_s.schema_id
|
|
363
|
+
WHERE s.name IN (${placeholders})
|
|
364
|
+
ORDER BY pt.name, fk.name, fkc.constraint_column_id`, schemaNames));
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Query: index columns from sys.indexes / sys.index_columns / sys.columns.
|
|
368
|
+
*
|
|
369
|
+
* MSSQL does NOT expose index metadata in INFORMATION_SCHEMA, so we query
|
|
370
|
+
* the sys catalog views instead. Returns one row per (index × column),
|
|
371
|
+
* grouped later in the build step.
|
|
372
|
+
*/
|
|
373
|
+
async queryIndexes(conn, schemaNames) {
|
|
374
|
+
if (schemaNames.length === 0)
|
|
375
|
+
return [];
|
|
376
|
+
const placeholders = schemaNames.map(() => '?').join(',');
|
|
377
|
+
return (await conn.query(`SELECT s.name AS schema_name,
|
|
378
|
+
o.name AS table_name,
|
|
379
|
+
i.name AS index_name,
|
|
380
|
+
i.is_unique AS is_unique,
|
|
381
|
+
i.is_primary_key AS is_primary_key,
|
|
382
|
+
c.name AS column_name,
|
|
383
|
+
ic.key_ordinal AS ordinal_position
|
|
384
|
+
FROM sys.indexes i
|
|
385
|
+
JOIN sys.objects o ON i.object_id = o.object_id
|
|
386
|
+
JOIN sys.schemas s ON o.schema_id = s.schema_id
|
|
387
|
+
JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
|
|
388
|
+
JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = ic.column_id
|
|
389
|
+
WHERE o.type IN ('U', 'V')
|
|
390
|
+
AND s.name IN (${placeholders})
|
|
391
|
+
ORDER BY o.name, i.name, ic.key_ordinal`, schemaNames));
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Query: view definitions.
|
|
395
|
+
*/
|
|
396
|
+
async queryViews(conn, schemaNames) {
|
|
397
|
+
if (schemaNames.length === 0)
|
|
398
|
+
return [];
|
|
399
|
+
const placeholders = schemaNames.map(() => '?').join(',');
|
|
400
|
+
return (await conn.query(`SELECT v.TABLE_SCHEMA AS schema_name,
|
|
401
|
+
v.TABLE_NAME AS table_name,
|
|
402
|
+
v.VIEW_DEFINITION AS view_definition
|
|
403
|
+
FROM INFORMATION_SCHEMA.VIEWS v
|
|
404
|
+
WHERE v.TABLE_SCHEMA IN (${placeholders})
|
|
405
|
+
ORDER BY v.TABLE_NAME`, schemaNames));
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
exports.MSSQLIntrospector = MSSQLIntrospector;
|
|
409
|
+
//# sourceMappingURL=mssql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mssql.js","sourceRoot":"","sources":["../../src/introspect/mssql.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/introspect/postgres.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAKnB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAuE1C,qBAAa,oBAAqB,SAAQ,gBAAgB;gBAC5C,MAAM,EAAE,kBAAkB;IAItC;;;;;;;OAOG;IACG,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/introspect/postgres.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAKnB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAuE1C,qBAAa,oBAAqB,SAAQ,gBAAgB;gBAC5C,MAAM,EAAE,kBAAkB;IAItC;;;;;;;OAOG;IACG,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC;IA8O7C;;OAEG;YACW,YAAY;IAW1B;;;OAGG;YACW,WAAW;IAqBzB;;OAEG;YACW,YAAY;IA8B1B;;OAEG;YACW,gBAAgB;IAsB9B;;OAEG;YACW,gBAAgB;IAmC9B;;OAEG;YACW,YAAY;IAiB1B;;OAEG;YACW,UAAU;CAezB"}
|
|
@@ -48,7 +48,11 @@ class PostgresIntrospector extends base_1.BaseIntrospector {
|
|
|
48
48
|
}
|
|
49
49
|
try {
|
|
50
50
|
// ----- 1. Determine which schemas to introspect -----
|
|
51
|
-
|
|
51
|
+
// schemas: undefined → no filter (all schemas)
|
|
52
|
+
// schemas: ["*"] → explicit "all schemas" (no filter)
|
|
53
|
+
// schemas: ["public"] → filter specific schemas
|
|
54
|
+
// schemas: [] → introspect nothing
|
|
55
|
+
const hasFilter = this.config.schemas !== undefined && !this.config.schemas.includes('*');
|
|
52
56
|
const schemaFilter = new Set(this.config.schemas ?? []);
|
|
53
57
|
const schemas = await this.querySchemas(conn);
|
|
54
58
|
// Apply user-configured schema filter
|
|
@@ -57,7 +61,9 @@ class PostgresIntrospector extends base_1.BaseIntrospector {
|
|
|
57
61
|
: schemas;
|
|
58
62
|
if (targetSchemas.length === 0) {
|
|
59
63
|
errors.push(hasFilter
|
|
60
|
-
?
|
|
64
|
+
? (this.config.schemas.length > 0
|
|
65
|
+
? `No matching schemas found. Filter: ${this.config.schemas.join(', ')}`
|
|
66
|
+
: 'No schemas to introspect (schemas: [])')
|
|
61
67
|
: 'No non-system schemas found');
|
|
62
68
|
return { nodes, edges, durationMs: Date.now() - startTime, errors };
|
|
63
69
|
}
|
|
@@ -236,11 +242,11 @@ class PostgresIntrospector extends base_1.BaseIntrospector {
|
|
|
236
242
|
* Query: non-system schemas.
|
|
237
243
|
*/
|
|
238
244
|
async querySchemas(conn) {
|
|
239
|
-
return (await conn.query(`-- Schemas
|
|
240
|
-
SELECT schema_name
|
|
241
|
-
FROM information_schema.schemata
|
|
242
|
-
WHERE schema_name NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
|
|
243
|
-
AND schema_name NOT LIKE 'pg_%'
|
|
245
|
+
return (await conn.query(`-- Schemas
|
|
246
|
+
SELECT schema_name
|
|
247
|
+
FROM information_schema.schemata
|
|
248
|
+
WHERE schema_name NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
|
|
249
|
+
AND schema_name NOT LIKE 'pg_%'
|
|
244
250
|
ORDER BY schema_name`));
|
|
245
251
|
}
|
|
246
252
|
/**
|
|
@@ -250,16 +256,16 @@ class PostgresIntrospector extends base_1.BaseIntrospector {
|
|
|
250
256
|
async queryTables(conn, schemaNames) {
|
|
251
257
|
if (schemaNames.length === 0)
|
|
252
258
|
return [];
|
|
253
|
-
return (await conn.query(`SELECT t.table_schema AS schema_name,
|
|
254
|
-
t.table_name,
|
|
255
|
-
t.table_type,
|
|
256
|
-
pg_catalog.obj_description(
|
|
257
|
-
(quote_ident(t.table_schema) || '.' || quote_ident(t.table_name))::regclass,
|
|
258
|
-
'pg_class'
|
|
259
|
-
) AS comment
|
|
260
|
-
FROM information_schema.tables t
|
|
261
|
-
WHERE t.table_schema = ANY($1)
|
|
262
|
-
AND t.table_type IN ('BASE TABLE', 'VIEW')
|
|
259
|
+
return (await conn.query(`SELECT t.table_schema AS schema_name,
|
|
260
|
+
t.table_name,
|
|
261
|
+
t.table_type,
|
|
262
|
+
pg_catalog.obj_description(
|
|
263
|
+
(quote_ident(t.table_schema) || '.' || quote_ident(t.table_name))::regclass,
|
|
264
|
+
'pg_class'
|
|
265
|
+
) AS comment
|
|
266
|
+
FROM information_schema.tables t
|
|
267
|
+
WHERE t.table_schema = ANY($1)
|
|
268
|
+
AND t.table_type IN ('BASE TABLE', 'VIEW')
|
|
263
269
|
ORDER BY t.table_name`, [schemaNames]));
|
|
264
270
|
}
|
|
265
271
|
/**
|
|
@@ -268,25 +274,25 @@ class PostgresIntrospector extends base_1.BaseIntrospector {
|
|
|
268
274
|
async queryColumns(conn, schemaNames) {
|
|
269
275
|
if (schemaNames.length === 0)
|
|
270
276
|
return [];
|
|
271
|
-
return (await conn.query(`SELECT c.table_schema AS schema_name,
|
|
272
|
-
c.table_name,
|
|
273
|
-
c.column_name,
|
|
274
|
-
c.data_type,
|
|
275
|
-
c.is_nullable,
|
|
276
|
-
c.column_default,
|
|
277
|
-
c.character_maximum_length,
|
|
278
|
-
c.numeric_precision,
|
|
279
|
-
c.numeric_scale,
|
|
280
|
-
c.datetime_precision,
|
|
281
|
-
c.ordinal_position,
|
|
282
|
-
c.udt_name,
|
|
283
|
-
c.collation_name,
|
|
284
|
-
pg_catalog.col_description(
|
|
285
|
-
(quote_ident(c.table_schema) || '.' || quote_ident(c.table_name))::regclass,
|
|
286
|
-
c.ordinal_position::integer
|
|
287
|
-
) AS description
|
|
288
|
-
FROM information_schema.columns c
|
|
289
|
-
WHERE c.table_schema = ANY($1)
|
|
277
|
+
return (await conn.query(`SELECT c.table_schema AS schema_name,
|
|
278
|
+
c.table_name,
|
|
279
|
+
c.column_name,
|
|
280
|
+
c.data_type,
|
|
281
|
+
c.is_nullable,
|
|
282
|
+
c.column_default,
|
|
283
|
+
c.character_maximum_length,
|
|
284
|
+
c.numeric_precision,
|
|
285
|
+
c.numeric_scale,
|
|
286
|
+
c.datetime_precision,
|
|
287
|
+
c.ordinal_position,
|
|
288
|
+
c.udt_name,
|
|
289
|
+
c.collation_name,
|
|
290
|
+
pg_catalog.col_description(
|
|
291
|
+
(quote_ident(c.table_schema) || '.' || quote_ident(c.table_name))::regclass,
|
|
292
|
+
c.ordinal_position::integer
|
|
293
|
+
) AS description
|
|
294
|
+
FROM information_schema.columns c
|
|
295
|
+
WHERE c.table_schema = ANY($1)
|
|
290
296
|
ORDER BY c.table_name, c.ordinal_position`, [schemaNames]));
|
|
291
297
|
}
|
|
292
298
|
/**
|
|
@@ -295,17 +301,17 @@ class PostgresIntrospector extends base_1.BaseIntrospector {
|
|
|
295
301
|
async queryPrimaryKeys(conn, schemaNames) {
|
|
296
302
|
if (schemaNames.length === 0)
|
|
297
303
|
return [];
|
|
298
|
-
return (await conn.query(`SELECT tc.table_schema AS schema_name,
|
|
299
|
-
tc.table_name,
|
|
300
|
-
tc.constraint_name,
|
|
301
|
-
kcu.column_name
|
|
302
|
-
FROM information_schema.table_constraints tc
|
|
303
|
-
JOIN information_schema.key_column_usage kcu
|
|
304
|
-
ON tc.constraint_catalog = kcu.constraint_catalog
|
|
305
|
-
AND tc.constraint_schema = kcu.constraint_schema
|
|
306
|
-
AND tc.constraint_name = kcu.constraint_name
|
|
307
|
-
WHERE tc.table_schema = ANY($1)
|
|
308
|
-
AND tc.constraint_type = 'PRIMARY KEY'
|
|
304
|
+
return (await conn.query(`SELECT tc.table_schema AS schema_name,
|
|
305
|
+
tc.table_name,
|
|
306
|
+
tc.constraint_name,
|
|
307
|
+
kcu.column_name
|
|
308
|
+
FROM information_schema.table_constraints tc
|
|
309
|
+
JOIN information_schema.key_column_usage kcu
|
|
310
|
+
ON tc.constraint_catalog = kcu.constraint_catalog
|
|
311
|
+
AND tc.constraint_schema = kcu.constraint_schema
|
|
312
|
+
AND tc.constraint_name = kcu.constraint_name
|
|
313
|
+
WHERE tc.table_schema = ANY($1)
|
|
314
|
+
AND tc.constraint_type = 'PRIMARY KEY'
|
|
309
315
|
ORDER BY tc.table_name, kcu.ordinal_position`, [schemaNames]));
|
|
310
316
|
}
|
|
311
317
|
/**
|
|
@@ -314,30 +320,30 @@ class PostgresIntrospector extends base_1.BaseIntrospector {
|
|
|
314
320
|
async queryForeignKeys(conn, schemaNames) {
|
|
315
321
|
if (schemaNames.length === 0)
|
|
316
322
|
return [];
|
|
317
|
-
return (await conn.query(`SELECT tc.table_schema AS schema_name,
|
|
318
|
-
tc.table_name,
|
|
319
|
-
tc.constraint_name,
|
|
320
|
-
kcu.column_name,
|
|
321
|
-
ccu.table_schema AS ref_table_schema,
|
|
322
|
-
ccu.table_name AS ref_table_name,
|
|
323
|
-
ccu.column_name AS ref_column_name,
|
|
324
|
-
rc.update_rule,
|
|
325
|
-
rc.delete_rule
|
|
326
|
-
FROM information_schema.table_constraints tc
|
|
327
|
-
JOIN information_schema.key_column_usage kcu
|
|
328
|
-
ON tc.constraint_catalog = kcu.constraint_catalog
|
|
329
|
-
AND tc.constraint_schema = kcu.constraint_schema
|
|
330
|
-
AND tc.constraint_name = kcu.constraint_name
|
|
331
|
-
JOIN information_schema.constraint_column_usage ccu
|
|
332
|
-
ON ccu.constraint_catalog = tc.constraint_catalog
|
|
333
|
-
AND ccu.constraint_schema = tc.constraint_schema
|
|
334
|
-
AND ccu.constraint_name = tc.constraint_name
|
|
335
|
-
JOIN information_schema.referential_constraints rc
|
|
336
|
-
ON rc.constraint_catalog = tc.constraint_catalog
|
|
337
|
-
AND rc.constraint_schema = tc.constraint_schema
|
|
338
|
-
AND rc.constraint_name = tc.constraint_name
|
|
339
|
-
WHERE tc.table_schema = ANY($1)
|
|
340
|
-
AND tc.constraint_type = 'FOREIGN KEY'
|
|
323
|
+
return (await conn.query(`SELECT tc.table_schema AS schema_name,
|
|
324
|
+
tc.table_name,
|
|
325
|
+
tc.constraint_name,
|
|
326
|
+
kcu.column_name,
|
|
327
|
+
ccu.table_schema AS ref_table_schema,
|
|
328
|
+
ccu.table_name AS ref_table_name,
|
|
329
|
+
ccu.column_name AS ref_column_name,
|
|
330
|
+
rc.update_rule,
|
|
331
|
+
rc.delete_rule
|
|
332
|
+
FROM information_schema.table_constraints tc
|
|
333
|
+
JOIN information_schema.key_column_usage kcu
|
|
334
|
+
ON tc.constraint_catalog = kcu.constraint_catalog
|
|
335
|
+
AND tc.constraint_schema = kcu.constraint_schema
|
|
336
|
+
AND tc.constraint_name = kcu.constraint_name
|
|
337
|
+
JOIN information_schema.constraint_column_usage ccu
|
|
338
|
+
ON ccu.constraint_catalog = tc.constraint_catalog
|
|
339
|
+
AND ccu.constraint_schema = tc.constraint_schema
|
|
340
|
+
AND ccu.constraint_name = tc.constraint_name
|
|
341
|
+
JOIN information_schema.referential_constraints rc
|
|
342
|
+
ON rc.constraint_catalog = tc.constraint_catalog
|
|
343
|
+
AND rc.constraint_schema = tc.constraint_schema
|
|
344
|
+
AND rc.constraint_name = tc.constraint_name
|
|
345
|
+
WHERE tc.table_schema = ANY($1)
|
|
346
|
+
AND tc.constraint_type = 'FOREIGN KEY'
|
|
341
347
|
ORDER BY tc.table_name, tc.constraint_name, kcu.ordinal_position`, [schemaNames]));
|
|
342
348
|
}
|
|
343
349
|
/**
|
|
@@ -346,12 +352,12 @@ class PostgresIntrospector extends base_1.BaseIntrospector {
|
|
|
346
352
|
async queryIndexes(conn, schemaNames) {
|
|
347
353
|
if (schemaNames.length === 0)
|
|
348
354
|
return [];
|
|
349
|
-
return (await conn.query(`SELECT pi.schemaname AS schema_name,
|
|
350
|
-
pi.tablename AS table_name,
|
|
351
|
-
pi.indexname,
|
|
352
|
-
pi.indexdef
|
|
353
|
-
FROM pg_indexes pi
|
|
354
|
-
WHERE pi.schemaname = ANY($1)
|
|
355
|
+
return (await conn.query(`SELECT pi.schemaname AS schema_name,
|
|
356
|
+
pi.tablename AS table_name,
|
|
357
|
+
pi.indexname,
|
|
358
|
+
pi.indexdef
|
|
359
|
+
FROM pg_indexes pi
|
|
360
|
+
WHERE pi.schemaname = ANY($1)
|
|
355
361
|
ORDER BY pi.tablename, pi.indexname`, [schemaNames]));
|
|
356
362
|
}
|
|
357
363
|
/**
|
|
@@ -360,11 +366,11 @@ class PostgresIntrospector extends base_1.BaseIntrospector {
|
|
|
360
366
|
async queryViews(conn, schemaNames) {
|
|
361
367
|
if (schemaNames.length === 0)
|
|
362
368
|
return [];
|
|
363
|
-
return (await conn.query(`SELECT v.table_schema AS schema_name,
|
|
364
|
-
v.table_name,
|
|
365
|
-
v.view_definition
|
|
366
|
-
FROM information_schema.views v
|
|
367
|
-
WHERE v.table_schema = ANY($1)
|
|
369
|
+
return (await conn.query(`SELECT v.table_schema AS schema_name,
|
|
370
|
+
v.table_name,
|
|
371
|
+
v.view_definition
|
|
372
|
+
FROM information_schema.views v
|
|
373
|
+
WHERE v.table_schema = ANY($1)
|
|
368
374
|
ORDER BY v.table_name`, [schemaNames]));
|
|
369
375
|
}
|
|
370
376
|
}
|