@bitblit/ratchet-rdbms
Version:
Ratchet tooling for working with relational databases
138 lines • 5.57 kB
JavaScript
import { BeginTransactionCommand, CommitTransactionCommand, ExecuteStatementCommand, RollbackTransactionCommand } from "@aws-sdk/client-rds-data";
import { Logger } from "@bitblit/ratchet-common/logger/logger";
import SqlString from 'sqlstring';
export class RdsDataApiDatabaseAccess {
client;
cfg;
_currentTransactionId;
constructor(client, cfg) {
this.client = client;
this.cfg = cfg;
}
async beginTransaction() {
const tmp = await this.client.send(new BeginTransactionCommand({ resourceArn: 'ss', secretArn: 'yy' }));
this._currentTransactionId = tmp.transactionId;
Logger.info('Started transaction %s', this._currentTransactionId);
}
async close() {
if (!this._currentTransactionId) {
Logger.info('Close called with transaction still open, rolling back');
await this.rollbackTransaction();
}
return true;
}
async commitTransaction() {
if (this._currentTransactionId) {
const out = await this.client.send(new CommitTransactionCommand({ resourceArn: this.cfg.resourceArn, secretArn: this.cfg.secretArn, transactionId: this._currentTransactionId }));
Logger.info('Commit transaction %s returned %j', this._currentTransactionId, out);
this._currentTransactionId = null;
}
else {
Logger.warn('Commit transaction called while no transaction in session');
}
}
escape(value) {
const rval = SqlString.escape(value);
return rval;
}
async modify(query, fields) {
const params = RdsDataApiDatabaseAccess.toSqlParameters(fields);
const tmp = await this.client.send(new ExecuteStatementCommand({ resourceArn: this.cfg.resourceArn, secretArn: this.cfg.secretArn, database: this.cfg.database, sql: query, parameters: params, includeResultMetadata: true }));
const rval = {
results: {
changedRows: tmp.numberOfRecordsUpdated,
affectedRows: tmp.numberOfRecordsUpdated
},
fields: tmp.columnMetadata
};
return rval;
}
static toSqlParameters(record) {
return Object.entries(record).map(([key, val]) => {
let value;
if (val === null) {
value = { isNull: true };
}
else if (typeof val === "number") {
value = { longValue: val };
}
else if (typeof val === "boolean") {
value = { booleanValue: val };
}
else if (val instanceof Date) {
value = { stringValue: val.toISOString(), typeHint: "TIMESTAMP" };
}
else {
value = { stringValue: String(val) };
}
return { name: key, value };
});
}
static fieldToValue(field) {
let rval = null;
if (field.isNull) {
rval = null;
}
else if (field.stringValue !== undefined) {
rval = field.stringValue;
}
else if (field.blobValue !== undefined) {
rval = Buffer.from(field.blobValue);
}
else if (field.doubleValue !== undefined) {
rval = field.doubleValue;
}
else if (field.longValue !== undefined) {
rval = field.longValue;
}
else if (field.booleanValue !== undefined) {
rval = field['booleanValue'];
}
;
return rval;
}
static parseRecords(output) {
const { records, columnMetadata } = output;
if (!records || !columnMetadata)
return [];
const rval = records.map((row) => {
const obj = {};
row.forEach((field, i) => {
const name = columnMetadata[i].name || `col${i}`;
obj[name] = RdsDataApiDatabaseAccess.fieldToValue(field);
});
return obj;
});
return rval;
}
async query(query, fields) {
const params = RdsDataApiDatabaseAccess.toSqlParameters(fields);
const _tmp = await this.client.send(new ExecuteStatementCommand({ resourceArn: this.cfg.resourceArn, secretArn: this.cfg.secretArn, database: this.cfg.database, sql: query, parameters: params, includeResultMetadata: true }));
Logger.info('tmp: %j cm: %j', _tmp.records, _tmp.columnMetadata);
const records = RdsDataApiDatabaseAccess.parseRecords(_tmp);
const rval = {
results: records,
fields: _tmp.columnMetadata ?? []
};
return rval;
}
async rollbackTransaction() {
if (this._currentTransactionId) {
const out = await this.client.send(new RollbackTransactionCommand({ resourceArn: this.cfg.resourceArn, secretArn: this.cfg.secretArn, transactionId: this._currentTransactionId }));
Logger.info('Rollback transaction %s returned %j', this._currentTransactionId, out);
this._currentTransactionId = null;
}
else {
Logger.warn('Rollback transaction called while no transaction in session');
}
}
async testConnection(logTestResults) {
const output = await this.query('SELECT 1 AS test_result', {});
if (logTestResults) {
Logger.info('Test connection returned %j', output);
}
const rval = output?.results?.length ? output.results[0]['test_result'] : null;
return rval;
}
}
//# sourceMappingURL=rds-data-api-database-access.js.map