schema-navigator-mcp 0.2.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.
- package/LICENSE +21 -0
- package/README.md +215 -0
- package/dist/db/pg-adapter.d.ts +17 -0
- package/dist/db/pg-adapter.js +74 -0
- package/dist/db/pg-adapter.js.map +1 -0
- package/dist/db/postgres.d.ts +19 -0
- package/dist/db/postgres.js +34 -0
- package/dist/db/postgres.js.map +1 -0
- package/dist/db/supabase-adapter.d.ts +45 -0
- package/dist/db/supabase-adapter.js +148 -0
- package/dist/db/supabase-adapter.js.map +1 -0
- package/dist/db/types.d.ts +25 -0
- package/dist/db/types.js +2 -0
- package/dist/db/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +129 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/constraints.d.ts +22 -0
- package/dist/tools/constraints.js +80 -0
- package/dist/tools/constraints.js.map +1 -0
- package/dist/tools/functions.d.ts +20 -0
- package/dist/tools/functions.js +118 -0
- package/dist/tools/functions.js.map +1 -0
- package/dist/tools/overview.d.ts +29 -0
- package/dist/tools/overview.js +142 -0
- package/dist/tools/overview.js.map +1 -0
- package/dist/tools/policies.d.ts +29 -0
- package/dist/tools/policies.js +96 -0
- package/dist/tools/policies.js.map +1 -0
- package/dist/tools/relations.d.ts +18 -0
- package/dist/tools/relations.js +72 -0
- package/dist/tools/relations.js.map +1 -0
- package/dist/tools/search.d.ts +13 -0
- package/dist/tools/search.js +77 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/table-profile.d.ts +68 -0
- package/dist/tools/table-profile.js +477 -0
- package/dist/tools/table-profile.js.map +1 -0
- package/dist/utils/check-parser.d.ts +17 -0
- package/dist/utils/check-parser.js +61 -0
- package/dist/utils/check-parser.js.map +1 -0
- package/dist/utils/pg-array.d.ts +6 -0
- package/dist/utils/pg-array.js +42 -0
- package/dist/utils/pg-array.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import { readOnlyMultiQuery, getIsPostgres } from "../db/postgres.js";
|
|
2
|
+
import { parseCheckExpression } from "../utils/check-parser.js";
|
|
3
|
+
import { parsePgArray } from "../utils/pg-array.js";
|
|
4
|
+
export async function schemaTable(tableName, schema) {
|
|
5
|
+
const isPg = getIsPostgres();
|
|
6
|
+
// Detect object type
|
|
7
|
+
const objectType = await detectObjectType(tableName, schema, isPg);
|
|
8
|
+
if (!objectType) {
|
|
9
|
+
return { error: `Table '${tableName}' not found in schema '${schema}'` };
|
|
10
|
+
}
|
|
11
|
+
if (objectType === "view") {
|
|
12
|
+
return profileView(tableName, schema, isPg);
|
|
13
|
+
}
|
|
14
|
+
if (objectType === "materialized view") {
|
|
15
|
+
return profileMatview(tableName, schema, isPg);
|
|
16
|
+
}
|
|
17
|
+
return profileTable(tableName, schema, isPg);
|
|
18
|
+
}
|
|
19
|
+
async function detectObjectType(name, schema, isPg) {
|
|
20
|
+
if (isPg) {
|
|
21
|
+
const queries = [
|
|
22
|
+
{
|
|
23
|
+
sql: `
|
|
24
|
+
SELECT CASE c.relkind
|
|
25
|
+
WHEN 'r' THEN 'table'
|
|
26
|
+
WHEN 'p' THEN 'partitioned table'
|
|
27
|
+
WHEN 'v' THEN 'view'
|
|
28
|
+
WHEN 'm' THEN 'materialized view'
|
|
29
|
+
END AS object_type
|
|
30
|
+
FROM pg_class c
|
|
31
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
32
|
+
WHERE n.nspname = $1 AND c.relname = $2
|
|
33
|
+
AND c.relkind IN ('r', 'p', 'v', 'm')
|
|
34
|
+
`,
|
|
35
|
+
params: [schema, name],
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
const [result] = await readOnlyMultiQuery(queries);
|
|
39
|
+
return result.rows[0]?.object_type ?? null;
|
|
40
|
+
}
|
|
41
|
+
// Fallback: information_schema
|
|
42
|
+
const queries = [
|
|
43
|
+
{
|
|
44
|
+
sql: `SELECT table_type FROM information_schema.tables WHERE table_schema = $1 AND table_name = $2`,
|
|
45
|
+
params: [schema, name],
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
const [result] = await readOnlyMultiQuery(queries);
|
|
49
|
+
if (result.rows.length === 0)
|
|
50
|
+
return null;
|
|
51
|
+
const tt = result.rows[0].table_type;
|
|
52
|
+
return tt === "VIEW" ? "view" : "table";
|
|
53
|
+
}
|
|
54
|
+
async function profileTable(tableName, schema, isPg) {
|
|
55
|
+
const queries = buildTableQueries(tableName, schema, isPg);
|
|
56
|
+
const results = await readOnlyMultiQuery(queries);
|
|
57
|
+
let idx = 0;
|
|
58
|
+
// Q1: Columns
|
|
59
|
+
const columnsResult = results[idx++];
|
|
60
|
+
const columns = columnsResult.rows.map((r) => ({
|
|
61
|
+
name: r.column_name,
|
|
62
|
+
type: r.data_type,
|
|
63
|
+
nullable: r.is_nullable === "YES",
|
|
64
|
+
default: r.column_default ?? null,
|
|
65
|
+
comment: r.description ?? null,
|
|
66
|
+
}));
|
|
67
|
+
// Q2: Constraints + FKs + Checks
|
|
68
|
+
const constraintsResult = results[idx++];
|
|
69
|
+
const constraints = [];
|
|
70
|
+
const fksOut = [];
|
|
71
|
+
for (const r of constraintsResult.rows) {
|
|
72
|
+
const conType = r.constraint_type;
|
|
73
|
+
if (conType === "FOREIGN KEY") {
|
|
74
|
+
fksOut.push({
|
|
75
|
+
constraint_name: r.constraint_name,
|
|
76
|
+
column: r.column_name,
|
|
77
|
+
foreign_table: r.foreign_table,
|
|
78
|
+
foreign_column: r.foreign_column,
|
|
79
|
+
on_delete: r.delete_rule ?? "NO ACTION",
|
|
80
|
+
on_update: r.update_rule ?? "NO ACTION",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
else if (conType === "CHECK") {
|
|
84
|
+
const parsed = parseCheckExpression(r.check_clause);
|
|
85
|
+
const constraint = {
|
|
86
|
+
name: r.constraint_name,
|
|
87
|
+
type: "CHECK",
|
|
88
|
+
columns: parsed.column ? [parsed.column] : [],
|
|
89
|
+
definition: r.check_clause,
|
|
90
|
+
};
|
|
91
|
+
if (parsed.type === "values" && parsed.allowed_values) {
|
|
92
|
+
constraint.allowed_values = parsed.allowed_values;
|
|
93
|
+
}
|
|
94
|
+
constraints.push(constraint);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
constraints.push({
|
|
98
|
+
name: r.constraint_name,
|
|
99
|
+
type: conType,
|
|
100
|
+
columns: r.column_name ? [r.column_name] : [],
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Q3: Indexes
|
|
105
|
+
const indexesResult = results[idx++];
|
|
106
|
+
const indexes = isPg
|
|
107
|
+
? indexesResult.rows.map((r) => ({
|
|
108
|
+
name: r.indexname,
|
|
109
|
+
columns: r.indexdef,
|
|
110
|
+
unique: r.indexdef.includes("UNIQUE"),
|
|
111
|
+
definition: r.indexdef,
|
|
112
|
+
}))
|
|
113
|
+
: [];
|
|
114
|
+
// Q4: RLS + Triggers
|
|
115
|
+
const rlsTriggersResult = results[idx++];
|
|
116
|
+
let rlsEnabled = null;
|
|
117
|
+
const policies = [];
|
|
118
|
+
const triggers = [];
|
|
119
|
+
if (isPg) {
|
|
120
|
+
// RLS enabled flag from sub-results
|
|
121
|
+
// Parse combined results
|
|
122
|
+
for (const r of rlsTriggersResult.rows) {
|
|
123
|
+
if (r.policyname != null) {
|
|
124
|
+
policies.push({
|
|
125
|
+
name: r.policyname,
|
|
126
|
+
command: r.cmd,
|
|
127
|
+
roles: parsePgArray(r.roles),
|
|
128
|
+
using: r.qual ?? null,
|
|
129
|
+
with_check: r.with_check ?? null,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
else if (r.trigger_name != null) {
|
|
133
|
+
triggers.push({
|
|
134
|
+
name: r.trigger_name,
|
|
135
|
+
event: r.event_manipulation,
|
|
136
|
+
timing: r.action_timing,
|
|
137
|
+
function: r.action_statement ?? "",
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Q5: Size + Row count + GRANTs + RLS flag
|
|
143
|
+
const metaResult = results[idx++];
|
|
144
|
+
let size = null;
|
|
145
|
+
let rowCount = null;
|
|
146
|
+
const grants = [];
|
|
147
|
+
if (isPg && metaResult.rows.length > 0) {
|
|
148
|
+
for (const r of metaResult.rows) {
|
|
149
|
+
if (r.total_size != null) {
|
|
150
|
+
size = r.total_size;
|
|
151
|
+
rowCount = r.row_estimate != null ? Number(r.row_estimate) : null;
|
|
152
|
+
rlsEnabled = r.rls_enabled;
|
|
153
|
+
}
|
|
154
|
+
else if (r.grantee != null) {
|
|
155
|
+
grants.push({
|
|
156
|
+
grantee: r.grantee,
|
|
157
|
+
privileges: parsePgArray(r.privileges),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// Inbound FKs
|
|
163
|
+
let fksIn = [];
|
|
164
|
+
if (isPg) {
|
|
165
|
+
const inboundResult = results[idx++];
|
|
166
|
+
fksIn = inboundResult.rows.map((r) => ({
|
|
167
|
+
constraint_name: r.constraint_name,
|
|
168
|
+
column: r.foreign_column,
|
|
169
|
+
foreign_table: r.source_table,
|
|
170
|
+
foreign_column: r.source_column,
|
|
171
|
+
on_delete: r.delete_rule ?? "NO ACTION",
|
|
172
|
+
on_update: r.update_rule ?? "NO ACTION",
|
|
173
|
+
}));
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
object_type: "table",
|
|
177
|
+
schema,
|
|
178
|
+
name: tableName,
|
|
179
|
+
columns,
|
|
180
|
+
constraints,
|
|
181
|
+
fks_out: fksOut,
|
|
182
|
+
fks_in: fksIn,
|
|
183
|
+
indexes,
|
|
184
|
+
triggers,
|
|
185
|
+
policies,
|
|
186
|
+
rls_enabled: rlsEnabled,
|
|
187
|
+
grants,
|
|
188
|
+
size,
|
|
189
|
+
row_count: rowCount,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function buildTableQueries(tableName, schema, isPg) {
|
|
193
|
+
const queries = [];
|
|
194
|
+
// Q1: Columns with comments
|
|
195
|
+
if (isPg) {
|
|
196
|
+
queries.push({
|
|
197
|
+
sql: `
|
|
198
|
+
SELECT
|
|
199
|
+
c.column_name, c.data_type, c.is_nullable, c.column_default,
|
|
200
|
+
pgd.description
|
|
201
|
+
FROM information_schema.columns c
|
|
202
|
+
LEFT JOIN pg_catalog.pg_statio_all_tables st
|
|
203
|
+
ON st.schemaname = c.table_schema AND st.relname = c.table_name
|
|
204
|
+
LEFT JOIN pg_catalog.pg_description pgd
|
|
205
|
+
ON pgd.objoid = st.relid AND pgd.objsubid = c.ordinal_position
|
|
206
|
+
WHERE c.table_schema = $1 AND c.table_name = $2
|
|
207
|
+
ORDER BY c.ordinal_position
|
|
208
|
+
`,
|
|
209
|
+
params: [schema, tableName],
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
queries.push({
|
|
214
|
+
sql: `
|
|
215
|
+
SELECT column_name, data_type, is_nullable, column_default, NULL AS description
|
|
216
|
+
FROM information_schema.columns
|
|
217
|
+
WHERE table_schema = $1 AND table_name = $2
|
|
218
|
+
ORDER BY ordinal_position
|
|
219
|
+
`,
|
|
220
|
+
params: [schema, tableName],
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
// Q2: Constraints + FKs + Checks
|
|
224
|
+
queries.push({
|
|
225
|
+
sql: `
|
|
226
|
+
SELECT
|
|
227
|
+
tc.constraint_name, tc.constraint_type,
|
|
228
|
+
kcu.column_name,
|
|
229
|
+
ccu.table_name AS foreign_table,
|
|
230
|
+
ccu.column_name AS foreign_column,
|
|
231
|
+
rc.delete_rule, rc.update_rule,
|
|
232
|
+
cc.check_clause
|
|
233
|
+
FROM information_schema.table_constraints tc
|
|
234
|
+
LEFT JOIN information_schema.key_column_usage kcu
|
|
235
|
+
ON kcu.constraint_name = tc.constraint_name AND kcu.constraint_schema = tc.constraint_schema
|
|
236
|
+
LEFT JOIN information_schema.constraint_column_usage ccu
|
|
237
|
+
ON ccu.constraint_name = tc.constraint_name AND ccu.constraint_schema = tc.constraint_schema
|
|
238
|
+
AND tc.constraint_type = 'FOREIGN KEY'
|
|
239
|
+
LEFT JOIN information_schema.referential_constraints rc
|
|
240
|
+
ON rc.constraint_name = tc.constraint_name AND rc.constraint_schema = tc.constraint_schema
|
|
241
|
+
LEFT JOIN information_schema.check_constraints cc
|
|
242
|
+
ON cc.constraint_name = tc.constraint_name AND cc.constraint_schema = tc.constraint_schema
|
|
243
|
+
WHERE tc.table_schema = $1 AND tc.table_name = $2
|
|
244
|
+
ORDER BY tc.constraint_type, tc.constraint_name
|
|
245
|
+
`,
|
|
246
|
+
params: [schema, tableName],
|
|
247
|
+
});
|
|
248
|
+
// Q3: Indexes (Postgres only)
|
|
249
|
+
if (isPg) {
|
|
250
|
+
queries.push({
|
|
251
|
+
sql: `SELECT indexname, indexdef FROM pg_indexes WHERE schemaname = $1 AND tablename = $2`,
|
|
252
|
+
params: [schema, tableName],
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
queries.push({ sql: `SELECT 1 WHERE false` });
|
|
257
|
+
}
|
|
258
|
+
// Q4: RLS Policies + Triggers
|
|
259
|
+
if (isPg) {
|
|
260
|
+
queries.push({
|
|
261
|
+
sql: `
|
|
262
|
+
(SELECT policyname, cmd, roles, qual, with_check, NULL AS trigger_name, NULL AS event_manipulation, NULL AS action_timing, NULL AS action_statement
|
|
263
|
+
FROM pg_policies WHERE schemaname = $1 AND tablename = $2)
|
|
264
|
+
UNION ALL
|
|
265
|
+
(SELECT NULL, NULL, NULL, NULL, NULL, trigger_name, event_manipulation, action_timing, action_statement
|
|
266
|
+
FROM information_schema.triggers WHERE trigger_schema = $1 AND event_object_table = $2)
|
|
267
|
+
`,
|
|
268
|
+
params: [schema, tableName],
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
queries.push({
|
|
273
|
+
sql: `
|
|
274
|
+
SELECT trigger_name, event_manipulation, action_timing, action_statement,
|
|
275
|
+
NULL AS policyname, NULL AS cmd, NULL AS roles, NULL AS qual, NULL AS with_check
|
|
276
|
+
FROM information_schema.triggers
|
|
277
|
+
WHERE trigger_schema = $1 AND event_object_table = $2
|
|
278
|
+
`,
|
|
279
|
+
params: [schema, tableName],
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
// Q5: Size + Row count + GRANTs + RLS flag
|
|
283
|
+
if (isPg) {
|
|
284
|
+
queries.push({
|
|
285
|
+
sql: `
|
|
286
|
+
(SELECT
|
|
287
|
+
pg_size_pretty(pg_total_relation_size(c.oid)) AS total_size,
|
|
288
|
+
c.reltuples::bigint AS row_estimate,
|
|
289
|
+
c.relrowsecurity AS rls_enabled,
|
|
290
|
+
NULL AS grantee, NULL AS privileges
|
|
291
|
+
FROM pg_class c
|
|
292
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
293
|
+
WHERE n.nspname = $1 AND c.relname = $2)
|
|
294
|
+
UNION ALL
|
|
295
|
+
(SELECT NULL, NULL, NULL, grantee,
|
|
296
|
+
array_agg(privilege_type ORDER BY privilege_type) AS privileges
|
|
297
|
+
FROM information_schema.role_table_grants
|
|
298
|
+
WHERE table_schema = $1 AND table_name = $2
|
|
299
|
+
GROUP BY grantee)
|
|
300
|
+
`,
|
|
301
|
+
params: [schema, tableName],
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
queries.push({ sql: `SELECT 1 WHERE false` });
|
|
306
|
+
}
|
|
307
|
+
// Q6: Inbound FKs (Postgres only)
|
|
308
|
+
if (isPg) {
|
|
309
|
+
queries.push({
|
|
310
|
+
sql: `
|
|
311
|
+
SELECT
|
|
312
|
+
tc.constraint_name,
|
|
313
|
+
kcu.table_name AS source_table,
|
|
314
|
+
kcu.column_name AS source_column,
|
|
315
|
+
ccu.column_name AS foreign_column,
|
|
316
|
+
rc.delete_rule, rc.update_rule
|
|
317
|
+
FROM information_schema.table_constraints tc
|
|
318
|
+
JOIN information_schema.key_column_usage kcu
|
|
319
|
+
ON kcu.constraint_name = tc.constraint_name AND kcu.constraint_schema = tc.constraint_schema
|
|
320
|
+
JOIN information_schema.constraint_column_usage ccu
|
|
321
|
+
ON ccu.constraint_name = tc.constraint_name AND ccu.constraint_schema = tc.constraint_schema
|
|
322
|
+
JOIN information_schema.referential_constraints rc
|
|
323
|
+
ON rc.constraint_name = tc.constraint_name AND rc.constraint_schema = tc.constraint_schema
|
|
324
|
+
WHERE ccu.table_schema = $1 AND ccu.table_name = $2
|
|
325
|
+
AND tc.constraint_type = 'FOREIGN KEY'
|
|
326
|
+
`,
|
|
327
|
+
params: [schema, tableName],
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
return queries;
|
|
331
|
+
}
|
|
332
|
+
async function profileView(viewName, schema, isPg) {
|
|
333
|
+
const queries = [];
|
|
334
|
+
// Columns
|
|
335
|
+
if (isPg) {
|
|
336
|
+
queries.push({
|
|
337
|
+
sql: `
|
|
338
|
+
SELECT c.column_name, c.data_type, c.is_nullable, c.column_default, pgd.description
|
|
339
|
+
FROM information_schema.columns c
|
|
340
|
+
LEFT JOIN pg_catalog.pg_statio_all_tables st ON st.schemaname = c.table_schema AND st.relname = c.table_name
|
|
341
|
+
LEFT JOIN pg_catalog.pg_description pgd ON pgd.objoid = st.relid AND pgd.objsubid = c.ordinal_position
|
|
342
|
+
WHERE c.table_schema = $1 AND c.table_name = $2
|
|
343
|
+
ORDER BY c.ordinal_position
|
|
344
|
+
`,
|
|
345
|
+
params: [schema, viewName],
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
queries.push({
|
|
350
|
+
sql: `SELECT column_name, data_type, is_nullable, column_default, NULL AS description
|
|
351
|
+
FROM information_schema.columns WHERE table_schema = $1 AND table_name = $2 ORDER BY ordinal_position`,
|
|
352
|
+
params: [schema, viewName],
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
// View definition + is_updatable
|
|
356
|
+
queries.push({
|
|
357
|
+
sql: `SELECT view_definition, is_updatable FROM information_schema.views WHERE table_schema = $1 AND table_name = $2`,
|
|
358
|
+
params: [schema, viewName],
|
|
359
|
+
});
|
|
360
|
+
const results = await readOnlyMultiQuery(queries);
|
|
361
|
+
const columns = results[0].rows.map((r) => ({
|
|
362
|
+
name: r.column_name,
|
|
363
|
+
type: r.data_type,
|
|
364
|
+
nullable: r.is_nullable === "YES",
|
|
365
|
+
default: r.column_default ?? null,
|
|
366
|
+
comment: r.description ?? null,
|
|
367
|
+
}));
|
|
368
|
+
const viewDef = results[1].rows[0];
|
|
369
|
+
return {
|
|
370
|
+
object_type: "view",
|
|
371
|
+
schema,
|
|
372
|
+
name: viewName,
|
|
373
|
+
columns,
|
|
374
|
+
constraints: [],
|
|
375
|
+
fks_out: [],
|
|
376
|
+
fks_in: [],
|
|
377
|
+
indexes: [],
|
|
378
|
+
triggers: [],
|
|
379
|
+
policies: [],
|
|
380
|
+
rls_enabled: null,
|
|
381
|
+
grants: [],
|
|
382
|
+
size: null,
|
|
383
|
+
row_count: null,
|
|
384
|
+
view_definition: viewDef?.view_definition ?? undefined,
|
|
385
|
+
is_updatable: viewDef?.is_updatable === "YES",
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
async function profileMatview(matviewName, schema, isPg) {
|
|
389
|
+
if (!isPg) {
|
|
390
|
+
return {
|
|
391
|
+
object_type: "materialized view",
|
|
392
|
+
schema,
|
|
393
|
+
name: matviewName,
|
|
394
|
+
columns: [],
|
|
395
|
+
constraints: [],
|
|
396
|
+
fks_out: [],
|
|
397
|
+
fks_in: [],
|
|
398
|
+
indexes: [],
|
|
399
|
+
triggers: [],
|
|
400
|
+
policies: [],
|
|
401
|
+
rls_enabled: null,
|
|
402
|
+
grants: [],
|
|
403
|
+
size: null,
|
|
404
|
+
row_count: null,
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
const queries = [
|
|
408
|
+
// Columns
|
|
409
|
+
{
|
|
410
|
+
sql: `
|
|
411
|
+
SELECT a.attname AS column_name,
|
|
412
|
+
pg_catalog.format_type(a.atttypid, a.atttypmod) AS data_type,
|
|
413
|
+
NOT a.attnotnull AS is_nullable,
|
|
414
|
+
pg_get_expr(d.adbin, d.adrelid) AS column_default,
|
|
415
|
+
col_description(c.oid, a.attnum) AS description
|
|
416
|
+
FROM pg_class c
|
|
417
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
418
|
+
JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum > 0 AND NOT a.attisdropped
|
|
419
|
+
LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = a.attnum
|
|
420
|
+
WHERE n.nspname = $1 AND c.relname = $2 AND c.relkind = 'm'
|
|
421
|
+
ORDER BY a.attnum
|
|
422
|
+
`,
|
|
423
|
+
params: [schema, matviewName],
|
|
424
|
+
},
|
|
425
|
+
// Definition + populated + size
|
|
426
|
+
{
|
|
427
|
+
sql: `
|
|
428
|
+
SELECT
|
|
429
|
+
definition,
|
|
430
|
+
ispopulated AS is_populated,
|
|
431
|
+
pg_size_pretty(pg_total_relation_size(($1 || '.' || $2)::regclass)) AS size
|
|
432
|
+
FROM pg_matviews
|
|
433
|
+
WHERE schemaname = $1 AND matviewname = $2
|
|
434
|
+
`,
|
|
435
|
+
params: [schema, matviewName],
|
|
436
|
+
},
|
|
437
|
+
// Indexes
|
|
438
|
+
{
|
|
439
|
+
sql: `SELECT indexname, indexdef FROM pg_indexes WHERE schemaname = $1 AND tablename = $2`,
|
|
440
|
+
params: [schema, matviewName],
|
|
441
|
+
},
|
|
442
|
+
];
|
|
443
|
+
const results = await readOnlyMultiQuery(queries);
|
|
444
|
+
const columns = results[0].rows.map((r) => ({
|
|
445
|
+
name: r.column_name,
|
|
446
|
+
type: r.data_type,
|
|
447
|
+
nullable: r.is_nullable,
|
|
448
|
+
default: r.column_default ?? null,
|
|
449
|
+
comment: r.description ?? null,
|
|
450
|
+
}));
|
|
451
|
+
const meta = results[1].rows[0];
|
|
452
|
+
const indexes = results[2].rows.map((r) => ({
|
|
453
|
+
name: r.indexname,
|
|
454
|
+
columns: r.indexdef,
|
|
455
|
+
unique: r.indexdef.includes("UNIQUE"),
|
|
456
|
+
definition: r.indexdef,
|
|
457
|
+
}));
|
|
458
|
+
return {
|
|
459
|
+
object_type: "materialized view",
|
|
460
|
+
schema,
|
|
461
|
+
name: matviewName,
|
|
462
|
+
columns,
|
|
463
|
+
constraints: [],
|
|
464
|
+
fks_out: [],
|
|
465
|
+
fks_in: [],
|
|
466
|
+
indexes,
|
|
467
|
+
triggers: [],
|
|
468
|
+
policies: [],
|
|
469
|
+
rls_enabled: null,
|
|
470
|
+
grants: [],
|
|
471
|
+
size: meta?.size ?? null,
|
|
472
|
+
row_count: null,
|
|
473
|
+
view_definition: meta?.definition ?? undefined,
|
|
474
|
+
is_populated: meta?.is_populated,
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
//# sourceMappingURL=table-profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-profile.js","sourceRoot":"","sources":["../../src/tools/table-profile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface CheckResult {
|
|
2
|
+
column: string | null;
|
|
3
|
+
type: "values" | "range" | "unknown";
|
|
4
|
+
allowed_values?: string[];
|
|
5
|
+
expression: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Parse PostgreSQL CHECK constraint expressions into allowed values.
|
|
9
|
+
*
|
|
10
|
+
* Handles 5 real patterns:
|
|
11
|
+
* 1. (status = ANY (ARRAY['pending'::text, 'processing'::text]))
|
|
12
|
+
* 2. ((currency)::text = ANY ((ARRAY['BGN'::character varying])::text[]))
|
|
13
|
+
* 3. ((tier IS NULL) OR (tier = ANY (ARRAY[...])))
|
|
14
|
+
* 4. (amount >= (0)::numeric) — range check
|
|
15
|
+
* 5. id IS NOT NULL — auto-generated (skip)
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseCheckExpression(expression: string): CheckResult;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse PostgreSQL CHECK constraint expressions into allowed values.
|
|
3
|
+
*
|
|
4
|
+
* Handles 5 real patterns:
|
|
5
|
+
* 1. (status = ANY (ARRAY['pending'::text, 'processing'::text]))
|
|
6
|
+
* 2. ((currency)::text = ANY ((ARRAY['BGN'::character varying])::text[]))
|
|
7
|
+
* 3. ((tier IS NULL) OR (tier = ANY (ARRAY[...])))
|
|
8
|
+
* 4. (amount >= (0)::numeric) — range check
|
|
9
|
+
* 5. id IS NOT NULL — auto-generated (skip)
|
|
10
|
+
*/
|
|
11
|
+
export function parseCheckExpression(expression) {
|
|
12
|
+
// Pattern 5: Skip auto-generated NOT NULL constraints
|
|
13
|
+
if (/^\(?[\w."]+\s+IS\s+NOT\s+NULL\)?$/i.test(expression.trim())) {
|
|
14
|
+
return { column: null, type: "unknown", expression };
|
|
15
|
+
}
|
|
16
|
+
// Try to extract column name
|
|
17
|
+
const column = extractColumn(expression);
|
|
18
|
+
// Pattern 1-3: ANY (ARRAY[...]) with various castings
|
|
19
|
+
const arrayMatch = expression.match(/ARRAY\[([^\]]+)\]/i);
|
|
20
|
+
if (arrayMatch) {
|
|
21
|
+
const values = extractArrayValues(arrayMatch[1]);
|
|
22
|
+
if (values.length > 0) {
|
|
23
|
+
return { column, type: "values", allowed_values: values, expression };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Pattern 4: Range checks (>=, <=, >, <, BETWEEN)
|
|
27
|
+
if (/[><=]+\s*\(?[\d.]+\)?/.test(expression)) {
|
|
28
|
+
return { column, type: "range", expression };
|
|
29
|
+
}
|
|
30
|
+
return { column, type: "unknown", expression };
|
|
31
|
+
}
|
|
32
|
+
function extractColumn(expression) {
|
|
33
|
+
// Match: ((column_name)::type = ...) or (column_name = ...)
|
|
34
|
+
const patterns = [
|
|
35
|
+
/\(\((\w+)\)::/, // ((column)::type
|
|
36
|
+
/\((\w+)\s*=\s*ANY/, // (column = ANY
|
|
37
|
+
/\(\((\w+)\)\s*=\s*ANY/, // ((column) = ANY — parenthesized
|
|
38
|
+
/\((\w+)\s*[><=]/, // (column >= ...
|
|
39
|
+
/OR\s*\((\w+)\s*=\s*ANY/i, // OR (column = ANY (nullable wrapper)
|
|
40
|
+
];
|
|
41
|
+
for (const pattern of patterns) {
|
|
42
|
+
const match = expression.match(pattern);
|
|
43
|
+
if (match)
|
|
44
|
+
return match[1];
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
function extractArrayValues(arrayContent) {
|
|
49
|
+
// Split by commas, strip casts and quotes
|
|
50
|
+
return arrayContent
|
|
51
|
+
.split(",")
|
|
52
|
+
.map((v) => {
|
|
53
|
+
// Remove ::text, ::character varying, etc.
|
|
54
|
+
let cleaned = v.replace(/::\w[\w\s]*/g, "").trim();
|
|
55
|
+
// Remove surrounding quotes and un-escape doubled single quotes
|
|
56
|
+
cleaned = cleaned.replace(/^'(.*)'$/, "$1").replace(/''/g, "'");
|
|
57
|
+
return cleaned;
|
|
58
|
+
})
|
|
59
|
+
.filter((v) => v.length > 0);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=check-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-parser.js","sourceRoot":"","sources":["../../src/utils/check-parser.ts"],"names":[],"mappings":"AAOA;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,UAAkB;IACrD,sDAAsD;IACtD,IAAI,oCAAoC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QACjE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;IACvD,CAAC;IAED,6BAA6B;IAC7B,MAAM,MAAM,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IAEzC,sDAAsD;IACtD,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAC1D,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QACjD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QACxE,CAAC;IACH,CAAC;IAED,kDAAkD;IAClD,IAAI,uBAAuB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7C,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IAC/C,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;AACjD,CAAC;AAED,SAAS,aAAa,CAAC,UAAkB;IACvC,4DAA4D;IAC5D,MAAM,QAAQ,GAAG;QACf,eAAe,EAAY,kBAAkB;QAC7C,mBAAmB,EAAQ,gBAAgB;QAC3C,uBAAuB,EAAI,kCAAkC;QAC7D,iBAAiB,EAAU,iBAAiB;QAC5C,yBAAyB,EAAE,sCAAsC;KAClE,CAAC;IAEF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,kBAAkB,CAAC,YAAoB;IAC9C,0CAA0C;IAC1C,OAAO,YAAY;SAChB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,2CAA2C;QAC3C,IAAI,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACnD,gEAAgE;QAChE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAChE,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse PostgreSQL text[] values that the pg driver may return as
|
|
3
|
+
* string literals like {value1,value2,"quoted,value"} instead of
|
|
4
|
+
* native JavaScript arrays.
|
|
5
|
+
*/
|
|
6
|
+
export function parsePgArray(value) {
|
|
7
|
+
if (Array.isArray(value))
|
|
8
|
+
return value;
|
|
9
|
+
if (typeof value !== "string")
|
|
10
|
+
return [];
|
|
11
|
+
const inner = value.replace(/^\{|\}$/g, "");
|
|
12
|
+
if (inner.length === 0)
|
|
13
|
+
return [];
|
|
14
|
+
const result = [];
|
|
15
|
+
let current = "";
|
|
16
|
+
let inQuotes = false;
|
|
17
|
+
for (let i = 0; i < inner.length; i++) {
|
|
18
|
+
const ch = inner[i];
|
|
19
|
+
if (ch === '"' && !inQuotes) {
|
|
20
|
+
inQuotes = true;
|
|
21
|
+
}
|
|
22
|
+
else if (ch === '"' && inQuotes) {
|
|
23
|
+
if (inner[i + 1] === '"') {
|
|
24
|
+
current += '"'; // escaped quote
|
|
25
|
+
i++;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
inQuotes = false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else if (ch === "," && !inQuotes) {
|
|
32
|
+
result.push(current);
|
|
33
|
+
current = "";
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
current += ch;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
result.push(current);
|
|
40
|
+
return result.filter((s) => s.length > 0);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=pg-array.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pg-array.js","sourceRoot":"","sources":["../../src/utils/pg-array.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IAEzC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC5C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5B,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,IAAI,QAAQ,EAAE,CAAC;YAClC,IAAI,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACzB,OAAO,IAAI,GAAG,CAAC,CAAC,gBAAgB;gBAChC,CAAC,EAAE,CAAC;YACN,CAAC;iBAAM,CAAC;gBACN,QAAQ,GAAG,KAAK,CAAC;YACnB,CAAC;QACH,CAAC;aAAM,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrB,OAAO,GAAG,EAAE,CAAC;QACf,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAErB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC5C,CAAC"}
|