@antelopejs/postgres 0.2.0 → 0.2.1

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 (57) hide show
  1. package/dist/config.d.ts +5 -0
  2. package/dist/config.js +1 -0
  3. package/dist/config.js.map +1 -1
  4. package/dist/implementations/catalog/index.d.ts +7 -0
  5. package/dist/implementations/catalog/index.js +60 -0
  6. package/dist/implementations/catalog/index.js.map +1 -0
  7. package/dist/implementations/database/external-catalog.d.ts +15 -0
  8. package/dist/implementations/database/external-catalog.js +22 -8
  9. package/dist/implementations/database/external-catalog.js.map +1 -1
  10. package/dist/implementations/database/external-column-profile.d.ts +18 -0
  11. package/dist/implementations/database/external-column-profile.js +223 -0
  12. package/dist/implementations/database/external-column-profile.js.map +1 -0
  13. package/dist/implementations/database/external-declarations.d.ts +9 -0
  14. package/dist/implementations/database/external-declarations.js +67 -0
  15. package/dist/implementations/database/external-declarations.js.map +1 -0
  16. package/dist/implementations/database/external-discovery.d.ts +39 -0
  17. package/dist/implementations/database/external-discovery.js +219 -0
  18. package/dist/implementations/database/external-discovery.js.map +1 -0
  19. package/dist/implementations/database/external-measures.d.ts +11 -0
  20. package/dist/implementations/database/external-measures.js +82 -0
  21. package/dist/implementations/database/external-measures.js.map +1 -0
  22. package/dist/implementations/database/external-profile.d.ts +4 -0
  23. package/dist/implementations/database/external-profile.js +129 -0
  24. package/dist/implementations/database/external-profile.js.map +1 -0
  25. package/dist/implementations/database/external-reference.d.ts +2 -0
  26. package/dist/implementations/database/external-reference.js +49 -0
  27. package/dist/implementations/database/external-reference.js.map +1 -0
  28. package/dist/implementations/database/external-rows.d.ts +2 -0
  29. package/dist/implementations/database/external-rows.js +81 -0
  30. package/dist/implementations/database/external-rows.js.map +1 -0
  31. package/dist/implementations/database/external-sample.d.ts +9 -0
  32. package/dist/implementations/database/external-sample.js +29 -0
  33. package/dist/implementations/database/external-sample.js.map +1 -0
  34. package/dist/implementations/database/external-schema.js +1 -11
  35. package/dist/implementations/database/external-schema.js.map +1 -1
  36. package/dist/implementations/database/external-types.d.ts +9 -1
  37. package/dist/implementations/database/external-types.js +14 -0
  38. package/dist/implementations/database/external-types.js.map +1 -1
  39. package/dist/index.d.ts +1 -1
  40. package/dist/index.js +1 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/test/antelope.test.js +1 -0
  43. package/dist/test/antelope.test.js.map +1 -1
  44. package/dist/test/catalog-owned.test.d.ts +1 -0
  45. package/dist/test/catalog-owned.test.js +17 -0
  46. package/dist/test/catalog-owned.test.js.map +1 -0
  47. package/dist/test/unit/external-comparisons.spec.js +2 -0
  48. package/dist/test/unit/external-comparisons.spec.js.map +1 -1
  49. package/dist/test/unit/external-types.spec.js +37 -0
  50. package/dist/test/unit/external-types.spec.js.map +1 -1
  51. package/dist/test-external/catalog.test.d.ts +1 -0
  52. package/dist/test-external/catalog.test.js +348 -0
  53. package/dist/test-external/catalog.test.js.map +1 -0
  54. package/dist/test-external/fixture.d.ts +1 -0
  55. package/dist/test-external/fixture.js +28 -1
  56. package/dist/test-external/fixture.js.map +1 -1
  57. package/package.json +4 -2
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RelationName = RelationName;
4
+ exports.ReadInfo = ReadInfo;
5
+ exports.ReadRelationRows = ReadRelationRows;
6
+ exports.ReadNamedRelationRows = ReadNamedRelationRows;
7
+ exports.EstimateOf = EstimateOf;
8
+ exports.KeyFrom = KeyFrom;
9
+ exports.Summarize = Summarize;
10
+ exports.ReferenceOf = ReferenceOf;
11
+ exports.ReadReferences = ReadReferences;
12
+ exports.DescribeRow = DescribeRow;
13
+ const connection_1 = require("../../connection");
14
+ const external_catalog_1 = require("./external-catalog");
15
+ const external_declarations_1 = require("./external-declarations");
16
+ const external_types_1 = require("./external-types");
17
+ const identifier_1 = require("./identifier");
18
+ const ENGINE = "postgresql";
19
+ const SYSTEM_SCHEMAS = "('pg_catalog', 'information_schema')";
20
+ const RELATIONS_SQL = `
21
+ WITH leaves AS (
22
+ SELECT c.oid, coalesce(sum(CASE WHEN l.reltuples >= 0 THEN l.reltuples END), 0) AS statistics,
23
+ coalesce(sum(s.n_live_tup), 0) AS live, bool_and(l.reltuples >= 0) AS analyzed
24
+ FROM pg_class c
25
+ JOIN LATERAL pg_partition_tree(c.oid) t ON t.isleaf
26
+ JOIN pg_class l ON l.oid = t.relid
27
+ LEFT JOIN pg_stat_all_tables s ON s.relid = l.oid
28
+ WHERE c.relkind = 'p'
29
+ GROUP BY c.oid
30
+ )
31
+ SELECT c.oid, n.nspname AS schema, c.relname AS name, c.relkind AS kind,
32
+ has_table_privilege(c.oid, 'SELECT') AS readable,
33
+ has_any_column_privilege(c.oid, 'SELECT') AS "someColumns",
34
+ has_table_privilege(c.oid, 'INSERT') AS insert,
35
+ has_table_privilege(c.oid, 'UPDATE') AS update,
36
+ has_table_privilege(c.oid, 'DELETE') AS delete,
37
+ coalesce(p.analyzed, c.reltuples >= 0) AS analyzed,
38
+ coalesce(p.statistics, CASE WHEN c.reltuples >= 0 THEN c.reltuples END)::float8 AS statistics,
39
+ coalesce(p.live, s.n_live_tup)::float8 AS "liveTuples",
40
+ obj_description(c.oid, 'pg_class') AS comment
41
+ FROM pg_class c
42
+ JOIN pg_namespace n ON n.oid = c.relnamespace
43
+ LEFT JOIN pg_stat_all_tables s ON s.relid = c.oid
44
+ LEFT JOIN leaves p ON p.oid = c.oid
45
+ WHERE c.relkind IN ${external_catalog_1.RELATION_KINDS} AND NOT c.relispartition
46
+ AND n.nspname NOT IN ${SYSTEM_SCHEMAS}
47
+ AND n.nspname NOT LIKE 'pg\\_%'
48
+ AND has_schema_privilege(n.oid, 'USAGE')
49
+ AND ($1::text[] IS NULL OR n.nspname = ANY($1::text[]))
50
+ ORDER BY n.nspname, c.relname`;
51
+ const NAMED_RELATIONS_SQL = RELATIONS_SQL.replace("AND ($1::text[] IS NULL OR n.nspname = ANY($1::text[]))", "AND (n.nspname || '.' || c.relname) = ANY($1::text[])");
52
+ const COLUMN_LIST = (relation, keys) => `ARRAY(
53
+ SELECT a.attname::text FROM unnest(con.${keys}) WITH ORDINALITY k(n, o)
54
+ JOIN pg_attribute a ON a.attrelid = con.${relation} AND a.attnum = k.n
55
+ ORDER BY k.o
56
+ )`;
57
+ const REFERENCES_SQL = `
58
+ SELECT con.conname AS name,
59
+ fn.nspname || '.' || fc.relname AS "fromRelation", ${COLUMN_LIST("conrelid", "conkey")} AS "fromColumns",
60
+ tn.nspname || '.' || tc.relname AS "toRelation", ${COLUMN_LIST("confrelid", "confkey")} AS "toColumns"
61
+ FROM pg_constraint con
62
+ JOIN pg_class fc ON fc.oid = con.conrelid
63
+ JOIN pg_namespace fn ON fn.oid = fc.relnamespace
64
+ JOIN pg_class tc ON tc.oid = con.confrelid
65
+ JOIN pg_namespace tn ON tn.oid = tc.relnamespace
66
+ WHERE con.contype = 'f' AND con.conparentid = 0 AND (con.conrelid = $1 OR con.confrelid = $1)
67
+ ORDER BY con.conname`;
68
+ const INFO_SQL = `
69
+ SELECT current_setting('server_version') AS version, current_database() AS database,
70
+ current_user AS role`;
71
+ const KINDS = {
72
+ r: "table",
73
+ p: "partitioned",
74
+ v: "view",
75
+ m: "materialized",
76
+ f: "foreign",
77
+ };
78
+ const PARTIAL_GRANTS = "SELECT is granted on some of its columns only";
79
+ const NOT_READABLE = "the connected role cannot SELECT from it";
80
+ function RelationName(row) {
81
+ return `${row.schema}.${row.name}`;
82
+ }
83
+ async function ReadInfo() {
84
+ const [row] = (await (0, connection_1.Query)(INFO_SQL)).rows;
85
+ return { engine: ENGINE, ...row };
86
+ }
87
+ async function ReadRelationRows(schemas) {
88
+ return (await (0, connection_1.Query)(RELATIONS_SQL, [schemas ?? null])).rows;
89
+ }
90
+ async function ReadNamedRelationRows(relations) {
91
+ return (await (0, connection_1.Query)(NAMED_RELATIONS_SQL, [relations])).rows;
92
+ }
93
+ async function PlannedRows(row) {
94
+ try {
95
+ const sql = `EXPLAIN (FORMAT JSON) SELECT * FROM ${(0, identifier_1.QualifiedName)(row.schema, row.name)}`;
96
+ const [plan] = (await (0, connection_1.Query)(sql)).rows;
97
+ return plan["QUERY PLAN"][0].Plan["Plan Rows"];
98
+ }
99
+ catch {
100
+ return null;
101
+ }
102
+ }
103
+ async function EstimateOf(row) {
104
+ if (row.analyzed && row.statistics !== null) {
105
+ return { estimatedRows: row.statistics, estimate: "statistics" };
106
+ }
107
+ if (row.liveTuples !== null) {
108
+ return { estimatedRows: row.liveTuples, estimate: "live-tuples" };
109
+ }
110
+ if (!row.readable) {
111
+ return { estimatedRows: null, estimate: null };
112
+ }
113
+ const planned = await PlannedRows(row);
114
+ return planned === null
115
+ ? { estimatedRows: null, estimate: null }
116
+ : { estimatedRows: planned, estimate: "plan" };
117
+ }
118
+ function UnmappableReason(row) {
119
+ if (row.readable) {
120
+ return undefined;
121
+ }
122
+ return row.someColumns ? PARTIAL_GRANTS : NOT_READABLE;
123
+ }
124
+ function KeyFrom(indexes, columns) {
125
+ const key = (0, external_catalog_1.KeyOf)(indexes);
126
+ const byName = new Map(columns.map((column) => [column.name, column]));
127
+ if (!key || !(0, external_types_1.DescribeKeyColumns)(key.columns, byName)) {
128
+ return null;
129
+ }
130
+ return { columns: key.columns, source: key.primary ? "primary" : "unique" };
131
+ }
132
+ async function SummaryOf(row, key) {
133
+ return {
134
+ schema: row.schema,
135
+ name: row.name,
136
+ kind: KINDS[row.kind],
137
+ ...(await EstimateOf(row)),
138
+ key,
139
+ unmappable: UnmappableReason(row),
140
+ writes: { insert: row.insert, update: row.update, delete: row.delete },
141
+ comment: row.comment,
142
+ };
143
+ }
144
+ async function Summarize(row) {
145
+ const [columns, indexes] = await Promise.all([
146
+ (0, external_catalog_1.ReadColumns)(row.oid),
147
+ (0, external_catalog_1.ReadIndexes)(row.oid),
148
+ ]);
149
+ return SummaryOf(row, KeyFrom(indexes, columns));
150
+ }
151
+ function ReadOnlyOf(column, path) {
152
+ const [proposed] = (0, external_declarations_1.AcceptedDeclarations)(column);
153
+ if (!proposed) {
154
+ return undefined;
155
+ }
156
+ const descriptor = (0, external_types_1.Describe)(column.name, proposed.kind, column, path);
157
+ return (0, external_types_1.IsReadOnly)(descriptor) ? (0, external_types_1.ReadOnlyReason)(descriptor) : undefined;
158
+ }
159
+ const IDENTITIES = {
160
+ a: "always",
161
+ d: "by default",
162
+ };
163
+ function DescribeColumn(column, relation) {
164
+ const accepts = (0, external_declarations_1.AcceptedDeclarations)(column).map(({ declared, lossy }) => lossy ? { declared, lossy } : { declared });
165
+ const described = {
166
+ name: column.name,
167
+ native: column.native,
168
+ nullable: !column.notNull,
169
+ hasDefault: column.hasDefault,
170
+ generated: column.generated,
171
+ identity: IDENTITIES[column.identity] ?? null,
172
+ accepts,
173
+ comment: column.comment,
174
+ };
175
+ if (column.enumLabels) {
176
+ described.enumLabels = column.enumLabels;
177
+ }
178
+ if (accepts.length === 0) {
179
+ described.unsupported = (0, external_declarations_1.UnsupportedReason)(column);
180
+ }
181
+ const readOnly = ReadOnlyOf(column, `${relation}.${column.name}`);
182
+ if (readOnly) {
183
+ described.readOnly = readOnly;
184
+ }
185
+ return described;
186
+ }
187
+ function IndexOf(index) {
188
+ return { name: index.name, columns: index.columns, unique: index.unique };
189
+ }
190
+ function ReferenceOf(row) {
191
+ return {
192
+ name: row.name,
193
+ from: { relation: row.fromRelation, columns: row.fromColumns },
194
+ to: { relation: row.toRelation, columns: row.toColumns },
195
+ };
196
+ }
197
+ async function ReadReferences(oid) {
198
+ return (await (0, connection_1.Query)(REFERENCES_SQL, [oid])).rows;
199
+ }
200
+ async function DescribeRow(row) {
201
+ const relation = RelationName(row);
202
+ const [columns, indexes, references] = await Promise.all([
203
+ (0, external_catalog_1.ReadColumns)(row.oid),
204
+ (0, external_catalog_1.ReadIndexes)(row.oid),
205
+ ReadReferences(row.oid),
206
+ ]);
207
+ return {
208
+ ...(await SummaryOf(row, KeyFrom(indexes, columns))),
209
+ columns: columns.map((column) => DescribeColumn(column, relation)),
210
+ indexes: indexes.filter((index) => index.columns.length > 0).map(IndexOf),
211
+ references: references
212
+ .filter((reference) => reference.fromRelation === relation)
213
+ .map(ReferenceOf),
214
+ referencedBy: references
215
+ .filter((reference) => reference.toRelation === relation)
216
+ .map(ReferenceOf),
217
+ };
218
+ }
219
+ //# sourceMappingURL=external-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-discovery.js","sourceRoot":"","sources":["../../../src/implementations/database/external-discovery.ts"],"names":[],"mappings":";;AA2JA,oCAEC;AAED,4BAGC;AAED,4CAIC;AAED,sDAIC;AAsBD,gCAcC;AAUD,0BAUC;AAkBD,8BAMC;AAkDD,kCAMC;AAED,wCAEC;AAED,kCAoBC;AApUD,iDAAyC;AACzC,yDAO4B;AAC5B,mEAGiC;AACjC,qDAK0B;AAC1B,6CAA6C;AA6C7C,MAAM,MAAM,GAAG,YAAY,CAAC;AAE5B,MAAM,cAAc,GAAG,sCAAsC,CAAC;AAM9D,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;uBAyBC,iCAAc;2BACV,cAAc;;;;gCAIT,CAAC;AAEjC,MAAM,mBAAmB,GAAG,aAAa,CAAC,OAAO,CAC/C,yDAAyD,EACzD,uDAAuD,CACxD,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAE,IAAY,EAAE,EAAE,CAAC;+CACT,IAAI;gDACH,QAAQ;;MAElD,CAAC;AAGP,MAAM,cAAc,GAAG;;yDAEkC,WAAW,CAAC,UAAU,EAAE,QAAQ,CAAC;uDACnC,WAAW,CAAC,WAAW,EAAE,SAAS,CAAC;;;;;;;uBAOnE,CAAC;AAExB,MAAM,QAAQ,GAAG;;yBAEQ,CAAC;AAE1B,MAAM,KAAK,GAAiC;IAC1C,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,aAAa;IAChB,CAAC,EAAE,MAAM;IACT,CAAC,EAAE,cAAc;IACjB,CAAC,EAAE,SAAS;CACb,CAAC;AAEF,MAAM,cAAc,GAAG,+CAA+C,CAAC;AACvE,MAAM,YAAY,GAAG,0CAA0C,CAAC;AAEhE,SAAgB,YAAY,CAAC,GAAgB;IAC3C,OAAO,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;AACrC,CAAC;AAEM,KAAK,UAAU,QAAQ;IAC5B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,IAAA,kBAAK,EAAU,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IACpD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC;AACpC,CAAC;AAEM,KAAK,UAAU,gBAAgB,CACpC,OAAkB;IAElB,OAAO,CAAC,MAAM,IAAA,kBAAK,EAAc,aAAa,EAAE,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3E,CAAC;AAEM,KAAK,UAAU,qBAAqB,CACzC,SAAmB;IAEnB,OAAO,CAAC,MAAM,IAAA,kBAAK,EAAc,mBAAmB,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3E,CAAC;AAGD,KAAK,UAAU,WAAW,CAAC,GAAgB;IACzC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,uCAAuC,IAAA,0BAAa,EAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACzF,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAA,kBAAK,EAAU,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QAChD,OAAO,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAWM,KAAK,UAAU,UAAU,CAAC,GAAgB;IAC/C,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO,EAAE,aAAa,EAAE,GAAG,CAAC,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;IACnE,CAAC;IACD,IAAI,GAAG,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAC5B,OAAO,EAAE,aAAa,EAAE,GAAG,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;IACpE,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAClB,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACjD,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;IACvC,OAAO,OAAO,KAAK,IAAI;QACrB,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;QACzC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;AACnD,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAgB;IACxC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QACjB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC;AACzD,CAAC;AAGD,SAAgB,OAAO,CACrB,OAAuB,EACvB,OAAwB;IAExB,MAAM,GAAG,GAAG,IAAA,wBAAK,EAAC,OAAO,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACvE,IAAI,CAAC,GAAG,IAAI,CAAC,IAAA,mCAAkB,EAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;AAC9E,CAAC;AAED,KAAK,UAAU,SAAS,CACtB,GAAgB,EAChB,GAAuB;IAEvB,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;QACrB,GAAG,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;QAC1B,GAAG;QACH,UAAU,EAAE,gBAAgB,CAAC,GAAG,CAAC;QACjC,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE;QACtE,OAAO,EAAE,GAAG,CAAC,OAAO;KACrB,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,SAAS,CAAC,GAAgB;IAC9C,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC3C,IAAA,8BAAW,EAAC,GAAG,CAAC,GAAG,CAAC;QACpB,IAAA,8BAAW,EAAC,GAAG,CAAC,GAAG,CAAC;KACrB,CAAC,CAAC;IACH,OAAO,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,UAAU,CAAC,MAAqB,EAAE,IAAY;IACrD,MAAM,CAAC,QAAQ,CAAC,GAAG,IAAA,4CAAoB,EAAC,MAAM,CAAC,CAAC;IAChD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,UAAU,GAAG,IAAA,yBAAQ,EAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IACtE,OAAO,IAAA,2BAAU,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAA,+BAAc,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,GAAkD;IAChE,CAAC,EAAE,QAAQ;IACX,CAAC,EAAE,YAAY;CAChB,CAAC;AAEF,SAAS,cAAc,CACrB,MAAqB,EACrB,QAAgB;IAEhB,MAAM,OAAO,GAAG,IAAA,4CAAoB,EAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CACvE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAC3C,CAAC;IACF,MAAM,SAAS,GAAsB;QACnC,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,CAAC,MAAM,CAAC,OAAO;QACzB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,IAAI;QAC7C,OAAO;QACP,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC;IACF,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,SAAS,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IAC3C,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,SAAS,CAAC,WAAW,GAAG,IAAA,yCAAiB,EAAC,MAAM,CAAC,CAAC;IACpD,CAAC;IACD,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,EAAE,GAAG,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAClE,IAAI,QAAQ,EAAE,CAAC;QACb,SAAS,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAChC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,OAAO,CAAC,KAAmB;IAClC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;AAC5E,CAAC;AAED,SAAgB,WAAW,CAAC,GAAiB;IAC3C,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,IAAI,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,YAAY,EAAE,OAAO,EAAE,GAAG,CAAC,WAAW,EAAE;QAC9D,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,CAAC,SAAS,EAAE;KACzD,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,cAAc,CAAC,GAAW;IAC9C,OAAO,CAAC,MAAM,IAAA,kBAAK,EAAe,cAAc,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjE,CAAC;AAEM,KAAK,UAAU,WAAW,CAC/B,GAAgB;IAEhB,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACvD,IAAA,8BAAW,EAAC,GAAG,CAAC,GAAG,CAAC;QACpB,IAAA,8BAAW,EAAC,GAAG,CAAC,GAAG,CAAC;QACpB,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC;KACxB,CAAC,CAAC;IACH,OAAO;QACL,GAAG,CAAC,MAAM,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACpD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAClE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;QACzE,UAAU,EAAE,UAAU;aACnB,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,YAAY,KAAK,QAAQ,CAAC;aAC1D,GAAG,CAAC,WAAW,CAAC;QACnB,YAAY,EAAE,UAAU;aACrB,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,KAAK,QAAQ,CAAC;aACxD,GAAG,CAAC,WAAW,CAAC;KACpB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { Measure } from "@antelopejs/interface-database-catalog";
2
+ import type { QueryResultRow } from "pg";
3
+ export declare function SetMeasureTimeoutForTests(ms?: number): void;
4
+ export interface MeasureSession {
5
+ measure<T extends QueryResultRow>(sql: string, params?: unknown[]): Promise<Measure<T[]>>;
6
+ }
7
+ export declare function WithMeasures<T>(work: (session: MeasureSession) => Promise<T>): Promise<T>;
8
+ export declare function FirstRow<T, R>(measured: Measure<T[]>, read: (row: T) => R): Measure<R>;
9
+ export declare function Mapped<T, R>(measured: Measure<T>, read: (value: T) => R): Measure<R>;
10
+ export declare function ValueOf<T>(measured: Measure<T> | undefined): T | undefined;
11
+ export declare function Sequentially<T, R>(items: T[], work: (item: T) => Promise<R>): Promise<R[]>;
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SetMeasureTimeoutForTests = SetMeasureTimeoutForTests;
4
+ exports.WithMeasures = WithMeasures;
5
+ exports.FirstRow = FirstRow;
6
+ exports.Mapped = Mapped;
7
+ exports.ValueOf = ValueOf;
8
+ exports.Sequentially = Sequentially;
9
+ const connection_1 = require("../../connection");
10
+ const DEFAULT_STATEMENT_TIMEOUT_MS = 5000;
11
+ const LOCK_TIMEOUT_MS = 1000;
12
+ const SAVEPOINT = "measure";
13
+ const TIMEOUT_CODES = ["57014", "55P03"];
14
+ let statementTimeoutMs = DEFAULT_STATEMENT_TIMEOUT_MS;
15
+ function SetMeasureTimeoutForTests(ms) {
16
+ statementTimeoutMs = ms ?? DEFAULT_STATEMENT_TIMEOUT_MS;
17
+ }
18
+ function Failed(error) {
19
+ const code = error.code ?? "unknown";
20
+ return TIMEOUT_CODES.includes(code)
21
+ ? { status: "timeout" }
22
+ : { status: "error", code };
23
+ }
24
+ function SessionOver(client) {
25
+ return {
26
+ async measure(sql, params) {
27
+ await client.query(`SAVEPOINT ${SAVEPOINT}`);
28
+ try {
29
+ const result = await client.query(sql, params);
30
+ await client.query(`RELEASE SAVEPOINT ${SAVEPOINT}`);
31
+ return { status: "ok", value: result.rows };
32
+ }
33
+ catch (error) {
34
+ await client.query(`ROLLBACK TO SAVEPOINT ${SAVEPOINT}`);
35
+ return Failed(error);
36
+ }
37
+ },
38
+ };
39
+ }
40
+ let queue = Promise.resolve();
41
+ function Serialized(work) {
42
+ const run = queue.then(work, work);
43
+ queue = run.catch(() => undefined);
44
+ return run;
45
+ }
46
+ function WithMeasures(work) {
47
+ return Serialized(async () => {
48
+ const client = await (0, connection_1.AcquireClient)();
49
+ try {
50
+ await client.query("BEGIN READ ONLY");
51
+ await client.query(`SET LOCAL statement_timeout = ${statementTimeoutMs}`);
52
+ await client.query(`SET LOCAL lock_timeout = ${LOCK_TIMEOUT_MS}`);
53
+ return await work(SessionOver(client));
54
+ }
55
+ finally {
56
+ await client.query("ROLLBACK").catch(() => undefined);
57
+ client.release();
58
+ }
59
+ });
60
+ }
61
+ function FirstRow(measured, read) {
62
+ if (measured.status !== "ok") {
63
+ return measured;
64
+ }
65
+ return { status: "ok", value: read(measured.value[0]) };
66
+ }
67
+ function Mapped(measured, read) {
68
+ return measured.status === "ok"
69
+ ? { status: "ok", value: read(measured.value) }
70
+ : measured;
71
+ }
72
+ function ValueOf(measured) {
73
+ return measured?.status === "ok" ? measured.value : undefined;
74
+ }
75
+ async function Sequentially(items, work) {
76
+ const results = [];
77
+ for (const item of items) {
78
+ results.push(await work(item));
79
+ }
80
+ return results;
81
+ }
82
+ //# sourceMappingURL=external-measures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-measures.js","sourceRoot":"","sources":["../../../src/implementations/database/external-measures.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ProfileRequest, RelationProfile } from "@antelopejs/interface-database-catalog";
2
+ import { type RelationRow } from "./external-discovery";
3
+ export declare function NamedRow(relation: string): Promise<RelationRow>;
4
+ export declare function ProfileRelation(request: ProfileRequest): Promise<RelationProfile>;
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NamedRow = NamedRow;
4
+ exports.ProfileRelation = ProfileRelation;
5
+ const external_column_profile_1 = require("./external-column-profile");
6
+ const external_catalog_1 = require("./external-catalog");
7
+ const external_discovery_1 = require("./external-discovery");
8
+ const external_measures_1 = require("./external-measures");
9
+ const external_sample_1 = require("./external-sample");
10
+ const identifier_1 = require("./identifier");
11
+ const sql_1 = require("./sql");
12
+ async function CountRows(session, row, estimate) {
13
+ if (estimate !== null && estimate > external_sample_1.SAMPLE_THRESHOLD_ROWS) {
14
+ return { status: "ok", value: { rows: estimate, exact: false } };
15
+ }
16
+ const measured = await session.measure(`SELECT count(*)::float8 AS rows FROM ${(0, identifier_1.QualifiedName)(row.schema, row.name)}`);
17
+ return (0, external_measures_1.FirstRow)(measured, (counted) => ({ rows: counted.rows, exact: true }));
18
+ }
19
+ async function MeasuredRows(session, source, counted) {
20
+ if (!source.sample) {
21
+ return (0, external_measures_1.ValueOf)(counted)?.rows;
22
+ }
23
+ const measured = await session.measure(`SELECT count(*)::float8 AS rows FROM ${source.from}`);
24
+ const rows = (0, external_measures_1.ValueOf)(measured)?.[0]?.rows;
25
+ source.sample.rows = rows ?? 0;
26
+ return rows;
27
+ }
28
+ function ColumnTuple(alias, columns) {
29
+ return `(${columns.map((column) => `${alias}.${(0, sql_1.QuoteIdentifier)(column)}`).join(", ")})`;
30
+ }
31
+ function QualifiedOf(relation) {
32
+ const dot = relation.indexOf(".");
33
+ return (0, identifier_1.QualifiedName)(relation.slice(0, dot), relation.slice(dot + 1));
34
+ }
35
+ function FanOutSql(reference) {
36
+ const child = QualifiedOf(reference.from.relation);
37
+ const parent = QualifiedOf(reference.to.relation);
38
+ const childKey = ColumnTuple("c", reference.from.columns);
39
+ const parentKey = ColumnTuple("p", reference.to.columns);
40
+ const filled = reference.from.columns
41
+ .map((column) => `c.${(0, sql_1.QuoteIdentifier)(column)} IS NOT NULL`)
42
+ .join(" AND ");
43
+ return `SELECT
44
+ (SELECT avg(n) FROM (SELECT count(*) AS n FROM ${child} AS c WHERE ${filled} GROUP BY ${childKey}) g)::float8 AS average,
45
+ (SELECT max(n) FROM (SELECT count(*) AS n FROM ${child} AS c WHERE ${filled} GROUP BY ${childKey}) g)::float8 AS max,
46
+ (SELECT count(*) FROM ${parent} AS p WHERE NOT EXISTS (
47
+ SELECT 1 FROM ${child} AS c WHERE ${childKey} = ${parentKey}))::float8 AS "parentsWithoutChildren"`;
48
+ }
49
+ async function ProfileReference(session, reference) {
50
+ const measured = await session.measure(FanOutSql(reference));
51
+ const fanOut = (0, external_measures_1.FirstRow)(measured, (row) => ({
52
+ average: row.average ?? 0,
53
+ max: row.max ?? 0,
54
+ parentsWithoutChildren: row.parentsWithoutChildren,
55
+ }));
56
+ return { reference, fanOut };
57
+ }
58
+ async function Inbound(references) {
59
+ const rows = await (0, external_discovery_1.ReadNamedRelationRows)(references.map((reference) => reference.from.relation));
60
+ const byName = new Map(rows.map((row) => [(0, external_discovery_1.RelationName)(row), row]));
61
+ return Promise.all(references.map(async (reference) => {
62
+ const row = byName.get(reference.from.relation);
63
+ const estimate = row ? (await (0, external_discovery_1.EstimateOf)(row)).estimatedRows : null;
64
+ return { reference, estimatedRows: estimate };
65
+ }));
66
+ }
67
+ async function NamedRow(relation) {
68
+ const [row] = await (0, external_discovery_1.ReadNamedRelationRows)([relation]);
69
+ if (!row) {
70
+ throw new Error(`Relation '${relation}' does not exist, or the connected role cannot see it`);
71
+ }
72
+ if (!row.readable) {
73
+ throw new Error(`Relation '${relation}' cannot be read by the connected role`);
74
+ }
75
+ return row;
76
+ }
77
+ function Selected(columns, request) {
78
+ const unknown = (request.columns ?? []).filter((name) => !columns.some((column) => column.name === name));
79
+ if (unknown.length > 0) {
80
+ throw new Error(`Relation '${request.relation}' has no column ${unknown.join(", ")}`);
81
+ }
82
+ return columns
83
+ .filter((column) => !request.columns || request.columns.includes(column.name))
84
+ .map(external_column_profile_1.Profiled)
85
+ .filter((column) => column !== undefined);
86
+ }
87
+ async function PlanProfile(request) {
88
+ const row = await NamedRow(request.relation);
89
+ const relation = (0, external_discovery_1.RelationName)(row);
90
+ const [columns, indexes, referenceRows] = await Promise.all([
91
+ (0, external_catalog_1.ReadColumns)(row.oid),
92
+ (0, external_catalog_1.ReadIndexes)(row.oid),
93
+ (0, external_discovery_1.ReadReferences)(row.oid),
94
+ ]);
95
+ const references = referenceRows.map(external_discovery_1.ReferenceOf);
96
+ const outgoing = references.filter((reference) => reference.from.relation === relation);
97
+ const { estimatedRows } = await (0, external_discovery_1.EstimateOf)(row);
98
+ return {
99
+ relation,
100
+ row,
101
+ estimate: estimatedRows,
102
+ source: (0, external_sample_1.SourceFor)(row, estimatedRows),
103
+ columns: Selected(columns, request),
104
+ outgoing,
105
+ inbound: await Inbound(references.filter((reference) => reference.to.relation === relation)),
106
+ roles: {
107
+ keys: new Set((0, external_discovery_1.KeyFrom)(indexes, columns)?.columns ?? []),
108
+ references: new Set(outgoing.flatMap((reference) => reference.from.columns)),
109
+ },
110
+ };
111
+ }
112
+ async function ProfileRelation(request) {
113
+ const plan = await PlanProfile(request);
114
+ return (0, external_measures_1.WithMeasures)(async (session) => {
115
+ const rows = await CountRows(session, plan.row, plan.estimate);
116
+ const measured = await MeasuredRows(session, plan.source, rows);
117
+ const columns = await (0, external_measures_1.Sequentially)(plan.columns, (column) => (0, external_column_profile_1.ProfileColumn)(session, column, plan.source, measured, plan.roles));
118
+ const references = await (0, external_measures_1.Sequentially)(plan.outgoing, (reference) => ProfileReference(session, reference));
119
+ return {
120
+ relation: plan.relation,
121
+ rows,
122
+ sample: plan.source.sample,
123
+ columns,
124
+ references,
125
+ inbound: plan.inbound,
126
+ };
127
+ });
128
+ }
129
+ //# sourceMappingURL=external-profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-profile.js","sourceRoot":"","sources":["../../../src/implementations/database/external-profile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Measure, ReferenceCheck, ReferenceMatch } from "@antelopejs/interface-database-catalog";
2
+ export declare function CheckColumnReference(check: ReferenceCheck): Promise<Measure<ReferenceMatch>>;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CheckColumnReference = CheckColumnReference;
4
+ const external_catalog_1 = require("./external-catalog");
5
+ const external_discovery_1 = require("./external-discovery");
6
+ const external_measures_1 = require("./external-measures");
7
+ const external_sample_1 = require("./external-sample");
8
+ const identifier_1 = require("./identifier");
9
+ const sql_1 = require("./sql");
10
+ async function Resolve(reference) {
11
+ const [row] = await (0, external_discovery_1.ReadNamedRelationRows)([reference.relation]);
12
+ if (!row || !row.readable) {
13
+ throw new Error(`Relation '${reference.relation}' does not exist, or the connected role cannot read it`);
14
+ }
15
+ const columns = await (0, external_catalog_1.ReadColumns)(row.oid);
16
+ const column = columns.find((candidate) => candidate.name === reference.column);
17
+ if (!column) {
18
+ throw new Error(`Relation '${reference.relation}' has no column ${reference.column}`);
19
+ }
20
+ return { row, column, columns };
21
+ }
22
+ async function IsKey(side) {
23
+ const key = (0, external_discovery_1.KeyFrom)(await (0, external_catalog_1.ReadIndexes)(side.row.oid), side.columns);
24
+ return key?.columns.length === 1 && key.columns[0] === side.column.name;
25
+ }
26
+ function Equality(from, to) {
27
+ const left = `t.${(0, sql_1.QuoteIdentifier)(to.column.name)}`;
28
+ const right = `f.${(0, sql_1.QuoteIdentifier)(from.column.name)}`;
29
+ return from.column.castType === to.column.castType
30
+ ? `${left} = ${right}`
31
+ : `${left}::text = ${right}::text`;
32
+ }
33
+ async function CheckColumnReference(check) {
34
+ const from = await Resolve(check.from);
35
+ const to = await Resolve(check.to);
36
+ const source = (0, external_sample_1.SourceFor)(from.row, (await (0, external_discovery_1.EstimateOf)(from.row)).estimatedRows, "f");
37
+ const targetIsKey = await IsKey(to);
38
+ const target = (0, identifier_1.QualifiedName)(to.row.schema, to.row.name);
39
+ const sql = `SELECT count(*)::float8 AS checked,
40
+ (count(*) FILTER (WHERE EXISTS (SELECT 1 FROM ${target} AS t WHERE ${Equality(from, to)})))::float8 AS found
41
+ FROM ${source.from} WHERE f.${(0, sql_1.QuoteIdentifier)(from.column.name)} IS NOT NULL`;
42
+ return (0, external_measures_1.WithMeasures)(async (session) => (0, external_measures_1.FirstRow)(await session.measure(sql), (row) => ({
43
+ containment: row.checked > 0 ? row.found / row.checked : 0,
44
+ checkedRows: row.checked,
45
+ sampled: source.sample !== null,
46
+ targetIsKey,
47
+ })));
48
+ }
49
+ //# sourceMappingURL=external-reference.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-reference.js","sourceRoot":"","sources":["../../../src/implementations/database/external-reference.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { type RowSample, type SampleRequest } from "@antelopejs/interface-database-catalog";
2
+ export declare function SampleRelationRows(request: SampleRequest): Promise<RowSample>;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SampleRelationRows = SampleRelationRows;
4
+ const interface_database_catalog_1 = require("@antelopejs/interface-database-catalog");
5
+ const external_catalog_1 = require("./external-catalog");
6
+ const external_discovery_1 = require("./external-discovery");
7
+ const external_measures_1 = require("./external-measures");
8
+ const external_profile_1 = require("./external-profile");
9
+ const external_sample_1 = require("./external-sample");
10
+ const sql_1 = require("./sql");
11
+ const BINARY_TYPES = ["bytea"];
12
+ const COLUMN_ALIAS_PREFIX = "c";
13
+ function SampledColumnOf(column) {
14
+ return {
15
+ name: column.name,
16
+ binary: BINARY_TYPES.includes(column.typname),
17
+ };
18
+ }
19
+ function CheckedLimit(limit) {
20
+ if (!Number.isInteger(limit) || limit < 1 || limit > interface_database_catalog_1.SAMPLE_ROWS_LIMIT) {
21
+ throw new Error(`A sample answers from 1 to ${interface_database_catalog_1.SAMPLE_ROWS_LIMIT} rows, not ${limit}`);
22
+ }
23
+ return limit;
24
+ }
25
+ function Chosen(columns, request) {
26
+ const unknown = (request.columns ?? []).filter((name) => !columns.some((column) => column.name === name));
27
+ if (unknown.length > 0) {
28
+ throw new Error(`Relation '${request.relation}' has no column ${unknown.join(", ")}`);
29
+ }
30
+ return columns
31
+ .filter((column) => !request.columns || request.columns.includes(column.name))
32
+ .map(SampledColumnOf);
33
+ }
34
+ function Expression(column, index) {
35
+ const value = `${external_sample_1.SOURCE_ALIAS}.${(0, sql_1.QuoteIdentifier)(column.name)}`;
36
+ const read = column.binary
37
+ ? `octet_length(${value})`
38
+ : `left(${value}::text, ${interface_database_catalog_1.SAMPLE_TEXT_LENGTH + 1})`;
39
+ return `${read} AS ${COLUMN_ALIAS_PREFIX}${index}`;
40
+ }
41
+ function Value(column, read) {
42
+ if (read === null) {
43
+ return null;
44
+ }
45
+ if (column.binary) {
46
+ return { bytes: Number(read) };
47
+ }
48
+ const text = String(read);
49
+ return {
50
+ text: text.slice(0, interface_database_catalog_1.SAMPLE_TEXT_LENGTH),
51
+ truncated: text.length > interface_database_catalog_1.SAMPLE_TEXT_LENGTH,
52
+ };
53
+ }
54
+ function Row(columns, row) {
55
+ return columns.map((column, index) => Value(column, row[`${COLUMN_ALIAS_PREFIX}${index}`] ?? null));
56
+ }
57
+ function FailureOf(measured) {
58
+ return measured.status === "timeout" ? "timeout" : measured.code;
59
+ }
60
+ async function SampleRelationRows(request) {
61
+ const limit = CheckedLimit(request.limit);
62
+ const row = await (0, external_profile_1.NamedRow)(request.relation);
63
+ const columns = Chosen(await (0, external_catalog_1.ReadColumns)(row.oid), request);
64
+ const { estimatedRows } = await (0, external_discovery_1.EstimateOf)(row);
65
+ const source = (0, external_sample_1.SourceFor)(row, estimatedRows);
66
+ const select = columns.map(Expression).join(", ");
67
+ const measured = await (0, external_measures_1.WithMeasures)((session) => session.measure(`SELECT ${select} FROM ${source.from} LIMIT $1`, [limit]));
68
+ if (measured.status !== "ok") {
69
+ throw new Error(`The sample of '${request.relation}' did not finish: ${FailureOf(measured)}`);
70
+ }
71
+ return {
72
+ relation: (0, external_discovery_1.RelationName)(row),
73
+ columns: columns.map((column) => column.name),
74
+ rows: measured.value.map((sampled) => Row(columns, sampled)),
75
+ sample: source.sample && {
76
+ ...source.sample,
77
+ rows: measured.value.length,
78
+ },
79
+ };
80
+ }
81
+ //# sourceMappingURL=external-rows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-rows.js","sourceRoot":"","sources":["../../../src/implementations/database/external-rows.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { SampleInfo } from "@antelopejs/interface-database-catalog";
2
+ import type { RelationRow } from "./external-discovery";
3
+ export declare const SAMPLE_THRESHOLD_ROWS = 1000000;
4
+ export declare const SOURCE_ALIAS = "r";
5
+ export interface Source {
6
+ from: string;
7
+ sample: SampleInfo | null;
8
+ }
9
+ export declare function SourceFor(row: RelationRow, estimate: number | null, alias?: string): Source;