diff --git a/storage/public/mozIStorageStatement.idl b/storage/public/mozIStorageStatement.idl index 3fc78435ad4d..a53f062e6fa4 100644 --- a/storage/public/mozIStorageStatement.idl +++ b/storage/public/mozIStorageStatement.idl @@ -45,7 +45,7 @@ interface nsISimpleEnumerator; [ptr] native sqlite3stmtptr(struct sqlite3_stmt); -[scriptable, uuid(80e5210f-c0da-4f37-b5f9-d9925a75612a)] +[scriptable, uuid(1a95a6ec-e4b0-4d0b-947b-d2f40b04d057)] interface mozIStorageStatement : mozIStorageValueArray { /** * Initialize this query with the given SQL statement. @@ -54,6 +54,13 @@ interface mozIStorageStatement : mozIStorageValueArray { void initialize(in mozIStorageConnection aDBConnection, in AUTF8String aSQLStatement); + /** + * Finalizes a statement so you can successfully close a database connection. + * This method does not need to be used from native callers since you can just + * set the statement to null, but is extremely useful to JS callers. + */ + void finalize(); + /** * Create a clone of this statement, by initializing a new statement * with the same connection and same SQL statement as this one. It diff --git a/storage/src/mozStorageStatement.cpp b/storage/src/mozStorageStatement.cpp index 8090e4f21af4..4ab32e85ea2c 100644 --- a/storage/src/mozStorageStatement.cpp +++ b/storage/src/mozStorageStatement.cpp @@ -192,8 +192,7 @@ mozStorageStatement::Initialize(mozIStorageConnection *aDBConnection, const nsAC mozStorageStatement::~mozStorageStatement() { - if (mDBStatement) - sqlite3_finalize (mDBStatement); + (void)Finalize(); } /* mozIStorageStatement clone (); */ @@ -211,6 +210,18 @@ mozStorageStatement::Clone(mozIStorageStatement **_retval) return NS_OK; } +/* void finalize(); */ +NS_IMETHODIMP +mozStorageStatement::Finalize() +{ + if (mDBStatement) { + int srv = sqlite3_finalize(mDBStatement); + mDBStatement = NULL; + return ConvertResultCode(srv); + } + return NS_OK; +} + /* readonly attribute unsigned long parameterCount; */ NS_IMETHODIMP mozStorageStatement::GetParameterCount(PRUint32 *aParameterCount) diff --git a/storage/test/unit/head_storage.js b/storage/test/unit/head_storage.js index fe60d31af806..c2a9f341b281 100644 --- a/storage/test/unit/head_storage.js +++ b/storage/test/unit/head_storage.js @@ -51,10 +51,19 @@ function getTestDB() function cleanup() { + // close the connection + print("*** Storage Tests: Trying to close!"); + getOpenedDatabase().close(); + + // we need to null out the database variable to get a new connection the next + // time getOpenedDatabase is called + gDBConn = null; + // removing test db + print("*** Storage Tests: Trying to remove file!"); var dbFile = getTestDB(); if (dbFile.exists()) - try { dbFile.remove(true); } catch(e) { /* stupid windows box */ } + try { dbFile.remove(false); } catch(e) { /* stupid windows box */ } } function getService() @@ -65,7 +74,10 @@ function getService() var gDBConn = null; function getOpenedDatabase() { - return gDBConn ? gDBConn : gDBConn = getService().openDatabase(getTestDB()); + if (!gDBConn) { + gDBConn = getService().openDatabase(getTestDB()); + } + return gDBConn; } function createStatement(aSQL) diff --git a/storage/test/unit/test_bug-365166.js b/storage/test/unit/test_bug-365166.js index 464061c45392..5a8e5e9bb25f 100644 --- a/storage/test/unit/test_bug-365166.js +++ b/storage/test/unit/test_bug-365166.js @@ -32,6 +32,7 @@ function run_test() { wrapper.initialize(statement); } finally { statement.reset(); + statement.finalize(); } } } diff --git a/storage/test/unit/test_bug-393952.js b/storage/test/unit/test_bug-393952.js index 3d4159d1a60b..166c200ea14c 100644 --- a/storage/test/unit/test_bug-393952.js +++ b/storage/test/unit/test_bug-393952.js @@ -48,6 +48,7 @@ function setup() var stmt = createStatement("INSERT INTO t1 (x) VALUES ('a')"); stmt.execute(); stmt.reset(); + stmt.finalize(); } function test_vacuum() @@ -55,6 +56,7 @@ function test_vacuum() var stmt = createStatement("VACUUM;"); stmt.executeStep(); stmt.reset(); + stmt.finalize(); } var tests = [test_vacuum]; diff --git a/storage/test/unit/test_like.js b/storage/test/unit/test_like.js index 8f693127bc2d..aae25f38f6d8 100644 --- a/storage/test/unit/test_like.js +++ b/storage/test/unit/test_like.js @@ -46,40 +46,51 @@ function setup() var stmt = createStatement("INSERT INTO t1 (x) VALUES ('a')"); stmt.execute(); + stmt.finalize(); stmt = createStatement("INSERT INTO t1 (x) VALUES ('ab')"); stmt.execute(); + stmt.finalize(); stmt = createStatement("INSERT INTO t1 (x) VALUES ('abc')"); stmt.execute(); + stmt.finalize(); stmt = createStatement("INSERT INTO t1 (x) VALUES ('abcd')"); stmt.execute(); + stmt.finalize(); stmt = createStatement("INSERT INTO t1 (x) VALUES ('acd')"); stmt.execute(); + stmt.finalize(); stmt = createStatement("INSERT INTO t1 (x) VALUES ('abd')"); stmt.execute(); + stmt.finalize(); stmt = createStatement("INSERT INTO t1 (x) VALUES ('bc')"); stmt.execute(); + stmt.finalize(); stmt = createStatement("INSERT INTO t1 (x) VALUES ('bcd')"); stmt.execute(); + stmt.finalize(); stmt = createStatement("INSERT INTO t1 (x) VALUES ('xyz')"); stmt.execute(); + stmt.finalize(); stmt = createStatement("INSERT INTO t1 (x) VALUES ('ABC')"); stmt.execute(); + stmt.finalize(); stmt = createStatement("INSERT INTO t1 (x) VALUES ('CDE')"); stmt.execute(); + stmt.finalize(); stmt = createStatement("INSERT INTO t1 (x) VALUES ('ABC abc xyz')"); stmt.execute(); - stmt.reset(); + stmt.finalize(); } function test_count() @@ -88,6 +99,7 @@ function test_count() do_check_true(stmt.executeStep()); do_check_eq(stmt.getInt32(0), 12); stmt.reset(); + stmt.finalize(); } function test_like_1() @@ -100,6 +112,7 @@ function test_like_1() do_check_true(solutions.indexOf(stmt.getString(0)) != -1); do_check_false(stmt.executeStep()); stmt.reset(); + stmt.finalize(); } function test_like_2() @@ -112,6 +125,7 @@ function test_like_2() do_check_true(solutions.indexOf(stmt.getString(0)) != -1); do_check_false(stmt.executeStep()); stmt.reset(); + stmt.finalize(); } function test_like_3() @@ -124,6 +138,7 @@ function test_like_3() do_check_true(solutions.indexOf(stmt.getString(0)) != -1); do_check_false(stmt.executeStep()); stmt.reset(); + stmt.finalize(); } function test_like_4() @@ -140,6 +155,7 @@ function test_like_4() do_check_true(solutions.indexOf(stmt.getString(0)) != -1); do_check_false(stmt.executeStep()); stmt.reset(); + stmt.finalize(); } function test_like_5() @@ -152,6 +168,7 @@ function test_like_5() do_check_true(solutions.indexOf(stmt.getString(0)) != -1); do_check_false(stmt.executeStep()); stmt.reset(); + stmt.finalize(); } function test_like_6() @@ -164,6 +181,7 @@ function test_like_6() do_check_true(solutions.indexOf(stmt.getString(0)) != -1); do_check_false(stmt.executeStep()); stmt.reset(); + stmt.finalize(); } function test_like_7() @@ -180,6 +198,7 @@ function test_like_7() do_check_true(solutions.indexOf(stmt.getString(0)) != -1); do_check_false(stmt.executeStep()); stmt.reset(); + stmt.finalize(); } function test_like_8() @@ -192,6 +211,7 @@ function test_like_8() do_check_true(solutions.indexOf(stmt.getString(0)) != -1); do_check_false(stmt.executeStep()); stmt.reset(); + stmt.finalize(); } var tests = [test_count, test_like_1, test_like_2, test_like_3, test_like_4, diff --git a/storage/test/unit/test_like_escape.js b/storage/test/unit/test_like_escape.js index 96e8c22755bb..c1dfa5455520 100644 --- a/storage/test/unit/test_like_escape.js +++ b/storage/test/unit/test_like_escape.js @@ -44,11 +44,13 @@ function setup() var stmt = createStatement("INSERT INTO t1 (x) VALUES ('foo/bar_baz%20cheese')"); stmt.execute(); + stmt.finalize(); stmt = createStatement("INSERT INTO t1 (x) VALUES (?1)"); // insert LATIN_ae, but search on LATIN_AE stmt.bindStringParameter(0, "foo%20" + LATIN1_ae + "/_bar"); stmt.execute(); + stmt.finalize(); } function test_escape_for_like_ascii() @@ -61,6 +63,7 @@ function test_escape_for_like_ascii() stmt.bindStringParameter(0, "%" + paramForLike + "%"); stmt.executeStep(); do_check_eq("foo/bar_baz%20cheese", stmt.getString(0)); + stmt.finalize(); } function test_escape_for_like_non_ascii() @@ -73,6 +76,7 @@ function test_escape_for_like_non_ascii() stmt.bindStringParameter(0, "%" + paramForLike + "%"); stmt.executeStep(); do_check_eq("foo%20" + LATIN1_ae + "/_bar", stmt.getString(0)); + stmt.finalize(); } var tests = [test_escape_for_like_ascii, test_escape_for_like_non_ascii]; diff --git a/storage/test/unit/test_storage_aggregates.js b/storage/test/unit/test_storage_aggregates.js index 5ca2515895b5..84993dfce842 100644 --- a/storage/test/unit/test_storage_aggregates.js +++ b/storage/test/unit/test_storage_aggregates.js @@ -48,6 +48,7 @@ function setup() stmt.execute(); } stmt.reset(); + stmt.finalize(); } var testSquareAndSumFunction = { @@ -113,6 +114,7 @@ function test_aggregate_call() while(stmt.executeStep()); do_check_eq(testNums.length, testSquareAndSumFunction.calls); testSquareAndSumFunction.reset(); + stmt.finalize(); } function test_aggregate_result() @@ -125,6 +127,7 @@ function test_aggregate_result() stmt.executeStep(); do_check_eq(sas, stmt.getInt32(0)); testSquareAndSumFunction.reset(); + stmt.finalize(); } var tests = [test_aggregate_registration, test_aggregate_no_double_registration, diff --git a/storage/test/unit/test_storage_function.js b/storage/test/unit/test_storage_function.js index 1395205ddc1c..9634582255ce 100644 --- a/storage/test/unit/test_storage_function.js +++ b/storage/test/unit/test_storage_function.js @@ -48,6 +48,7 @@ function setup() stmt.execute(); } stmt.reset(); + stmt.finalize(); } var testSquareFunction = { @@ -96,6 +97,7 @@ function test_function_call() while(stmt.executeStep()); do_check_eq(testNums.length, testSquareFunction.calls); testSquareFunction.calls = 0; + stmt.finalize(); } function test_function_result() @@ -104,6 +106,7 @@ function test_function_result() stmt.executeStep(); do_check_eq(42*42, stmt.getInt32(0)); testSquareFunction.calls = 0; + stmt.finalize(); } var tests = [test_function_registration, test_function_no_double_registration, diff --git a/storage/test/unit/test_storage_progresshandler.js b/storage/test/unit/test_storage_progresshandler.js index 93ea3bce72a7..a8ff12697b21 100644 --- a/storage/test/unit/test_storage_progresshandler.js +++ b/storage/test/unit/test_storage_progresshandler.js @@ -50,6 +50,7 @@ function setup() } stmt.reset(); msc.commitTransaction(); + stmt.finalize(); } var testProgressHandler = { @@ -92,6 +93,7 @@ function test_handler_call() "SELECT SUM(t1.num * t2.num) FROM handler_tests AS t1, handler_tests AS t2"); while(stmt.executeStep()); do_check_true(testProgressHandler.calls > 0); + stmt.finalize(); } function test_handler_abort() @@ -102,13 +104,22 @@ function test_handler_abort() // Some long-executing request var stmt = createStatement( "SELECT SUM(t1.num * t2.num) FROM handler_tests AS t1, handler_tests AS t2"); + + const SQLITE_INTERRUPT = 9; try { while(stmt.executeStep()); do_throw("We shouldn't get here!"); } catch (e) { do_check_eq(Cr.NS_ERROR_ABORT, e.result); - // Magic value: SQLITE_INTERRUPT - do_check_eq(msc.lastError, 9); + do_check_eq(SQLITE_INTERRUPT, msc.lastError); + } + try { + stmt.finalize(); + do_throw("We shouldn't get here!"); + } catch (e) { + // finalize should return the error code since we encountered an error + do_check_eq(Cr.NS_ERROR_ABORT, e.result); + do_check_eq(SQLITE_INTERRUPT, msc.lastError); } } diff --git a/storage/test/unit/test_storage_statement.js b/storage/test/unit/test_storage_statement.js index 7a1b46eb4945..651c7137fde5 100644 --- a/storage/test/unit/test_storage_statement.js +++ b/storage/test/unit/test_storage_statement.js @@ -46,18 +46,24 @@ function test_parameterCount_none() { var stmt = createStatement("SELECT * FROM test"); do_check_eq(0, stmt.parameterCount); + stmt.reset(); + stmt.finalize(); } function test_parameterCount_one() { var stmt = createStatement("SELECT * FROM test WHERE id = ?1"); do_check_eq(1, stmt.parameterCount); + stmt.reset(); + stmt.finalize(); } function test_getParameterName() { var stmt = createStatement("SELECT * FROM test WHERE id = :id"); do_check_eq(":id", stmt.getParameterName(0)); + stmt.reset(); + stmt.finalize(); } function test_getParameterIndex_different() @@ -65,18 +71,24 @@ function test_getParameterIndex_different() var stmt = createStatement("SELECT * FROM test WHERE id = :id OR name = :name"); do_check_eq(0, stmt.getParameterIndex(":id")); do_check_eq(1, stmt.getParameterIndex(":name")); + stmt.reset(); + stmt.finalize(); } function test_getParameterIndex_same() { var stmt = createStatement("SELECT * FROM test WHERE id = @test OR name = @test"); do_check_eq(0, stmt.getParameterIndex("@test")); + stmt.reset(); + stmt.finalize(); } function test_columnCount() { var stmt = createStatement("SELECT * FROM test WHERE id = ?1 OR name = ?2"); do_check_eq(2, stmt.columnCount); + stmt.reset(); + stmt.finalize(); } function test_getColumnName() @@ -84,6 +96,8 @@ function test_getColumnName() var stmt = createStatement("SELECT name, id FROM test"); do_check_eq("id", stmt.getColumnName(1)); do_check_eq("name", stmt.getColumnName(0)); + stmt.reset(); + stmt.finalize(); } function test_getColumnIndex_same_case() @@ -91,6 +105,8 @@ function test_getColumnIndex_same_case() var stmt = createStatement("SELECT name, id FROM test"); do_check_eq(0, stmt.getColumnIndex("name")); do_check_eq(1, stmt.getColumnIndex("id")); + stmt.reset(); + stmt.finalize(); } function test_getColumnIndex_different_case() @@ -108,12 +124,16 @@ function test_getColumnIndex_different_case() } catch (e) { do_check_eq(Cr.NS_ERROR_INVALID_ARG, e.result); } + stmt.reset(); + stmt.finalize(); } function test_state_ready() { var stmt = createStatement("SELECT name, id FROM test"); do_check_eq(Ci.mozIStorageStatement.MOZ_STORAGE_STATEMENT_READY, stmt.state); + stmt.reset(); + stmt.finalize(); } function test_state_executing() @@ -121,6 +141,7 @@ function test_state_executing() var stmt = createStatement("INSERT INTO test (name) VALUES ('foo')"); stmt.execute(); stmt.execute(); + stmt.finalize(); stmt = createStatement("SELECT name, id FROM test"); stmt.executeStep(); @@ -131,6 +152,15 @@ function test_state_executing() stmt.state); stmt.reset(); do_check_eq(Ci.mozIStorageStatement.MOZ_STORAGE_STATEMENT_READY, stmt.state); + stmt.finalize(); +} + +function test_state_after_finalize() +{ + var stmt = createStatement("SELECT name, id FROM test"); + stmt.executeStep(); + stmt.finalize(); + do_check_eq(Ci.mozIStorageStatement.MOZ_STORAGE_STATEMENT_INVALID, stmt.state); } var tests = [test_parameterCount_none, test_parameterCount_one, @@ -138,7 +168,7 @@ var tests = [test_parameterCount_none, test_parameterCount_one, test_getParameterIndex_same, test_columnCount, test_getColumnName, test_getColumnIndex_same_case, test_getColumnIndex_different_case, test_state_ready, - test_state_executing]; + test_state_executing, test_state_after_finalize]; function run_test() { diff --git a/storage/test/unit/test_storage_statement_wrapper.js b/storage/test/unit/test_storage_statement_wrapper.js index 7094149cfdff..86499659758e 100644 --- a/storage/test/unit/test_storage_statement_wrapper.js +++ b/storage/test/unit/test_storage_statement_wrapper.js @@ -59,16 +59,19 @@ function test_binding_params() const name = "foo"; stmt.params.name = name; stmt.execute(); + stmt.statement.finalize(); stmt = createStatement("SELECT COUNT(*) AS number FROM test"); do_check_true(stmt.step()); do_check_eq(1, stmt.row.number); stmt.reset(); + stmt.statement.finalize(); stmt = createStatement("SELECT name FROM test WHERE id = 1"); do_check_true(stmt.step()); do_check_eq(name, stmt.row.name); stmt.reset(); + stmt.statement.finalize(); } function test_binding_multiple_params() @@ -78,17 +81,20 @@ function test_binding_multiple_params() const name = "me"; stmt.params.name = name; stmt.execute(); + stmt.statement.finalize(); stmt = createStatement("SELECT COUNT(*) AS number FROM test"); do_check_true(stmt.step()); do_check_eq(2, stmt.row.number); stmt.reset(); + stmt.statement.finalize(); stmt = createStatement("SELECT name, alt_name FROM test WHERE id = 2"); do_check_true(stmt.step()); do_check_eq(name, stmt.row.name); do_check_eq(name, stmt.row.alt_name); stmt.reset(); + stmt.statement.finalize(); } var tests = [test_binding_params, test_binding_multiple_params]; diff --git a/storage/test/unit/test_storage_value_array.js b/storage/test/unit/test_storage_value_array.js index 14c3edfa1e8c..672e7e2da9ba 100644 --- a/storage/test/unit/test_storage_value_array.js +++ b/storage/test/unit/test_storage_value_array.js @@ -55,6 +55,7 @@ function setup() stmt.execute(); stmt.reset(); + stmt.finalize(); } function test_getIsNull_for_null() @@ -66,6 +67,7 @@ function test_getIsNull_for_null() do_check_true(stmt.getIsNull(0)); // null field do_check_true(stmt.getIsNull(1)); // data is null if size is 0 stmt.reset(); + stmt.finalize(); } function test_getIsNull_for_non_null() @@ -77,6 +79,7 @@ function test_getIsNull_for_non_null() do_check_false(stmt.getIsNull(0)); do_check_false(stmt.getIsNull(1)); stmt.reset(); + stmt.finalize(); } function test_value_type_null() @@ -88,6 +91,7 @@ function test_value_type_null() do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_NULL, stmt.getTypeOfIndex(0)); stmt.reset(); + stmt.finalize(); } function test_value_type_integer() @@ -99,6 +103,7 @@ function test_value_type_integer() do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER, stmt.getTypeOfIndex(0)); stmt.reset(); + stmt.finalize(); } function test_value_type_float() @@ -110,6 +115,7 @@ function test_value_type_float() do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT, stmt.getTypeOfIndex(0)); stmt.reset(); + stmt.finalize(); } function test_value_type_text() @@ -121,6 +127,7 @@ function test_value_type_text() do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_TEXT, stmt.getTypeOfIndex(0)); stmt.reset(); + stmt.finalize(); } function test_value_type_blob() @@ -132,6 +139,7 @@ function test_value_type_blob() do_check_eq(Ci.mozIStorageValueArray.VALUE_TYPE_BLOB, stmt.getTypeOfIndex(0)); stmt.reset(); + stmt.finalize(); } function test_numEntries_one() @@ -142,6 +150,7 @@ function test_numEntries_one() do_check_eq(1, stmt.numEntries); stmt.reset(); + stmt.finalize(); } function test_numEntries_all() @@ -152,6 +161,7 @@ function test_numEntries_all() do_check_eq(5, stmt.numEntries); stmt.reset(); + stmt.finalize(); } function test_getInt() @@ -163,6 +173,7 @@ function test_getInt() do_check_eq(2, stmt.getInt32(0)); do_check_eq(2, stmt.getInt64(0)); stmt.reset(); + stmt.finalize(); } function test_getDouble() @@ -173,6 +184,7 @@ function test_getDouble() do_check_eq(1.23, stmt.getDouble(0)); stmt.reset(); + stmt.finalize(); } function test_getUTF8String() @@ -183,6 +195,7 @@ function test_getUTF8String() do_check_eq("foo", stmt.getUTF8String(0)); stmt.reset(); + stmt.finalize(); } function test_getString() @@ -193,6 +206,7 @@ function test_getString() do_check_eq("", stmt.getString(0)); stmt.reset(); + stmt.finalize(); } function test_getBlob() @@ -208,6 +222,7 @@ function test_getBlob() do_check_eq(1, arr.value[0]); do_check_eq(2, arr.value[1]); stmt.reset(); + stmt.finalize(); } var tests = [test_getIsNull_for_null, test_getIsNull_for_non_null, diff --git a/storage/test/unit/test_unicode.js b/storage/test/unit/test_unicode.js index 889782c20b3e..003e748a09ad 100644 --- a/storage/test/unit/test_unicode.js +++ b/storage/test/unit/test_unicode.js @@ -57,6 +57,7 @@ function setup() stmt.bindStringParameter(0, LATIN1_ae); stmt.bindInt32Parameter(1, 4); stmt.execute(); + stmt.finalize(); } function test_upper_ascii() @@ -66,6 +67,7 @@ function test_upper_ascii() do_check_eq("A", stmt.getString(0)); do_check_eq(2, stmt.getInt32(1)); stmt.reset(); + stmt.finalize(); } function test_upper_non_ascii() @@ -76,6 +78,7 @@ function test_upper_non_ascii() do_check_eq(LATIN1_AE, stmt.getString(0)); do_check_eq(1, stmt.getInt32(1)); stmt.reset(); + stmt.finalize(); } function test_lower_ascii() @@ -85,6 +88,7 @@ function test_lower_ascii() do_check_eq("b", stmt.getString(0)); do_check_eq(3, stmt.getInt32(1)); stmt.reset(); + stmt.finalize(); } function test_lower_non_ascii() @@ -95,6 +99,7 @@ function test_lower_non_ascii() do_check_eq(LATIN1_ae, stmt.getString(0)); do_check_eq(4, stmt.getInt32(1)); stmt.reset(); + stmt.finalize(); } function test_like_search_different() @@ -103,6 +108,7 @@ function test_like_search_different() stmt.bindStringParameter(0, LATIN1_AE); do_check_true(stmt.executeStep()); do_check_eq(2, stmt.getInt32(0)); + stmt.finalize(); } function test_like_search_same() @@ -111,6 +117,7 @@ function test_like_search_same() stmt.bindStringParameter(0, LATIN1_ae); do_check_true(stmt.executeStep()); do_check_eq(2, stmt.getInt32(0)); + stmt.finalize(); } var tests = [test_upper_ascii, test_upper_non_ascii, test_lower_ascii,