pocketsmith-mcp
Version:
MCP server for managing budgets via PocketSmith API
114 lines (113 loc) • 4.25 kB
JavaScript
/**
* @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);
}
}