@sqb/sqljs
Version:
SQB serialization extension for sql.js driver
146 lines (145 loc) • 4.69 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SqljsConnection = void 0;
const sqljs_cursor_js_1 = require("./sqljs-cursor.js");
class SqljsConnection {
constructor(db, _onClose) {
this._onClose = _onClose;
this.intlcon = db;
}
get sessionId() {
return 0;
}
async close() {
if (this.intlcon) {
this.intlcon = undefined;
await this._onClose();
}
}
async reset() {
return this.rollback();
}
async startTransaction() {
assertDefined(this.intlcon);
try {
this.intlcon.exec('BEGIN TRANSACTION;');
}
catch (e) {
if (e instanceof Error && e.message.match(/within a transaction/))
return;
throw e;
}
}
async commit() {
assertDefined(this.intlcon);
try {
this.intlcon.exec('COMMIT;');
}
catch (e) {
if (e instanceof Error && e.message.match(/no transaction/))
return;
throw e;
}
}
async rollback() {
assertDefined(this.intlcon);
try {
this.intlcon.exec('ROLLBACK;');
}
catch (e) {
if (e instanceof Error && e.message.match(/no transaction/))
return;
throw e;
}
}
async test() {
assertDefined(this.intlcon);
this.intlcon.exec('select 1');
}
async execute(query) {
assertDefined(this.intlcon);
if (!query.autoCommit)
await this.startTransaction();
const out = {};
let params;
if (query.params) {
const prms = query.params;
params = Object.keys(prms).reduce((obj, k) => {
obj[':' + k] = prms[k];
return obj;
}, {});
}
const m = query.sql.match(/\b(insert into|update|delete from)\b ("?\w+"?)/i);
if (m) {
const stmt = this.intlcon.prepare(query.sql);
stmt.run(params);
stmt.free();
out.rowsAffected = this.intlcon.getRowsModified();
if (query.autoCommit)
await this.commit();
if (out.rowsAffected === 1 && query.returningFields) {
const selectFields = query.returningFields.map(x => x.field + (x.alias ? ' as ' + x.alias : ''));
let sql = `select ${selectFields.join(',')} from ${m[2]}\n`;
// Emulate insert into ... returning
if (m[1].toLowerCase() === 'insert into') {
sql += 'where rowid=last_insert_rowid();';
const r = this.intlcon.exec(sql);
if (r.length) {
out.fields = this._convertFields(r[0].columns);
out.rows = r[0].values;
out.rowType = 'array';
}
return out;
}
// Emulate update ... returning
if (m[1].toLowerCase() === 'update') {
const m2 = query.sql.match(/where (.+)/);
query = { ...query };
query.sql = sql + (m2 ? ' where ' + m2[1] : '');
}
else
return out;
}
}
let stmt = this.intlcon.prepare(query.sql, query.params);
try {
const colNames = stmt.getColumnNames();
if (colNames && colNames.length) {
out.fields = this._convertFields(colNames);
const rowType = query.objectRows ? 'object' : 'array';
out.rowType = rowType;
const cursor = new sqljs_cursor_js_1.SqljsCursor(stmt, { rowType });
if (query.cursor) {
out.cursor = cursor;
stmt = undefined;
}
else
out.rows = await cursor.fetch(query.fetchRows || 100);
}
return out;
}
finally {
if (stmt)
stmt.free();
}
}
_convertFields(fields) {
const result = [];
for (let i = 0; i < fields.length; i++) {
const v = fields[i];
const o = {
fieldName: v,
dataType: 'any',
jsType: 'any',
_inf: { name: v },
};
result.push(o);
}
return result;
}
}
exports.SqljsConnection = SqljsConnection;
function assertDefined(d) {
if (d == null)
throw new Error('Invalid data');
}