@malloy-publisher/server 0.0.132 → 0.0.133
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/app/assets/{HomePage-ujbTuDol.js → HomePage-B5w7_h5t.js} +1 -1
- package/dist/app/assets/{MainPage-atr7-FWG.js → MainPage-BuxirnMV.js} +1 -1
- package/dist/app/assets/{ModelPage-CcPoN-wg.js → ModelPage-Chbssj36.js} +1 -1
- package/dist/app/assets/{PackagePage-78sobA7e.js → PackagePage-BNOrnrrm.js} +1 -1
- package/dist/app/assets/{ProjectPage-CqnH1q5F.js → ProjectPage-C9PKYf36.js} +1 -1
- package/dist/app/assets/{RouteError-Cn5AP476.js → RouteError-BH7d-TI6.js} +1 -1
- package/dist/app/assets/{WorkbookPage-BSyHhV3n.js → WorkbookPage-Cqd0v7QI.js} +1 -1
- package/dist/app/assets/{index-TtWivME-.js → index-DSXSHYic.js} +72 -72
- package/dist/app/assets/{index---iwNDWs.js → index-JbXykaAK.js} +1 -1
- package/dist/app/assets/{index-BUurEQTs.js → index-Xll613qL.js} +1 -1
- package/dist/app/assets/{index.umd-CqAK7-fS.js → index.umd-BYSfzPe-.js} +1 -1
- package/dist/app/index.html +1 -1
- package/dist/server.js +81 -8
- package/package.json +1 -1
- package/src/service/connection.ts +2 -0
- package/src/service/db_utils.ts +76 -11
- package/src/service/model.ts +36 -1
package/dist/server.js
CHANGED
|
@@ -131914,6 +131914,8 @@ function validateAndBuildTrinoConfig(trinoConfig) {
|
|
|
131914
131914
|
}
|
|
131915
131915
|
};
|
|
131916
131916
|
delete baseConfig.password;
|
|
131917
|
+
delete baseConfig.catalog;
|
|
131918
|
+
delete baseConfig.schema;
|
|
131917
131919
|
} else if (trinoConfig.server?.startsWith("https://") && trinoConfig.password) {
|
|
131918
131920
|
baseConfig.password = trinoConfig.password;
|
|
131919
131921
|
}
|
|
@@ -132541,7 +132543,35 @@ async function getSchemasForConnection(connection, malloyConnection) {
|
|
|
132541
132543
|
throw new Error("Trino connection is required");
|
|
132542
132544
|
}
|
|
132543
132545
|
try {
|
|
132544
|
-
|
|
132546
|
+
let result;
|
|
132547
|
+
if (connection.trinoConnection.catalog) {
|
|
132548
|
+
result = await malloyConnection.runSQL(`SHOW SCHEMAS FROM ${connection.trinoConnection.catalog}`);
|
|
132549
|
+
} else {
|
|
132550
|
+
const catalogs = await malloyConnection.runSQL(`SHOW CATALOGS`);
|
|
132551
|
+
console.log("catalogs", catalogs);
|
|
132552
|
+
let catalogNames = standardizeRunSQLResult(catalogs);
|
|
132553
|
+
catalogNames = catalogNames.map((catalog) => {
|
|
132554
|
+
const typedCatalog = catalog;
|
|
132555
|
+
return typedCatalog.Catalog;
|
|
132556
|
+
});
|
|
132557
|
+
const schemas = [];
|
|
132558
|
+
console.log("catalogNames", catalogNames);
|
|
132559
|
+
for (const catalog of catalogNames) {
|
|
132560
|
+
const schemasResult = await malloyConnection.runSQL(`SHOW SCHEMAS FROM ${catalog}`);
|
|
132561
|
+
const schemasResultRows = standardizeRunSQLResult(schemasResult);
|
|
132562
|
+
console.log("schemasResultRows", schemasResultRows);
|
|
132563
|
+
const schemasWithCatalog = schemasResultRows.map((row) => {
|
|
132564
|
+
const typedRow = row;
|
|
132565
|
+
return {
|
|
132566
|
+
...typedRow,
|
|
132567
|
+
Schema: `${catalog}.${typedRow.Schema ?? typedRow.schema ?? ""}`
|
|
132568
|
+
};
|
|
132569
|
+
});
|
|
132570
|
+
schemas.push(...schemasWithCatalog);
|
|
132571
|
+
console.log("schemas", schemas);
|
|
132572
|
+
}
|
|
132573
|
+
result = schemas;
|
|
132574
|
+
}
|
|
132545
132575
|
const rows = standardizeRunSQLResult(result);
|
|
132546
132576
|
return rows.map((row) => {
|
|
132547
132577
|
const typedRow = row;
|
|
@@ -132618,7 +132648,11 @@ async function getTablesForSchema(connection, schemaName, malloyConnection) {
|
|
|
132618
132648
|
try {
|
|
132619
132649
|
let tablePath;
|
|
132620
132650
|
if (connection.type === "trino") {
|
|
132621
|
-
|
|
132651
|
+
if (connection.trinoConnection?.catalog) {
|
|
132652
|
+
tablePath = `${connection.trinoConnection?.catalog}.${schemaName}.${tableName}`;
|
|
132653
|
+
} else {
|
|
132654
|
+
tablePath = `${schemaName}.${tableName}`;
|
|
132655
|
+
}
|
|
132622
132656
|
} else {
|
|
132623
132657
|
tablePath = `${schemaName}.${tableName}`;
|
|
132624
132658
|
}
|
|
@@ -132651,10 +132685,12 @@ async function getConnectionTableSource(malloyConnection, tableKey, tablePath) {
|
|
|
132651
132685
|
});
|
|
132652
132686
|
const source = await malloyConnection.fetchTableSchema(tableKey, tablePath);
|
|
132653
132687
|
if (source === undefined) {
|
|
132654
|
-
throw new ConnectionError(`Table ${tablePath} not found`);
|
|
132688
|
+
throw new ConnectionError(`Table ${tablePath} not found: ${JSON.stringify(source)}`);
|
|
132655
132689
|
}
|
|
132656
|
-
if (!source
|
|
132690
|
+
if (!source) {
|
|
132657
132691
|
throw new ConnectionError(`Invalid table source returned for ${tablePath}`);
|
|
132692
|
+
} else if (typeof source !== "object") {
|
|
132693
|
+
throw new ConnectionError(JSON.stringify(source));
|
|
132658
132694
|
}
|
|
132659
132695
|
const malloyFields = source.fields;
|
|
132660
132696
|
if (!malloyFields || !Array.isArray(malloyFields)) {
|
|
@@ -132675,8 +132711,13 @@ async function getConnectionTableSource(malloyConnection, tableKey, tablePath) {
|
|
|
132675
132711
|
columns: fields
|
|
132676
132712
|
};
|
|
132677
132713
|
} catch (error) {
|
|
132678
|
-
|
|
132679
|
-
|
|
132714
|
+
const errorMessage = error instanceof Error ? error.message : typeof error === "string" ? error : JSON.stringify(error);
|
|
132715
|
+
logger2.error("fetchTableSchema error", {
|
|
132716
|
+
error,
|
|
132717
|
+
tableKey,
|
|
132718
|
+
tablePath
|
|
132719
|
+
});
|
|
132720
|
+
throw new ConnectionError(errorMessage);
|
|
132680
132721
|
}
|
|
132681
132722
|
}
|
|
132682
132723
|
async function listTablesForSchema(connection, schemaName, malloyConnection) {
|
|
@@ -132737,7 +132778,12 @@ async function listTablesForSchema(connection, schemaName, malloyConnection) {
|
|
|
132737
132778
|
throw new Error("Trino connection is required");
|
|
132738
132779
|
}
|
|
132739
132780
|
try {
|
|
132740
|
-
|
|
132781
|
+
let result;
|
|
132782
|
+
if (connection.trinoConnection?.catalog) {
|
|
132783
|
+
result = await malloyConnection.runSQL(`SHOW TABLES FROM ${connection.trinoConnection.catalog}.${schemaName}`);
|
|
132784
|
+
} else {
|
|
132785
|
+
result = await malloyConnection.runSQL(`SHOW TABLES FROM ${schemaName}`);
|
|
132786
|
+
}
|
|
132741
132787
|
const rows = standardizeRunSQLResult(result);
|
|
132742
132788
|
return rows.map((row) => {
|
|
132743
132789
|
const typedRow = row;
|
|
@@ -139063,7 +139109,34 @@ run: ${sourceName ? sourceName + "->" : ""}${queryName}`);
|
|
|
139063
139109
|
const rowLimit = (await runnable.getPreparedResult()).resultExplore.limit || ROW_LIMIT;
|
|
139064
139110
|
const endTime = performance.now();
|
|
139065
139111
|
const executionTime = endTime - startTime;
|
|
139066
|
-
|
|
139112
|
+
let queryResults;
|
|
139113
|
+
try {
|
|
139114
|
+
queryResults = await runnable.run({ rowLimit });
|
|
139115
|
+
} catch (error) {
|
|
139116
|
+
const errorEndTime = performance.now();
|
|
139117
|
+
const errorExecutionTime = errorEndTime - startTime;
|
|
139118
|
+
this.queryExecutionHistogram.record(errorExecutionTime, {
|
|
139119
|
+
"malloy.model.path": this.modelPath,
|
|
139120
|
+
"malloy.model.query.name": queryName,
|
|
139121
|
+
"malloy.model.query.source": sourceName,
|
|
139122
|
+
"malloy.model.query.query": query,
|
|
139123
|
+
"malloy.model.query.status": "error"
|
|
139124
|
+
});
|
|
139125
|
+
if (error instanceof import_malloy2.MalloyError) {
|
|
139126
|
+
throw error;
|
|
139127
|
+
}
|
|
139128
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
139129
|
+
logger2.error("Query execution error", {
|
|
139130
|
+
error,
|
|
139131
|
+
errorMessage,
|
|
139132
|
+
projectName: this.packageName,
|
|
139133
|
+
modelPath: this.modelPath,
|
|
139134
|
+
query,
|
|
139135
|
+
queryName,
|
|
139136
|
+
sourceName
|
|
139137
|
+
});
|
|
139138
|
+
throw new BadRequestError(`Query execution failed: ${errorMessage}`);
|
|
139139
|
+
}
|
|
139067
139140
|
this.queryExecutionHistogram.record(executionTime, {
|
|
139068
139141
|
"malloy.model.path": this.modelPath,
|
|
139069
139142
|
"malloy.model.query.name": queryName,
|
package/package.json
CHANGED
package/src/service/db_utils.ts
CHANGED
|
@@ -188,10 +188,47 @@ export async function getSchemasForConnection(
|
|
|
188
188
|
throw new Error("Trino connection is required");
|
|
189
189
|
}
|
|
190
190
|
try {
|
|
191
|
+
let result: unknown;
|
|
191
192
|
// Use the connection's runSQL method to query schemas
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
193
|
+
if (connection.trinoConnection.catalog) {
|
|
194
|
+
result = await malloyConnection.runSQL(
|
|
195
|
+
`SHOW SCHEMAS FROM ${connection.trinoConnection.catalog}`,
|
|
196
|
+
);
|
|
197
|
+
} else {
|
|
198
|
+
const catalogs = await malloyConnection.runSQL(`SHOW CATALOGS`);
|
|
199
|
+
console.log("catalogs", catalogs);
|
|
200
|
+
let catalogNames = standardizeRunSQLResult(catalogs);
|
|
201
|
+
catalogNames = catalogNames.map((catalog: unknown) => {
|
|
202
|
+
const typedCatalog = catalog as Record<string, unknown>;
|
|
203
|
+
return typedCatalog.Catalog as string;
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const schemas: unknown[] = [];
|
|
207
|
+
|
|
208
|
+
console.log("catalogNames", catalogNames);
|
|
209
|
+
for (const catalog of catalogNames) {
|
|
210
|
+
const schemasResult = await malloyConnection.runSQL(
|
|
211
|
+
`SHOW SCHEMAS FROM ${catalog}`,
|
|
212
|
+
);
|
|
213
|
+
const schemasResultRows = standardizeRunSQLResult(schemasResult);
|
|
214
|
+
console.log("schemasResultRows", schemasResultRows);
|
|
215
|
+
|
|
216
|
+
// Concat catalog name to schema name for each schema row
|
|
217
|
+
const schemasWithCatalog = schemasResultRows.map(
|
|
218
|
+
(row: unknown) => {
|
|
219
|
+
const typedRow = row as Record<string, unknown>;
|
|
220
|
+
// For display, use the convention "catalog.schema"
|
|
221
|
+
return {
|
|
222
|
+
...typedRow,
|
|
223
|
+
Schema: `${catalog}.${typedRow.Schema ?? typedRow.schema ?? ""}`,
|
|
224
|
+
};
|
|
225
|
+
},
|
|
226
|
+
);
|
|
227
|
+
schemas.push(...schemasWithCatalog);
|
|
228
|
+
console.log("schemas", schemas);
|
|
229
|
+
}
|
|
230
|
+
result = schemas;
|
|
231
|
+
}
|
|
195
232
|
|
|
196
233
|
const rows = standardizeRunSQLResult(result);
|
|
197
234
|
return rows.map((row: unknown) => {
|
|
@@ -316,7 +353,12 @@ export async function getTablesForSchema(
|
|
|
316
353
|
let tablePath: string;
|
|
317
354
|
|
|
318
355
|
if (connection.type === "trino") {
|
|
319
|
-
|
|
356
|
+
if (connection.trinoConnection?.catalog) {
|
|
357
|
+
tablePath = `${connection.trinoConnection?.catalog}.${schemaName}.${tableName}`;
|
|
358
|
+
} else {
|
|
359
|
+
// Catalog name is included in the schema name
|
|
360
|
+
tablePath = `${schemaName}.${tableName}`;
|
|
361
|
+
}
|
|
320
362
|
} else {
|
|
321
363
|
tablePath = `${schemaName}.${tableName}`;
|
|
322
364
|
}
|
|
@@ -374,14 +416,18 @@ export async function getConnectionTableSource(
|
|
|
374
416
|
}
|
|
375
417
|
).fetchTableSchema(tableKey, tablePath);
|
|
376
418
|
if (source === undefined) {
|
|
377
|
-
throw new ConnectionError(
|
|
419
|
+
throw new ConnectionError(
|
|
420
|
+
`Table ${tablePath} not found: ${JSON.stringify(source)}`,
|
|
421
|
+
);
|
|
378
422
|
}
|
|
379
423
|
|
|
380
424
|
// Validate that source has the expected structure
|
|
381
|
-
if (!source
|
|
425
|
+
if (!source) {
|
|
382
426
|
throw new ConnectionError(
|
|
383
427
|
`Invalid table source returned for ${tablePath}`,
|
|
384
428
|
);
|
|
429
|
+
} else if (typeof source !== "object") {
|
|
430
|
+
throw new ConnectionError(JSON.stringify(source));
|
|
385
431
|
}
|
|
386
432
|
|
|
387
433
|
const malloyFields = (source as TableSourceDef).fields;
|
|
@@ -406,8 +452,18 @@ export async function getConnectionTableSource(
|
|
|
406
452
|
columns: fields,
|
|
407
453
|
};
|
|
408
454
|
} catch (error) {
|
|
409
|
-
|
|
410
|
-
|
|
455
|
+
const errorMessage =
|
|
456
|
+
error instanceof Error
|
|
457
|
+
? error.message
|
|
458
|
+
: typeof error === "string"
|
|
459
|
+
? error
|
|
460
|
+
: JSON.stringify(error);
|
|
461
|
+
logger.error("fetchTableSchema error", {
|
|
462
|
+
error,
|
|
463
|
+
tableKey,
|
|
464
|
+
tablePath,
|
|
465
|
+
});
|
|
466
|
+
throw new ConnectionError(errorMessage);
|
|
411
467
|
}
|
|
412
468
|
}
|
|
413
469
|
|
|
@@ -505,9 +561,18 @@ export async function listTablesForSchema(
|
|
|
505
561
|
throw new Error("Trino connection is required");
|
|
506
562
|
}
|
|
507
563
|
try {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
)
|
|
564
|
+
let result: unknown;
|
|
565
|
+
|
|
566
|
+
if (connection.trinoConnection?.catalog) {
|
|
567
|
+
result = await malloyConnection.runSQL(
|
|
568
|
+
`SHOW TABLES FROM ${connection.trinoConnection.catalog}.${schemaName}`,
|
|
569
|
+
);
|
|
570
|
+
} else {
|
|
571
|
+
// Catalog name is included in the schema name
|
|
572
|
+
result = await malloyConnection.runSQL(
|
|
573
|
+
`SHOW TABLES FROM ${schemaName}`,
|
|
574
|
+
);
|
|
575
|
+
}
|
|
511
576
|
const rows = standardizeRunSQLResult(result);
|
|
512
577
|
return rows.map((row: unknown) => {
|
|
513
578
|
const typedRow = row as Record<string, unknown>;
|
package/src/service/model.ts
CHANGED
|
@@ -269,7 +269,42 @@ export class Model {
|
|
|
269
269
|
(await runnable.getPreparedResult()).resultExplore.limit || ROW_LIMIT;
|
|
270
270
|
const endTime = performance.now();
|
|
271
271
|
const executionTime = endTime - startTime;
|
|
272
|
-
|
|
272
|
+
|
|
273
|
+
let queryResults;
|
|
274
|
+
try {
|
|
275
|
+
queryResults = await runnable.run({ rowLimit });
|
|
276
|
+
} catch (error) {
|
|
277
|
+
// Record error metrics
|
|
278
|
+
const errorEndTime = performance.now();
|
|
279
|
+
const errorExecutionTime = errorEndTime - startTime;
|
|
280
|
+
this.queryExecutionHistogram.record(errorExecutionTime, {
|
|
281
|
+
"malloy.model.path": this.modelPath,
|
|
282
|
+
"malloy.model.query.name": queryName,
|
|
283
|
+
"malloy.model.query.source": sourceName,
|
|
284
|
+
"malloy.model.query.query": query,
|
|
285
|
+
"malloy.model.query.status": "error",
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// Re-throw Malloy errors as-is (they will be handled by error handler)
|
|
289
|
+
if (error instanceof MalloyError) {
|
|
290
|
+
throw error;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// For other runtime errors (like divide by zero), throw as BadRequestError
|
|
294
|
+
const errorMessage =
|
|
295
|
+
error instanceof Error ? error.message : String(error);
|
|
296
|
+
logger.error("Query execution error", {
|
|
297
|
+
error,
|
|
298
|
+
errorMessage,
|
|
299
|
+
projectName: this.packageName,
|
|
300
|
+
modelPath: this.modelPath,
|
|
301
|
+
query,
|
|
302
|
+
queryName,
|
|
303
|
+
sourceName,
|
|
304
|
+
});
|
|
305
|
+
throw new BadRequestError(`Query execution failed: ${errorMessage}`);
|
|
306
|
+
}
|
|
307
|
+
|
|
273
308
|
this.queryExecutionHistogram.record(executionTime, {
|
|
274
309
|
"malloy.model.path": this.modelPath,
|
|
275
310
|
"malloy.model.query.name": queryName,
|