@deepagents/text2sql 7.0.1 → 7.1.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.
Files changed (162) hide show
  1. package/README.md +3 -2
  2. package/dist/bin/sql.js +57 -32
  3. package/dist/index.js +793 -498
  4. package/dist/index.js.map +4 -4
  5. package/dist/lib/adapters/adapter.d.ts +23 -1
  6. package/dist/lib/adapters/adapter.d.ts.map +1 -1
  7. package/dist/lib/adapters/bigquery/bigquery-fk.d.ts +0 -11
  8. package/dist/lib/adapters/bigquery/bigquery-fk.d.ts.map +1 -1
  9. package/dist/lib/adapters/bigquery/bigquery-rows.d.ts +22 -0
  10. package/dist/lib/adapters/bigquery/bigquery-rows.d.ts.map +1 -0
  11. package/dist/lib/adapters/bigquery/bigquery.d.ts +1 -1
  12. package/dist/lib/adapters/bigquery/bigquery.d.ts.map +1 -1
  13. package/dist/lib/adapters/bigquery/constraint.bigquery.grounding.d.ts.map +1 -1
  14. package/dist/lib/adapters/bigquery/index.d.ts +6 -13
  15. package/dist/lib/adapters/bigquery/index.d.ts.map +1 -1
  16. package/dist/lib/adapters/bigquery/index.js +244 -51
  17. package/dist/lib/adapters/bigquery/index.js.map +4 -4
  18. package/dist/lib/adapters/bigquery/indexes.bigquery.grounding.d.ts.map +1 -1
  19. package/dist/lib/adapters/bigquery/row-count.bigquery.grounding.d.ts.map +1 -1
  20. package/dist/lib/adapters/bigquery/table.bigquery.grounding.d.ts.map +1 -1
  21. package/dist/lib/adapters/bigquery/view.bigquery.grounding.d.ts.map +1 -1
  22. package/dist/lib/adapters/clickhouse/clickhouse-rows.d.ts +7 -0
  23. package/dist/lib/adapters/clickhouse/clickhouse-rows.d.ts.map +1 -0
  24. package/dist/lib/adapters/clickhouse/clickhouse.d.ts +1 -1
  25. package/dist/lib/adapters/clickhouse/clickhouse.d.ts.map +1 -1
  26. package/dist/lib/adapters/clickhouse/constraint.clickhouse.grounding.d.ts.map +1 -1
  27. package/dist/lib/adapters/clickhouse/index.js +133 -44
  28. package/dist/lib/adapters/clickhouse/index.js.map +4 -4
  29. package/dist/lib/adapters/clickhouse/indexes.clickhouse.grounding.d.ts.map +1 -1
  30. package/dist/lib/adapters/clickhouse/info.clickhouse.grounding.d.ts.map +1 -1
  31. package/dist/lib/adapters/clickhouse/row-count.clickhouse.grounding.d.ts.map +1 -1
  32. package/dist/lib/adapters/clickhouse/table.clickhouse.grounding.d.ts.map +1 -1
  33. package/dist/lib/adapters/clickhouse/view.clickhouse.grounding.d.ts.map +1 -1
  34. package/dist/lib/adapters/duckdb/duckdb.d.ts +1 -1
  35. package/dist/lib/adapters/duckdb/duckdb.d.ts.map +1 -1
  36. package/dist/lib/adapters/duckdb/duckdb.groundings.d.ts.map +1 -1
  37. package/dist/lib/adapters/duckdb/index.d.ts +8 -10
  38. package/dist/lib/adapters/duckdb/index.d.ts.map +1 -1
  39. package/dist/lib/adapters/duckdb/index.js +1549 -1412
  40. package/dist/lib/adapters/duckdb/index.js.map +4 -4
  41. package/dist/lib/adapters/groundings/index.js.map +1 -1
  42. package/dist/lib/adapters/groundings/rows.d.ts +32 -0
  43. package/dist/lib/adapters/groundings/rows.d.ts.map +1 -0
  44. package/dist/lib/adapters/mysql/column-stats.mysql.grounding.d.ts.map +1 -1
  45. package/dist/lib/adapters/mysql/column-values.mysql.grounding.d.ts.map +1 -1
  46. package/dist/lib/adapters/mysql/constraint.mysql.grounding.d.ts.map +1 -1
  47. package/dist/lib/adapters/mysql/index.d.ts +2 -4
  48. package/dist/lib/adapters/mysql/index.d.ts.map +1 -1
  49. package/dist/lib/adapters/mysql/index.js +230 -76
  50. package/dist/lib/adapters/mysql/index.js.map +4 -4
  51. package/dist/lib/adapters/mysql/indexes.mysql.grounding.d.ts.map +1 -1
  52. package/dist/lib/adapters/mysql/info.mysql.grounding.d.ts.map +1 -1
  53. package/dist/lib/adapters/mysql/mysql-rows.d.ts +11 -0
  54. package/dist/lib/adapters/mysql/mysql-rows.d.ts.map +1 -0
  55. package/dist/lib/adapters/mysql/mysql.d.ts +1 -1
  56. package/dist/lib/adapters/mysql/mysql.d.ts.map +1 -1
  57. package/dist/lib/adapters/mysql/row-count.mysql.grounding.d.ts.map +1 -1
  58. package/dist/lib/adapters/mysql/table.mysql.grounding.d.ts +3 -2
  59. package/dist/lib/adapters/mysql/table.mysql.grounding.d.ts.map +1 -1
  60. package/dist/lib/adapters/mysql/view.mysql.grounding.d.ts +2 -2
  61. package/dist/lib/adapters/mysql/view.mysql.grounding.d.ts.map +1 -1
  62. package/dist/lib/adapters/postgres/column-stats.postgres.grounding.d.ts.map +1 -1
  63. package/dist/lib/adapters/postgres/column-values.postgres.grounding.d.ts.map +1 -1
  64. package/dist/lib/adapters/postgres/constraint.postgres.grounding.d.ts.map +1 -1
  65. package/dist/lib/adapters/postgres/index.d.ts +2 -4
  66. package/dist/lib/adapters/postgres/index.d.ts.map +1 -1
  67. package/dist/lib/adapters/postgres/index.js +266 -487
  68. package/dist/lib/adapters/postgres/index.js.map +4 -4
  69. package/dist/lib/adapters/postgres/indexes.postgres.grounding.d.ts +1 -5
  70. package/dist/lib/adapters/postgres/indexes.postgres.grounding.d.ts.map +1 -1
  71. package/dist/lib/adapters/postgres/info.postgres.grounding.d.ts.map +1 -1
  72. package/dist/lib/adapters/postgres/postgres-rows.d.ts +7 -0
  73. package/dist/lib/adapters/postgres/postgres-rows.d.ts.map +1 -0
  74. package/dist/lib/adapters/postgres/postgres.d.ts +6 -1
  75. package/dist/lib/adapters/postgres/postgres.d.ts.map +1 -1
  76. package/dist/lib/adapters/postgres/row-count.postgres.grounding.d.ts.map +1 -1
  77. package/dist/lib/adapters/postgres/table.postgres.grounding.d.ts +5 -4
  78. package/dist/lib/adapters/postgres/table.postgres.grounding.d.ts.map +1 -1
  79. package/dist/lib/adapters/postgres/view.postgres.grounding.d.ts +3 -3
  80. package/dist/lib/adapters/postgres/view.postgres.grounding.d.ts.map +1 -1
  81. package/dist/lib/adapters/posthog/definitions.posthog.grounding.d.ts.map +1 -1
  82. package/dist/lib/adapters/posthog/index.d.ts +4 -5
  83. package/dist/lib/adapters/posthog/index.d.ts.map +1 -1
  84. package/dist/lib/adapters/posthog/index.js +349 -287
  85. package/dist/lib/adapters/posthog/index.js.map +4 -4
  86. package/dist/lib/adapters/posthog/posthog.d.ts +2 -2
  87. package/dist/lib/adapters/posthog/posthog.d.ts.map +1 -1
  88. package/dist/lib/adapters/posthog/posthog.sql-policy.d.ts.map +1 -1
  89. package/dist/lib/adapters/posthog/schema.posthog.grounding.d.ts.map +1 -1
  90. package/dist/lib/adapters/posthog/transport.d.ts.map +1 -1
  91. package/dist/lib/adapters/posthog/types.d.ts +16 -6
  92. package/dist/lib/adapters/posthog/types.d.ts.map +1 -1
  93. package/dist/lib/adapters/spreadsheet/index.js +113 -34
  94. package/dist/lib/adapters/spreadsheet/index.js.map +4 -4
  95. package/dist/lib/adapters/sqlite/column-stats.sqlite.grounding.d.ts.map +1 -1
  96. package/dist/lib/adapters/sqlite/column-values.sqlite.grounding.d.ts.map +1 -1
  97. package/dist/lib/adapters/sqlite/constraint.sqlite.grounding.d.ts.map +1 -1
  98. package/dist/lib/adapters/sqlite/index.js +136 -49
  99. package/dist/lib/adapters/sqlite/index.js.map +4 -4
  100. package/dist/lib/adapters/sqlite/indexes.sqlite.grounding.d.ts.map +1 -1
  101. package/dist/lib/adapters/sqlite/info.sqlite.grounding.d.ts.map +1 -1
  102. package/dist/lib/adapters/sqlite/row-count.sqlite.grounding.d.ts.map +1 -1
  103. package/dist/lib/adapters/sqlite/sqlite-rows.d.ts +41 -0
  104. package/dist/lib/adapters/sqlite/sqlite-rows.d.ts.map +1 -0
  105. package/dist/lib/adapters/sqlite/sqlite.d.ts +1 -1
  106. package/dist/lib/adapters/sqlite/sqlite.d.ts.map +1 -1
  107. package/dist/lib/adapters/sqlite/table.sqlite.grounding.d.ts.map +1 -1
  108. package/dist/lib/adapters/sqlite/view.sqlite.grounding.d.ts.map +1 -1
  109. package/dist/lib/adapters/sqlserver/column-stats.sqlserver.grounding.d.ts.map +1 -1
  110. package/dist/lib/adapters/sqlserver/column-values.sqlserver.grounding.d.ts.map +1 -1
  111. package/dist/lib/adapters/sqlserver/constraint.sqlserver.grounding.d.ts.map +1 -1
  112. package/dist/lib/adapters/sqlserver/index.d.ts +2 -4
  113. package/dist/lib/adapters/sqlserver/index.d.ts.map +1 -1
  114. package/dist/lib/adapters/sqlserver/index.js +223 -455
  115. package/dist/lib/adapters/sqlserver/index.js.map +4 -4
  116. package/dist/lib/adapters/sqlserver/indexes.sqlserver.grounding.d.ts +1 -5
  117. package/dist/lib/adapters/sqlserver/indexes.sqlserver.grounding.d.ts.map +1 -1
  118. package/dist/lib/adapters/sqlserver/info.sqlserver.grounding.d.ts.map +1 -1
  119. package/dist/lib/adapters/sqlserver/row-count.sqlserver.grounding.d.ts.map +1 -1
  120. package/dist/lib/adapters/sqlserver/sqlserver-rows.d.ts +7 -0
  121. package/dist/lib/adapters/sqlserver/sqlserver-rows.d.ts.map +1 -0
  122. package/dist/lib/adapters/sqlserver/sqlserver.d.ts +6 -1
  123. package/dist/lib/adapters/sqlserver/sqlserver.d.ts.map +1 -1
  124. package/dist/lib/adapters/sqlserver/table.sqlserver.grounding.d.ts +4 -3
  125. package/dist/lib/adapters/sqlserver/table.sqlserver.grounding.d.ts.map +1 -1
  126. package/dist/lib/adapters/sqlserver/view.sqlserver.grounding.d.ts +3 -3
  127. package/dist/lib/adapters/sqlserver/view.sqlserver.grounding.d.ts.map +1 -1
  128. package/dist/lib/agents/sql-transform-plugins.d.ts.map +1 -1
  129. package/dist/lib/checkpoint.d.ts +34 -21
  130. package/dist/lib/checkpoint.d.ts.map +1 -1
  131. package/dist/lib/file-cache.d.ts +6 -1
  132. package/dist/lib/file-cache.d.ts.map +1 -1
  133. package/dist/lib/fs/columns.d.ts +14 -0
  134. package/dist/lib/fs/columns.d.ts.map +1 -0
  135. package/dist/lib/fs/mssql/mssql-fs.d.ts +4 -4
  136. package/dist/lib/fs/mssql/mssql-fs.d.ts.map +1 -1
  137. package/dist/lib/fs/postgres/postgres-fs.d.ts +4 -4
  138. package/dist/lib/fs/postgres/postgres-fs.d.ts.map +1 -1
  139. package/dist/lib/fs/sqlite/sqlite-fs.d.ts +4 -4
  140. package/dist/lib/fs/sqlite/sqlite-fs.d.ts.map +1 -1
  141. package/dist/lib/index-cache.d.ts +4 -3
  142. package/dist/lib/index-cache.d.ts.map +1 -1
  143. package/dist/lib/sql.d.ts.map +1 -1
  144. package/dist/lib/synthesis/decorators/deduplicated-producer.d.ts +1 -2
  145. package/dist/lib/synthesis/decorators/deduplicated-producer.d.ts.map +1 -1
  146. package/dist/lib/synthesis/decorators/filtered-producer.d.ts +0 -2
  147. package/dist/lib/synthesis/decorators/filtered-producer.d.ts.map +1 -1
  148. package/dist/lib/synthesis/decorators/validated-producer.d.ts +1 -3
  149. package/dist/lib/synthesis/decorators/validated-producer.d.ts.map +1 -1
  150. package/dist/lib/synthesis/extractors/base-contextual-extractor.d.ts.map +1 -1
  151. package/dist/lib/synthesis/extractors/message-extractor.d.ts.map +1 -1
  152. package/dist/lib/synthesis/extractors/tool-input.d.ts +6 -0
  153. package/dist/lib/synthesis/extractors/tool-input.d.ts.map +1 -0
  154. package/dist/lib/synthesis/index.js +124 -114
  155. package/dist/lib/synthesis/index.js.map +4 -4
  156. package/dist/lib/synthesis/synthesizers/breadth-evolver.d.ts +0 -2
  157. package/dist/lib/synthesis/synthesizers/breadth-evolver.d.ts.map +1 -1
  158. package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts +0 -3
  159. package/dist/lib/synthesis/synthesizers/depth-evolver.d.ts.map +1 -1
  160. package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts +0 -2
  161. package/dist/lib/synthesis/synthesizers/schema-synthesizer.d.ts.map +1 -1
  162. package/package.json +8 -8
@@ -1,5 +1,6 @@
1
1
  // packages/text2sql/src/lib/adapters/adapter.ts
2
2
  import { format as formatSql } from "sql-formatter";
3
+ import { z } from "zod";
3
4
 
4
5
  // packages/text2sql/src/lib/agents/exceptions.ts
5
6
  var sqlValidationMarker = /* @__PURE__ */ Symbol("SQLValidationError");
@@ -172,6 +173,16 @@ function createGroundingContext(options = {}) {
172
173
  }
173
174
 
174
175
  // packages/text2sql/src/lib/adapters/adapter.ts
176
+ function groundingFor(adapterType, create) {
177
+ return (adapter) => {
178
+ if (!(adapter instanceof adapterType)) {
179
+ throw new Error(
180
+ `A ${adapterType.name} grounding needs a ${adapterType.name} adapter, not ${adapter.constructor.name}.`
181
+ );
182
+ }
183
+ return create(adapter);
184
+ };
185
+ }
175
186
  var Adapter = class {
176
187
  #policyAnalyzer;
177
188
  /**
@@ -432,6 +443,40 @@ var Adapter = class {
432
443
  }
433
444
  return decoded;
434
445
  }
446
+ /**
447
+ * Run an introspection query and check every row against `row`, the shape
448
+ * the driver returns for that query. A row of any other shape throws.
449
+ */
450
+ async runQuery(sql, row) {
451
+ const rows = z.array(row).safeParse(await this.queryRows(sql));
452
+ if (!rows.success) {
453
+ throw new Error(
454
+ `${this.constructor.name} introspection query returned rows of an unexpected shape:
455
+ ${z.prettifyError(rows.error)}
456
+ SQL: ${sql.trim()}`,
457
+ { cause: rows.error }
458
+ );
459
+ }
460
+ return rows.data;
461
+ }
462
+ /**
463
+ * The rows in a driver's execute() result: the result itself when it is an
464
+ * array, otherwise the first array found at one of `paths` (dot-separated,
465
+ * so `recordsets.0` reads `result.recordsets[0]`).
466
+ */
467
+ rowsFrom(result, paths) {
468
+ if (Array.isArray(result)) return result;
469
+ for (const path of paths) {
470
+ const rows = path.split(".").reduce(
471
+ (value, key) => typeof value === "object" && value !== null ? Reflect.get(value, key) : void 0,
472
+ result
473
+ );
474
+ if (Array.isArray(rows)) return rows;
475
+ }
476
+ throw new Error(
477
+ `${this.constructor.name} execute() must return an array of rows or an object holding one at ${paths.map((path) => `result.${path}`).join(", ")}.`
478
+ );
479
+ }
435
480
  /**
436
481
  * Convert unknown database value to number.
437
482
  * Handles number, bigint, and string types.
@@ -992,6 +1037,35 @@ var TableGrounding = class extends AbstractGrounding {
992
1037
  };
993
1038
 
994
1039
  // packages/text2sql/src/lib/adapters/postgres/column-stats.postgres.grounding.ts
1040
+ import { z as z3 } from "zod";
1041
+
1042
+ // packages/text2sql/src/lib/adapters/groundings/rows.ts
1043
+ import { z as z2 } from "zod";
1044
+ var nameRow = z2.object({ name: z2.string() });
1045
+ var versionRow = z2.object({ version: z2.string() });
1046
+ var databaseRow = z2.object({ db: z2.string() });
1047
+ var viewDefinitionRow = z2.object({
1048
+ definition: z2.string().nullable()
1049
+ });
1050
+ var distinctValueRow = z2.object({ value: z2.unknown() });
1051
+ var textValueRow = z2.object({ value: z2.string() });
1052
+ var numericValue = z2.union([z2.number(), z2.bigint(), z2.string()]);
1053
+
1054
+ // packages/text2sql/src/lib/adapters/postgres/column-stats.postgres.grounding.ts
1055
+ var pgStatsRow = z3.object({
1056
+ schemaname: z3.string(),
1057
+ tablename: z3.string(),
1058
+ attname: z3.string(),
1059
+ null_frac: z3.number().nullable(),
1060
+ n_distinct: z3.number().nullable(),
1061
+ histogram_bounds: z3.string().nullable(),
1062
+ correlation: z3.number().nullable()
1063
+ });
1064
+ var liveStatsRow = z3.object({
1065
+ min_value: z3.string().nullable(),
1066
+ max_value: z3.string().nullable(),
1067
+ null_fraction: numericValue.nullable()
1068
+ });
995
1069
  var PostgresColumnStatsGrounding = class extends ColumnStatsGrounding {
996
1070
  #adapter;
997
1071
  #pgStatsCache = /* @__PURE__ */ new Map();
@@ -1010,7 +1084,8 @@ var PostgresColumnStatsGrounding = class extends ColumnStatsGrounding {
1010
1084
  const { schema, table: table2 } = this.#adapter.parseTableName(container.name);
1011
1085
  return `(schemaname = '${this.#adapter.escapeString(schema)}' AND tablename = '${this.#adapter.escapeString(table2)}')`;
1012
1086
  });
1013
- const rows = await this.#adapter.runQuery(`
1087
+ const rows = await this.#adapter.runQuery(
1088
+ `
1014
1089
  SELECT
1015
1090
  schemaname,
1016
1091
  tablename,
@@ -1021,7 +1096,9 @@ var PostgresColumnStatsGrounding = class extends ColumnStatsGrounding {
1021
1096
  correlation
1022
1097
  FROM pg_stats
1023
1098
  WHERE ${conditions.join(" OR ")}
1024
- `);
1099
+ `,
1100
+ pgStatsRow
1101
+ );
1025
1102
  for (const row of rows) {
1026
1103
  const tableName = allContainers.find((c) => {
1027
1104
  const { schema, table: table2 } = this.#adapter.parseTableName(c.name);
@@ -1068,13 +1145,16 @@ var PostgresColumnStatsGrounding = class extends ColumnStatsGrounding {
1068
1145
  const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
1069
1146
  const tableIdentifier = `${this.#adapter.quoteIdentifier(schema)}.${this.#adapter.quoteIdentifier(table2)}`;
1070
1147
  const columnIdentifier = this.#adapter.quoteIdentifier(column2.name);
1071
- const rows = await this.#adapter.runQuery(`
1148
+ const rows = await this.#adapter.runQuery(
1149
+ `
1072
1150
  SELECT
1073
1151
  MIN(${columnIdentifier})::text AS min_value,
1074
1152
  MAX(${columnIdentifier})::text AS max_value,
1075
1153
  AVG(CASE WHEN ${columnIdentifier} IS NULL THEN 1.0 ELSE 0.0 END) AS null_fraction
1076
1154
  FROM ${tableIdentifier}
1077
- `);
1155
+ `,
1156
+ liveStatsRow
1157
+ );
1078
1158
  if (!rows.length) {
1079
1159
  return void 0;
1080
1160
  }
@@ -1133,6 +1213,17 @@ var PostgresColumnStatsGrounding = class extends ColumnStatsGrounding {
1133
1213
  };
1134
1214
 
1135
1215
  // packages/text2sql/src/lib/adapters/postgres/column-values.postgres.grounding.ts
1216
+ import { z as z4 } from "zod";
1217
+ var enumValueRow = z4.object({
1218
+ type_name: z4.string(),
1219
+ type_schema: z4.string(),
1220
+ enum_value: z4.string()
1221
+ });
1222
+ var columnTypeRow = z4.object({
1223
+ udt_name: z4.string(),
1224
+ udt_schema: z4.string()
1225
+ });
1226
+ var textValueRow2 = z4.object({ value: z4.string().nullable() });
1136
1227
  var PostgresColumnValuesGrounding = class extends ColumnValuesGrounding {
1137
1228
  #adapter;
1138
1229
  #enumCache = /* @__PURE__ */ new Map();
@@ -1149,7 +1240,8 @@ var PostgresColumnValuesGrounding = class extends ColumnValuesGrounding {
1149
1240
  if (this.#enumCacheLoaded) {
1150
1241
  return;
1151
1242
  }
1152
- const rows = await this.#adapter.runQuery(`
1243
+ const rows = await this.#adapter.runQuery(
1244
+ `
1153
1245
  SELECT
1154
1246
  t.typname AS type_name,
1155
1247
  n.nspname AS type_schema,
@@ -1158,7 +1250,9 @@ var PostgresColumnValuesGrounding = class extends ColumnValuesGrounding {
1158
1250
  JOIN pg_enum e ON t.oid = e.enumtypid
1159
1251
  JOIN pg_namespace n ON n.oid = t.typnamespace
1160
1252
  ORDER BY t.typname, e.enumsortorder
1161
- `);
1253
+ `,
1254
+ enumValueRow
1255
+ );
1162
1256
  for (const row of rows) {
1163
1257
  const key = `${row.type_schema}.${row.type_name}`;
1164
1258
  const existing = this.#enumCache.get(key) ?? [];
@@ -1177,13 +1271,16 @@ var PostgresColumnValuesGrounding = class extends ColumnValuesGrounding {
1177
1271
  }
1178
1272
  await this.#loadEnumCache();
1179
1273
  const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
1180
- const rows = await this.#adapter.runQuery(`
1274
+ const rows = await this.#adapter.runQuery(
1275
+ `
1181
1276
  SELECT udt_name, udt_schema
1182
1277
  FROM information_schema.columns
1183
1278
  WHERE table_schema = '${this.#adapter.escapeString(schema)}'
1184
1279
  AND table_name = '${this.#adapter.escapeString(table2)}'
1185
1280
  AND column_name = '${this.#adapter.escapeString(column2.name)}'
1186
- `);
1281
+ `,
1282
+ columnTypeRow
1283
+ );
1187
1284
  if (!rows.length) {
1188
1285
  return void 0;
1189
1286
  }
@@ -1206,7 +1303,7 @@ var PostgresColumnValuesGrounding = class extends ColumnValuesGrounding {
1206
1303
  WHERE ${columnIdentifier} IS NOT NULL
1207
1304
  LIMIT ${limit}
1208
1305
  `;
1209
- const rows = await this.#adapter.runQuery(sql);
1306
+ const rows = await this.#adapter.runQuery(sql, textValueRow2);
1210
1307
  if (!rows.length || rows.length > this.lowCardinalityLimit) {
1211
1308
  return void 0;
1212
1309
  }
@@ -1228,6 +1325,21 @@ var PostgresColumnValuesGrounding = class extends ColumnValuesGrounding {
1228
1325
  };
1229
1326
 
1230
1327
  // packages/text2sql/src/lib/adapters/postgres/constraint.postgres.grounding.ts
1328
+ import { z as z5 } from "zod";
1329
+ var constraintRow = z5.object({
1330
+ constraint_name: z5.string(),
1331
+ constraint_type: z5.string(),
1332
+ definition: z5.string().nullable(),
1333
+ column_name: z5.string().nullable(),
1334
+ ref_schema: z5.string().nullable(),
1335
+ ref_table: z5.string().nullable(),
1336
+ ref_column: z5.string().nullable()
1337
+ });
1338
+ var columnDefaultRow = z5.object({
1339
+ column_name: z5.string(),
1340
+ column_default: z5.string().nullable(),
1341
+ is_nullable: z5.string()
1342
+ });
1231
1343
  var PostgresConstraintGrounding = class extends ConstraintGrounding {
1232
1344
  #adapter;
1233
1345
  constructor(adapter, config = {}) {
@@ -1237,7 +1349,8 @@ var PostgresConstraintGrounding = class extends ConstraintGrounding {
1237
1349
  async getConstraints(tableName) {
1238
1350
  const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
1239
1351
  const constraints2 = [];
1240
- const constraintRows = await this.#adapter.runQuery(`
1352
+ const constraintRows = await this.#adapter.runQuery(
1353
+ `
1241
1354
  SELECT
1242
1355
  con.conname AS constraint_name,
1243
1356
  con.contype AS constraint_type,
@@ -1259,7 +1372,9 @@ var PostgresConstraintGrounding = class extends ConstraintGrounding {
1259
1372
  AND rel.relname = '${this.#adapter.escapeString(table2)}'
1260
1373
  AND con.contype IN ('p', 'f', 'c', 'u')
1261
1374
  ORDER BY con.conname, key.ord
1262
- `);
1375
+ `,
1376
+ constraintRow
1377
+ );
1263
1378
  const constraintMap = /* @__PURE__ */ new Map();
1264
1379
  for (const row of constraintRows) {
1265
1380
  const existing = constraintMap.get(row.constraint_name);
@@ -1312,7 +1427,8 @@ var PostgresConstraintGrounding = class extends ConstraintGrounding {
1312
1427
  });
1313
1428
  }
1314
1429
  }
1315
- const columnRows = await this.#adapter.runQuery(`
1430
+ const columnRows = await this.#adapter.runQuery(
1431
+ `
1316
1432
  SELECT
1317
1433
  column_name,
1318
1434
  column_default,
@@ -1320,7 +1436,9 @@ var PostgresConstraintGrounding = class extends ConstraintGrounding {
1320
1436
  FROM information_schema.columns
1321
1437
  WHERE table_schema = '${this.#adapter.escapeString(schema)}'
1322
1438
  AND table_name = '${this.#adapter.escapeString(table2)}'
1323
- `);
1439
+ `,
1440
+ columnDefaultRow
1441
+ );
1324
1442
  for (const col of columnRows) {
1325
1443
  const pkConstraint = constraints2.find((c) => c.type === "PRIMARY_KEY");
1326
1444
  const isPkColumn = pkConstraint?.columns?.includes(col.column_name);
@@ -1345,17 +1463,24 @@ var PostgresConstraintGrounding = class extends ConstraintGrounding {
1345
1463
  };
1346
1464
 
1347
1465
  // packages/text2sql/src/lib/adapters/postgres/indexes.postgres.grounding.ts
1466
+ import { z as z6 } from "zod";
1467
+ var indexRow = z6.object({
1468
+ index_name: z6.string(),
1469
+ column_name: z6.string(),
1470
+ is_unique: z6.boolean(),
1471
+ index_type: z6.string(),
1472
+ column_position: z6.number()
1473
+ });
1348
1474
  var PostgresIndexesGrounding = class extends IndexesGrounding {
1349
1475
  #adapter;
1350
- #schemas;
1351
1476
  constructor(adapter, config = {}) {
1352
1477
  super(config);
1353
1478
  this.#adapter = adapter;
1354
- this.#schemas = config.schemas;
1355
1479
  }
1356
1480
  async getIndexes(tableName) {
1357
1481
  const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
1358
- const rows = await this.#adapter.runQuery(`
1482
+ const rows = await this.#adapter.runQuery(
1483
+ `
1359
1484
  SELECT
1360
1485
  i.relname AS index_name,
1361
1486
  a.attname AS column_name,
@@ -1371,7 +1496,9 @@ var PostgresIndexesGrounding = class extends IndexesGrounding {
1371
1496
  WHERE n.nspname = '${this.#adapter.escapeString(schema)}'
1372
1497
  AND t.relname = '${this.#adapter.escapeString(table2)}'
1373
1498
  ORDER BY i.relname, array_position(ix.indkey, a.attnum)
1374
- `);
1499
+ `,
1500
+ indexRow
1501
+ );
1375
1502
  return this.#groupIndexes(rows);
1376
1503
  }
1377
1504
  #groupIndexes(rows) {
@@ -1403,10 +1530,8 @@ var PostgresInfoGrounding = class extends InfoGrounding {
1403
1530
  }
1404
1531
  async collectInfo() {
1405
1532
  const [versionRows, dbRows] = await Promise.all([
1406
- this.#adapter.runQuery(
1407
- "SELECT version() AS version"
1408
- ),
1409
- this.#adapter.runQuery("SELECT current_database() AS db")
1533
+ this.#adapter.runQuery("SELECT version() AS version", versionRow),
1534
+ this.#adapter.runQuery("SELECT current_database() AS db", databaseRow)
1410
1535
  ]);
1411
1536
  return {
1412
1537
  dialect: "postgresql",
@@ -1801,9 +1926,6 @@ var POSTGRES_ERROR_MAP = {
1801
1926
  hint: "The function or operator you used is not recognized. Confirm its name and argument types."
1802
1927
  }
1803
1928
  };
1804
- var LOW_CARDINALITY_LIMIT = 20;
1805
- var noopProgress2 = () => {
1806
- };
1807
1929
  function isPostgresError(error) {
1808
1930
  return typeof error === "object" && error !== null && "code" in error && typeof error.code === "string";
1809
1931
  }
@@ -1857,9 +1979,6 @@ var Postgres = class extends Adapter {
1857
1979
  return JSON.stringify(formatPostgresError(sql, error));
1858
1980
  }
1859
1981
  }
1860
- async runQuery(sql) {
1861
- return this.#runIntrospectionQuery(sql);
1862
- }
1863
1982
  quoteIdentifier(name) {
1864
1983
  return `"${name.replace(/"/g, '""')}"`;
1865
1984
  }
@@ -1872,398 +1991,22 @@ var Postgres = class extends Adapter {
1872
1991
  const columnList = columns?.length ? columns.map((c) => this.quoteIdentifier(c)).join(", ") : "*";
1873
1992
  return `SELECT ${columnList} FROM ${tableIdentifier} LIMIT ${limit}`;
1874
1993
  }
1875
- async #loadTables() {
1876
- const rows = await this.#runIntrospectionQuery(`
1877
- SELECT
1878
- c.table_schema,
1879
- c.table_name,
1880
- c.column_name,
1881
- c.data_type
1882
- FROM information_schema.columns AS c
1883
- JOIN information_schema.tables AS t
1884
- ON c.table_schema = t.table_schema
1885
- AND c.table_name = t.table_name
1886
- WHERE t.table_type = 'BASE TABLE'
1887
- ${this.#buildSchemaFilter("c.table_schema")}
1888
- ORDER BY c.table_schema, c.table_name, c.ordinal_position
1889
- `);
1890
- const tables2 = /* @__PURE__ */ new Map();
1891
- for (const row of rows) {
1892
- if (!row.table_name) {
1893
- continue;
1894
- }
1895
- const schema = row.table_schema ?? "public";
1896
- const tableName = row.table_name;
1897
- const qualifiedName = `${schema}.${tableName}`;
1898
- const table2 = tables2.get(qualifiedName) ?? {
1899
- name: qualifiedName,
1900
- schema,
1901
- rawName: tableName,
1902
- columns: []
1903
- };
1904
- table2.columns.push({
1905
- name: row.column_name ?? "unknown",
1906
- type: row.data_type ?? "unknown"
1907
- });
1908
- tables2.set(qualifiedName, table2);
1909
- }
1910
- return Array.from(tables2.values());
1911
- }
1912
- async #loadRelationships(filterTableNames) {
1913
- const tableFilter = this.#buildTableNamesFilter(filterTableNames);
1914
- const rows = await this.#runIntrospectionQuery(`
1915
- SELECT
1916
- tc.constraint_name,
1917
- tc.table_schema,
1918
- tc.table_name,
1919
- kcu.column_name,
1920
- ccu.table_schema AS foreign_table_schema,
1921
- ccu.table_name AS foreign_table_name,
1922
- ccu.column_name AS foreign_column_name
1923
- FROM information_schema.table_constraints AS tc
1924
- JOIN information_schema.key_column_usage AS kcu
1925
- ON tc.constraint_name = kcu.constraint_name
1926
- AND tc.table_schema = kcu.table_schema
1927
- JOIN information_schema.constraint_column_usage AS ccu
1928
- ON ccu.constraint_name = tc.constraint_name
1929
- AND ccu.table_schema = tc.table_schema
1930
- WHERE tc.constraint_type = 'FOREIGN KEY'
1931
- ${this.#buildSchemaFilter("tc.table_schema")}
1932
- ${tableFilter}
1933
- ORDER BY tc.table_schema, tc.table_name, tc.constraint_name, kcu.ordinal_position
1934
- `);
1935
- const relationships = /* @__PURE__ */ new Map();
1936
- for (const row of rows) {
1937
- if (!row.table_name || !row.foreign_table_name || !row.constraint_name) {
1938
- continue;
1939
- }
1940
- const schema = row.table_schema ?? "public";
1941
- const referencedSchema = row.foreign_table_schema ?? "public";
1942
- const key = `${schema}.${row.table_name}:${row.constraint_name}`;
1943
- const relationship2 = relationships.get(key) ?? {
1944
- table: `${schema}.${row.table_name}`,
1945
- from: [],
1946
- referenced_table: `${referencedSchema}.${row.foreign_table_name}`,
1947
- to: []
1948
- };
1949
- relationship2.from.push(row.column_name ?? "unknown");
1950
- relationship2.to.push(row.foreign_column_name ?? "unknown");
1951
- relationships.set(key, relationship2);
1952
- }
1953
- return Array.from(relationships.values());
1954
- }
1955
- async #annotateRowCounts(tables2, onProgress = noopProgress2) {
1956
- const total = tables2.length;
1957
- for (let i = 0; i < tables2.length; i++) {
1958
- const table2 = tables2[i];
1959
- const tableIdentifier = this.#formatQualifiedTableName(table2);
1960
- onProgress({
1961
- type: "phase:progress",
1962
- phase: "row_counts",
1963
- table: table2.name,
1964
- message: `Counting rows in ${table2.name}...`,
1965
- current: i + 1,
1966
- total
1967
- });
1968
- try {
1969
- const rows = await this.#runIntrospectionQuery(`SELECT COUNT(*) as count FROM ${tableIdentifier}`);
1970
- const rowCount2 = this.#toNumber(rows[0]?.count);
1971
- if (rowCount2 != null) {
1972
- table2.rowCount = rowCount2;
1973
- table2.sizeHint = this.#classifyRowCount(rowCount2);
1974
- }
1975
- } catch {
1976
- continue;
1977
- }
1978
- }
1979
- }
1980
- async #annotateIndexes(tables2) {
1981
- if (!tables2.length) {
1982
- return;
1983
- }
1984
- const tableMap = new Map(tables2.map((table2) => [table2.name, table2]));
1985
- const rows = await this.#runIntrospectionQuery(`
1986
- SELECT
1987
- n.nspname AS table_schema,
1988
- t.relname AS table_name,
1989
- i.relname AS index_name,
1990
- a.attname AS column_name,
1991
- ix.indisunique,
1992
- ix.indisprimary,
1993
- ix.indisclustered,
1994
- am.amname AS method
1995
- FROM pg_index ix
1996
- JOIN pg_class t ON t.oid = ix.indrelid
1997
- JOIN pg_namespace n ON n.oid = t.relnamespace
1998
- JOIN pg_class i ON i.oid = ix.indexrelid
1999
- JOIN pg_am am ON am.oid = i.relam
2000
- LEFT JOIN LATERAL unnest(ix.indkey) WITH ORDINALITY AS key(attnum, ordinality) ON TRUE
2001
- LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = key.attnum
2002
- WHERE t.relkind = 'r'
2003
- ${this.#buildSchemaFilter("n.nspname")}
2004
- ORDER BY n.nspname, t.relname, i.relname, key.ordinality
2005
- `);
2006
- const indexMap = /* @__PURE__ */ new Map();
2007
- for (const row of rows) {
2008
- if (!row.table_name || !row.index_name) {
2009
- continue;
2010
- }
2011
- const schema = row.table_schema ?? "public";
2012
- const tableKey = `${schema}.${row.table_name}`;
2013
- const table2 = tableMap.get(tableKey);
2014
- if (!table2) {
2015
- continue;
2016
- }
2017
- const indexKey = `${tableKey}:${row.index_name}`;
2018
- let index2 = indexMap.get(indexKey);
2019
- if (!index2) {
2020
- index2 = {
2021
- name: row.index_name,
2022
- columns: [],
2023
- unique: Boolean(row.indisunique ?? false),
2024
- type: row.indisclustered ? "clustered" : row.method ?? void 0
2025
- };
2026
- indexMap.set(indexKey, index2);
2027
- if (!table2.indexes) {
2028
- table2.indexes = [];
2029
- }
2030
- table2.indexes.push(index2);
2031
- }
2032
- if (row.column_name) {
2033
- index2.columns.push(row.column_name);
2034
- const column2 = table2.columns.find(
2035
- (col) => col.name === row.column_name
2036
- );
2037
- if (column2) {
2038
- column2.isIndexed = true;
2039
- }
2040
- }
2041
- }
2042
- }
2043
- async #annotateColumnStats(tables2, onProgress = noopProgress2) {
2044
- if (!tables2.length) {
2045
- return;
2046
- }
2047
- const total = tables2.length;
2048
- for (let i = 0; i < tables2.length; i++) {
2049
- const table2 = tables2[i];
2050
- const tableIdentifier = this.#formatQualifiedTableName(table2);
2051
- onProgress({
2052
- type: "phase:progress",
2053
- phase: "column_stats",
2054
- table: table2.name,
2055
- message: `Collecting stats for ${table2.name}...`,
2056
- current: i + 1,
2057
- total
2058
- });
2059
- for (const column2 of table2.columns) {
2060
- if (!this.#shouldCollectStats(column2.type)) {
2061
- continue;
2062
- }
2063
- const columnIdentifier = this.#quoteIdentifier(column2.name);
2064
- const sql = `
2065
- SELECT
2066
- MIN(${columnIdentifier})::text AS min_value,
2067
- MAX(${columnIdentifier})::text AS max_value,
2068
- AVG(CASE WHEN ${columnIdentifier} IS NULL THEN 1.0 ELSE 0.0 END)::float AS null_fraction
2069
- FROM ${tableIdentifier}
2070
- `;
2071
- try {
2072
- const rows = await this.#runIntrospectionQuery(sql);
2073
- if (!rows.length) {
2074
- continue;
2075
- }
2076
- const min = rows[0]?.min_value ?? void 0;
2077
- const max = rows[0]?.max_value ?? void 0;
2078
- const nullFraction = this.#toNumber(rows[0]?.null_fraction);
2079
- if (min != null || max != null || nullFraction != null) {
2080
- column2.stats = {
2081
- min,
2082
- max,
2083
- nullFraction: nullFraction != null && Number.isFinite(nullFraction) ? Math.max(0, Math.min(1, nullFraction)) : void 0
2084
- };
2085
- }
2086
- } catch {
2087
- continue;
2088
- }
2089
- }
2090
- }
2091
- }
2092
- async #annotateLowCardinalityColumns(tables2, onProgress = noopProgress2) {
2093
- const total = tables2.length;
2094
- for (let i = 0; i < tables2.length; i++) {
2095
- const table2 = tables2[i];
2096
- const tableIdentifier = this.#formatQualifiedTableName(table2);
2097
- onProgress({
2098
- type: "phase:progress",
2099
- phase: "low_cardinality",
2100
- table: table2.name,
2101
- message: `Analyzing cardinality in ${table2.name}...`,
2102
- current: i + 1,
2103
- total
2104
- });
2105
- for (const column2 of table2.columns) {
2106
- const columnIdentifier = this.#quoteIdentifier(column2.name);
2107
- const limit = LOW_CARDINALITY_LIMIT + 1;
2108
- const sql = `
2109
- SELECT DISTINCT ${columnIdentifier} AS value
2110
- FROM ${tableIdentifier}
2111
- WHERE ${columnIdentifier} IS NOT NULL
2112
- LIMIT ${limit}
2113
- `;
2114
- let rows = [];
2115
- try {
2116
- rows = await this.#runIntrospectionQuery(sql);
2117
- } catch {
2118
- continue;
2119
- }
2120
- if (!rows.length || rows.length > LOW_CARDINALITY_LIMIT) {
2121
- continue;
2122
- }
2123
- const values = [];
2124
- let shouldSkip = false;
2125
- for (const row of rows) {
2126
- const formatted = this.#normalizeValue(row.value);
2127
- if (formatted == null) {
2128
- shouldSkip = true;
2129
- break;
2130
- }
2131
- values.push(formatted);
2132
- }
2133
- if (shouldSkip || !values.length) {
2134
- continue;
2135
- }
2136
- column2.kind = "LowCardinality";
2137
- column2.values = values;
2138
- }
2139
- }
2140
- }
2141
- #buildSchemaFilter(columnName) {
2142
- if (this.#options.schemas && this.#options.schemas.length > 0) {
2143
- const values = this.#options.schemas.map((schema) => `'${schema.replace(/'/g, "''")}'`).join(", ");
2144
- return `AND ${columnName} IN (${values})`;
2145
- }
2146
- return `AND ${columnName} NOT IN ('pg_catalog', 'information_schema')`;
2147
- }
2148
1994
  /**
2149
- * Build a filter for table names (qualified as schema.table).
2150
- * Matches if either the source table or referenced table is in the list.
1995
+ * The schemas introspection is limited to; table and view discovery use
1996
+ * them unless a grounding lists its own.
2151
1997
  */
2152
- #buildTableNamesFilter(tableNames) {
2153
- if (!tableNames || tableNames.length === 0) {
2154
- return "";
2155
- }
2156
- const conditions = [];
2157
- for (const name of tableNames) {
2158
- if (name.includes(".")) {
2159
- const [schema, ...rest] = name.split(".");
2160
- const tableName = rest.join(".");
2161
- const escapedSchema = schema.replace(/'/g, "''");
2162
- const escapedTable = tableName.replace(/'/g, "''");
2163
- conditions.push(
2164
- `(tc.table_schema = '${escapedSchema}' AND tc.table_name = '${escapedTable}')`
2165
- );
2166
- conditions.push(
2167
- `(ccu.table_schema = '${escapedSchema}' AND ccu.table_name = '${escapedTable}')`
2168
- );
2169
- } else {
2170
- const escaped = name.replace(/'/g, "''");
2171
- conditions.push(`tc.table_name = '${escaped}'`);
2172
- conditions.push(`ccu.table_name = '${escaped}'`);
2173
- }
2174
- }
2175
- return `AND (${conditions.join(" OR ")})`;
2176
- }
2177
- async #runIntrospectionQuery(sql) {
2178
- const result = await this.#options.execute(sql);
2179
- if (Array.isArray(result)) {
2180
- return result;
2181
- }
2182
- if (result && typeof result === "object" && "rows" in result && Array.isArray(result.rows)) {
2183
- return result.rows;
2184
- }
2185
- throw new Error(
2186
- "Postgres adapter execute() must return an array of rows or an object with a rows array when introspecting."
2187
- );
2188
- }
2189
- #quoteIdentifier(name) {
2190
- return `"${name.replace(/"/g, '""')}"`;
2191
- }
2192
- #formatQualifiedTableName(table2) {
2193
- if (table2.schema && table2.rawName) {
2194
- return `${this.#quoteIdentifier(table2.schema)}.${this.#quoteIdentifier(table2.rawName)}`;
2195
- }
2196
- if (table2.name.includes(".")) {
2197
- const [schemaPart, ...rest] = table2.name.split(".");
2198
- const tablePart = rest.join(".") || schemaPart;
2199
- if (rest.length === 0) {
2200
- return this.#quoteIdentifier(schemaPart);
2201
- }
2202
- return `${this.#quoteIdentifier(schemaPart)}.${this.#quoteIdentifier(tablePart)}`;
2203
- }
2204
- return this.#quoteIdentifier(table2.name);
1998
+ get schemas() {
1999
+ return this.#options.schemas;
2205
2000
  }
2206
- #toNumber(value) {
2207
- if (typeof value === "number" && Number.isFinite(value)) {
2208
- return value;
2209
- }
2210
- if (typeof value === "bigint") {
2211
- return Number(value);
2212
- }
2213
- if (typeof value === "string" && value.trim() !== "") {
2214
- const parsed = Number(value);
2215
- return Number.isFinite(parsed) ? parsed : null;
2216
- }
2217
- return null;
2218
- }
2219
- #shouldCollectStats(type) {
2220
- if (!type) {
2221
- return false;
2222
- }
2223
- const normalized = type.toLowerCase();
2224
- return /int|numeric|decimal|double|real|money|date|time|timestamp|bool/.test(
2225
- normalized
2226
- );
2227
- }
2228
- #classifyRowCount(count) {
2229
- if (count < 100) {
2230
- return "tiny";
2231
- }
2232
- if (count < 1e3) {
2233
- return "small";
2234
- }
2235
- if (count < 1e4) {
2236
- return "medium";
2237
- }
2238
- if (count < 1e5) {
2239
- return "large";
2240
- }
2241
- return "huge";
2242
- }
2243
- #normalizeValue(value) {
2244
- if (value === null || value === void 0) {
2245
- return null;
2246
- }
2247
- if (typeof value === "string") {
2248
- return value;
2249
- }
2250
- if (typeof value === "number" || typeof value === "bigint") {
2251
- return String(value);
2252
- }
2253
- if (typeof value === "boolean") {
2254
- return value ? "true" : "false";
2255
- }
2256
- if (value instanceof Date) {
2257
- return value.toISOString();
2258
- }
2259
- if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) {
2260
- return value.toString("utf-8");
2261
- }
2262
- return null;
2001
+ async queryRows(sql) {
2002
+ return this.rowsFrom(await this.#options.execute(sql), ["rows"]);
2263
2003
  }
2264
2004
  };
2265
2005
 
2266
2006
  // packages/text2sql/src/lib/adapters/postgres/row-count.postgres.grounding.ts
2007
+ import { z as z7 } from "zod";
2008
+ var estimateRow = z7.object({ estimate: numericValue.nullable() });
2009
+ var countRow = z7.object({ count: numericValue.nullable() });
2267
2010
  var PostgresRowCountGrounding = class extends RowCountGrounding {
2268
2011
  #adapter;
2269
2012
  constructor(adapter, config = {}) {
@@ -2279,51 +2022,82 @@ var PostgresRowCountGrounding = class extends RowCountGrounding {
2279
2022
  }
2280
2023
  async #getEstimatedRowCount(tableName) {
2281
2024
  const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
2282
- const rows = await this.#adapter.runQuery(`
2025
+ const rows = await this.#adapter.runQuery(
2026
+ `
2283
2027
  SELECT c.reltuples::bigint AS estimate
2284
2028
  FROM pg_class c
2285
2029
  JOIN pg_namespace n ON n.oid = c.relnamespace
2286
2030
  WHERE n.nspname = '${this.#adapter.escapeString(schema)}'
2287
2031
  AND c.relname = '${this.#adapter.escapeString(table2)}'
2288
- `);
2032
+ `,
2033
+ estimateRow
2034
+ );
2289
2035
  return this.#adapter.toNumber(rows[0]?.estimate);
2290
2036
  }
2291
2037
  async #getLiveRowCount(tableName) {
2292
2038
  const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
2293
2039
  const tableIdentifier = `${this.#adapter.quoteIdentifier(schema)}.${this.#adapter.quoteIdentifier(table2)}`;
2294
- const rows = await this.#adapter.runQuery(`SELECT COUNT(*) as count FROM ${tableIdentifier}`);
2040
+ const rows = await this.#adapter.runQuery(
2041
+ `SELECT COUNT(*) as count FROM ${tableIdentifier}`,
2042
+ countRow
2043
+ );
2295
2044
  return this.#adapter.toNumber(rows[0]?.count);
2296
2045
  }
2297
2046
  };
2298
2047
 
2299
2048
  // packages/text2sql/src/lib/adapters/postgres/table.postgres.grounding.ts
2049
+ import { z as z9 } from "zod";
2050
+
2051
+ // packages/text2sql/src/lib/adapters/postgres/postgres-rows.ts
2052
+ import { z as z8 } from "zod";
2053
+ var columnRow = z8.object({
2054
+ column_name: z8.string().nullable(),
2055
+ data_type: z8.string().nullable()
2056
+ });
2057
+
2058
+ // packages/text2sql/src/lib/adapters/postgres/table.postgres.grounding.ts
2059
+ var relationshipRow = z9.object({
2060
+ constraint_name: z9.string(),
2061
+ table_schema: z9.string(),
2062
+ table_name: z9.string(),
2063
+ column_name: z9.string(),
2064
+ foreign_table_schema: z9.string(),
2065
+ foreign_table_name: z9.string(),
2066
+ foreign_column_name: z9.string()
2067
+ });
2300
2068
  var PostgresTableGrounding = class extends TableGrounding {
2301
2069
  #adapter;
2302
2070
  #schemas;
2303
2071
  constructor(adapter, config = {}) {
2304
2072
  super(config);
2305
2073
  this.#adapter = adapter;
2306
- this.#schemas = config.schemas;
2074
+ this.#schemas = config.schemas ?? adapter.schemas;
2307
2075
  }
2308
2076
  async getAllTableNames() {
2309
- const rows = await this.#adapter.runQuery(`
2077
+ const rows = await this.#adapter.runQuery(
2078
+ `
2310
2079
  SELECT DISTINCT table_schema || '.' || table_name AS name
2311
2080
  FROM information_schema.tables
2312
2081
  WHERE table_type = 'BASE TABLE'
2313
2082
  ${this.#adapter.buildSchemaFilter("table_schema", this.#schemas)}
2314
2083
  ORDER BY name
2315
- `);
2084
+ `,
2085
+ nameRow
2086
+ );
2316
2087
  return rows.map((r) => r.name);
2317
2088
  }
2318
2089
  async getTable(tableName) {
2319
2090
  const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
2320
- const columns = await this.#adapter.runQuery(`
2091
+ const columns = await this.#adapter.runQuery(
2092
+ `
2321
2093
  SELECT column_name, data_type
2322
2094
  FROM information_schema.columns
2323
2095
  WHERE table_schema = '${this.#adapter.escapeString(schema)}'
2324
2096
  AND table_name = '${this.#adapter.escapeString(table2)}'
2325
2097
  ORDER BY ordinal_position
2326
- `);
2098
+ `,
2099
+ columnRow
2100
+ );
2327
2101
  return {
2328
2102
  name: tableName,
2329
2103
  schema,
@@ -2336,72 +2110,64 @@ var PostgresTableGrounding = class extends TableGrounding {
2336
2110
  }
2337
2111
  async findOutgoingRelations(tableName) {
2338
2112
  const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
2339
- const rows = await this.#adapter.runQuery(`
2340
- SELECT
2341
- tc.constraint_name,
2342
- tc.table_schema,
2343
- tc.table_name,
2344
- kcu.column_name,
2345
- ccu.table_schema AS foreign_table_schema,
2346
- ccu.table_name AS foreign_table_name,
2347
- ccu.column_name AS foreign_column_name
2348
- FROM information_schema.table_constraints AS tc
2349
- JOIN information_schema.key_column_usage AS kcu
2350
- ON tc.constraint_name = kcu.constraint_name
2351
- AND tc.table_schema = kcu.table_schema
2352
- JOIN information_schema.constraint_column_usage AS ccu
2353
- ON ccu.constraint_name = tc.constraint_name
2354
- AND ccu.table_schema = tc.table_schema
2355
- WHERE tc.constraint_type = 'FOREIGN KEY'
2356
- AND tc.table_schema = '${this.#adapter.escapeString(schema)}'
2357
- AND tc.table_name = '${this.#adapter.escapeString(table2)}'
2358
- ORDER BY tc.constraint_name, kcu.ordinal_position
2359
- `);
2360
- return this.#groupRelationships(rows);
2113
+ return this.#foreignKeys(
2114
+ `nsp.nspname = '${this.#adapter.escapeString(schema)}'
2115
+ AND rel.relname = '${this.#adapter.escapeString(table2)}'`
2116
+ );
2361
2117
  }
2362
2118
  async findIncomingRelations(tableName) {
2363
2119
  const { schema, table: table2 } = this.#adapter.parseTableName(tableName);
2364
- const rows = await this.#adapter.runQuery(`
2120
+ return this.#foreignKeys(
2121
+ `ref_nsp.nspname = '${this.#adapter.escapeString(schema)}'
2122
+ AND ref_rel.relname = '${this.#adapter.escapeString(table2)}'`
2123
+ );
2124
+ }
2125
+ /**
2126
+ * The foreign keys matching `where`. unnest(conkey, confkey) WITH
2127
+ * ORDINALITY pairs each column with the column it references by position,
2128
+ * and each side carries its own schema, so composite and cross-schema keys
2129
+ * come back whole.
2130
+ */
2131
+ async #foreignKeys(where) {
2132
+ const rows = await this.#adapter.runQuery(
2133
+ `
2365
2134
  SELECT
2366
- tc.constraint_name,
2367
- tc.table_schema,
2368
- tc.table_name,
2369
- kcu.column_name,
2370
- ccu.table_schema AS foreign_table_schema,
2371
- ccu.table_name AS foreign_table_name,
2372
- ccu.column_name AS foreign_column_name
2373
- FROM information_schema.table_constraints AS tc
2374
- JOIN information_schema.key_column_usage AS kcu
2375
- ON tc.constraint_name = kcu.constraint_name
2376
- AND tc.table_schema = kcu.table_schema
2377
- JOIN information_schema.constraint_column_usage AS ccu
2378
- ON ccu.constraint_name = tc.constraint_name
2379
- AND ccu.table_schema = tc.table_schema
2380
- WHERE tc.constraint_type = 'FOREIGN KEY'
2381
- AND ccu.table_schema = '${this.#adapter.escapeString(schema)}'
2382
- AND ccu.table_name = '${this.#adapter.escapeString(table2)}'
2383
- ORDER BY tc.constraint_name, kcu.ordinal_position
2384
- `);
2385
- return this.#groupRelationships(rows);
2386
- }
2387
- #groupRelationships(rows) {
2135
+ con.conname AS constraint_name,
2136
+ nsp.nspname AS table_schema,
2137
+ rel.relname AS table_name,
2138
+ att.attname AS column_name,
2139
+ ref_nsp.nspname AS foreign_table_schema,
2140
+ ref_rel.relname AS foreign_table_name,
2141
+ ref_att.attname AS foreign_column_name
2142
+ FROM pg_constraint AS con
2143
+ JOIN pg_class AS rel ON rel.oid = con.conrelid
2144
+ JOIN pg_namespace AS nsp ON nsp.oid = rel.relnamespace
2145
+ JOIN pg_class AS ref_rel ON ref_rel.oid = con.confrelid
2146
+ JOIN pg_namespace AS ref_nsp ON ref_nsp.oid = ref_rel.relnamespace
2147
+ CROSS JOIN LATERAL unnest(con.conkey, con.confkey)
2148
+ WITH ORDINALITY AS key(attnum, ref_attnum, ord)
2149
+ JOIN pg_attribute AS att
2150
+ ON att.attrelid = con.conrelid AND att.attnum = key.attnum
2151
+ JOIN pg_attribute AS ref_att
2152
+ ON ref_att.attrelid = con.confrelid AND ref_att.attnum = key.ref_attnum
2153
+ WHERE con.contype = 'f'
2154
+ AND ${where}
2155
+ ORDER BY nsp.nspname, rel.relname, con.conname, key.ord
2156
+ `,
2157
+ relationshipRow
2158
+ );
2388
2159
  const relationships = /* @__PURE__ */ new Map();
2389
- const defaultSchema = this.#adapter.defaultSchema ?? "public";
2390
2160
  for (const row of rows) {
2391
- if (!row.table_name || !row.foreign_table_name || !row.constraint_name) {
2392
- continue;
2393
- }
2394
- const schema = row.table_schema ?? defaultSchema;
2395
- const referencedSchema = row.foreign_table_schema ?? defaultSchema;
2396
- const key = `${schema}.${row.table_name}:${row.constraint_name}`;
2161
+ const table2 = `${row.table_schema}.${row.table_name}`;
2162
+ const key = `${table2}:${row.constraint_name}`;
2397
2163
  const relationship2 = relationships.get(key) ?? {
2398
- table: `${schema}.${row.table_name}`,
2164
+ table: table2,
2399
2165
  from: [],
2400
- referenced_table: `${referencedSchema}.${row.foreign_table_name}`,
2166
+ referenced_table: `${row.foreign_table_schema}.${row.foreign_table_name}`,
2401
2167
  to: []
2402
2168
  };
2403
- relationship2.from.push(row.column_name ?? "unknown");
2404
- relationship2.to.push(row.foreign_column_name ?? "unknown");
2169
+ relationship2.from.push(row.column_name);
2170
+ relationship2.to.push(row.foreign_column_name);
2405
2171
  relationships.set(key, relationship2);
2406
2172
  }
2407
2173
  return Array.from(relationships.values());
@@ -2470,37 +2236,46 @@ var PostgresViewGrounding = class extends ViewGrounding {
2470
2236
  constructor(adapter, config = {}) {
2471
2237
  super(config);
2472
2238
  this.#adapter = adapter;
2473
- this.#schemas = config.schemas;
2239
+ this.#schemas = config.schemas ?? adapter.schemas;
2474
2240
  }
2475
2241
  async getAllViewNames() {
2476
- const rows = await this.#adapter.runQuery(`
2242
+ const rows = await this.#adapter.runQuery(
2243
+ `
2477
2244
  SELECT table_schema || '.' || table_name AS name
2478
2245
  FROM information_schema.views
2479
2246
  WHERE 1=1
2480
2247
  ${this.#adapter.buildSchemaFilter("table_schema", this.#schemas)}
2481
2248
  ORDER BY name
2482
- `);
2249
+ `,
2250
+ nameRow
2251
+ );
2483
2252
  return rows.map((r) => r.name);
2484
2253
  }
2485
2254
  async getView(viewName) {
2486
2255
  const { schema, table: view2 } = this.#adapter.parseTableName(viewName);
2487
2256
  let definition;
2488
2257
  if (this.includeDefinition) {
2489
- const defRows = await this.#adapter.runQuery(`
2258
+ const defRows = await this.#adapter.runQuery(
2259
+ `
2490
2260
  SELECT definition
2491
2261
  FROM pg_views
2492
2262
  WHERE schemaname = '${this.#adapter.escapeString(schema)}'
2493
2263
  AND viewname = '${this.#adapter.escapeString(view2)}'
2494
- `);
2264
+ `,
2265
+ viewDefinitionRow
2266
+ );
2495
2267
  definition = defRows[0]?.definition ?? void 0;
2496
2268
  }
2497
- const columns = await this.#adapter.runQuery(`
2269
+ const columns = await this.#adapter.runQuery(
2270
+ `
2498
2271
  SELECT column_name, data_type
2499
2272
  FROM information_schema.columns
2500
2273
  WHERE table_schema = '${this.#adapter.escapeString(schema)}'
2501
2274
  AND table_name = '${this.#adapter.escapeString(view2)}'
2502
2275
  ORDER BY ordinal_position
2503
- `);
2276
+ `,
2277
+ columnRow
2278
+ );
2504
2279
  return {
2505
2280
  name: viewName,
2506
2281
  schema,
@@ -2516,15 +2291,19 @@ var PostgresViewGrounding = class extends ViewGrounding {
2516
2291
 
2517
2292
  // packages/text2sql/src/lib/adapters/postgres/index.ts
2518
2293
  function tables(config = {}) {
2519
- return (adapter) => new PostgresTableGrounding(adapter, config);
2294
+ return groundingFor(
2295
+ Postgres,
2296
+ (adapter) => new PostgresTableGrounding(adapter, config)
2297
+ );
2520
2298
  }
2521
2299
  function info(config = {}) {
2522
2300
  return (adapter) => new PostgresInfoGrounding(adapter, config);
2523
2301
  }
2524
2302
  function views(config = {}) {
2525
- return (adapter) => {
2526
- return new PostgresViewGrounding(adapter, config);
2527
- };
2303
+ return groundingFor(
2304
+ Postgres,
2305
+ (adapter) => new PostgresViewGrounding(adapter, config)
2306
+ );
2528
2307
  }
2529
2308
  function columnStats(config = {}) {
2530
2309
  return (adapter) => {