UNPKG

pocketsmith-mcp

Version:

MCP server for managing budgets via PocketSmith API

114 lines (113 loc) 4.25 kB
/** * @fileoverview Executes SQL queries and manages transactions for DuckDB. * @module services/duck-db/duckDBQueryExecutor */ import { BaseErrorCode } from "../../types-global/errors.js"; import { ErrorHandler, logger, requestContextService, } from "../../utils/index.js"; export class DuckDBQueryExecutor { constructor(connection) { this.dbConnection = connection; } async run(sql, params) { const context = requestContextService.createRequestContext({ operation: "DuckDBQueryExecutor.run", initialData: { sql, params }, }); return ErrorHandler.tryCatch(async () => { logger.debug(`Executing SQL (run): ${sql}`, { ...context, params }); if (params === undefined) { await this.dbConnection.run(sql); } else { await this.dbConnection.run(sql, params); } }, { operation: "DuckDBQueryExecutor.run", context, input: { sql, params }, errorCode: BaseErrorCode.DATABASE_ERROR, }); } async query(sql, params) { const context = requestContextService.createRequestContext({ operation: "DuckDBQueryExecutor.query", initialData: { sql, params }, }); return ErrorHandler.tryCatch(async () => { logger.debug(`Executing SQL (query): ${sql}`, { ...context, params }); const resultObject = await this.stream(sql, params); const rows = (await resultObject.getRows()); const columnNames = resultObject.columnNames(); const columnTypes = resultObject .columnTypes() .map((ct) => ct.typeId); return { rows: rows, columnNames: columnNames, columnTypes: columnTypes, rowCount: rows.length, }; }, { operation: "DuckDBQueryExecutor.query", context, input: { sql, params }, errorCode: BaseErrorCode.DATABASE_ERROR, }); } async stream(sql, params) { const context = requestContextService.createRequestContext({ operation: "DuckDBQueryExecutor.stream", initialData: { sql, params }, }); return ErrorHandler.tryCatch(async () => { logger.debug(`Executing SQL (stream): ${sql}`, { ...context, params }); if (params === undefined) { return this.dbConnection.stream(sql); } else { return this.dbConnection.stream(sql, params); } }, { operation: "DuckDBQueryExecutor.stream", context, input: { sql, params }, errorCode: BaseErrorCode.DATABASE_ERROR, }); } async prepare(sql) { const context = requestContextService.createRequestContext({ operation: "DuckDBQueryExecutor.prepare", initialData: { sql }, }); return ErrorHandler.tryCatch(async () => { logger.debug(`Preparing SQL: ${sql}`, context); return this.dbConnection.prepare(sql); }, { operation: "DuckDBQueryExecutor.prepare", context, input: { sql }, errorCode: BaseErrorCode.DATABASE_ERROR, }); } async beginTransaction() { const context = requestContextService.createRequestContext({ operation: "DuckDBQueryExecutor.beginTransaction", }); await this.run("BEGIN TRANSACTION"); logger.info("Transaction started.", context); } async commitTransaction() { const context = requestContextService.createRequestContext({ operation: "DuckDBQueryExecutor.commitTransaction", }); await this.run("COMMIT"); logger.info("Transaction committed.", context); } async rollbackTransaction() { const context = requestContextService.createRequestContext({ operation: "DuckDBQueryExecutor.rollbackTransaction", }); await this.run("ROLLBACK"); logger.info("Transaction rolled back.", context); } }