Bug 1247602 - Allow to bind blobs in Sqlite.jsm. r=mak
MozReview-Commit-ID: 2yPO6kidqfn
--- a/toolkit/modules/Sqlite.jsm
+++ b/toolkit/modules/Sqlite.jsm
@@ -674,43 +674,51 @@ ConnectionData.prototype = Object.freeze
* Helper method to bind parameters of various kinds through
* reflection.
*/
_bindParameters(statement, params) {
if (!params) {
return;
}
+ function bindParam(obj, key, val) {
+ let isBlob = Array.isArray(val);
+ let args = [key, val].concat(isBlob ? [val.length] : []);
+ let methodName =
+ `bind${isBlob ? "Blob" : ""}By${typeof key == "number" ? "Index" : "Name"}`;
+ obj[methodName](...args);
+ }
+
if (Array.isArray(params)) {
// It's an array of separate params.
if (params.length && (typeof(params[0]) == "object")) {
let paramsArray = statement.newBindingParamsArray();
for (let p of params) {
let bindings = paramsArray.newBindingParams();
for (let [key, value] of Object.entries(p)) {
- bindings.bindByName(key, value);
+ bindParam(bindings, key, value);
}
paramsArray.addParams(bindings);
}
statement.bindParameters(paramsArray);
return;
}
// Indexed params.
for (let i = 0; i < params.length; i++) {
- statement.bindByIndex(i, params[i]);
+ bindParam(statement, i, params[i]);
}
return;
}
// Named params.
if (params && typeof(params) == "object") {
for (let k in params) {
- statement.bindByName(k, params[k]);
+ bindParam(statement, k, params[k]);
}
return;
}
throw new Error("Invalid type for bound parameters. Expected Array or " +
"object. Got: " + params);
},
--- a/toolkit/modules/tests/xpcshell/test_sqlite.js
+++ b/toolkit/modules/tests/xpcshell/test_sqlite.js
@@ -1,11 +1,8 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
"use strict";
var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
do_get_profile();
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/PromiseUtils.jsm");
@@ -79,22 +76,20 @@ function* getDummyTempDatabase(name, ext
for (let [k, v] of Object.entries(TABLES)) {
yield c.execute("CREATE TEMP TABLE " + k + "(" + v + ")");
c._initialStatementCount++;
}
return c;
}
-function run_test() {
+add_task(function* test_setup() {
Cu.import("resource://testing-common/services/common/logging.js");
initTestLogging("Trace");
-
- run_next_test();
-}
+});
add_task(function* test_open_normal() {
let c = yield Sqlite.openConnection({path: "test_open_normal.sqlite"});
yield c.close();
});
add_task(function* test_open_unshared() {
let path = OS.Path.join(OS.Constants.Path.profileDir, "test_open_unshared.sqlite");
@@ -1086,8 +1081,64 @@ add_task(function* test_close_database_o
Components.utils.forceGC();
Components.utils.forceCC();
Components.utils.forceShrinkingGC();
yield finalPromise;
failTestsOnAutoClose(true);
});
+
+// Test all supported datatypes
+add_task(function* test_datatypes() {
+ let c = yield getConnection("datatypes");
+ yield c.execute("DROP TABLE IF EXISTS datatypes");
+ yield c.execute(`CREATE TABLE datatypes (
+ null_col NULL,
+ integer_col INTEGER NOT NULL,
+ text_col TEXT NOT NULL,
+ blob_col BLOB NOT NULL,
+ real_col REAL NOT NULL,
+ numeric_col NUMERIC NOT NULL
+ )`);
+ const bindings = [
+ {
+ null_col: null,
+ integer_col: 12345,
+ text_col: "qwerty",
+ blob_col: new Array(256).fill(undefined).map( (value, index) => index % 256 ),
+ real_col: 3.14159265359,
+ numeric_col: true
+ },
+ {
+ null_col: null,
+ integer_col: -12345,
+ text_col: "",
+ blob_col: new Array(256 * 2).fill(undefined).map( (value, index) => index % 256 ),
+ real_col: Number.NEGATIVE_INFINITY,
+ numeric_col: false
+ }
+ ];
+
+ yield c.execute(`INSERT INTO datatypes VALUES (
+ :null_col,
+ :integer_col,
+ :text_col,
+ :blob_col,
+ :real_col,
+ :numeric_col
+ )`, bindings);
+
+ let rows = yield c.execute("SELECT * FROM datatypes");
+ Assert.ok(Array.isArray(rows));
+ Assert.equal(rows.length, bindings.length);
+ for (let i = 0 ; i < bindings.length; ++i) {
+ let binding = bindings[i];
+ let row = rows[i];
+ for (let colName in binding) {
+ // In Sqlite bool is stored and then retrieved as numeric.
+ let val = typeof binding[colName] == "boolean" ? +binding[colName]
+ : binding[colName];
+ Assert.deepEqual(val, row.getResultByName(colName));
+ }
+ }
+ yield c.close();
+});