@malloydata/db-postgres 0.0.295 → 0.0.296
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/dist/postgres_connection.js +86 -17
- package/package.json +2 -2
|
@@ -69,7 +69,6 @@ const malloy_1 = require("@malloydata/malloy");
|
|
|
69
69
|
const connection_1 = require("@malloydata/malloy/connection");
|
|
70
70
|
const pg_1 = require("pg");
|
|
71
71
|
const pg_query_stream_1 = __importDefault(require("pg-query-stream"));
|
|
72
|
-
const crypto_1 = require("crypto");
|
|
73
72
|
const DEFAULT_PAGE_SIZE = 1000;
|
|
74
73
|
const SCHEMA_PAGE_SIZE = 1000;
|
|
75
74
|
class PostgresConnection extends connection_1.BaseConnection {
|
|
@@ -162,24 +161,94 @@ class PostgresConnection extends connection_1.BaseConnection {
|
|
|
162
161
|
fields: [],
|
|
163
162
|
name: (0, malloy_1.sqlKey)(sqlRef.connection, sqlRef.selectStr),
|
|
164
163
|
};
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
164
|
+
const client = await this.getClient();
|
|
165
|
+
await client.connect();
|
|
166
|
+
await this.connectionSetup(client);
|
|
167
|
+
// 1) Get row-descriptor without fetching data
|
|
168
|
+
const res = await client.query({
|
|
169
|
+
text: `SELECT * FROM (${sqlRef.selectStr}) _t LIMIT 0`,
|
|
170
|
+
});
|
|
171
|
+
// 2) Resolve every OID we might touch (field, array element, domain base)
|
|
172
|
+
const neededOids = new Set();
|
|
173
|
+
res.fields.forEach(f => neededOids.add(f.dataTypeID));
|
|
174
|
+
// we'll add more OIDs later (typelem / typebasetype) lazily
|
|
175
|
+
// helper to fetch pg_type rows on demand, with cache
|
|
176
|
+
const pgTypeCache = new Map();
|
|
177
|
+
const loadTypes = async (oids) => {
|
|
178
|
+
if (oids.length === 0)
|
|
179
|
+
return;
|
|
180
|
+
const params = oids.map((_, i) => `$${i + 1}`).join(',');
|
|
181
|
+
const { rows } = await client.query(`
|
|
182
|
+
SELECT
|
|
183
|
+
oid,
|
|
184
|
+
typname,
|
|
185
|
+
typtype,
|
|
186
|
+
typcategory,
|
|
187
|
+
typelem,
|
|
188
|
+
typbasetype,
|
|
189
|
+
format_type(oid, NULL) AS formatted
|
|
190
|
+
FROM pg_type
|
|
191
|
+
WHERE oid IN (${params})
|
|
192
|
+
`, oids);
|
|
193
|
+
rows.forEach(r => pgTypeCache.set(r.oid, r));
|
|
194
|
+
};
|
|
195
|
+
// Prime the cache
|
|
196
|
+
await loadTypes([...neededOids]);
|
|
197
|
+
// 3) recursive mapper → info-schema compliant strings
|
|
198
|
+
const mapDataType = async (oid) => {
|
|
199
|
+
let t = pgTypeCache.get(oid);
|
|
200
|
+
if (!t) {
|
|
201
|
+
await loadTypes([oid]);
|
|
202
|
+
t = pgTypeCache.get(oid);
|
|
203
|
+
}
|
|
204
|
+
// ARRAY?
|
|
205
|
+
if (t.typcategory === 'A')
|
|
206
|
+
return 'ARRAY';
|
|
207
|
+
// DOMAIN? recurse to its base type
|
|
208
|
+
if (t.typtype === 'd')
|
|
209
|
+
return mapDataType(t.typbasetype);
|
|
210
|
+
// ENUM, COMPOSITE, RANGE, MULTIRANGE, PSEUDO → USER-DEFINED
|
|
211
|
+
if (['e', 'c', 'r', 'm', 'p'].includes(t.typtype))
|
|
212
|
+
return 'USER-DEFINED';
|
|
213
|
+
// built-in scalar or base type of domain
|
|
214
|
+
return t.formatted;
|
|
215
|
+
};
|
|
216
|
+
// helper to resolve element_type (NULL for scalars)
|
|
217
|
+
const mapElementType = async (oid) => {
|
|
218
|
+
let t = pgTypeCache.get(oid);
|
|
219
|
+
if (!t) {
|
|
220
|
+
await loadTypes([oid]);
|
|
221
|
+
t = pgTypeCache.get(oid);
|
|
222
|
+
}
|
|
223
|
+
if (t.typcategory !== 'A')
|
|
224
|
+
return null; // not an array
|
|
225
|
+
// Ensure element row cached
|
|
226
|
+
if (!pgTypeCache.has(t.typelem))
|
|
227
|
+
await loadTypes([t.typelem]);
|
|
228
|
+
return mapDataType(t.typelem);
|
|
229
|
+
};
|
|
230
|
+
// 4) Build final array in original column order
|
|
231
|
+
const result = [];
|
|
232
|
+
for (const field of res.fields) {
|
|
233
|
+
result.push({
|
|
234
|
+
columnName: field.name,
|
|
235
|
+
dataType: await mapDataType(field.dataTypeID),
|
|
236
|
+
elementType: await mapElementType(field.dataTypeID),
|
|
237
|
+
});
|
|
179
238
|
}
|
|
180
|
-
|
|
181
|
-
|
|
239
|
+
for (const row of result) {
|
|
240
|
+
const postgresDataType = row.dataType;
|
|
241
|
+
const name = row.columnName;
|
|
242
|
+
if (postgresDataType === 'ARRAY') {
|
|
243
|
+
const elementType = this.dialect.sqlTypeToMalloyType(row.elementType);
|
|
244
|
+
structDef.fields.push((0, malloy_1.mkArrayDef)(elementType, name));
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
const malloyType = this.dialect.sqlTypeToMalloyType(postgresDataType);
|
|
248
|
+
structDef.fields.push({ ...malloyType, name });
|
|
249
|
+
}
|
|
182
250
|
}
|
|
251
|
+
await client.end();
|
|
183
252
|
return structDef;
|
|
184
253
|
}
|
|
185
254
|
async schemaFromQuery(infoQuery, structDef) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@malloydata/db-postgres",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.296",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"prepublishOnly": "npm run build"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@malloydata/malloy": "0.0.
|
|
25
|
+
"@malloydata/malloy": "0.0.296",
|
|
26
26
|
"@types/pg": "^8.6.1",
|
|
27
27
|
"pg": "^8.7.1",
|
|
28
28
|
"pg-query-stream": "4.2.3"
|