mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 833965 - Sqlite.jsm should support an array of binding parameters. r=gps
This commit is contained in:
parent
e93befdd15
commit
3fae00304f
@ -689,6 +689,50 @@ OpenedConnection.prototype = Object.freeze({
|
||||
return count;
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper method to bind parameters of various kinds through
|
||||
* reflection.
|
||||
*/
|
||||
_bindParameters: function (statement, params) {
|
||||
if (!params) {
|
||||
return;
|
||||
}
|
||||
|
||||
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 Iterator(p)) {
|
||||
bindings.bindByName(key, value);
|
||||
}
|
||||
paramsArray.addParams(bindings);
|
||||
}
|
||||
|
||||
statement.bindParameters(paramsArray);
|
||||
return;
|
||||
}
|
||||
|
||||
// Indexed params.
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
statement.bindByIndex(i, params[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Named params.
|
||||
if (params && typeof(params) == "object") {
|
||||
for (let k in params) {
|
||||
statement.bindByName(k, params[k]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error("Invalid type for bound parameters. Expected Array or " +
|
||||
"object. Got: " + params);
|
||||
},
|
||||
|
||||
_executeStatement: function (sql, statement, params, onRow) {
|
||||
if (statement.state != statement.MOZ_STORAGE_STATEMENT_READY) {
|
||||
throw new Error("Statement is not ready for execution.");
|
||||
@ -698,18 +742,7 @@ OpenedConnection.prototype = Object.freeze({
|
||||
throw new Error("onRow must be a function. Got: " + onRow);
|
||||
}
|
||||
|
||||
if (Array.isArray(params)) {
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
statement.bindByIndex(i, params[i]);
|
||||
}
|
||||
} else if (params && typeof(params) == "object") {
|
||||
for (let k in params) {
|
||||
statement.bindByName(k, params[k]);
|
||||
}
|
||||
} else if (params) {
|
||||
throw new Error("Invalid type for bound parameters. Expected Array or " +
|
||||
"object. Got: " + params);
|
||||
}
|
||||
this._bindParameters(statement, params);
|
||||
|
||||
let index = this._statementCounter++;
|
||||
|
||||
|
@ -575,6 +575,118 @@ add_task(function test_discard_cached() {
|
||||
yield c.close();
|
||||
});
|
||||
|
||||
add_task(function test_programmatic_binding() {
|
||||
let c = yield getDummyDatabase("programmatic_binding");
|
||||
|
||||
let bindings = [
|
||||
{id: 1, path: "foobar"},
|
||||
{id: null, path: "baznoo"},
|
||||
{id: 5, path: "toofoo"},
|
||||
];
|
||||
|
||||
let sql = "INSERT INTO dirs VALUES (:id, :path)";
|
||||
let result = yield c.execute(sql, bindings);
|
||||
do_check_eq(result.length, 0);
|
||||
|
||||
let rows = yield c.executeCached("SELECT * from dirs");
|
||||
do_check_eq(rows.length, 3);
|
||||
yield c.close();
|
||||
});
|
||||
|
||||
add_task(function test_programmatic_binding_transaction() {
|
||||
let c = yield getDummyDatabase("programmatic_binding_transaction");
|
||||
|
||||
let bindings = [
|
||||
{id: 1, path: "foobar"},
|
||||
{id: null, path: "baznoo"},
|
||||
{id: 5, path: "toofoo"},
|
||||
];
|
||||
|
||||
let sql = "INSERT INTO dirs VALUES (:id, :path)";
|
||||
yield c.executeTransaction(function transaction() {
|
||||
let result = yield c.execute(sql, bindings);
|
||||
do_check_eq(result.length, 0);
|
||||
|
||||
let rows = yield c.executeCached("SELECT * from dirs");
|
||||
do_check_eq(rows.length, 3);
|
||||
});
|
||||
|
||||
// Transaction committed.
|
||||
let rows = yield c.executeCached("SELECT * from dirs");
|
||||
do_check_eq(rows.length, 3);
|
||||
yield c.close();
|
||||
});
|
||||
|
||||
add_task(function test_programmatic_binding_transaction_partial_rollback() {
|
||||
let c = yield getDummyDatabase("programmatic_binding_transaction_partial_rollback");
|
||||
|
||||
let bindings = [
|
||||
{id: 2, path: "foobar"},
|
||||
{id: 3, path: "toofoo"},
|
||||
];
|
||||
|
||||
let sql = "INSERT INTO dirs VALUES (:id, :path)";
|
||||
|
||||
// Add some data in an implicit transaction before beginning the batch insert.
|
||||
yield c.execute(sql, {id: 1, path: "works"});
|
||||
|
||||
let secondSucceeded = false;
|
||||
try {
|
||||
yield c.executeTransaction(function transaction() {
|
||||
// Insert one row. This won't implicitly start a transaction.
|
||||
let result = yield c.execute(sql, bindings[0]);
|
||||
|
||||
// Insert multiple rows. mozStorage will want to start a transaction.
|
||||
// One of the inserts will fail, so the transaction should be rolled back.
|
||||
let result = yield c.execute(sql, bindings);
|
||||
secondSucceeded = true;
|
||||
});
|
||||
} catch (ex) {
|
||||
print("Caught expected exception: " + ex);
|
||||
}
|
||||
|
||||
// We did not get to the end of our in-transaction block.
|
||||
do_check_false(secondSucceeded);
|
||||
|
||||
// Everything that happened in *our* transaction, not mozStorage's, got
|
||||
// rolled back, but the first row still exists.
|
||||
let rows = yield c.executeCached("SELECT * from dirs");
|
||||
do_check_eq(rows.length, 1);
|
||||
do_check_eq(rows[0].getResultByName("path"), "works");
|
||||
yield c.close();
|
||||
});
|
||||
|
||||
/**
|
||||
* Just like the previous test, but relying on the implicit
|
||||
* transaction established by mozStorage.
|
||||
*/
|
||||
add_task(function test_programmatic_binding_implicit_transaction() {
|
||||
let c = yield getDummyDatabase("programmatic_binding_implicit_transaction");
|
||||
|
||||
let bindings = [
|
||||
{id: 2, path: "foobar"},
|
||||
{id: 1, path: "toofoo"},
|
||||
];
|
||||
|
||||
let sql = "INSERT INTO dirs VALUES (:id, :path)";
|
||||
let secondSucceeded = false;
|
||||
yield c.execute(sql, {id: 1, path: "works"});
|
||||
try {
|
||||
let result = yield c.execute(sql, bindings);
|
||||
secondSucceeded = true;
|
||||
} catch (ex) {
|
||||
print("Caught expected exception: " + ex);
|
||||
}
|
||||
|
||||
do_check_false(secondSucceeded);
|
||||
|
||||
// The entire batch failed.
|
||||
let rows = yield c.executeCached("SELECT * from dirs");
|
||||
do_check_eq(rows.length, 1);
|
||||
do_check_eq(rows[0].getResultByName("path"), "works");
|
||||
yield c.close();
|
||||
});
|
||||
|
||||
/**
|
||||
* Test that direct binding of params and execution through mozStorage doesn't
|
||||
* error when we manually create a transaction. See Bug 856925.
|
||||
|
Loading…
Reference in New Issue
Block a user