@deepagents/text2sql 0.10.1 → 0.11.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/README.md +32 -41
- package/dist/index.d.ts +1 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2338 -2395
- package/dist/index.js.map +4 -4
- package/dist/lib/adapters/adapter.d.ts +13 -1
- package/dist/lib/adapters/adapter.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/abstract.grounding.d.ts +19 -3
- package/dist/lib/adapters/groundings/abstract.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/column-stats.grounding.d.ts +1 -2
- package/dist/lib/adapters/groundings/column-stats.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/column-values.grounding.d.ts +1 -2
- package/dist/lib/adapters/groundings/column-values.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/constraint.grounding.d.ts +1 -1
- package/dist/lib/adapters/groundings/constraint.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/index.js +15 -222
- package/dist/lib/adapters/groundings/index.js.map +3 -3
- package/dist/lib/adapters/groundings/indexes.grounding.d.ts +1 -1
- package/dist/lib/adapters/groundings/indexes.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/info.grounding.d.ts +1 -1
- package/dist/lib/adapters/groundings/info.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/report.grounding.d.ts +1 -1
- package/dist/lib/adapters/groundings/report.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/row-count.grounding.d.ts +1 -1
- package/dist/lib/adapters/groundings/row-count.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/table.grounding.d.ts +3 -3
- package/dist/lib/adapters/groundings/table.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/groundings/view.grounding.d.ts +1 -1
- package/dist/lib/adapters/groundings/view.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/mysql/index.js +343 -315
- package/dist/lib/adapters/mysql/index.js.map +4 -4
- package/dist/lib/adapters/postgres/index.js +385 -357
- package/dist/lib/adapters/postgres/index.js.map +4 -4
- package/dist/lib/adapters/spreadsheet/index.js +290 -223
- package/dist/lib/adapters/spreadsheet/index.js.map +4 -4
- package/dist/lib/adapters/sqlite/index.js +307 -279
- package/dist/lib/adapters/sqlite/index.js.map +4 -4
- package/dist/lib/adapters/sqlserver/index.js +383 -355
- package/dist/lib/adapters/sqlserver/index.js.map +4 -4
- package/dist/lib/agents/developer.agent.d.ts +33 -23
- package/dist/lib/agents/developer.agent.d.ts.map +1 -1
- package/dist/lib/agents/sql.agent.d.ts +4 -4
- package/dist/lib/agents/sql.agent.d.ts.map +1 -1
- package/dist/lib/agents/teachables.agent.d.ts +2 -2
- package/dist/lib/agents/teachables.agent.d.ts.map +1 -1
- package/dist/lib/agents/text2sql.agent.d.ts +18 -71
- package/dist/lib/agents/text2sql.agent.d.ts.map +1 -1
- package/dist/lib/fragments/schema.d.ts +214 -0
- package/dist/lib/fragments/schema.d.ts.map +1 -0
- package/dist/lib/instructions.d.ts +29 -2
- package/dist/lib/instructions.d.ts.map +1 -1
- package/dist/lib/instructions.js +336 -319
- package/dist/lib/instructions.js.map +4 -4
- package/dist/lib/sql.d.ts +13 -103
- package/dist/lib/sql.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/base-contextual-extractor.d.ts +2 -2
- package/dist/lib/synthesis/extractors/base-contextual-extractor.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/message-extractor.d.ts +1 -2
- package/dist/lib/synthesis/extractors/message-extractor.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/sql-extractor.d.ts.map +1 -1
- package/dist/lib/synthesis/index.js +1794 -572
- package/dist/lib/synthesis/index.js.map +4 -4
- package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts.map +1 -1
- package/dist/lib/synthesis/synthesizers/persona-generator.d.ts +7 -17
- package/dist/lib/synthesis/synthesizers/persona-generator.d.ts.map +1 -1
- package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts +2 -2
- package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts.map +1 -1
- package/dist/lib/synthesis/synthesizers/teachings-generator.d.ts +8 -20
- package/dist/lib/synthesis/synthesizers/teachings-generator.d.ts.map +1 -1
- package/dist/lib/teach/teachings.d.ts +2 -2
- package/dist/lib/teach/teachings.d.ts.map +1 -1
- package/package.json +4 -3
- package/dist/lib/agents/chat1.agent.d.ts +0 -50
- package/dist/lib/agents/chat1.agent.d.ts.map +0 -1
- package/dist/lib/agents/chat2.agent.d.ts +0 -68
- package/dist/lib/agents/chat2.agent.d.ts.map +0 -1
- package/dist/lib/agents/chat3.agent.d.ts +0 -80
- package/dist/lib/agents/chat3.agent.d.ts.map +0 -1
- package/dist/lib/agents/chat4.agent.d.ts +0 -88
- package/dist/lib/agents/chat4.agent.d.ts.map +0 -1
- package/dist/lib/history/history.d.ts +0 -41
- package/dist/lib/history/history.d.ts.map +0 -1
- package/dist/lib/history/memory.history.d.ts +0 -5
- package/dist/lib/history/memory.history.d.ts.map +0 -1
- package/dist/lib/history/sqlite.history.d.ts +0 -15
- package/dist/lib/history/sqlite.history.d.ts.map +0 -1
- package/dist/lib/memory/memory.prompt.d.ts +0 -3
- package/dist/lib/memory/memory.prompt.d.ts.map +0 -1
- package/dist/lib/memory/memory.store.d.ts +0 -5
- package/dist/lib/memory/memory.store.d.ts.map +0 -1
- package/dist/lib/memory/sqlite.store.d.ts +0 -14
- package/dist/lib/memory/sqlite.store.d.ts.map +0 -1
- package/dist/lib/memory/store.d.ts +0 -40
- package/dist/lib/memory/store.d.ts.map +0 -1
- package/dist/lib/teach/teachables.d.ts +0 -648
- package/dist/lib/teach/teachables.d.ts.map +0 -1
- package/dist/lib/teach/xml.d.ts +0 -6
- package/dist/lib/teach/xml.d.ts.map +0 -1
|
@@ -1,3 +1,94 @@
|
|
|
1
|
+
// packages/text2sql/src/lib/fragments/schema.ts
|
|
2
|
+
function dialectInfo(input) {
|
|
3
|
+
return {
|
|
4
|
+
name: "dialectInfo",
|
|
5
|
+
data: {
|
|
6
|
+
dialect: input.dialect,
|
|
7
|
+
...input.version && { version: input.version },
|
|
8
|
+
...input.database && { database: input.database }
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function table(input) {
|
|
13
|
+
return {
|
|
14
|
+
name: "table",
|
|
15
|
+
data: {
|
|
16
|
+
name: input.name,
|
|
17
|
+
...input.schema && { schema: input.schema },
|
|
18
|
+
...input.rowCount != null && { rowCount: input.rowCount },
|
|
19
|
+
...input.sizeHint && { sizeHint: input.sizeHint },
|
|
20
|
+
columns: input.columns,
|
|
21
|
+
...input.indexes?.length && { indexes: input.indexes },
|
|
22
|
+
...input.constraints?.length && { constraints: input.constraints }
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function column(input) {
|
|
27
|
+
return {
|
|
28
|
+
name: "column",
|
|
29
|
+
data: {
|
|
30
|
+
name: input.name,
|
|
31
|
+
type: input.type,
|
|
32
|
+
...input.pk && { pk: true },
|
|
33
|
+
...input.fk && { fk: input.fk },
|
|
34
|
+
...input.unique && { unique: true },
|
|
35
|
+
...input.notNull && { notNull: true },
|
|
36
|
+
...input.default && { default: input.default },
|
|
37
|
+
...input.indexed && { indexed: true },
|
|
38
|
+
...input.values?.length && { values: input.values },
|
|
39
|
+
...input.stats && { stats: input.stats }
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function index(input) {
|
|
44
|
+
return {
|
|
45
|
+
name: "index",
|
|
46
|
+
data: {
|
|
47
|
+
name: input.name,
|
|
48
|
+
columns: input.columns,
|
|
49
|
+
...input.unique && { unique: true },
|
|
50
|
+
...input.type && { type: input.type }
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function constraint(input) {
|
|
55
|
+
return {
|
|
56
|
+
name: "constraint",
|
|
57
|
+
data: {
|
|
58
|
+
name: input.name,
|
|
59
|
+
type: input.type,
|
|
60
|
+
...input.columns?.length && { columns: input.columns },
|
|
61
|
+
...input.definition && { definition: input.definition },
|
|
62
|
+
...input.defaultValue && { defaultValue: input.defaultValue },
|
|
63
|
+
...input.referencedTable && { referencedTable: input.referencedTable },
|
|
64
|
+
...input.referencedColumns?.length && {
|
|
65
|
+
referencedColumns: input.referencedColumns
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function view(input) {
|
|
71
|
+
return {
|
|
72
|
+
name: "view",
|
|
73
|
+
data: {
|
|
74
|
+
name: input.name,
|
|
75
|
+
...input.schema && { schema: input.schema },
|
|
76
|
+
columns: input.columns,
|
|
77
|
+
...input.definition && { definition: input.definition }
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function relationship(input) {
|
|
82
|
+
return {
|
|
83
|
+
name: "relationship",
|
|
84
|
+
data: {
|
|
85
|
+
from: input.from,
|
|
86
|
+
to: input.to,
|
|
87
|
+
...input.cardinality && { cardinality: input.cardinality }
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
1
92
|
// packages/text2sql/src/lib/adapters/groundings/context.ts
|
|
2
93
|
function createGroundingContext() {
|
|
3
94
|
return {
|
|
@@ -10,24 +101,169 @@ function createGroundingContext() {
|
|
|
10
101
|
|
|
11
102
|
// packages/text2sql/src/lib/adapters/adapter.ts
|
|
12
103
|
var Adapter = class {
|
|
104
|
+
/**
|
|
105
|
+
* Introspect the database schema and return context fragments.
|
|
106
|
+
*
|
|
107
|
+
* Executes all configured groundings to populate the context, then
|
|
108
|
+
* generates fragments from the complete context data.
|
|
109
|
+
*
|
|
110
|
+
* @param ctx - Optional grounding context for sharing state between groundings
|
|
111
|
+
* @returns Array of context fragments representing the database schema
|
|
112
|
+
*/
|
|
13
113
|
async introspect(ctx = createGroundingContext()) {
|
|
14
|
-
const lines = [];
|
|
15
114
|
for (const fn of this.grounding) {
|
|
16
115
|
const grounding = fn(this);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
116
|
+
await grounding.execute(ctx);
|
|
117
|
+
}
|
|
118
|
+
return this.#toSchemaFragments(ctx);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Convert complete grounding context to schema fragments.
|
|
122
|
+
* Called after all groundings have populated ctx with data.
|
|
123
|
+
*/
|
|
124
|
+
#toSchemaFragments(ctx) {
|
|
125
|
+
const fragments = [];
|
|
126
|
+
if (ctx.info) {
|
|
127
|
+
fragments.push(
|
|
128
|
+
dialectInfo({
|
|
129
|
+
dialect: ctx.info.dialect,
|
|
130
|
+
version: ctx.info.version,
|
|
131
|
+
database: ctx.info.database
|
|
132
|
+
})
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
for (const t of ctx.tables) {
|
|
136
|
+
fragments.push(this.#tableToFragment(t));
|
|
137
|
+
}
|
|
138
|
+
for (const v of ctx.views) {
|
|
139
|
+
fragments.push(this.#viewToFragment(v));
|
|
140
|
+
}
|
|
141
|
+
const tableMap = new Map(ctx.tables.map((t) => [t.name, t]));
|
|
142
|
+
for (const rel of ctx.relationships) {
|
|
143
|
+
const sourceTable = tableMap.get(rel.table);
|
|
144
|
+
const targetTable = tableMap.get(rel.referenced_table);
|
|
145
|
+
fragments.push(
|
|
146
|
+
this.#relationshipToFragment(rel, sourceTable, targetTable)
|
|
147
|
+
);
|
|
21
148
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
149
|
+
if (ctx.report) {
|
|
150
|
+
fragments.push({ name: "businessContext", data: ctx.report });
|
|
151
|
+
}
|
|
152
|
+
return fragments;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Convert a Table to a table fragment with nested column, index, and constraint fragments.
|
|
156
|
+
*/
|
|
157
|
+
#tableToFragment(t) {
|
|
158
|
+
const pkConstraint = t.constraints?.find((c) => c.type === "PRIMARY_KEY");
|
|
159
|
+
const pkColumns = new Set(pkConstraint?.columns ?? []);
|
|
160
|
+
const notNullColumns = new Set(
|
|
161
|
+
t.constraints?.filter((c) => c.type === "NOT_NULL").flatMap((c) => c.columns ?? []) ?? []
|
|
162
|
+
);
|
|
163
|
+
const defaultByColumn = /* @__PURE__ */ new Map();
|
|
164
|
+
for (const c of t.constraints?.filter((c2) => c2.type === "DEFAULT") ?? []) {
|
|
165
|
+
for (const col of c.columns ?? []) {
|
|
166
|
+
if (c.defaultValue != null) {
|
|
167
|
+
defaultByColumn.set(col, c.defaultValue);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const uniqueColumns = new Set(
|
|
172
|
+
t.constraints?.filter((c) => c.type === "UNIQUE" && c.columns?.length === 1).flatMap((c) => c.columns ?? []) ?? []
|
|
173
|
+
);
|
|
174
|
+
const fkByColumn = /* @__PURE__ */ new Map();
|
|
175
|
+
for (const c of t.constraints?.filter((c2) => c2.type === "FOREIGN_KEY") ?? []) {
|
|
176
|
+
const cols = c.columns ?? [];
|
|
177
|
+
const refCols = c.referencedColumns ?? [];
|
|
178
|
+
for (let i = 0; i < cols.length; i++) {
|
|
179
|
+
const refCol = refCols[i] ?? refCols[0] ?? cols[i];
|
|
180
|
+
fkByColumn.set(cols[i], `${c.referencedTable}.${refCol}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const columnFragments = t.columns.map(
|
|
184
|
+
(col) => column({
|
|
185
|
+
name: col.name,
|
|
186
|
+
type: col.type,
|
|
187
|
+
pk: pkColumns.has(col.name) || void 0,
|
|
188
|
+
fk: fkByColumn.get(col.name),
|
|
189
|
+
unique: uniqueColumns.has(col.name) || void 0,
|
|
190
|
+
notNull: notNullColumns.has(col.name) || void 0,
|
|
191
|
+
default: defaultByColumn.get(col.name),
|
|
192
|
+
indexed: col.isIndexed || void 0,
|
|
193
|
+
values: col.values,
|
|
194
|
+
stats: col.stats
|
|
195
|
+
})
|
|
196
|
+
);
|
|
197
|
+
const indexFragments = (t.indexes ?? []).map(
|
|
198
|
+
(idx) => index({
|
|
199
|
+
name: idx.name,
|
|
200
|
+
columns: idx.columns,
|
|
201
|
+
unique: idx.unique,
|
|
202
|
+
type: idx.type
|
|
203
|
+
})
|
|
204
|
+
);
|
|
205
|
+
const constraintFragments = (t.constraints ?? []).filter(
|
|
206
|
+
(c) => c.type === "CHECK" || c.type === "UNIQUE" && (c.columns?.length ?? 0) > 1
|
|
207
|
+
).map(
|
|
208
|
+
(c) => constraint({
|
|
209
|
+
name: c.name,
|
|
210
|
+
type: c.type,
|
|
211
|
+
columns: c.columns,
|
|
212
|
+
definition: c.definition
|
|
213
|
+
})
|
|
214
|
+
);
|
|
215
|
+
return table({
|
|
216
|
+
name: t.name,
|
|
217
|
+
schema: t.schema,
|
|
218
|
+
rowCount: t.rowCount,
|
|
219
|
+
sizeHint: t.sizeHint,
|
|
220
|
+
columns: columnFragments,
|
|
221
|
+
indexes: indexFragments.length > 0 ? indexFragments : void 0,
|
|
222
|
+
constraints: constraintFragments.length > 0 ? constraintFragments : void 0
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Convert a View to a view fragment with nested column fragments.
|
|
227
|
+
*/
|
|
228
|
+
#viewToFragment(v) {
|
|
229
|
+
const columnFragments = v.columns.map(
|
|
230
|
+
(col) => column({
|
|
231
|
+
name: col.name,
|
|
232
|
+
type: col.type,
|
|
233
|
+
values: col.values,
|
|
234
|
+
stats: col.stats
|
|
235
|
+
})
|
|
236
|
+
);
|
|
237
|
+
return view({
|
|
238
|
+
name: v.name,
|
|
239
|
+
schema: v.schema,
|
|
240
|
+
columns: columnFragments,
|
|
241
|
+
definition: v.definition
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Convert a Relationship to a relationship fragment.
|
|
246
|
+
* Infers cardinality from row counts if available.
|
|
247
|
+
*/
|
|
248
|
+
#relationshipToFragment(rel, sourceTable, targetTable) {
|
|
249
|
+
const sourceCount = sourceTable?.rowCount;
|
|
250
|
+
const targetCount = targetTable?.rowCount;
|
|
251
|
+
let cardinality;
|
|
252
|
+
if (sourceCount != null && targetCount != null && targetCount > 0) {
|
|
253
|
+
const ratio = sourceCount / targetCount;
|
|
254
|
+
if (ratio > 5) {
|
|
255
|
+
cardinality = "many-to-one";
|
|
256
|
+
} else if (ratio < 1.2 && ratio > 0.8) {
|
|
257
|
+
cardinality = "one-to-one";
|
|
258
|
+
} else if (ratio < 0.2) {
|
|
259
|
+
cardinality = "one-to-many";
|
|
26
260
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
261
|
+
}
|
|
262
|
+
return relationship({
|
|
263
|
+
from: { table: rel.table, columns: rel.from },
|
|
264
|
+
to: { table: rel.referenced_table, columns: rel.to },
|
|
265
|
+
cardinality
|
|
266
|
+
});
|
|
31
267
|
}
|
|
32
268
|
/**
|
|
33
269
|
* Convert unknown database value to number.
|
|
@@ -83,16 +319,19 @@ ${description}
|
|
|
83
319
|
|
|
84
320
|
// packages/text2sql/src/lib/adapters/groundings/abstract.grounding.ts
|
|
85
321
|
var AbstractGrounding = class {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
322
|
+
/**
|
|
323
|
+
* Grounding identifier for debugging/logging.
|
|
324
|
+
*/
|
|
325
|
+
name;
|
|
326
|
+
constructor(name) {
|
|
327
|
+
this.name = name;
|
|
89
328
|
}
|
|
90
329
|
};
|
|
91
330
|
|
|
92
331
|
// packages/text2sql/src/lib/adapters/groundings/column-stats.grounding.ts
|
|
93
332
|
var ColumnStatsGrounding = class extends AbstractGrounding {
|
|
94
333
|
constructor(config = {}) {
|
|
95
|
-
super("
|
|
334
|
+
super("columnStats");
|
|
96
335
|
}
|
|
97
336
|
/**
|
|
98
337
|
* Execute the grounding process.
|
|
@@ -101,79 +340,73 @@ var ColumnStatsGrounding = class extends AbstractGrounding {
|
|
|
101
340
|
async execute(ctx) {
|
|
102
341
|
const allContainers = [...ctx.tables, ...ctx.views];
|
|
103
342
|
for (const container of allContainers) {
|
|
104
|
-
for (const
|
|
343
|
+
for (const column2 of container.columns) {
|
|
105
344
|
try {
|
|
106
|
-
const stats = await this.collectStats(container.name,
|
|
345
|
+
const stats = await this.collectStats(container.name, column2);
|
|
107
346
|
if (stats) {
|
|
108
|
-
|
|
347
|
+
column2.stats = stats;
|
|
109
348
|
}
|
|
110
349
|
} catch (error) {
|
|
111
350
|
console.warn(
|
|
112
351
|
"Error collecting stats for",
|
|
113
352
|
container.name,
|
|
114
|
-
|
|
353
|
+
column2.name,
|
|
115
354
|
error
|
|
116
355
|
);
|
|
117
356
|
}
|
|
118
357
|
}
|
|
119
358
|
}
|
|
120
|
-
return () => this.#describe();
|
|
121
|
-
}
|
|
122
|
-
#describe() {
|
|
123
|
-
return null;
|
|
124
359
|
}
|
|
125
360
|
};
|
|
126
361
|
|
|
127
362
|
// packages/text2sql/src/lib/adapters/groundings/constraint.grounding.ts
|
|
128
363
|
var ConstraintGrounding = class extends AbstractGrounding {
|
|
129
364
|
constructor(config = {}) {
|
|
130
|
-
super("
|
|
365
|
+
super("constraint");
|
|
131
366
|
}
|
|
132
367
|
/**
|
|
133
368
|
* Execute the grounding process.
|
|
134
369
|
* Annotates tables in ctx.tables with their constraints.
|
|
135
370
|
*/
|
|
136
371
|
async execute(ctx) {
|
|
137
|
-
for (const
|
|
372
|
+
for (const table2 of ctx.tables) {
|
|
138
373
|
try {
|
|
139
|
-
|
|
374
|
+
table2.constraints = await this.getConstraints(table2.name);
|
|
140
375
|
} catch (error) {
|
|
141
|
-
console.warn("Error collecting constraints for",
|
|
376
|
+
console.warn("Error collecting constraints for", table2.name, error);
|
|
142
377
|
}
|
|
143
378
|
}
|
|
144
|
-
return () => null;
|
|
145
379
|
}
|
|
146
380
|
};
|
|
147
381
|
|
|
148
382
|
// packages/text2sql/src/lib/adapters/groundings/indexes.grounding.ts
|
|
149
383
|
var IndexesGrounding = class extends AbstractGrounding {
|
|
150
384
|
constructor(config = {}) {
|
|
151
|
-
super("
|
|
385
|
+
super("index");
|
|
152
386
|
}
|
|
153
387
|
/**
|
|
154
388
|
* Execute the grounding process.
|
|
155
389
|
* Annotates tables in ctx.tables with their indexes and marks indexed columns.
|
|
156
390
|
*/
|
|
157
391
|
async execute(ctx) {
|
|
158
|
-
for (const
|
|
159
|
-
|
|
160
|
-
for (const
|
|
161
|
-
for (const colName of
|
|
162
|
-
const
|
|
163
|
-
if (
|
|
164
|
-
|
|
392
|
+
for (const table2 of ctx.tables) {
|
|
393
|
+
table2.indexes = await this.getIndexes(table2.name);
|
|
394
|
+
for (const index2 of table2.indexes ?? []) {
|
|
395
|
+
for (const colName of index2.columns) {
|
|
396
|
+
const column2 = table2.columns.find((c) => c.name === colName);
|
|
397
|
+
if (column2) {
|
|
398
|
+
column2.isIndexed = true;
|
|
165
399
|
}
|
|
166
400
|
}
|
|
167
401
|
}
|
|
168
402
|
}
|
|
169
|
-
return () => null;
|
|
170
403
|
}
|
|
171
404
|
};
|
|
172
405
|
|
|
173
406
|
// packages/text2sql/src/lib/adapters/groundings/info.grounding.ts
|
|
174
407
|
var InfoGrounding = class extends AbstractGrounding {
|
|
175
408
|
constructor(config = {}) {
|
|
176
|
-
super("
|
|
409
|
+
super("dialectInfo");
|
|
177
410
|
}
|
|
178
411
|
/**
|
|
179
412
|
* Execute the grounding process.
|
|
@@ -181,17 +414,6 @@ var InfoGrounding = class extends AbstractGrounding {
|
|
|
181
414
|
*/
|
|
182
415
|
async execute(ctx) {
|
|
183
416
|
ctx.info = await this.collectInfo();
|
|
184
|
-
const lines = [`Dialect: ${ctx.info.dialect ?? "unknown"}`];
|
|
185
|
-
if (ctx.info.version) {
|
|
186
|
-
lines.push(`Version: ${ctx.info.version}`);
|
|
187
|
-
}
|
|
188
|
-
if (ctx.info.database) {
|
|
189
|
-
lines.push(`Database: ${ctx.info.database}`);
|
|
190
|
-
}
|
|
191
|
-
if (ctx.info.details && Object.keys(ctx.info.details).length) {
|
|
192
|
-
lines.push(`Details: ${JSON.stringify(ctx.info.details)}`);
|
|
193
|
-
}
|
|
194
|
-
return () => lines.join("\n");
|
|
195
417
|
}
|
|
196
418
|
};
|
|
197
419
|
|
|
@@ -199,7 +421,7 @@ var InfoGrounding = class extends AbstractGrounding {
|
|
|
199
421
|
var ColumnValuesGrounding = class extends AbstractGrounding {
|
|
200
422
|
lowCardinalityLimit;
|
|
201
423
|
constructor(config = {}) {
|
|
202
|
-
super("
|
|
424
|
+
super("columnValues");
|
|
203
425
|
this.lowCardinalityLimit = config.lowCardinalityLimit ?? 20;
|
|
204
426
|
}
|
|
205
427
|
/**
|
|
@@ -217,14 +439,14 @@ var ColumnValuesGrounding = class extends AbstractGrounding {
|
|
|
217
439
|
* - CHECK ((status)::text = ANY (ARRAY['a'::text, 'b'::text]))
|
|
218
440
|
* - CHECK (status = 'active' OR status = 'inactive')
|
|
219
441
|
*/
|
|
220
|
-
parseCheckConstraint(
|
|
221
|
-
if (
|
|
442
|
+
parseCheckConstraint(constraint2, columnName) {
|
|
443
|
+
if (constraint2.type !== "CHECK" || !constraint2.definition) {
|
|
222
444
|
return void 0;
|
|
223
445
|
}
|
|
224
|
-
if (
|
|
446
|
+
if (constraint2.columns && !constraint2.columns.includes(columnName)) {
|
|
225
447
|
return void 0;
|
|
226
448
|
}
|
|
227
|
-
const def =
|
|
449
|
+
const def = constraint2.definition;
|
|
228
450
|
const escapedCol = this.escapeRegex(columnName);
|
|
229
451
|
const colPattern = `(?:\\(?\\(?${escapedCol}\\)?(?:::(?:text|varchar|character varying))?\\)?)`;
|
|
230
452
|
const inMatch = def.match(
|
|
@@ -282,55 +504,51 @@ var ColumnValuesGrounding = class extends AbstractGrounding {
|
|
|
282
504
|
async execute(ctx) {
|
|
283
505
|
const allContainers = [...ctx.tables, ...ctx.views];
|
|
284
506
|
for (const container of allContainers) {
|
|
285
|
-
const
|
|
286
|
-
for (const
|
|
507
|
+
const table2 = this.getTable(ctx, container.name);
|
|
508
|
+
for (const column2 of container.columns) {
|
|
287
509
|
try {
|
|
288
510
|
const result = await this.resolveColumnValues(
|
|
289
511
|
container.name,
|
|
290
|
-
|
|
291
|
-
|
|
512
|
+
column2,
|
|
513
|
+
table2?.constraints
|
|
292
514
|
);
|
|
293
515
|
if (result) {
|
|
294
|
-
|
|
295
|
-
|
|
516
|
+
column2.kind = result.kind;
|
|
517
|
+
column2.values = result.values;
|
|
296
518
|
}
|
|
297
519
|
} catch (error) {
|
|
298
520
|
console.warn(
|
|
299
521
|
"Error collecting column values for",
|
|
300
522
|
container.name,
|
|
301
|
-
|
|
523
|
+
column2.name,
|
|
302
524
|
error
|
|
303
525
|
);
|
|
304
526
|
}
|
|
305
527
|
}
|
|
306
528
|
}
|
|
307
|
-
return () => this.#describe();
|
|
308
529
|
}
|
|
309
530
|
/**
|
|
310
531
|
* Resolve column values from all sources in priority order.
|
|
311
532
|
*/
|
|
312
|
-
async resolveColumnValues(tableName,
|
|
313
|
-
const enumValues = await this.collectEnumValues(tableName,
|
|
533
|
+
async resolveColumnValues(tableName, column2, constraints2) {
|
|
534
|
+
const enumValues = await this.collectEnumValues(tableName, column2);
|
|
314
535
|
if (enumValues?.length) {
|
|
315
536
|
return { kind: "Enum", values: enumValues };
|
|
316
537
|
}
|
|
317
538
|
if (constraints2) {
|
|
318
|
-
for (const
|
|
319
|
-
const checkValues = this.parseCheckConstraint(
|
|
539
|
+
for (const constraint2 of constraints2) {
|
|
540
|
+
const checkValues = this.parseCheckConstraint(constraint2, column2.name);
|
|
320
541
|
if (checkValues?.length) {
|
|
321
542
|
return { kind: "Enum", values: checkValues };
|
|
322
543
|
}
|
|
323
544
|
}
|
|
324
545
|
}
|
|
325
|
-
const lowCardValues = await this.collectLowCardinality(tableName,
|
|
546
|
+
const lowCardValues = await this.collectLowCardinality(tableName, column2);
|
|
326
547
|
if (lowCardValues?.length) {
|
|
327
548
|
return { kind: "LowCardinality", values: lowCardValues };
|
|
328
549
|
}
|
|
329
550
|
return void 0;
|
|
330
551
|
}
|
|
331
|
-
#describe() {
|
|
332
|
-
return null;
|
|
333
|
-
}
|
|
334
552
|
};
|
|
335
553
|
|
|
336
554
|
// packages/text2sql/src/lib/adapters/groundings/report.grounding.ts
|
|
@@ -402,7 +620,7 @@ var ReportGrounding = class extends AbstractGrounding {
|
|
|
402
620
|
const cached = await this.#cache.get();
|
|
403
621
|
if (cached) {
|
|
404
622
|
ctx.report = cached;
|
|
405
|
-
return
|
|
623
|
+
return;
|
|
406
624
|
}
|
|
407
625
|
}
|
|
408
626
|
const report2 = await this.#generateReport();
|
|
@@ -410,7 +628,6 @@ var ReportGrounding = class extends AbstractGrounding {
|
|
|
410
628
|
if (this.#cache) {
|
|
411
629
|
await this.#cache.set(report2);
|
|
412
630
|
}
|
|
413
|
-
return () => report2;
|
|
414
631
|
}
|
|
415
632
|
async #generateReport() {
|
|
416
633
|
const { text } = await generate(
|
|
@@ -429,21 +646,20 @@ var ReportGrounding = class extends AbstractGrounding {
|
|
|
429
646
|
// packages/text2sql/src/lib/adapters/groundings/row-count.grounding.ts
|
|
430
647
|
var RowCountGrounding = class extends AbstractGrounding {
|
|
431
648
|
constructor(config = {}) {
|
|
432
|
-
super("
|
|
649
|
+
super("rowCount");
|
|
433
650
|
}
|
|
434
651
|
/**
|
|
435
652
|
* Execute the grounding process.
|
|
436
653
|
* Annotates tables in ctx.tables with row counts and size hints.
|
|
437
654
|
*/
|
|
438
655
|
async execute(ctx) {
|
|
439
|
-
for (const
|
|
440
|
-
const count = await this.getRowCount(
|
|
656
|
+
for (const table2 of ctx.tables) {
|
|
657
|
+
const count = await this.getRowCount(table2.name);
|
|
441
658
|
if (count != null) {
|
|
442
|
-
|
|
443
|
-
|
|
659
|
+
table2.rowCount = count;
|
|
660
|
+
table2.sizeHint = this.#classifyRowCount(count);
|
|
444
661
|
}
|
|
445
662
|
}
|
|
446
|
-
return () => null;
|
|
447
663
|
}
|
|
448
664
|
/**
|
|
449
665
|
* Classify row count into a size hint category.
|
|
@@ -458,13 +674,12 @@ var RowCountGrounding = class extends AbstractGrounding {
|
|
|
458
674
|
};
|
|
459
675
|
|
|
460
676
|
// packages/text2sql/src/lib/adapters/groundings/table.grounding.ts
|
|
461
|
-
import pluralize from "pluralize";
|
|
462
677
|
var TableGrounding = class extends AbstractGrounding {
|
|
463
678
|
#filter;
|
|
464
679
|
#forward;
|
|
465
680
|
#backward;
|
|
466
681
|
constructor(config = {}) {
|
|
467
|
-
super("
|
|
682
|
+
super("table");
|
|
468
683
|
this.#filter = config.filter;
|
|
469
684
|
this.#forward = config.forward;
|
|
470
685
|
this.#backward = config.backward;
|
|
@@ -482,7 +697,7 @@ var TableGrounding = class extends AbstractGrounding {
|
|
|
482
697
|
seedTables.map((name) => this.getTable(name))
|
|
483
698
|
);
|
|
484
699
|
ctx.tables.push(...tables3);
|
|
485
|
-
return
|
|
700
|
+
return;
|
|
486
701
|
}
|
|
487
702
|
const tables2 = {};
|
|
488
703
|
const allRelationships = [];
|
|
@@ -538,7 +753,6 @@ var TableGrounding = class extends AbstractGrounding {
|
|
|
538
753
|
const tablesList = Object.values(tables2);
|
|
539
754
|
ctx.tables.push(...tablesList);
|
|
540
755
|
ctx.relationships.push(...allRelationships);
|
|
541
|
-
return () => this.#describeTables(tablesList);
|
|
542
756
|
}
|
|
543
757
|
/**
|
|
544
758
|
* Apply the filter to get seed table names.
|
|
@@ -568,156 +782,6 @@ var TableGrounding = class extends AbstractGrounding {
|
|
|
568
782
|
all.push(rel);
|
|
569
783
|
}
|
|
570
784
|
}
|
|
571
|
-
#describeTables(tables2) {
|
|
572
|
-
if (!tables2.length) {
|
|
573
|
-
return "Schema unavailable.";
|
|
574
|
-
}
|
|
575
|
-
return tables2.map((table) => {
|
|
576
|
-
const rowCountInfo = table.rowCount != null ? ` [rows: ${table.rowCount}${table.sizeHint ? `, size: ${table.sizeHint}` : ""}]` : "";
|
|
577
|
-
const pkConstraint = table.constraints?.find(
|
|
578
|
-
(c) => c.type === "PRIMARY_KEY"
|
|
579
|
-
);
|
|
580
|
-
const pkColumns = new Set(pkConstraint?.columns ?? []);
|
|
581
|
-
const notNullColumns = new Set(
|
|
582
|
-
table.constraints?.filter((c) => c.type === "NOT_NULL").flatMap((c) => c.columns ?? []) ?? []
|
|
583
|
-
);
|
|
584
|
-
const defaultByColumn = /* @__PURE__ */ new Map();
|
|
585
|
-
for (const c of table.constraints?.filter(
|
|
586
|
-
(c2) => c2.type === "DEFAULT"
|
|
587
|
-
) ?? []) {
|
|
588
|
-
for (const col of c.columns ?? []) {
|
|
589
|
-
if (c.defaultValue != null) {
|
|
590
|
-
defaultByColumn.set(col, c.defaultValue);
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
const uniqueColumns = new Set(
|
|
595
|
-
table.constraints?.filter((c) => c.type === "UNIQUE" && c.columns?.length === 1).flatMap((c) => c.columns ?? []) ?? []
|
|
596
|
-
);
|
|
597
|
-
const fkByColumn = /* @__PURE__ */ new Map();
|
|
598
|
-
for (const c of table.constraints?.filter(
|
|
599
|
-
(c2) => c2.type === "FOREIGN_KEY"
|
|
600
|
-
) ?? []) {
|
|
601
|
-
const cols = c.columns ?? [];
|
|
602
|
-
const refCols = c.referencedColumns ?? [];
|
|
603
|
-
for (let i = 0; i < cols.length; i++) {
|
|
604
|
-
const refCol = refCols[i] ?? refCols[0] ?? cols[i];
|
|
605
|
-
fkByColumn.set(cols[i], `${c.referencedTable}.${refCol}`);
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
const columns = table.columns.map((column) => {
|
|
609
|
-
const annotations = [];
|
|
610
|
-
const isPrimaryKey = pkColumns.has(column.name);
|
|
611
|
-
if (isPrimaryKey) {
|
|
612
|
-
annotations.push("PK");
|
|
613
|
-
}
|
|
614
|
-
if (fkByColumn.has(column.name)) {
|
|
615
|
-
annotations.push(`FK -> ${fkByColumn.get(column.name)}`);
|
|
616
|
-
}
|
|
617
|
-
if (uniqueColumns.has(column.name)) {
|
|
618
|
-
annotations.push("UNIQUE");
|
|
619
|
-
}
|
|
620
|
-
if (notNullColumns.has(column.name)) {
|
|
621
|
-
annotations.push("NOT NULL");
|
|
622
|
-
}
|
|
623
|
-
if (defaultByColumn.has(column.name)) {
|
|
624
|
-
annotations.push(`DEFAULT: ${defaultByColumn.get(column.name)}`);
|
|
625
|
-
}
|
|
626
|
-
if (column.isIndexed && !isPrimaryKey) {
|
|
627
|
-
annotations.push("Indexed");
|
|
628
|
-
}
|
|
629
|
-
if (column.kind === "Enum" && column.values?.length) {
|
|
630
|
-
annotations.push(`Enum: ${column.values.join(", ")}`);
|
|
631
|
-
} else if (column.kind === "LowCardinality" && column.values?.length) {
|
|
632
|
-
annotations.push(`LowCardinality: ${column.values.join(", ")}`);
|
|
633
|
-
}
|
|
634
|
-
if (column.stats) {
|
|
635
|
-
const statParts = [];
|
|
636
|
-
if (column.stats.min != null || column.stats.max != null) {
|
|
637
|
-
const minText = column.stats.min ?? "n/a";
|
|
638
|
-
const maxText = column.stats.max ?? "n/a";
|
|
639
|
-
statParts.push(`range ${minText} \u2192 ${maxText}`);
|
|
640
|
-
}
|
|
641
|
-
if (column.stats.nullFraction != null && Number.isFinite(column.stats.nullFraction)) {
|
|
642
|
-
const percent = Math.round(column.stats.nullFraction * 1e3) / 10;
|
|
643
|
-
statParts.push(`null\u2248${percent}%`);
|
|
644
|
-
}
|
|
645
|
-
if (statParts.length) {
|
|
646
|
-
annotations.push(statParts.join(", "));
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
const annotationText = annotations.length ? ` [${annotations.join(", ")}]` : "";
|
|
650
|
-
return ` - ${column.name} (${column.type})${annotationText}`;
|
|
651
|
-
}).join("\n");
|
|
652
|
-
const indexes2 = table.indexes?.length ? `
|
|
653
|
-
Indexes:
|
|
654
|
-
${table.indexes.map((index) => {
|
|
655
|
-
const props = [];
|
|
656
|
-
if (index.unique) {
|
|
657
|
-
props.push("UNIQUE");
|
|
658
|
-
}
|
|
659
|
-
if (index.type) {
|
|
660
|
-
props.push(index.type);
|
|
661
|
-
}
|
|
662
|
-
const propsText = props.length ? ` (${props.join(", ")})` : "";
|
|
663
|
-
const columnsText = index.columns?.length ? index.columns.join(", ") : "expression";
|
|
664
|
-
return ` - ${index.name}${propsText}: ${columnsText}`;
|
|
665
|
-
}).join("\n")}` : "";
|
|
666
|
-
const multiColumnUniques = table.constraints?.filter(
|
|
667
|
-
(c) => c.type === "UNIQUE" && (c.columns?.length ?? 0) > 1
|
|
668
|
-
) ?? [];
|
|
669
|
-
const uniqueConstraints = multiColumnUniques.length ? `
|
|
670
|
-
Unique Constraints:
|
|
671
|
-
${multiColumnUniques.map((c) => ` - ${c.name}: (${c.columns?.join(", ")})`).join("\n")}` : "";
|
|
672
|
-
const checkConstraints = table.constraints?.filter((c) => c.type === "CHECK") ?? [];
|
|
673
|
-
const checks = checkConstraints.length ? `
|
|
674
|
-
Check Constraints:
|
|
675
|
-
${checkConstraints.map((c) => ` - ${c.name}: ${c.definition}`).join("\n")}` : "";
|
|
676
|
-
return `- Table: ${table.name}${rowCountInfo}
|
|
677
|
-
Columns:
|
|
678
|
-
${columns}${indexes2}${uniqueConstraints}${checks}`;
|
|
679
|
-
}).join("\n\n");
|
|
680
|
-
}
|
|
681
|
-
#formatTableLabel = (tableName) => {
|
|
682
|
-
const base = tableName.split(".").pop() ?? tableName;
|
|
683
|
-
return base.replace(/_/g, " ");
|
|
684
|
-
};
|
|
685
|
-
#describeRelationships = (tables2, relationships) => {
|
|
686
|
-
if (!relationships.length) {
|
|
687
|
-
return "None detected";
|
|
688
|
-
}
|
|
689
|
-
const tableMap = new Map(tables2.map((table) => [table.name, table]));
|
|
690
|
-
return relationships.map((relationship) => {
|
|
691
|
-
const sourceLabel = this.#formatTableLabel(relationship.table);
|
|
692
|
-
const targetLabel = this.#formatTableLabel(
|
|
693
|
-
relationship.referenced_table
|
|
694
|
-
);
|
|
695
|
-
const singularSource = pluralize.singular(sourceLabel);
|
|
696
|
-
const pluralSource = pluralize.plural(sourceLabel);
|
|
697
|
-
const singularTarget = pluralize.singular(targetLabel);
|
|
698
|
-
const pluralTarget = pluralize.plural(targetLabel);
|
|
699
|
-
const sourceTable = tableMap.get(relationship.table);
|
|
700
|
-
const targetTable = tableMap.get(relationship.referenced_table);
|
|
701
|
-
const sourceCount = sourceTable?.rowCount;
|
|
702
|
-
const targetCount = targetTable?.rowCount;
|
|
703
|
-
const ratio = sourceCount != null && targetCount != null && targetCount > 0 ? sourceCount / targetCount : null;
|
|
704
|
-
let cardinality = "each";
|
|
705
|
-
if (ratio != null) {
|
|
706
|
-
if (ratio > 5) {
|
|
707
|
-
cardinality = `many-to-one (\u2248${sourceCount} vs ${targetCount})`;
|
|
708
|
-
} else if (ratio < 1.2 && ratio > 0.8) {
|
|
709
|
-
cardinality = `roughly 1:1 (${sourceCount} vs ${targetCount})`;
|
|
710
|
-
} else if (ratio < 0.2) {
|
|
711
|
-
cardinality = `one-to-many (${sourceCount} vs ${targetCount})`;
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
const mappings = relationship.from.map((fromCol, idx) => {
|
|
715
|
-
const targetCol = relationship.to[idx] ?? relationship.to[0] ?? fromCol;
|
|
716
|
-
return `${relationship.table}.${fromCol} -> ${relationship.referenced_table}.${targetCol}`;
|
|
717
|
-
}).join(", ");
|
|
718
|
-
return `- ${relationship.table} (${relationship.from.join(", ")}) -> ${relationship.referenced_table} (${relationship.to.join(", ")}) [${cardinality}]`;
|
|
719
|
-
}).join("\n");
|
|
720
|
-
};
|
|
721
785
|
};
|
|
722
786
|
|
|
723
787
|
// packages/text2sql/src/lib/adapters/postgres/column-stats.postgres.grounding.ts
|
|
@@ -727,13 +791,13 @@ var PostgresColumnStatsGrounding = class extends ColumnStatsGrounding {
|
|
|
727
791
|
super(config);
|
|
728
792
|
this.#adapter = adapter;
|
|
729
793
|
}
|
|
730
|
-
async collectStats(tableName,
|
|
731
|
-
if (!this.#shouldCollectStats(
|
|
794
|
+
async collectStats(tableName, column2) {
|
|
795
|
+
if (!this.#shouldCollectStats(column2.type)) {
|
|
732
796
|
return void 0;
|
|
733
797
|
}
|
|
734
|
-
const { schema, table } = this.#adapter.parseTableName(tableName);
|
|
735
|
-
const tableIdentifier = `${this.#adapter.quoteIdentifier(schema)}.${this.#adapter.quoteIdentifier(
|
|
736
|
-
const columnIdentifier = this.#adapter.quoteIdentifier(
|
|
798
|
+
const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
|
|
799
|
+
const tableIdentifier = `${this.#adapter.quoteIdentifier(schema)}.${this.#adapter.quoteIdentifier(table2)}`;
|
|
800
|
+
const columnIdentifier = this.#adapter.quoteIdentifier(column2.name);
|
|
737
801
|
const sql = `
|
|
738
802
|
SELECT
|
|
739
803
|
MIN(${columnIdentifier})::text AS min_value,
|
|
@@ -776,7 +840,7 @@ var PostgresConstraintGrounding = class extends ConstraintGrounding {
|
|
|
776
840
|
this.#adapter = adapter;
|
|
777
841
|
}
|
|
778
842
|
async getConstraints(tableName) {
|
|
779
|
-
const { schema, table } = this.#adapter.parseTableName(tableName);
|
|
843
|
+
const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
|
|
780
844
|
const constraints2 = [];
|
|
781
845
|
const constraintRows = await this.#adapter.runQuery(`
|
|
782
846
|
SELECT
|
|
@@ -797,7 +861,7 @@ var PostgresConstraintGrounding = class extends ConstraintGrounding {
|
|
|
797
861
|
LEFT JOIN LATERAL unnest(con.confkey) WITH ORDINALITY AS ref_key(attnum, ord) ON key.ord = ref_key.ord
|
|
798
862
|
LEFT JOIN pg_attribute ref_a ON ref_a.attrelid = ref_rel.oid AND ref_a.attnum = ref_key.attnum
|
|
799
863
|
WHERE nsp.nspname = '${this.#adapter.escapeString(schema)}'
|
|
800
|
-
AND rel.relname = '${this.#adapter.escapeString(
|
|
864
|
+
AND rel.relname = '${this.#adapter.escapeString(table2)}'
|
|
801
865
|
AND con.contype IN ('p', 'f', 'c', 'u')
|
|
802
866
|
ORDER BY con.conname, key.ord
|
|
803
867
|
`);
|
|
@@ -860,21 +924,21 @@ var PostgresConstraintGrounding = class extends ConstraintGrounding {
|
|
|
860
924
|
is_nullable
|
|
861
925
|
FROM information_schema.columns
|
|
862
926
|
WHERE table_schema = '${this.#adapter.escapeString(schema)}'
|
|
863
|
-
AND table_name = '${this.#adapter.escapeString(
|
|
927
|
+
AND table_name = '${this.#adapter.escapeString(table2)}'
|
|
864
928
|
`);
|
|
865
929
|
for (const col of columnRows) {
|
|
866
930
|
const pkConstraint = constraints2.find((c) => c.type === "PRIMARY_KEY");
|
|
867
931
|
const isPkColumn = pkConstraint?.columns?.includes(col.column_name);
|
|
868
932
|
if (col.is_nullable === "NO" && !isPkColumn) {
|
|
869
933
|
constraints2.push({
|
|
870
|
-
name: `${
|
|
934
|
+
name: `${table2}_${col.column_name}_notnull`,
|
|
871
935
|
type: "NOT_NULL",
|
|
872
936
|
columns: [col.column_name]
|
|
873
937
|
});
|
|
874
938
|
}
|
|
875
939
|
if (col.column_default != null) {
|
|
876
940
|
constraints2.push({
|
|
877
|
-
name: `${
|
|
941
|
+
name: `${table2}_${col.column_name}_default`,
|
|
878
942
|
type: "DEFAULT",
|
|
879
943
|
columns: [col.column_name],
|
|
880
944
|
defaultValue: col.column_default
|
|
@@ -895,7 +959,7 @@ var PostgresIndexesGrounding = class extends IndexesGrounding {
|
|
|
895
959
|
this.#schemas = config.schemas;
|
|
896
960
|
}
|
|
897
961
|
async getIndexes(tableName) {
|
|
898
|
-
const { schema, table } = this.#adapter.parseTableName(tableName);
|
|
962
|
+
const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
|
|
899
963
|
const rows = await this.#adapter.runQuery(`
|
|
900
964
|
SELECT
|
|
901
965
|
i.relname AS index_name,
|
|
@@ -910,7 +974,7 @@ var PostgresIndexesGrounding = class extends IndexesGrounding {
|
|
|
910
974
|
JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)
|
|
911
975
|
JOIN pg_am am ON am.oid = i.relam
|
|
912
976
|
WHERE n.nspname = '${this.#adapter.escapeString(schema)}'
|
|
913
|
-
AND t.relname = '${this.#adapter.escapeString(
|
|
977
|
+
AND t.relname = '${this.#adapter.escapeString(table2)}'
|
|
914
978
|
ORDER BY i.relname, array_position(ix.indkey, a.attnum)
|
|
915
979
|
`);
|
|
916
980
|
return this.#groupIndexes(rows);
|
|
@@ -999,18 +1063,18 @@ var PostgresColumnValuesGrounding = class extends ColumnValuesGrounding {
|
|
|
999
1063
|
}
|
|
1000
1064
|
this.#enumCacheLoaded = true;
|
|
1001
1065
|
}
|
|
1002
|
-
async collectEnumValues(tableName,
|
|
1003
|
-
if (
|
|
1066
|
+
async collectEnumValues(tableName, column2) {
|
|
1067
|
+
if (column2.type.toLowerCase() !== "user-defined") {
|
|
1004
1068
|
return void 0;
|
|
1005
1069
|
}
|
|
1006
1070
|
await this.#loadEnumCache();
|
|
1007
|
-
const { schema, table } = this.#adapter.parseTableName(tableName);
|
|
1071
|
+
const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
|
|
1008
1072
|
const rows = await this.#adapter.runQuery(`
|
|
1009
1073
|
SELECT udt_name, udt_schema
|
|
1010
1074
|
FROM information_schema.columns
|
|
1011
1075
|
WHERE table_schema = '${this.#adapter.escapeString(schema)}'
|
|
1012
|
-
AND table_name = '${this.#adapter.escapeString(
|
|
1013
|
-
AND column_name = '${this.#adapter.escapeString(
|
|
1076
|
+
AND table_name = '${this.#adapter.escapeString(table2)}'
|
|
1077
|
+
AND column_name = '${this.#adapter.escapeString(column2.name)}'
|
|
1014
1078
|
`);
|
|
1015
1079
|
if (!rows.length) {
|
|
1016
1080
|
return void 0;
|
|
@@ -1020,10 +1084,10 @@ var PostgresColumnValuesGrounding = class extends ColumnValuesGrounding {
|
|
|
1020
1084
|
const values = this.#enumCache.get(fullKey) ?? this.#enumCache.get(udt_name);
|
|
1021
1085
|
return values?.length ? values : void 0;
|
|
1022
1086
|
}
|
|
1023
|
-
async collectLowCardinality(tableName,
|
|
1024
|
-
const { schema, table } = this.#adapter.parseTableName(tableName);
|
|
1025
|
-
const tableIdentifier = `${this.#adapter.quoteIdentifier(schema)}.${this.#adapter.quoteIdentifier(
|
|
1026
|
-
const columnIdentifier = this.#adapter.quoteIdentifier(
|
|
1087
|
+
async collectLowCardinality(tableName, column2) {
|
|
1088
|
+
const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
|
|
1089
|
+
const tableIdentifier = `${this.#adapter.quoteIdentifier(schema)}.${this.#adapter.quoteIdentifier(table2)}`;
|
|
1090
|
+
const columnIdentifier = this.#adapter.quoteIdentifier(column2.name);
|
|
1027
1091
|
const limit = this.lowCardinalityLimit + 1;
|
|
1028
1092
|
const sql = `
|
|
1029
1093
|
SELECT DISTINCT ${columnIdentifier}::text AS value
|
|
@@ -1132,8 +1196,8 @@ var Postgres = class extends Adapter {
|
|
|
1132
1196
|
return value.replace(/"/g, '""');
|
|
1133
1197
|
}
|
|
1134
1198
|
buildSampleRowsQuery(tableName, columns, limit) {
|
|
1135
|
-
const { schema, table } = this.parseTableName(tableName);
|
|
1136
|
-
const tableIdentifier = schema ? `${this.quoteIdentifier(schema)}.${this.quoteIdentifier(
|
|
1199
|
+
const { schema, table: table2 } = this.parseTableName(tableName);
|
|
1200
|
+
const tableIdentifier = schema ? `${this.quoteIdentifier(schema)}.${this.quoteIdentifier(table2)}` : this.quoteIdentifier(table2);
|
|
1137
1201
|
const columnList = columns?.length ? columns.map((c) => this.quoteIdentifier(c)).join(", ") : "*";
|
|
1138
1202
|
return `SELECT ${columnList} FROM ${tableIdentifier} LIMIT ${limit}`;
|
|
1139
1203
|
}
|
|
@@ -1160,17 +1224,17 @@ var Postgres = class extends Adapter {
|
|
|
1160
1224
|
const schema = row.table_schema ?? "public";
|
|
1161
1225
|
const tableName = row.table_name;
|
|
1162
1226
|
const qualifiedName = `${schema}.${tableName}`;
|
|
1163
|
-
const
|
|
1227
|
+
const table2 = tables2.get(qualifiedName) ?? {
|
|
1164
1228
|
name: qualifiedName,
|
|
1165
1229
|
schema,
|
|
1166
1230
|
rawName: tableName,
|
|
1167
1231
|
columns: []
|
|
1168
1232
|
};
|
|
1169
|
-
|
|
1233
|
+
table2.columns.push({
|
|
1170
1234
|
name: row.column_name ?? "unknown",
|
|
1171
1235
|
type: row.data_type ?? "unknown"
|
|
1172
1236
|
});
|
|
1173
|
-
tables2.set(qualifiedName,
|
|
1237
|
+
tables2.set(qualifiedName, table2);
|
|
1174
1238
|
}
|
|
1175
1239
|
return Array.from(tables2.values());
|
|
1176
1240
|
}
|
|
@@ -1205,26 +1269,26 @@ var Postgres = class extends Adapter {
|
|
|
1205
1269
|
const schema = row.table_schema ?? "public";
|
|
1206
1270
|
const referencedSchema = row.foreign_table_schema ?? "public";
|
|
1207
1271
|
const key = `${schema}.${row.table_name}:${row.constraint_name}`;
|
|
1208
|
-
const
|
|
1272
|
+
const relationship2 = relationships.get(key) ?? {
|
|
1209
1273
|
table: `${schema}.${row.table_name}`,
|
|
1210
1274
|
from: [],
|
|
1211
1275
|
referenced_table: `${referencedSchema}.${row.foreign_table_name}`,
|
|
1212
1276
|
to: []
|
|
1213
1277
|
};
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
relationships.set(key,
|
|
1278
|
+
relationship2.from.push(row.column_name ?? "unknown");
|
|
1279
|
+
relationship2.to.push(row.foreign_column_name ?? "unknown");
|
|
1280
|
+
relationships.set(key, relationship2);
|
|
1217
1281
|
}
|
|
1218
1282
|
return Array.from(relationships.values());
|
|
1219
1283
|
}
|
|
1220
1284
|
async #annotateRowCounts(tables2, onProgress) {
|
|
1221
1285
|
const total = tables2.length;
|
|
1222
1286
|
for (let i = 0; i < tables2.length; i++) {
|
|
1223
|
-
const
|
|
1224
|
-
const tableIdentifier = this.#formatQualifiedTableName(
|
|
1287
|
+
const table2 = tables2[i];
|
|
1288
|
+
const tableIdentifier = this.#formatQualifiedTableName(table2);
|
|
1225
1289
|
onProgress?.({
|
|
1226
1290
|
phase: "row_counts",
|
|
1227
|
-
message: `Counting rows in ${
|
|
1291
|
+
message: `Counting rows in ${table2.name}...`,
|
|
1228
1292
|
current: i + 1,
|
|
1229
1293
|
total
|
|
1230
1294
|
});
|
|
@@ -1232,8 +1296,8 @@ var Postgres = class extends Adapter {
|
|
|
1232
1296
|
const rows = await this.#runIntrospectionQuery(`SELECT COUNT(*) as count FROM ${tableIdentifier}`);
|
|
1233
1297
|
const rowCount2 = this.#toNumber(rows[0]?.count);
|
|
1234
1298
|
if (rowCount2 != null) {
|
|
1235
|
-
|
|
1236
|
-
|
|
1299
|
+
table2.rowCount = rowCount2;
|
|
1300
|
+
table2.sizeHint = this.#classifyRowCount(rowCount2);
|
|
1237
1301
|
}
|
|
1238
1302
|
} catch {
|
|
1239
1303
|
continue;
|
|
@@ -1250,7 +1314,7 @@ var Postgres = class extends Adapter {
|
|
|
1250
1314
|
if (!tables2.length) {
|
|
1251
1315
|
return;
|
|
1252
1316
|
}
|
|
1253
|
-
const tableMap = new Map(tables2.map((
|
|
1317
|
+
const tableMap = new Map(tables2.map((table2) => [table2.name, table2]));
|
|
1254
1318
|
const rows = await this.#runIntrospectionQuery(`
|
|
1255
1319
|
SELECT
|
|
1256
1320
|
n.nspname AS table_schema,
|
|
@@ -1279,32 +1343,32 @@ var Postgres = class extends Adapter {
|
|
|
1279
1343
|
}
|
|
1280
1344
|
const schema = row.table_schema ?? "public";
|
|
1281
1345
|
const tableKey = `${schema}.${row.table_name}`;
|
|
1282
|
-
const
|
|
1283
|
-
if (!
|
|
1346
|
+
const table2 = tableMap.get(tableKey);
|
|
1347
|
+
if (!table2) {
|
|
1284
1348
|
continue;
|
|
1285
1349
|
}
|
|
1286
1350
|
const indexKey = `${tableKey}:${row.index_name}`;
|
|
1287
|
-
let
|
|
1288
|
-
if (!
|
|
1289
|
-
|
|
1351
|
+
let index2 = indexMap.get(indexKey);
|
|
1352
|
+
if (!index2) {
|
|
1353
|
+
index2 = {
|
|
1290
1354
|
name: row.index_name,
|
|
1291
1355
|
columns: [],
|
|
1292
1356
|
unique: Boolean(row.indisunique ?? false),
|
|
1293
1357
|
type: row.indisclustered ? "clustered" : row.method ?? void 0
|
|
1294
1358
|
};
|
|
1295
|
-
indexMap.set(indexKey,
|
|
1296
|
-
if (!
|
|
1297
|
-
|
|
1359
|
+
indexMap.set(indexKey, index2);
|
|
1360
|
+
if (!table2.indexes) {
|
|
1361
|
+
table2.indexes = [];
|
|
1298
1362
|
}
|
|
1299
|
-
|
|
1363
|
+
table2.indexes.push(index2);
|
|
1300
1364
|
}
|
|
1301
1365
|
if (row.column_name) {
|
|
1302
|
-
|
|
1303
|
-
const
|
|
1366
|
+
index2.columns.push(row.column_name);
|
|
1367
|
+
const column2 = table2.columns.find(
|
|
1304
1368
|
(col) => col.name === row.column_name
|
|
1305
1369
|
);
|
|
1306
|
-
if (
|
|
1307
|
-
|
|
1370
|
+
if (column2) {
|
|
1371
|
+
column2.isIndexed = true;
|
|
1308
1372
|
}
|
|
1309
1373
|
}
|
|
1310
1374
|
}
|
|
@@ -1315,19 +1379,19 @@ var Postgres = class extends Adapter {
|
|
|
1315
1379
|
}
|
|
1316
1380
|
const total = tables2.length;
|
|
1317
1381
|
for (let i = 0; i < tables2.length; i++) {
|
|
1318
|
-
const
|
|
1319
|
-
const tableIdentifier = this.#formatQualifiedTableName(
|
|
1382
|
+
const table2 = tables2[i];
|
|
1383
|
+
const tableIdentifier = this.#formatQualifiedTableName(table2);
|
|
1320
1384
|
onProgress?.({
|
|
1321
1385
|
phase: "column_stats",
|
|
1322
|
-
message: `Collecting stats for ${
|
|
1386
|
+
message: `Collecting stats for ${table2.name}...`,
|
|
1323
1387
|
current: i + 1,
|
|
1324
1388
|
total
|
|
1325
1389
|
});
|
|
1326
|
-
for (const
|
|
1327
|
-
if (!this.#shouldCollectStats(
|
|
1390
|
+
for (const column2 of table2.columns) {
|
|
1391
|
+
if (!this.#shouldCollectStats(column2.type)) {
|
|
1328
1392
|
continue;
|
|
1329
1393
|
}
|
|
1330
|
-
const columnIdentifier = this.#quoteIdentifier(
|
|
1394
|
+
const columnIdentifier = this.#quoteIdentifier(column2.name);
|
|
1331
1395
|
const sql = `
|
|
1332
1396
|
SELECT
|
|
1333
1397
|
MIN(${columnIdentifier})::text AS min_value,
|
|
@@ -1344,7 +1408,7 @@ var Postgres = class extends Adapter {
|
|
|
1344
1408
|
const max = rows[0]?.max_value ?? void 0;
|
|
1345
1409
|
const nullFraction = this.#toNumber(rows[0]?.null_fraction);
|
|
1346
1410
|
if (min != null || max != null || nullFraction != null) {
|
|
1347
|
-
|
|
1411
|
+
column2.stats = {
|
|
1348
1412
|
min,
|
|
1349
1413
|
max,
|
|
1350
1414
|
nullFraction: nullFraction != null && Number.isFinite(nullFraction) ? Math.max(0, Math.min(1, nullFraction)) : void 0
|
|
@@ -1359,16 +1423,16 @@ var Postgres = class extends Adapter {
|
|
|
1359
1423
|
async #annotateLowCardinalityColumns(tables2, onProgress) {
|
|
1360
1424
|
const total = tables2.length;
|
|
1361
1425
|
for (let i = 0; i < tables2.length; i++) {
|
|
1362
|
-
const
|
|
1363
|
-
const tableIdentifier = this.#formatQualifiedTableName(
|
|
1426
|
+
const table2 = tables2[i];
|
|
1427
|
+
const tableIdentifier = this.#formatQualifiedTableName(table2);
|
|
1364
1428
|
onProgress?.({
|
|
1365
1429
|
phase: "low_cardinality",
|
|
1366
|
-
message: `Analyzing cardinality in ${
|
|
1430
|
+
message: `Analyzing cardinality in ${table2.name}...`,
|
|
1367
1431
|
current: i + 1,
|
|
1368
1432
|
total
|
|
1369
1433
|
});
|
|
1370
|
-
for (const
|
|
1371
|
-
const columnIdentifier = this.#quoteIdentifier(
|
|
1434
|
+
for (const column2 of table2.columns) {
|
|
1435
|
+
const columnIdentifier = this.#quoteIdentifier(column2.name);
|
|
1372
1436
|
const limit = LOW_CARDINALITY_LIMIT + 1;
|
|
1373
1437
|
const sql = `
|
|
1374
1438
|
SELECT DISTINCT ${columnIdentifier} AS value
|
|
@@ -1398,8 +1462,8 @@ var Postgres = class extends Adapter {
|
|
|
1398
1462
|
if (shouldSkip || !values.length) {
|
|
1399
1463
|
continue;
|
|
1400
1464
|
}
|
|
1401
|
-
|
|
1402
|
-
|
|
1465
|
+
column2.kind = "LowCardinality";
|
|
1466
|
+
column2.values = values;
|
|
1403
1467
|
}
|
|
1404
1468
|
}
|
|
1405
1469
|
}
|
|
@@ -1454,19 +1518,19 @@ var Postgres = class extends Adapter {
|
|
|
1454
1518
|
#quoteIdentifier(name) {
|
|
1455
1519
|
return `"${name.replace(/"/g, '""')}"`;
|
|
1456
1520
|
}
|
|
1457
|
-
#formatQualifiedTableName(
|
|
1458
|
-
if (
|
|
1459
|
-
return `${this.#quoteIdentifier(
|
|
1521
|
+
#formatQualifiedTableName(table2) {
|
|
1522
|
+
if (table2.schema && table2.rawName) {
|
|
1523
|
+
return `${this.#quoteIdentifier(table2.schema)}.${this.#quoteIdentifier(table2.rawName)}`;
|
|
1460
1524
|
}
|
|
1461
|
-
if (
|
|
1462
|
-
const [schemaPart, ...rest] =
|
|
1525
|
+
if (table2.name.includes(".")) {
|
|
1526
|
+
const [schemaPart, ...rest] = table2.name.split(".");
|
|
1463
1527
|
const tablePart = rest.join(".") || schemaPart;
|
|
1464
1528
|
if (rest.length === 0) {
|
|
1465
1529
|
return this.#quoteIdentifier(schemaPart);
|
|
1466
1530
|
}
|
|
1467
1531
|
return `${this.#quoteIdentifier(schemaPart)}.${this.#quoteIdentifier(tablePart)}`;
|
|
1468
1532
|
}
|
|
1469
|
-
return this.#quoteIdentifier(
|
|
1533
|
+
return this.#quoteIdentifier(table2.name);
|
|
1470
1534
|
}
|
|
1471
1535
|
#toNumber(value) {
|
|
1472
1536
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -1536,8 +1600,8 @@ var PostgresRowCountGrounding = class extends RowCountGrounding {
|
|
|
1536
1600
|
this.#adapter = adapter;
|
|
1537
1601
|
}
|
|
1538
1602
|
async getRowCount(tableName) {
|
|
1539
|
-
const { schema, table } = this.#adapter.parseTableName(tableName);
|
|
1540
|
-
const tableIdentifier = `${this.#adapter.quoteIdentifier(schema)}.${this.#adapter.quoteIdentifier(
|
|
1603
|
+
const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
|
|
1604
|
+
const tableIdentifier = `${this.#adapter.quoteIdentifier(schema)}.${this.#adapter.quoteIdentifier(table2)}`;
|
|
1541
1605
|
const rows = await this.#adapter.runQuery(
|
|
1542
1606
|
`SELECT COUNT(*) as count FROM ${tableIdentifier}`
|
|
1543
1607
|
);
|
|
@@ -1565,18 +1629,18 @@ var PostgresTableGrounding = class extends TableGrounding {
|
|
|
1565
1629
|
return rows.map((r) => r.name);
|
|
1566
1630
|
}
|
|
1567
1631
|
async getTable(tableName) {
|
|
1568
|
-
const { schema, table } = this.#adapter.parseTableName(tableName);
|
|
1632
|
+
const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
|
|
1569
1633
|
const columns = await this.#adapter.runQuery(`
|
|
1570
1634
|
SELECT column_name, data_type
|
|
1571
1635
|
FROM information_schema.columns
|
|
1572
1636
|
WHERE table_schema = '${this.#adapter.escapeString(schema)}'
|
|
1573
|
-
AND table_name = '${this.#adapter.escapeString(
|
|
1637
|
+
AND table_name = '${this.#adapter.escapeString(table2)}'
|
|
1574
1638
|
ORDER BY ordinal_position
|
|
1575
1639
|
`);
|
|
1576
1640
|
return {
|
|
1577
1641
|
name: tableName,
|
|
1578
1642
|
schema,
|
|
1579
|
-
rawName:
|
|
1643
|
+
rawName: table2,
|
|
1580
1644
|
columns: columns.map((col) => ({
|
|
1581
1645
|
name: col.column_name ?? "unknown",
|
|
1582
1646
|
type: col.data_type ?? "unknown"
|
|
@@ -1584,7 +1648,7 @@ var PostgresTableGrounding = class extends TableGrounding {
|
|
|
1584
1648
|
};
|
|
1585
1649
|
}
|
|
1586
1650
|
async findOutgoingRelations(tableName) {
|
|
1587
|
-
const { schema, table } = this.#adapter.parseTableName(tableName);
|
|
1651
|
+
const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
|
|
1588
1652
|
const rows = await this.#adapter.runQuery(`
|
|
1589
1653
|
SELECT
|
|
1590
1654
|
tc.constraint_name,
|
|
@@ -1603,13 +1667,13 @@ var PostgresTableGrounding = class extends TableGrounding {
|
|
|
1603
1667
|
AND ccu.table_schema = tc.table_schema
|
|
1604
1668
|
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
1605
1669
|
AND tc.table_schema = '${this.#adapter.escapeString(schema)}'
|
|
1606
|
-
AND tc.table_name = '${this.#adapter.escapeString(
|
|
1670
|
+
AND tc.table_name = '${this.#adapter.escapeString(table2)}'
|
|
1607
1671
|
ORDER BY tc.constraint_name, kcu.ordinal_position
|
|
1608
1672
|
`);
|
|
1609
1673
|
return this.#groupRelationships(rows);
|
|
1610
1674
|
}
|
|
1611
1675
|
async findIncomingRelations(tableName) {
|
|
1612
|
-
const { schema, table } = this.#adapter.parseTableName(tableName);
|
|
1676
|
+
const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
|
|
1613
1677
|
const rows = await this.#adapter.runQuery(`
|
|
1614
1678
|
SELECT
|
|
1615
1679
|
tc.constraint_name,
|
|
@@ -1628,7 +1692,7 @@ var PostgresTableGrounding = class extends TableGrounding {
|
|
|
1628
1692
|
AND ccu.table_schema = tc.table_schema
|
|
1629
1693
|
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
1630
1694
|
AND ccu.table_schema = '${this.#adapter.escapeString(schema)}'
|
|
1631
|
-
AND ccu.table_name = '${this.#adapter.escapeString(
|
|
1695
|
+
AND ccu.table_name = '${this.#adapter.escapeString(table2)}'
|
|
1632
1696
|
ORDER BY tc.constraint_name, kcu.ordinal_position
|
|
1633
1697
|
`);
|
|
1634
1698
|
return this.#groupRelationships(rows);
|
|
@@ -1643,15 +1707,15 @@ var PostgresTableGrounding = class extends TableGrounding {
|
|
|
1643
1707
|
const schema = row.table_schema ?? defaultSchema;
|
|
1644
1708
|
const referencedSchema = row.foreign_table_schema ?? defaultSchema;
|
|
1645
1709
|
const key = `${schema}.${row.table_name}:${row.constraint_name}`;
|
|
1646
|
-
const
|
|
1710
|
+
const relationship2 = relationships.get(key) ?? {
|
|
1647
1711
|
table: `${schema}.${row.table_name}`,
|
|
1648
1712
|
from: [],
|
|
1649
1713
|
referenced_table: `${referencedSchema}.${row.foreign_table_name}`,
|
|
1650
1714
|
to: []
|
|
1651
1715
|
};
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
relationships.set(key,
|
|
1716
|
+
relationship2.from.push(row.column_name ?? "unknown");
|
|
1717
|
+
relationship2.to.push(row.foreign_column_name ?? "unknown");
|
|
1718
|
+
relationships.set(key, relationship2);
|
|
1655
1719
|
}
|
|
1656
1720
|
return Array.from(relationships.values());
|
|
1657
1721
|
}
|
|
@@ -1661,7 +1725,7 @@ var PostgresTableGrounding = class extends TableGrounding {
|
|
|
1661
1725
|
var ViewGrounding = class extends AbstractGrounding {
|
|
1662
1726
|
#filter;
|
|
1663
1727
|
constructor(config = {}) {
|
|
1664
|
-
super("
|
|
1728
|
+
super("view");
|
|
1665
1729
|
this.#filter = config.filter;
|
|
1666
1730
|
}
|
|
1667
1731
|
/**
|
|
@@ -1674,42 +1738,6 @@ var ViewGrounding = class extends AbstractGrounding {
|
|
|
1674
1738
|
viewNames.map((name) => this.getView(name))
|
|
1675
1739
|
);
|
|
1676
1740
|
ctx.views.push(...views2);
|
|
1677
|
-
return () => this.#describe(views2);
|
|
1678
|
-
}
|
|
1679
|
-
#describe(views2) {
|
|
1680
|
-
if (!views2.length) {
|
|
1681
|
-
return "No views available.";
|
|
1682
|
-
}
|
|
1683
|
-
return views2.map((view) => {
|
|
1684
|
-
const columns = view.columns.map((column) => {
|
|
1685
|
-
const annotations = [];
|
|
1686
|
-
if (column.kind === "LowCardinality" && column.values?.length) {
|
|
1687
|
-
annotations.push(`LowCardinality: ${column.values.join(", ")}`);
|
|
1688
|
-
}
|
|
1689
|
-
if (column.stats) {
|
|
1690
|
-
const statParts = [];
|
|
1691
|
-
if (column.stats.min != null || column.stats.max != null) {
|
|
1692
|
-
const minText = column.stats.min ?? "n/a";
|
|
1693
|
-
const maxText = column.stats.max ?? "n/a";
|
|
1694
|
-
statParts.push(`range ${minText} \u2192 ${maxText}`);
|
|
1695
|
-
}
|
|
1696
|
-
if (column.stats.nullFraction != null && Number.isFinite(column.stats.nullFraction)) {
|
|
1697
|
-
const percent = Math.round(column.stats.nullFraction * 1e3) / 10;
|
|
1698
|
-
statParts.push(`null\u2248${percent}%`);
|
|
1699
|
-
}
|
|
1700
|
-
if (statParts.length) {
|
|
1701
|
-
annotations.push(statParts.join(", "));
|
|
1702
|
-
}
|
|
1703
|
-
}
|
|
1704
|
-
const annotationText = annotations.length ? ` [${annotations.join(", ")}]` : "";
|
|
1705
|
-
return ` - ${column.name} (${column.type})${annotationText}`;
|
|
1706
|
-
}).join("\n");
|
|
1707
|
-
const definition = view.definition ? `
|
|
1708
|
-
Definition: ${view.definition.length > 200 ? view.definition.slice(0, 200) + "..." : view.definition}` : "";
|
|
1709
|
-
return `- View: ${view.name}${definition}
|
|
1710
|
-
Columns:
|
|
1711
|
-
${columns}`;
|
|
1712
|
-
}).join("\n\n");
|
|
1713
1741
|
}
|
|
1714
1742
|
/**
|
|
1715
1743
|
* Apply the filter to get view names.
|
|
@@ -1751,24 +1779,24 @@ var PostgresViewGrounding = class extends ViewGrounding {
|
|
|
1751
1779
|
return rows.map((r) => r.name);
|
|
1752
1780
|
}
|
|
1753
1781
|
async getView(viewName) {
|
|
1754
|
-
const { schema, table:
|
|
1782
|
+
const { schema, table: view2 } = this.#adapter.parseTableName(viewName);
|
|
1755
1783
|
const defRows = await this.#adapter.runQuery(`
|
|
1756
1784
|
SELECT definition
|
|
1757
1785
|
FROM pg_views
|
|
1758
1786
|
WHERE schemaname = '${this.#adapter.escapeString(schema)}'
|
|
1759
|
-
AND viewname = '${this.#adapter.escapeString(
|
|
1787
|
+
AND viewname = '${this.#adapter.escapeString(view2)}'
|
|
1760
1788
|
`);
|
|
1761
1789
|
const columns = await this.#adapter.runQuery(`
|
|
1762
1790
|
SELECT column_name, data_type
|
|
1763
1791
|
FROM information_schema.columns
|
|
1764
1792
|
WHERE table_schema = '${this.#adapter.escapeString(schema)}'
|
|
1765
|
-
AND table_name = '${this.#adapter.escapeString(
|
|
1793
|
+
AND table_name = '${this.#adapter.escapeString(view2)}'
|
|
1766
1794
|
ORDER BY ordinal_position
|
|
1767
1795
|
`);
|
|
1768
1796
|
return {
|
|
1769
1797
|
name: viewName,
|
|
1770
1798
|
schema,
|
|
1771
|
-
rawName:
|
|
1799
|
+
rawName: view2,
|
|
1772
1800
|
definition: defRows[0]?.definition ?? void 0,
|
|
1773
1801
|
columns: columns.map((col) => ({
|
|
1774
1802
|
name: col.column_name ?? "unknown",
|