Line data Source code
1 : import * as arrow from 'apache-arrow';
2 : import * as dashql from '@ankoh/dashql-core';
3 :
4 : import { catalogTablesFromPgAttribute, pgAttributeQuery, type PgAttributeColumnsTable } from '../connections/catalog/catalog_query_pg_attribute.js';
5 : import { DEFAULT_DATABASE_NAME, packCatalogTable, packRelationName, readRelationName } from '../connections/catalog/catalog_sql_generator.js';
6 :
7 1 : const LAYER = dashql.buffers.catalog.CatalogLayer.CONNECTION;
8 :
9 : /// The catalog of a shell on an embedded database. Its descriptor holds what the database reports.
10 1 : export class EmbeddedDatabaseCatalog {
11 : /// The catalog entry of the descriptor
12 1 : private readonly entryId: number;
13 :
14 1 : constructor(
15 1 : private readonly core: dashql.DashQL,
16 1 : private readonly catalog: dashql.DashQLCatalog,
17 1 : private readonly query: (text: string) => Promise<arrow.Table>,
18 1 : ) {
19 1 : this.entryId = catalog.allocateEntryId();
20 1 : }
21 :
22 : /// Ask the database about what a statement touched, before the prompt returns. Also after a failure: a statement of
23 : /// many may have run.
24 1 : async afterStatement(statement: string): Promise<void> {
25 1 : const relations = this.core.touchedRelations(statement).map(name => readRelationName(name, DEFAULT_DATABASE_NAME));
26 1 : for (const databaseName of new Set(relations.map(relation => relation.databaseName))) {
27 1 : const ofDatabase = relations.filter(relation => relation.databaseName === databaseName);
28 1 : const queryDatabaseName = databaseName === DEFAULT_DATABASE_NAME ? null : databaseName;
29 1 : const rows = await this.query(pgAttributeQuery({ queryDatabaseName, relations: ofDatabase })) as PgAttributeColumnsTable;
30 1 : const tables = catalogTablesFromPgAttribute(rows, databaseName);
31 1 : this.catalog.replaceTables(this.entryId, LAYER, { relations: ofDatabase.map(packRelationName), tables: tables.map(packCatalogTable) });
32 1 : }
33 1 : }
34 :
35 1 : destroy(): void {
36 1 : this.catalog.dropDescriptor(this.entryId);
37 1 : }
38 1 : }
|