/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This file tests binding arrays to statements. */ add_task(async function test_errors() { let db = Services.storage.openSpecialDatabase("memory"); let stmt = db.createStatement("SELECT * FROM carray(?1)"); Assert.throws( () => stmt.bindArrayOfIntegersByIndex(0, 1), /NS_ERROR_XPC_CANT_CONVERT_PRIMITIVE_TO_ARRAY/, "Not an array" ); Assert.throws( () => stmt.bindArrayOfIntegersByIndex(0, "string"), /NS_ERROR_XPC_CANT_CONVERT_PRIMITIVE_TO_ARRAY/, "Not an array" ); Assert.throws( () => stmt.bindArrayOfIntegersByIndex(0, null), /NS_ERROR_XPC_CANT_CONVERT_PRIMITIVE_TO_ARRAY/, "Not an array" ); Assert.throws( () => stmt.bindArrayOfUTF8StringsByIndex(0, null), /NS_ERROR_XPC_CANT_CONVERT_PRIMITIVE_TO_ARRAY/, "Not an array" ); stmt.finalize(); db.close(); }); add_task(async function test_bind_empty_array() { let db = Services.storage.openSpecialDatabase("memory"); let stmt = db.createStatement("SELECT * FROM carray(?1)"); stmt.bindArrayOfIntegersByIndex(0, []); Assert.ok(!stmt.executeStep(), "Execution succeeds with no results"); stmt.finalize(); db.close(); }); add_task(async function test_bind() { let db = getOpenedDatabase(); db.executeSimpleSQL(` CREATE TABLE test ( id INTEGER, value BLOB /* no affinity */ ) `); db.executeSimpleSQL(` INSERT INTO test (value) VALUES (1), (2), (1.1), (2.2), ("test1"), ("test2") `); function bindStatement(stmt, results) { if (Number.isInteger(results[0])) { stmt.bindArrayOfIntegersByIndex(0, results); stmt.bindArrayOfIntegersByName("values", results); } else if (typeof results[0] == "number") { stmt.bindArrayOfDoublesByIndex(0, results); stmt.bindArrayOfDoublesByName("values", results); } else if (typeof results[0] == "string") { stmt.bindArrayOfStringsByIndex(0, results); stmt.bindArrayOfStringsByName("values", results); } } for (let results of [[1, 2], [1.1, 2.2], ["test1", "test2"], []]) { info("sync statement"); let query = ` SELECT value FROM test WHERE value IN carray(?1) AND value IN carray(:values) `; let stmt = db.createStatement(query); bindStatement(stmt, results); for (let result of results) { Assert.ok(stmt.executeStep()); Assert.equal(stmt.row.value, result); } stmt.finalize(); info("async statement"); stmt = db.createAsyncStatement(query); bindStatement(stmt, results); let rv = await new Promise((resolve, reject) => { let rows = []; stmt.executeAsync({ handleResult(resultSet) { let row = null; do { row = resultSet.getNextRow(); if (row) { rows.push(row); } } while (row); }, handleError(error) { reject(new Error(`Failed to execute statement: ${error.message}`)); }, handleCompletion(reason) { if (reason == Ci.mozIStorageStatementCallback.REASON_FINISHED) { resolve(rows.map(r => r.getResultByIndex(0))); } else { reject(new Error("Statement failed to execute or was cancelled")); } }, }); }); Assert.deepEqual(rv, results); stmt.finalize(); } // we are the last test using this connection and since it has gone async // we *must* call asyncClose on it. await asyncClose(db); });