@malloydata/db-trino 0.0.195-dev241003204819 → 0.0.195-dev241007154000
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/trino_connection.d.ts +7 -24
- package/dist/trino_connection.js +64 -226
- package/dist/trino_connection.spec.js +30 -86
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Connection, ConnectionConfig,
|
|
1
|
+
import { Connection, ConnectionConfig, MalloyQueryData, PersistSQLResults, QueryData, QueryOptionsReader, QueryRunStats, RunSQLOptions, StructDef, TableSourceDef, SQLSourceDef, AtomicTypeDef } from '@malloydata/malloy';
|
|
2
2
|
import { BaseConnection } from '@malloydata/malloy/connection';
|
|
3
3
|
export interface TrinoManagerOptions {
|
|
4
4
|
credentials?: {
|
|
@@ -30,15 +30,9 @@ export interface BaseRunner {
|
|
|
30
30
|
}>;
|
|
31
31
|
}
|
|
32
32
|
export declare abstract class TrinoPrestoConnection extends BaseConnection implements Connection, PersistSQLResults {
|
|
33
|
-
trinoToMalloyTypes: {
|
|
34
|
-
[key: string]: FieldAtomicTypeDef;
|
|
35
|
-
};
|
|
36
|
-
private sqlToMalloyType;
|
|
37
33
|
name: string;
|
|
38
34
|
private readonly dialect;
|
|
39
35
|
static DEFAULT_QUERY_OPTIONS: RunSQLOptions;
|
|
40
|
-
private schemaCache;
|
|
41
|
-
private sqlSchemaCache;
|
|
42
36
|
private queryOptions?;
|
|
43
37
|
private client;
|
|
44
38
|
constructor(name: string, queryOptions?: QueryOptionsReader, pConfig?: TrinoConnectionConfiguration);
|
|
@@ -48,30 +42,19 @@ export declare abstract class TrinoPrestoConnection extends BaseConnection imple
|
|
|
48
42
|
get supportsNesting(): boolean;
|
|
49
43
|
manifestTemporaryTable(_sqlCommand: string): Promise<string>;
|
|
50
44
|
unpackArray(data: unknown): unknown[];
|
|
51
|
-
convertRow(structDef: StructDef,
|
|
52
|
-
convertNest(structDef: StructDef, _data: unknown):
|
|
45
|
+
convertRow(structDef: StructDef, rawRow: unknown): {};
|
|
46
|
+
convertNest(structDef: StructDef, _data: unknown): unknown[];
|
|
53
47
|
runSQL(sqlCommand: string, options?: RunSQLOptions, _rowIndex?: number): Promise<MalloyQueryData>;
|
|
54
|
-
runSQLBlockAndFetchResultSchema(_sqlBlock:
|
|
48
|
+
runSQLBlockAndFetchResultSchema(_sqlBlock: SQLSourceDef, _options?: RunSQLOptions): Promise<{
|
|
55
49
|
data: MalloyQueryData;
|
|
56
50
|
schema: StructDef;
|
|
57
51
|
}>;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
errors: Record<string, string>;
|
|
61
|
-
}>;
|
|
62
|
-
private structDefFromTableSchema;
|
|
63
|
-
fetchSchemaForSQLBlock(sqlRef: SQLBlock, { refreshTimestamp }: FetchSchemaOptions): Promise<{
|
|
64
|
-
structDef: StructDef;
|
|
65
|
-
error?: undefined;
|
|
66
|
-
} | {
|
|
67
|
-
error: string;
|
|
68
|
-
structDef?: undefined;
|
|
69
|
-
}>;
|
|
70
|
-
private structDefFromSqlBlock;
|
|
52
|
+
fetchTableSchema(tableKey: string, tablePath: string): Promise<TableSourceDef>;
|
|
53
|
+
fetchSelectSchema(sqlRef: SQLSourceDef): Promise<SQLSourceDef>;
|
|
71
54
|
protected abstract fillStructDefForSqlBlockSchema(sql: string, structDef: StructDef): Promise<void>;
|
|
72
55
|
protected executeAndWait(sqlBlock: string): Promise<void>;
|
|
73
56
|
splitColumns(s: string): string[];
|
|
74
|
-
malloyTypeFromTrinoType(name: string, trinoType: string):
|
|
57
|
+
malloyTypeFromTrinoType(name: string, trinoType: string): AtomicTypeDef;
|
|
75
58
|
structDefFromSchema(rows: string[][], structDef: StructDef): void;
|
|
76
59
|
protected loadSchemaForSqlBlock(sqlBlock: string, structDef: StructDef, element: string): Promise<StructDef>;
|
|
77
60
|
estimateQueryCost(_sqlCommand: string): Promise<QueryRunStats>;
|
package/dist/trino_connection.js
CHANGED
|
@@ -102,49 +102,10 @@ class TrinoRunner {
|
|
|
102
102
|
return { rows: outputRows, columns };
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
|
-
// manage access to BQ, control costs, enforce global data/API limits
|
|
106
105
|
class TrinoPrestoConnection extends connection_1.BaseConnection {
|
|
107
|
-
sqlToMalloyType(sqlType) {
|
|
108
|
-
var _a, _b;
|
|
109
|
-
const baseSqlType = (_b = (_a = sqlType.match(/^(\w+)/)) === null || _a === void 0 ? void 0 : _a.at(0)) !== null && _b !== void 0 ? _b : sqlType;
|
|
110
|
-
if (this.trinoToMalloyTypes[baseSqlType]) {
|
|
111
|
-
return this.trinoToMalloyTypes[baseSqlType];
|
|
112
|
-
}
|
|
113
|
-
return undefined;
|
|
114
|
-
}
|
|
115
106
|
constructor(name, queryOptions, pConfig) {
|
|
116
107
|
super();
|
|
117
|
-
this.
|
|
118
|
-
'varchar': { type: 'string' },
|
|
119
|
-
'integer': { type: 'number', numberType: 'integer' },
|
|
120
|
-
'bigint': { type: 'number', numberType: 'integer' },
|
|
121
|
-
'smallint': { type: 'number', numberType: 'integer' },
|
|
122
|
-
'tinyint': { type: 'number', numberType: 'integer' },
|
|
123
|
-
'double': { type: 'number', numberType: 'float' },
|
|
124
|
-
'decimal': { type: 'number', numberType: 'float' },
|
|
125
|
-
'string': { type: 'string' },
|
|
126
|
-
'date': { type: 'date' },
|
|
127
|
-
'timestamp': { type: 'timestamp' },
|
|
128
|
-
'boolean': { type: 'boolean' },
|
|
129
|
-
// TODO(figutierrez0): cleanup.
|
|
130
|
-
/* 'INT64': {type: 'number', numberType: 'integer'},
|
|
131
|
-
'FLOAT': {type: 'number', numberType: 'float'},
|
|
132
|
-
'FLOAT64': {type: 'number', numberType: 'float'},
|
|
133
|
-
'NUMERIC': {type: 'number', numberType: 'float'},
|
|
134
|
-
'BIGNUMERIC': {type: 'number', numberType: 'float'},
|
|
135
|
-
'TIMESTAMP': {type: 'timestamp'},
|
|
136
|
-
'BOOLEAN': {type: 'boolean'},
|
|
137
|
-
'BOOL': {type: 'boolean'},
|
|
138
|
-
'JSON': {type: 'json'},*/
|
|
139
|
-
// TODO (https://cloud.google.com/bigquery/docs/reference/rest/v2/tables#tablefieldschema):
|
|
140
|
-
// BYTES
|
|
141
|
-
// DATETIME
|
|
142
|
-
// TIME
|
|
143
|
-
// GEOGRAPHY
|
|
144
|
-
};
|
|
145
|
-
this.dialect = new malloy_1.StandardSQLDialect();
|
|
146
|
-
this.schemaCache = new Map();
|
|
147
|
-
this.sqlSchemaCache = new Map();
|
|
108
|
+
this.dialect = new malloy_1.TrinoDialect();
|
|
148
109
|
const config = pConfig || {};
|
|
149
110
|
this.name = name;
|
|
150
111
|
if (name === 'trino') {
|
|
@@ -185,22 +146,29 @@ class TrinoPrestoConnection extends connection_1.BaseConnection {
|
|
|
185
146
|
unpackArray(data) {
|
|
186
147
|
return data;
|
|
187
148
|
}
|
|
188
|
-
convertRow(structDef,
|
|
149
|
+
convertRow(structDef, rawRow) {
|
|
150
|
+
var _a;
|
|
189
151
|
const retRow = {};
|
|
190
|
-
const row = this.unpackArray(
|
|
152
|
+
const row = this.unpackArray(rawRow);
|
|
191
153
|
for (let i = 0; i < structDef.fields.length; i++) {
|
|
192
154
|
const field = structDef.fields[i];
|
|
193
|
-
if (field.type === '
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
155
|
+
if (field.type === 'record') {
|
|
156
|
+
retRow[field.name] = this.convertRow(field, row[i]);
|
|
157
|
+
}
|
|
158
|
+
else if ((0, malloy_1.isRepeatedRecord)(field)) {
|
|
159
|
+
retRow[field.name] = this.convertNest(field, row[i]);
|
|
160
|
+
}
|
|
161
|
+
else if (field.type === 'array') {
|
|
162
|
+
const newArray = {
|
|
163
|
+
fields: [],
|
|
164
|
+
dialect: '',
|
|
165
|
+
...field,
|
|
166
|
+
join: 'many',
|
|
167
|
+
};
|
|
168
|
+
retRow[field.name] = this.convertNest(newArray, row[i]);
|
|
201
169
|
}
|
|
202
170
|
else {
|
|
203
|
-
retRow[field.name] = row[i]
|
|
171
|
+
retRow[field.name] = (_a = row[i]) !== null && _a !== void 0 ? _a : null;
|
|
204
172
|
}
|
|
205
173
|
}
|
|
206
174
|
//console.log(retRow);
|
|
@@ -209,12 +177,6 @@ class TrinoPrestoConnection extends connection_1.BaseConnection {
|
|
|
209
177
|
convertNest(structDef, _data) {
|
|
210
178
|
const data = this.unpackArray(_data);
|
|
211
179
|
const ret = [];
|
|
212
|
-
//console.log(
|
|
213
|
-
// `${JSON.stringify(structDef, null, 2)} ${JSON.stringify(data, null, 2)} `
|
|
214
|
-
// );
|
|
215
|
-
if (structDef.structSource.type === 'inline') {
|
|
216
|
-
return this.convertRow(structDef, data);
|
|
217
|
-
}
|
|
218
180
|
const rows = (data === null || data === undefined ? [] : data);
|
|
219
181
|
for (const row of rows) {
|
|
220
182
|
ret.push(this.convertRow(structDef, row));
|
|
@@ -224,17 +186,6 @@ class TrinoPrestoConnection extends connection_1.BaseConnection {
|
|
|
224
186
|
async runSQL(sqlCommand, options = {},
|
|
225
187
|
// TODO(figutierrez): Use.
|
|
226
188
|
_rowIndex = 0) {
|
|
227
|
-
// const result = await this.trino.query(sqlCommand);
|
|
228
|
-
// let queryResult = await result.next();
|
|
229
|
-
// if (queryResult.value.error) {
|
|
230
|
-
// // TODO: handle.
|
|
231
|
-
// const {failureInfo: _, ...error} = queryResult.value.error;
|
|
232
|
-
// throw new Error(
|
|
233
|
-
// `Failed to execute sql: ${sqlCommand}. \n Error: ${JSON.stringify(
|
|
234
|
-
// error
|
|
235
|
-
// )}`
|
|
236
|
-
// );
|
|
237
|
-
// }
|
|
238
189
|
const r = await this.client.runSQL(sqlCommand, options.rowLimit);
|
|
239
190
|
if (r.error) {
|
|
240
191
|
throw new Error(r.error);
|
|
@@ -242,37 +193,32 @@ class TrinoPrestoConnection extends connection_1.BaseConnection {
|
|
|
242
193
|
const inputRows = r.rows;
|
|
243
194
|
const columns = r.columns;
|
|
244
195
|
const malloyColumns = columns.map(c => this.malloyTypeFromTrinoType(c.name, c.type));
|
|
245
|
-
// Debugging types
|
|
246
|
-
// const _x = queryResult.value.columns.map(c => console.log(c.type));
|
|
247
|
-
// console.log(JSON.stringify(malloyColumns, null, 2));
|
|
248
|
-
// console.log(JSON.stringify(queryResult.value.data, null, 2));
|
|
249
196
|
const malloyRows = [];
|
|
250
197
|
const rows = inputRows !== null && inputRows !== void 0 ? inputRows : [];
|
|
251
198
|
for (const row of rows) {
|
|
252
199
|
const malloyRow = {};
|
|
253
200
|
for (let i = 0; i < columns.length; i++) {
|
|
254
201
|
const column = columns[i];
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
// );
|
|
202
|
+
const schemaColumn = malloyColumns[i];
|
|
203
|
+
if (schemaColumn.type === 'record') {
|
|
204
|
+
malloyRow[column.name] = this.convertRow(schemaColumn, row[i]);
|
|
205
|
+
}
|
|
206
|
+
else if (schemaColumn.type === 'array') {
|
|
207
|
+
const newArray = {
|
|
208
|
+
name: '',
|
|
209
|
+
fields: [],
|
|
210
|
+
dialect: '',
|
|
211
|
+
...schemaColumn,
|
|
212
|
+
join: 'many',
|
|
213
|
+
};
|
|
214
|
+
malloyRow[column.name] = this.convertNest(newArray, row[i]);
|
|
269
215
|
}
|
|
270
|
-
else if (
|
|
216
|
+
else if (schemaColumn.type === 'number' &&
|
|
271
217
|
typeof row[i] === 'string') {
|
|
272
218
|
// decimal numbers come back as strings
|
|
273
219
|
malloyRow[column.name] = Number(row[i]);
|
|
274
220
|
}
|
|
275
|
-
else if (
|
|
221
|
+
else if (schemaColumn.type === 'timestamp' &&
|
|
276
222
|
typeof row[i] === 'string') {
|
|
277
223
|
// timestamps come back as strings
|
|
278
224
|
malloyRow[column.name] = new Date(row[i]);
|
|
@@ -283,113 +229,26 @@ class TrinoPrestoConnection extends connection_1.BaseConnection {
|
|
|
283
229
|
}
|
|
284
230
|
malloyRows.push(malloyRow);
|
|
285
231
|
}
|
|
286
|
-
// TODO(figutierrez): Remove.
|
|
287
|
-
// eslint-disable-next-line no-console
|
|
288
|
-
// console.log(`ROWS: ${JSON.stringify(malloyRows)} ${malloyRows.length}`);
|
|
289
|
-
// TODO: handle totalrows.
|
|
290
232
|
return { rows: malloyRows, totalRows: malloyRows.length };
|
|
291
233
|
}
|
|
292
234
|
async runSQLBlockAndFetchResultSchema(_sqlBlock, _options) {
|
|
293
|
-
/*const {data, schema: schemaRaw} = await this._runSQL(
|
|
294
|
-
sqlBlock.selectStr,
|
|
295
|
-
options
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
// TODO need to probably surface the cause of the schema not present error
|
|
299
|
-
if (schemaRaw === undefined) {
|
|
300
|
-
throw new Error('Schema not present');
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
const schema = this.structDefFromSQLSchema(sqlBlock, schemaRaw);
|
|
304
|
-
return {data, schema};*/
|
|
305
235
|
throw new Error('Not implemented 3');
|
|
306
236
|
}
|
|
307
|
-
async
|
|
308
|
-
const schemas = {};
|
|
309
|
-
const errors = {};
|
|
310
|
-
for (const tableKey in missing) {
|
|
311
|
-
let inCache = this.schemaCache.get(tableKey);
|
|
312
|
-
const tablePath = missing[tableKey];
|
|
313
|
-
if (!inCache ||
|
|
314
|
-
(refreshTimestamp && refreshTimestamp > inCache.timestamp)) {
|
|
315
|
-
const timestamp = refreshTimestamp !== null && refreshTimestamp !== void 0 ? refreshTimestamp : Date.now();
|
|
316
|
-
try {
|
|
317
|
-
const schema = await this.structDefFromTableSchema(tableKey,
|
|
318
|
-
// TODO: remove.
|
|
319
|
-
tablePath);
|
|
320
|
-
inCache = {
|
|
321
|
-
schema,
|
|
322
|
-
timestamp,
|
|
323
|
-
};
|
|
324
|
-
this.schemaCache.set(tableKey, inCache);
|
|
325
|
-
}
|
|
326
|
-
catch (error) {
|
|
327
|
-
inCache = { error: error.message, timestamp };
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
if (inCache.schema !== undefined) {
|
|
331
|
-
schemas[tableKey] = inCache.schema;
|
|
332
|
-
}
|
|
333
|
-
else {
|
|
334
|
-
errors[tableKey] = inCache.error || 'Unknown schema fetch error';
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
return { schemas: schemas, errors: errors };
|
|
338
|
-
}
|
|
339
|
-
async structDefFromTableSchema(tableKey, tablePath) {
|
|
237
|
+
async fetchTableSchema(tableKey, tablePath) {
|
|
340
238
|
const structDef = {
|
|
341
|
-
type: '
|
|
239
|
+
type: 'table',
|
|
342
240
|
name: tableKey,
|
|
343
241
|
dialect: this.dialectName,
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
tablePath,
|
|
347
|
-
},
|
|
348
|
-
structRelationship: {
|
|
349
|
-
type: 'basetable',
|
|
350
|
-
connectionName: this.name,
|
|
351
|
-
},
|
|
242
|
+
tablePath,
|
|
243
|
+
connection: this.name,
|
|
352
244
|
fields: [],
|
|
353
245
|
};
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
358
|
-
{ refreshTimestamp }) {
|
|
359
|
-
const key = sqlRef.name;
|
|
360
|
-
let inCache = this.sqlSchemaCache.get(key);
|
|
361
|
-
if (!inCache ||
|
|
362
|
-
(refreshTimestamp && refreshTimestamp > inCache.timestamp)) {
|
|
363
|
-
const timestamp = refreshTimestamp !== null && refreshTimestamp !== void 0 ? refreshTimestamp : Date.now();
|
|
364
|
-
try {
|
|
365
|
-
inCache = {
|
|
366
|
-
structDef: await this.structDefFromSqlBlock(sqlRef),
|
|
367
|
-
timestamp,
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
catch (error) {
|
|
371
|
-
inCache = { error: error.message, timestamp };
|
|
372
|
-
}
|
|
373
|
-
this.sqlSchemaCache.set(key, inCache);
|
|
374
|
-
}
|
|
375
|
-
return inCache;
|
|
246
|
+
const schemaDesc = await this.loadSchemaForSqlBlock(`DESCRIBE ${tablePath}`, structDef, `table ${tablePath}`);
|
|
247
|
+
structDef.fields = schemaDesc.fields;
|
|
248
|
+
return structDef;
|
|
376
249
|
}
|
|
377
|
-
async
|
|
378
|
-
const structDef = {
|
|
379
|
-
type: 'struct',
|
|
380
|
-
name: sqlRef.name,
|
|
381
|
-
dialect: this.dialectName,
|
|
382
|
-
structSource: {
|
|
383
|
-
type: 'sql',
|
|
384
|
-
method: 'subquery',
|
|
385
|
-
sqlBlock: sqlRef,
|
|
386
|
-
},
|
|
387
|
-
structRelationship: {
|
|
388
|
-
type: 'basetable',
|
|
389
|
-
connectionName: this.name,
|
|
390
|
-
},
|
|
391
|
-
fields: [],
|
|
392
|
-
};
|
|
250
|
+
async fetchSelectSchema(sqlRef) {
|
|
251
|
+
const structDef = { ...sqlRef, fields: [] };
|
|
393
252
|
await this.fillStructDefForSqlBlockSchema(sqlRef.selectStr, structDef);
|
|
394
253
|
return structDef;
|
|
395
254
|
}
|
|
@@ -430,38 +289,34 @@ class TrinoPrestoConnection extends connection_1.BaseConnection {
|
|
|
430
289
|
return columns;
|
|
431
290
|
}
|
|
432
291
|
malloyTypeFromTrinoType(name, trinoType) {
|
|
433
|
-
var _a;
|
|
434
|
-
let malloyType;
|
|
435
292
|
// Arrays look like `array(type)`
|
|
436
293
|
const arrayMatch = trinoType.match(/^(([^,])+\s)?array\((.*)\)$/);
|
|
437
|
-
// console.log(`${trinoType} arrayMatch: ${arrayMatch}`);
|
|
438
294
|
// Structs look like `row(name type, name type)`
|
|
439
295
|
const structMatch = trinoType.match(/^(([^,])+\s)?row\((.*)\)$/);
|
|
440
|
-
// console.log(`${trinoType} structMatch: ${structMatch}`);
|
|
441
296
|
if (arrayMatch) {
|
|
442
297
|
const arrayType = arrayMatch[3];
|
|
443
298
|
const innerType = this.malloyTypeFromTrinoType(name, arrayType);
|
|
444
|
-
if (innerType.type === '
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
299
|
+
if (innerType.type === 'record') {
|
|
300
|
+
const complexStruct = {
|
|
301
|
+
type: 'array',
|
|
302
|
+
name,
|
|
303
|
+
elementTypeDef: { type: 'record_element' },
|
|
304
|
+
dialect: this.dialectName,
|
|
305
|
+
join: 'many',
|
|
306
|
+
fields: innerType.fields,
|
|
450
307
|
};
|
|
308
|
+
return complexStruct;
|
|
451
309
|
}
|
|
452
310
|
else {
|
|
453
|
-
|
|
454
|
-
type: '
|
|
311
|
+
const arrayStruct = {
|
|
312
|
+
type: 'array',
|
|
455
313
|
name,
|
|
314
|
+
elementTypeDef: innerType,
|
|
456
315
|
dialect: this.dialectName,
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
type: 'nested',
|
|
460
|
-
fieldName: name,
|
|
461
|
-
isArray: true,
|
|
462
|
-
},
|
|
463
|
-
fields: [{ ...innerType, name: 'value' }],
|
|
316
|
+
join: 'many',
|
|
317
|
+
fields: (0, malloy_1.arrayEachFields)(innerType),
|
|
464
318
|
};
|
|
319
|
+
return arrayStruct;
|
|
465
320
|
}
|
|
466
321
|
}
|
|
467
322
|
else if (structMatch) {
|
|
@@ -469,15 +324,11 @@ class TrinoPrestoConnection extends connection_1.BaseConnection {
|
|
|
469
324
|
// so some magic is going to need to be applied before we get here
|
|
470
325
|
// to avoid confusion if a field name contains a comma
|
|
471
326
|
const innerTypes = this.splitColumns(structMatch[3]);
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
type: 'struct',
|
|
327
|
+
const recordType = {
|
|
328
|
+
type: 'record',
|
|
475
329
|
name,
|
|
476
330
|
dialect: this.dialectName,
|
|
477
|
-
|
|
478
|
-
structRelationship: {
|
|
479
|
-
type: 'inline',
|
|
480
|
-
},
|
|
331
|
+
join: 'one',
|
|
481
332
|
fields: [],
|
|
482
333
|
};
|
|
483
334
|
for (let innerType of innerTypes) {
|
|
@@ -493,25 +344,12 @@ class TrinoPrestoConnection extends connection_1.BaseConnection {
|
|
|
493
344
|
const innerName = parts[1].replace(/^"(.+(?="$))"$/, '$1');
|
|
494
345
|
const innerTrinoType = parts[2];
|
|
495
346
|
const innerMalloyType = this.malloyTypeFromTrinoType(innerName, innerTrinoType);
|
|
496
|
-
|
|
497
|
-
}
|
|
498
|
-
else {
|
|
499
|
-
malloyType.fields.push({
|
|
500
|
-
name: 'unknown',
|
|
501
|
-
type: 'sql native',
|
|
502
|
-
rawType: innerType.toLowerCase(),
|
|
503
|
-
});
|
|
347
|
+
recordType.fields.push({ ...innerMalloyType, name: innerName });
|
|
504
348
|
}
|
|
505
349
|
}
|
|
350
|
+
return recordType;
|
|
506
351
|
}
|
|
507
|
-
|
|
508
|
-
malloyType = (_a = this.sqlToMalloyType(trinoType)) !== null && _a !== void 0 ? _a : {
|
|
509
|
-
type: 'sql native',
|
|
510
|
-
rawType: trinoType.toLowerCase(),
|
|
511
|
-
};
|
|
512
|
-
}
|
|
513
|
-
// console.log('>', trinoType, '\n<', malloyType);
|
|
514
|
-
return malloyType;
|
|
352
|
+
return this.dialect.sqlTypeToMalloyType(trinoType);
|
|
515
353
|
}
|
|
516
354
|
structDefFromSchema(rows, structDef) {
|
|
517
355
|
for (const row of rows) {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
const malloy_1 = require("@malloydata/malloy");
|
|
25
26
|
const _1 = require(".");
|
|
26
27
|
// array(varchar) is array
|
|
27
28
|
const ARRAY_SCHEMA = 'array(integer)';
|
|
@@ -31,6 +32,14 @@ const INLINE_SCHEMA = 'row(a double, b integer, c varchar(60))';
|
|
|
31
32
|
const NESTED_SCHEMA = 'array(row(a double, b integer, c varchar(60)))';
|
|
32
33
|
// array(row(..., array(row(....)))) is deeply nested
|
|
33
34
|
const DEEP_SCHEMA = 'array(row(a double, b array(row(c integer, d varchar(60)))))';
|
|
35
|
+
const intType = { type: 'number', numberType: 'integer' };
|
|
36
|
+
const doubleType = { type: 'number', numberType: 'float' };
|
|
37
|
+
const stringType = { type: 'string' };
|
|
38
|
+
const recordSchema = [
|
|
39
|
+
{ name: 'a', ...doubleType },
|
|
40
|
+
{ name: 'b', ...intType },
|
|
41
|
+
{ name: 'c', ...stringType },
|
|
42
|
+
];
|
|
34
43
|
describe('Trino connection', () => {
|
|
35
44
|
let connection;
|
|
36
45
|
beforeAll(() => {
|
|
@@ -43,118 +52,53 @@ describe('Trino connection', () => {
|
|
|
43
52
|
it('parses arrays', () => {
|
|
44
53
|
expect(connection.malloyTypeFromTrinoType('test', ARRAY_SCHEMA)).toEqual({
|
|
45
54
|
'name': 'test',
|
|
46
|
-
'type': '
|
|
55
|
+
'type': 'array',
|
|
47
56
|
'dialect': 'trino',
|
|
48
|
-
'
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
'type': 'nested',
|
|
52
|
-
},
|
|
53
|
-
'structSource': {
|
|
54
|
-
'type': 'nested',
|
|
55
|
-
},
|
|
56
|
-
'fields': [
|
|
57
|
-
{
|
|
58
|
-
'name': 'value',
|
|
59
|
-
'type': 'number',
|
|
60
|
-
'numberType': 'integer',
|
|
61
|
-
},
|
|
62
|
-
],
|
|
57
|
+
'elementTypeDef': intType,
|
|
58
|
+
'join': 'many',
|
|
59
|
+
'fields': (0, malloy_1.arrayEachFields)(intType),
|
|
63
60
|
});
|
|
64
61
|
});
|
|
65
62
|
it('parses inline', () => {
|
|
66
63
|
expect(connection.malloyTypeFromTrinoType('test', INLINE_SCHEMA)).toEqual({
|
|
67
64
|
'name': 'test',
|
|
68
|
-
'type': '
|
|
65
|
+
'type': 'record',
|
|
69
66
|
'dialect': 'trino',
|
|
70
|
-
'
|
|
71
|
-
|
|
72
|
-
},
|
|
73
|
-
'structSource': {
|
|
74
|
-
'type': 'inline',
|
|
75
|
-
},
|
|
76
|
-
'fields': [
|
|
77
|
-
{
|
|
78
|
-
'name': 'a',
|
|
79
|
-
'type': 'number',
|
|
80
|
-
'numberType': 'float',
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
'name': 'b',
|
|
84
|
-
'type': 'number',
|
|
85
|
-
'numberType': 'integer',
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
'name': 'c',
|
|
89
|
-
'type': 'string',
|
|
90
|
-
},
|
|
91
|
-
],
|
|
67
|
+
'join': 'one',
|
|
68
|
+
'fields': recordSchema,
|
|
92
69
|
});
|
|
93
70
|
});
|
|
94
71
|
it('parses nested', () => {
|
|
95
72
|
expect(connection.malloyTypeFromTrinoType('test', NESTED_SCHEMA)).toEqual({
|
|
96
73
|
'name': 'test',
|
|
97
|
-
'type': '
|
|
74
|
+
'type': 'array',
|
|
75
|
+
'elementTypeDef': { type: 'record_element' },
|
|
98
76
|
'dialect': 'trino',
|
|
99
|
-
'
|
|
100
|
-
|
|
101
|
-
'isArray': false,
|
|
102
|
-
'type': 'nested',
|
|
103
|
-
},
|
|
104
|
-
'structSource': { 'type': 'nested' },
|
|
105
|
-
'fields': [
|
|
106
|
-
{ 'name': 'a', 'numberType': 'float', 'type': 'number' },
|
|
107
|
-
{ 'name': 'b', 'numberType': 'integer', 'type': 'number' },
|
|
108
|
-
{ 'name': 'c', 'type': 'string' },
|
|
109
|
-
],
|
|
77
|
+
'join': 'many',
|
|
78
|
+
'fields': recordSchema,
|
|
110
79
|
});
|
|
111
80
|
});
|
|
112
81
|
it('parses a simple type', () => {
|
|
113
|
-
expect(connection.malloyTypeFromTrinoType('test', 'varchar(60)')).toEqual(
|
|
114
|
-
'type': 'string',
|
|
115
|
-
});
|
|
82
|
+
expect(connection.malloyTypeFromTrinoType('test', 'varchar(60)')).toEqual(stringType);
|
|
116
83
|
});
|
|
117
84
|
it('parses deep nesting', () => {
|
|
118
85
|
expect(connection.malloyTypeFromTrinoType('test', DEEP_SCHEMA)).toEqual({
|
|
119
86
|
'name': 'test',
|
|
120
|
-
'type': '
|
|
87
|
+
'type': 'array',
|
|
121
88
|
'dialect': 'trino',
|
|
122
|
-
'
|
|
123
|
-
|
|
124
|
-
'isArray': false,
|
|
125
|
-
'type': 'nested',
|
|
126
|
-
},
|
|
127
|
-
'structSource': {
|
|
128
|
-
'type': 'nested',
|
|
129
|
-
},
|
|
89
|
+
'elementTypeDef': { type: 'record_element' },
|
|
90
|
+
'join': 'many',
|
|
130
91
|
'fields': [
|
|
131
|
-
{
|
|
132
|
-
'name': 'a',
|
|
133
|
-
'numberType': 'float',
|
|
134
|
-
'type': 'number',
|
|
135
|
-
},
|
|
92
|
+
{ 'name': 'a', ...doubleType },
|
|
136
93
|
{
|
|
137
94
|
'name': 'b',
|
|
138
|
-
'type': '
|
|
95
|
+
'type': 'array',
|
|
139
96
|
'dialect': 'trino',
|
|
140
|
-
'
|
|
141
|
-
|
|
142
|
-
'isArray': false,
|
|
143
|
-
'type': 'nested',
|
|
144
|
-
},
|
|
145
|
-
'structSource': {
|
|
146
|
-
'type': 'nested',
|
|
147
|
-
},
|
|
97
|
+
'elementTypeDef': { type: 'record_element' },
|
|
98
|
+
'join': 'many',
|
|
148
99
|
'fields': [
|
|
149
|
-
{
|
|
150
|
-
|
|
151
|
-
'numberType': 'integer',
|
|
152
|
-
'type': 'number',
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
'name': 'd',
|
|
156
|
-
'type': 'string',
|
|
157
|
-
},
|
|
100
|
+
{ 'name': 'c', ...intType },
|
|
101
|
+
{ 'name': 'd', ...stringType },
|
|
158
102
|
],
|
|
159
103
|
},
|
|
160
104
|
],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@malloydata/db-trino",
|
|
3
|
-
"version": "0.0.195-
|
|
3
|
+
"version": "0.0.195-dev241007154000",
|
|
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.195-
|
|
25
|
+
"@malloydata/malloy": "^0.0.195-dev241007154000",
|
|
26
26
|
"@prestodb/presto-js-client": "^1.0.0",
|
|
27
27
|
"gaxios": "^4.2.0",
|
|
28
28
|
"trino-client": "^0.2.2"
|