'use strict'; var sqlite3 = require('sqlite3'); var SQLiteResult = require('./SQLiteResult'); var READ_ONLY_ERROR = new Error( 'could not prepare statement (23 not authorized)'); function SQLiteDatabase(name) { this._db = new sqlite3.Database(name); } function runSelect(db, sql, args, cb) { db.all(sql, args, function (err, rows) { if (err) { return cb(new SQLiteResult(err)); } var insertId = void 0; var rowsAffected = 0; var resultSet = new SQLiteResult(null, insertId, rowsAffected, rows); cb(resultSet); }); } function runNonSelect(db, sql, args, cb) { db.run(sql, args, function (err) { if (err) { return cb(new SQLiteResult(err)); } /* jshint validthis:true */ var executionResult = this; var insertId = executionResult.lastID; var rowsAffected = executionResult.changes; var rows = []; var resultSet = new SQLiteResult(null, insertId, rowsAffected, rows); cb(resultSet); }); } SQLiteDatabase.prototype.exec = function exec(queries, readOnly, callback) { var db = this._db; var len = queries.length; var results = new Array(len); var i = 0; function checkDone() { if (++i === len) { callback(null, results); } else { doNext(); } } function onQueryComplete(i) { return function (res) { results[i] = res; checkDone(); }; } function doNext() { var query = queries[i]; var sql = query.sql; var args = query.args; // TODO: It seems like the node-sqlite3 API either allows: // 1) all(), which returns results but not rowsAffected or lastID // 2) run(), which doesn't return results, but returns rowsAffected and lastID // So we try to sniff whether it's a SELECT query or not. // This is inherently error-prone, although it will probably work in the 99% // case. var isSelect = /^\s*SELECT\b/i.test(sql); if (readOnly && !isSelect) { onQueryComplete(i)(new SQLiteResult(READ_ONLY_ERROR)); } else if (isSelect) { runSelect(db, sql, args, onQueryComplete(i)); } else { runNonSelect(db, sql, args, onQueryComplete(i)); } } doNext(); }; module.exports = SQLiteDatabase;