diff --git a/README.md b/README.md index 9b0f3857..0f9563aa 100644 --- a/README.md +++ b/README.md @@ -231,6 +231,33 @@ Example: }); ``` +### Enabling BigInt support +If you need ```BigInt``` support, it is partially supported since most browsers now supports it including Safari.Binding ```BigInt``` is still not supported, only getting ```BigInt``` from the database is supported for now. + +```html + +``` +On WebWorker, you can just add ```config``` param before posting a message. With this, you wont have to pass config param on ```get``` function. + +```html + +``` See [examples/GUI/gui.js](examples/GUI/gui.js) for a full working example. diff --git a/src/api.js b/src/api.js index 52bbab58..fba33e57 100644 --- a/src/api.js +++ b/src/api.js @@ -116,6 +116,7 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { "number", ["number", "number", "number"] ); + var sqlite3_bind_parameter_index = cwrap( "sqlite3_bind_parameter_index", "number", @@ -358,6 +359,19 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { return sqlite3_column_double(this.stmt, pos); }; + Statement.prototype.getBigInt = function getBigInt(pos) { + if (pos == null) { + pos = this.pos; + this.pos += 1; + } + var text = sqlite3_column_text(this.stmt, pos); + if (typeof BigInt !== "function") { + throw new Error("BigInt is not supported"); + } + /* global BigInt */ + return BigInt(text); + }; + Statement.prototype.getString = function getString(pos) { if (pos == null) { pos = this.pos; @@ -390,8 +404,13 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { Print all the rows of the table test to the console var stmt = db.prepare("SELECT * FROM test"); while (stmt.step()) console.log(stmt.get()); + + Enable BigInt support + var stmt = db.prepare("SELECT * FROM test"); + while (stmt.step()) console.log(stmt.get(null, {useBigInt: true})); */ - Statement.prototype["get"] = function get(params) { + Statement.prototype["get"] = function get(params, config) { + config = config || {}; if (params != null && this["bind"](params)) { this["step"](); } @@ -400,6 +419,11 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { for (var field = 0; field < ref; field += 1) { switch (sqlite3_column_type(this.stmt, field)) { case SQLITE_INTEGER: + var getfunc = config["useBigInt"] + ? this.getBigInt(field) + : this.getNumber(field); + results1.push(getfunc); + break; case SQLITE_FLOAT: results1.push(this.getNumber(field)); break; @@ -451,8 +475,8 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { console.log(stmt.getAsObject()); // Will print {nbr:5, data: Uint8Array([1,2,3]), null_value:null} */ - Statement.prototype["getAsObject"] = function getAsObject(params) { - var values = this["get"](params); + Statement.prototype["getAsObject"] = function getAsObject(params, config) { + var values = this["get"](params, config); var names = this["getColumnNames"](); var rowObject = {}; for (var i = 0; i < names.length; i += 1) { @@ -560,10 +584,15 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { pos = this.pos; this.pos += 1; } + switch (typeof val) { case "string": return this.bindString(val, pos); case "number": + return this.bindNumber(val + 0, pos); + case "bigint": + // BigInt is not fully supported yet at WASM level. + return this.bindString(val.toString(), pos); case "boolean": return this.bindNumber(val + 0, pos); case "object": @@ -899,7 +928,7 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { (separated by `;`). This limitation does not apply to params as an object. * @return {Database.QueryExecResult[]} The results of each statement */ - Database.prototype["exec"] = function exec(sql, params) { + Database.prototype["exec"] = function exec(sql, params, config) { if (!this.db) { throw "Database closed"; } @@ -937,7 +966,7 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { }; results.push(curresult); } - curresult["values"].push(stmt["get"]()); + curresult["values"].push(stmt["get"](null, config)); } stmt["free"](); } @@ -971,7 +1000,9 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { function (row){console.log(row.name + " is a grown-up.")} ); */ - Database.prototype["each"] = function each(sql, params, callback, done) { + Database.prototype["each"] = function each( + sql, params, callback, done, config + ) { var stmt; if (typeof params === "function") { done = callback; @@ -981,7 +1012,7 @@ Module["onRuntimeInitialized"] = function onRuntimeInitialized() { stmt = this["prepare"](sql, params); try { while (stmt["step"]()) { - callback(stmt["getAsObject"]()); + callback(stmt["getAsObject"](null, config)); } } finally { stmt["free"](); diff --git a/src/worker.js b/src/worker.js index c4f31d83..f75bf6a1 100644 --- a/src/worker.js +++ b/src/worker.js @@ -15,6 +15,7 @@ function onModuleReady(SQL) { var buff; var data; var result; data = this["data"]; + var config = data["config"] ? data["config"] : {}; switch (data && data["action"]) { case "open": buff = data["buffer"]; @@ -32,7 +33,7 @@ function onModuleReady(SQL) { } return postMessage({ id: data["id"], - results: db.exec(data["sql"], data["params"]) + results: db.exec(data["sql"], data["params"], config) }); case "each": if (db === null) { @@ -51,7 +52,7 @@ function onModuleReady(SQL) { finished: true }); }; - return db.each(data["sql"], data["params"], callback, done); + return db.each(data["sql"], data["params"], callback, done, config); case "export": buff = db["export"](); result = { diff --git a/test/test_big_int.js b/test/test_big_int.js new file mode 100644 index 00000000..4745e531 --- /dev/null +++ b/test/test_big_int.js @@ -0,0 +1,35 @@ +exports.test = function(sql, assert){ + // Create a database + var db = new sql.Database(); + + // Create table, insert data + sqlstr = "CREATE TABLE IF NOT EXISTS Test_BigInt (someNumber BIGINT NOT NULL);" + + "INSERT INTO Test_BigInt (someNumber) VALUES (1628675501000);"; + db.exec(sqlstr); + + var config = {useBigInt: true}; + + var stmt = db.prepare("SELECT * FROM Test_BigInt;"); + stmt.step(); + + assert.strictEqual(typeof stmt.get()[0], 'number', "Reading number value"); + assert.strictEqual(typeof stmt.get(null, config)[0], 'bigint', "Reading bigint value"); + + db.close(); +}; + +if (module == require.main) { + const target_file = process.argv[2]; + const sql_loader = require('./load_sql_lib'); + sql_loader(target_file).then((sql)=>{ + require('test').run({ + 'test big int': function(assert){ + exports.test(sql, assert); + } + }); + }) + .catch((e)=>{ + console.error(e); + assert.fail(e); + }); +}