Bug 1247602 - Allow to bind blobs in Sqlite.jsm. r=mak
authorIlya Gordeev <mirraz1@rambler.ru>
Fri, 19 Feb 2016 14:24:54 +0500
changeset 375485 160914d65dac284bba2646f52a1ce1a5aa2d22b1
parent 375484 67abe927efae16762e55bdc8cad49366b8ca5db6
child 375554 d5343b0f7e6a9619dfdf333d259cff6b4f773bff
child 375555 44f4eef0b271fc85dadb6738c23060b6e57b1a36
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmak
bugs1247602
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1247602 - Allow to bind blobs in Sqlite.jsm. r=mak MozReview-Commit-ID: 2yPO6kidqfn
toolkit/modules/Sqlite.jsm
toolkit/modules/tests/xpcshell/test_sqlite.js
--- 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();
+});