jam/js/sql/sqlite3.js

104 lines
2.9 KiB
JavaScript

/** JavaScript Sqlite3 Implementation with raw file system access
* (sqlite3C compiled with emscripten from C source)
* Usage:
*
* db = Database(fileName:string)
* db.open()
* ret=db.exec('CREATE TABLE ?? (id INTEGER PRIMARY KEY, name TEXT NOT NULL);', tableName)
* ret=db.exec('INSERT INTO ?? VALUES (null, ?);', tableName, 'John'))
* ret=db.exec('SELECT * FROM ??;', tableName)
* ->
* { code: 0,
* ok: true,
* statement: 'SELECT * FROM "newtable";',
* result:
* [ { id: '1', name: 'John' }]}
*
*
*
*/
var sql = require('./sqlite3C.js')
var PTR_SIZE = 4;
var SQLITE_OK = 0;
var SQLite = {
open: sql.cwrap('sqlite3_open', 'number', ['string', 'number']),
exec: sql.cwrap('sqlite3_exec', 'number', ['number', 'string', 'number']),
close: sql.cwrap('sqlite3_close', 'number', ['number'])
};
/* output buffer and sqlite3_exec callback function mapping to js */
var execOutput = [];
var execCallback = sql.addFunction(function (_, colNumber, valArray, keyArray) {
var row = {};
for (var offset = 0; offset < colNumber * PTR_SIZE; offset += PTR_SIZE) {
var key = sql.UTF8ToString(sql.getValue(keyArray + offset, '*'));
var val = sql.UTF8ToString(sql.getValue(valArray + offset, '*'));
row[key] = val;
}
execOutput.push(row);
});
function escapeText(t) {
return String(t).replace(/'/g, "''");
}
function escapeIdentifier(i) {
return String(i).replace(/"/g, '""');
}
function prepareStatement(statement, parameters) {
return String(statement).replace(/\?+/g, function (match) {
var param = parameters.shift() || '';
switch (match.length) {
case 1: return `'${escapeText(param)}'`;
case 2: return `"${escapeIdentifier(param)}"`;
default: return match;
}
});
}
function createResult(code, statement, result) {
var o = { code: code, ok: !code };
if (statement) o.statement=statement;
if (result) o.result=result;
return o;
}
function Database (fileName) {
if (!(this instanceof Database)) return new Database (fileName);
this.fileName = String(fileName);
this.dbPointer = null;
}
Database.prototype.open = function () {
var dbPointer = sql._malloc(PTR_SIZE);
var returnValue = SQLite.open(this.fileName, dbPointer);
if (returnValue === SQLITE_OK) {
this.dbPointer = sql.getValue(dbPointer, '*');
}
return createResult(returnValue);
}
Database.prototype.exec = function () {
var statement,parameters=[];
for(var i in arguments) {
if (i=='0') statement=arguments[0];
else parameters.push(arguments[i]);
}
var preparedStatement = prepareStatement(statement, parameters);
var returnValue = SQLite.exec(this.dbPointer, preparedStatement, execCallback);
var result = returnValue === SQLITE_OK ? execOutput.splice(0) : null;
return createResult(returnValue, preparedStatement, result);
}
Database.prototype.close = function () {
var returnValue = SQLite.close(this.dbPointer);
return createResult(returnValue);
}
module.exports = Database