зеркало из https://github.com/mozilla/gecko-dev.git
Bug 658135 - Use sqlite3_stmt_readonly to check if multiple async statements need a transaction.
r=sdwilsh
This commit is contained in:
Родитель
1e67f54266
Коммит
50b71d031b
|
@ -155,6 +155,7 @@ EXPORTS
|
|||
sqlite3_sql
|
||||
sqlite3_status
|
||||
sqlite3_step
|
||||
sqlite3_stmt_readonly
|
||||
sqlite3_stmt_status
|
||||
sqlite3_thread_cleanup
|
||||
sqlite3_total_changes
|
||||
|
|
|
@ -534,6 +534,21 @@ NS_IMPL_THREADSAFE_ISUPPORTS2(
|
|||
mozIStoragePendingStatement
|
||||
)
|
||||
|
||||
bool
|
||||
AsyncExecuteStatements::statementsNeedTransaction()
|
||||
{
|
||||
// If there is more than one write statement, run in a transaction.
|
||||
// Additionally, if we have only one statement but it needs a transaction, due
|
||||
// to multiple BindingParams, we will wrap it in one.
|
||||
for (PRUint32 i = 0, transactionsCount = 0; i < mStatements.Length(); ++i) {
|
||||
transactionsCount += mStatements[i].needsTransaction();
|
||||
if (transactionsCount > 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// mozIStoragePendingStatement
|
||||
|
||||
|
@ -575,13 +590,7 @@ AsyncExecuteStatements::Run()
|
|||
if (mState == CANCELED)
|
||||
return notifyComplete();
|
||||
|
||||
// If there is more than one statement, run it in a transaction. We assume
|
||||
// that we have been given write statements since getting a batch of read
|
||||
// statements doesn't make a whole lot of sense.
|
||||
// Additionally, if we have only one statement and it needs a transaction, we
|
||||
// will wrap it in one.
|
||||
if (mStatements.Length() > 1 || mStatements[0].needsTransaction()) {
|
||||
// We don't error if this failed because it's not terrible if it does.
|
||||
if (statementsNeedTransaction()) {
|
||||
mTransactionManager = new mozStorageTransaction(mConnection, PR_FALSE,
|
||||
mozIStorageConnection::TRANSACTION_IMMEDIATE);
|
||||
}
|
||||
|
|
|
@ -201,6 +201,14 @@ private:
|
|||
*/
|
||||
nsresult notifyResults();
|
||||
|
||||
/**
|
||||
* Tests whether the current statements should be wrapped in an explicit
|
||||
* transaction.
|
||||
*
|
||||
* @return true if an explicit transaction is needed, false otherwise.
|
||||
*/
|
||||
bool statementsNeedTransaction();
|
||||
|
||||
StatementDataArray mStatements;
|
||||
nsRefPtr<Connection> mConnection;
|
||||
mozStorageTransaction *mTransactionManager;
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#include "mozilla/Mutex.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "mozIStorageProgressHandler.h"
|
||||
#include "SQLiteMutex.h"
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#include "nsAutoPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIEventTarget.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "mozStorageBindingParamsArray.h"
|
||||
#include "mozIStorageBaseStatement.h"
|
||||
|
@ -143,13 +145,27 @@ public:
|
|||
*/
|
||||
inline bool hasParametersToBeBound() const { return !!mParamsArray; }
|
||||
/**
|
||||
* Indicates if this statement needs a transaction for execution.
|
||||
* Indicates the number of implicit statements generated by this statement
|
||||
* requiring a transaction for execution. For example a single statement
|
||||
* with N BindingParams will execute N implicit staments.
|
||||
*
|
||||
* @return true if the statement needs a transaction, false otherwise.
|
||||
* @return number of statements requiring a transaction for execution.
|
||||
*
|
||||
* @note In the case of AsyncStatements this may actually create the
|
||||
* statement.
|
||||
*/
|
||||
inline bool needsTransaction() const
|
||||
inline PRUint32 needsTransaction()
|
||||
{
|
||||
return mParamsArray != nsnull && mParamsArray->length() > 1;
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
// Be sure to use the getSqliteStatement helper, since sqlite3_stmt_readonly
|
||||
// can only analyze prepared statements and AsyncStatements are prepared
|
||||
// lazily.
|
||||
sqlite3_stmt *stmt;
|
||||
int rc = getSqliteStatement(&stmt);
|
||||
if (SQLITE_OK != rc || ::sqlite3_stmt_readonly(stmt)) {
|
||||
return 0;
|
||||
}
|
||||
return mParamsArray ? mParamsArray->length() : 1;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -61,6 +61,7 @@ CPP_UNIT_TESTS = \
|
|||
test_StatementCache.cpp \
|
||||
test_async_callbacks_with_spun_event_loops.cpp \
|
||||
test_file_perms.cpp \
|
||||
test_asyncStatementExecution_transaction.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_DEBUG
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "mozIStorageAsyncStatement.h"
|
||||
#include "mozIStorageStatement.h"
|
||||
#include "mozIStoragePendingStatement.h"
|
||||
#include "mozIStorageError.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
static int gTotalTests = 0;
|
||||
|
@ -176,6 +177,20 @@ AsyncStatementSpinner::HandleResult(mozIStorageResultSet *aResultSet)
|
|||
NS_IMETHODIMP
|
||||
AsyncStatementSpinner::HandleError(mozIStorageError *aError)
|
||||
{
|
||||
PRInt32 result;
|
||||
nsresult rv = aError->GetResult(&result);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCAutoString message;
|
||||
rv = aError->GetMessage(message);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString warnMsg;
|
||||
warnMsg.Append("An error occurred while executing an async statement: ");
|
||||
warnMsg.AppendInt(result);
|
||||
warnMsg.Append(" ");
|
||||
warnMsg.Append(message);
|
||||
NS_WARNING(warnMsg.get());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -206,3 +221,33 @@ void AsyncStatementSpinner::SpinUntilCompleted()
|
|||
|
||||
#define NS_DECL_ASYNCSTATEMENTSPINNER \
|
||||
NS_IMETHOD HandleResult(mozIStorageResultSet *aResultSet);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Async Helpers
|
||||
|
||||
/**
|
||||
* Execute an async statement, blocking the main thread until we get the
|
||||
* callback completion notification.
|
||||
*/
|
||||
void
|
||||
blocking_async_execute(mozIStorageBaseStatement *stmt)
|
||||
{
|
||||
nsRefPtr<AsyncStatementSpinner> spinner(new AsyncStatementSpinner());
|
||||
|
||||
nsCOMPtr<mozIStoragePendingStatement> pendy;
|
||||
(void)stmt->ExecuteAsync(spinner, getter_AddRefs(pendy));
|
||||
spinner->SpinUntilCompleted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke AsyncClose on the given connection, blocking the main thread until we
|
||||
* get the completion notification.
|
||||
*/
|
||||
void
|
||||
blocking_async_close(mozIStorageConnection *db)
|
||||
{
|
||||
nsRefPtr<AsyncStatementSpinner> spinner(new AsyncStatementSpinner());
|
||||
|
||||
db->AsyncClose(spinner);
|
||||
spinner->SpinUntilCompleted();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,508 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
#include "storage_test_harness.h"
|
||||
|
||||
#include "nsIEventTarget.h"
|
||||
#include "mozStorageConnection.h"
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
using namespace mozilla::storage;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Helpers
|
||||
|
||||
/**
|
||||
* Commit hook to detect transactions.
|
||||
*
|
||||
* @param aArg
|
||||
* An integer pointer that will be incremented for each commit.
|
||||
*/
|
||||
int commit_hook(void *aArg)
|
||||
{
|
||||
int *arg = static_cast<int *>(aArg);
|
||||
(*arg)++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the passed-in statements and checks if a transaction is created.
|
||||
* When done statements are finalized and database connection is closed.
|
||||
*
|
||||
* @param aDB
|
||||
* The database connection.
|
||||
* @param aStmts
|
||||
* Vector of statements.
|
||||
* @param aStmtsLen
|
||||
* Number of statements.
|
||||
* @param aTransactionExpected
|
||||
* Whether a transaction is expected or not.
|
||||
*/
|
||||
void
|
||||
check_transaction(mozIStorageConnection *aDB,
|
||||
mozIStorageBaseStatement **aStmts,
|
||||
PRUint32 aStmtsLen,
|
||||
bool aTransactionExpected)
|
||||
{
|
||||
// -- install a transaction commit hook.
|
||||
int commit = 0;
|
||||
::sqlite3_commit_hook(*static_cast<Connection *>(aDB), commit_hook, &commit);
|
||||
|
||||
nsRefPtr<AsyncStatementSpinner> asyncSpin(new AsyncStatementSpinner());
|
||||
nsCOMPtr<mozIStoragePendingStatement> asyncPend;
|
||||
do_check_success(aDB->ExecuteAsync(aStmts, aStmtsLen, asyncSpin,
|
||||
getter_AddRefs(asyncPend)));
|
||||
do_check_true(asyncPend);
|
||||
|
||||
// -- complete the execution
|
||||
asyncSpin->SpinUntilCompleted();
|
||||
|
||||
// -- uninstall the transaction commit hook.
|
||||
::sqlite3_commit_hook(*static_cast<Connection *>(aDB), NULL, NULL);
|
||||
|
||||
// -- check transaction
|
||||
do_check_eq(aTransactionExpected, !!commit);
|
||||
|
||||
// -- check that only one transaction was created.
|
||||
if (aTransactionExpected) {
|
||||
do_check_eq(1, commit);
|
||||
}
|
||||
|
||||
// -- cleanup
|
||||
for (PRUint32 i = 0; i < aStmtsLen; ++i) {
|
||||
aStmts[i]->Finalize();
|
||||
}
|
||||
blocking_async_close(aDB);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Tests
|
||||
|
||||
/**
|
||||
* Test that executing multiple readonly AsyncStatements doesn't create a
|
||||
* transaction.
|
||||
*/
|
||||
void
|
||||
test_MultipleAsyncReadStatements()
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
|
||||
|
||||
// -- create statements and execute them
|
||||
nsCOMPtr<mozIStorageAsyncStatement> stmt1;
|
||||
db->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT * FROM sqlite_master"
|
||||
), getter_AddRefs(stmt1));
|
||||
|
||||
nsCOMPtr<mozIStorageAsyncStatement> stmt2;
|
||||
db->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT * FROM sqlite_master"
|
||||
), getter_AddRefs(stmt2));
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
stmt1,
|
||||
stmt2,
|
||||
};
|
||||
|
||||
check_transaction(db, stmts, NS_ARRAY_LENGTH(stmts), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that executing multiple readonly Statements doesn't create a
|
||||
* transaction.
|
||||
*/
|
||||
void
|
||||
test_MultipleReadStatements()
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
|
||||
|
||||
// -- create statements and execute them
|
||||
nsCOMPtr<mozIStorageStatement> stmt1;
|
||||
db->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT * FROM sqlite_master"
|
||||
), getter_AddRefs(stmt1));
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt2;
|
||||
db->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT * FROM sqlite_master"
|
||||
), getter_AddRefs(stmt2));
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
stmt1,
|
||||
stmt2,
|
||||
};
|
||||
|
||||
check_transaction(db, stmts, NS_ARRAY_LENGTH(stmts), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that executing multiple AsyncStatements causing writes creates a
|
||||
* transaction.
|
||||
*/
|
||||
void
|
||||
test_MultipleAsyncReadWriteStatements()
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
|
||||
|
||||
// -- create statements and execute them
|
||||
nsCOMPtr<mozIStorageAsyncStatement> stmt1;
|
||||
db->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT * FROM sqlite_master"
|
||||
), getter_AddRefs(stmt1));
|
||||
|
||||
nsCOMPtr<mozIStorageAsyncStatement> stmt2;
|
||||
db->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE test (id INTEGER PRIMARY KEY)"
|
||||
), getter_AddRefs(stmt2));
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
stmt1,
|
||||
stmt2,
|
||||
};
|
||||
|
||||
check_transaction(db, stmts, NS_ARRAY_LENGTH(stmts), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that executing multiple Statements causing writes creates a transaction.
|
||||
*/
|
||||
void
|
||||
test_MultipleReadWriteStatements()
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
|
||||
|
||||
// -- create statements and execute them
|
||||
nsCOMPtr<mozIStorageStatement> stmt1;
|
||||
db->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT * FROM sqlite_master"
|
||||
), getter_AddRefs(stmt1));
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt2;
|
||||
db->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE test (id INTEGER PRIMARY KEY)"
|
||||
), getter_AddRefs(stmt2));
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
stmt1,
|
||||
stmt2,
|
||||
};
|
||||
|
||||
check_transaction(db, stmts, NS_ARRAY_LENGTH(stmts), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that executing multiple AsyncStatements causing writes creates a
|
||||
* single transaction.
|
||||
*/
|
||||
void
|
||||
test_MultipleAsyncWriteStatements()
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
|
||||
|
||||
// -- create statements and execute them
|
||||
nsCOMPtr<mozIStorageAsyncStatement> stmt1;
|
||||
db->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE test1 (id INTEGER PRIMARY KEY)"
|
||||
), getter_AddRefs(stmt1));
|
||||
|
||||
nsCOMPtr<mozIStorageAsyncStatement> stmt2;
|
||||
db->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE test2 (id INTEGER PRIMARY KEY)"
|
||||
), getter_AddRefs(stmt2));
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
stmt1,
|
||||
stmt2,
|
||||
};
|
||||
|
||||
check_transaction(db, stmts, NS_ARRAY_LENGTH(stmts), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that executing multiple Statements causing writes creates a
|
||||
* single transaction.
|
||||
*/
|
||||
void
|
||||
test_MultipleWriteStatements()
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
|
||||
|
||||
// -- create statements and execute them
|
||||
nsCOMPtr<mozIStorageStatement> stmt1;
|
||||
db->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE test1 (id INTEGER PRIMARY KEY)"
|
||||
), getter_AddRefs(stmt1));
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> stmt2;
|
||||
db->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE test2 (id INTEGER PRIMARY KEY)"
|
||||
), getter_AddRefs(stmt2));
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
stmt1,
|
||||
stmt2,
|
||||
};
|
||||
|
||||
check_transaction(db, stmts, NS_ARRAY_LENGTH(stmts), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that executing a single read-only AsyncStatement doesn't create a
|
||||
* transaction.
|
||||
*/
|
||||
void
|
||||
test_SingleAsyncReadStatement()
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
|
||||
|
||||
// -- create statements and execute them
|
||||
nsCOMPtr<mozIStorageAsyncStatement> stmt;
|
||||
db->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT * FROM sqlite_master"
|
||||
), getter_AddRefs(stmt));
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
stmt,
|
||||
};
|
||||
|
||||
check_transaction(db, stmts, NS_ARRAY_LENGTH(stmts), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that executing a single read-only Statement doesn't create a
|
||||
* transaction.
|
||||
*/
|
||||
void
|
||||
test_SingleReadStatement()
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
|
||||
|
||||
// -- create statements and execute them
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
db->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT * FROM sqlite_master"
|
||||
), getter_AddRefs(stmt));
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
stmt,
|
||||
};
|
||||
|
||||
check_transaction(db, stmts, NS_ARRAY_LENGTH(stmts), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that executing a single AsyncStatement causing writes creates a
|
||||
* transaction.
|
||||
*/
|
||||
void
|
||||
test_SingleAsyncWriteStatement()
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
|
||||
|
||||
// -- create statements and execute them
|
||||
nsCOMPtr<mozIStorageAsyncStatement> stmt;
|
||||
db->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE test (id INTEGER PRIMARY KEY)"
|
||||
), getter_AddRefs(stmt));
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
stmt,
|
||||
};
|
||||
|
||||
check_transaction(db, stmts, NS_ARRAY_LENGTH(stmts), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that executing a single Statement causing writes creates a transaction.
|
||||
*/
|
||||
void
|
||||
test_SingleWriteStatement()
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
|
||||
|
||||
// -- create statements and execute them
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
db->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE test (id INTEGER PRIMARY KEY)"
|
||||
), getter_AddRefs(stmt));
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
stmt,
|
||||
};
|
||||
|
||||
check_transaction(db, stmts, NS_ARRAY_LENGTH(stmts), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that executing a single read-only AsyncStatement with multiple params
|
||||
* doesn't create a transaction.
|
||||
*/
|
||||
void
|
||||
test_MultipleParamsAsyncReadStatement()
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
|
||||
|
||||
// -- create statements and execute them
|
||||
nsCOMPtr<mozIStorageAsyncStatement> stmt;
|
||||
db->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT :param FROM sqlite_master"
|
||||
), getter_AddRefs(stmt));
|
||||
|
||||
// -- bind multiple BindingParams
|
||||
nsCOMPtr<mozIStorageBindingParamsArray> paramsArray;
|
||||
stmt->NewBindingParamsArray(getter_AddRefs(paramsArray));
|
||||
for (PRInt32 i = 0; i < 2; i++) {
|
||||
nsCOMPtr<mozIStorageBindingParams> params;
|
||||
paramsArray->NewBindingParams(getter_AddRefs(params));
|
||||
params->BindInt32ByName(NS_LITERAL_CSTRING("param"), 1);
|
||||
paramsArray->AddParams(params);
|
||||
}
|
||||
stmt->BindParameters(paramsArray);
|
||||
paramsArray = nsnull;
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
stmt,
|
||||
};
|
||||
|
||||
check_transaction(db, stmts, NS_ARRAY_LENGTH(stmts), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that executing a single read-only Statement with multiple params
|
||||
* doesn't create a transaction.
|
||||
*/
|
||||
void
|
||||
test_MultipleParamsReadStatement()
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
|
||||
|
||||
// -- create statements and execute them
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
db->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT :param FROM sqlite_master"
|
||||
), getter_AddRefs(stmt));
|
||||
|
||||
// -- bind multiple BindingParams
|
||||
nsCOMPtr<mozIStorageBindingParamsArray> paramsArray;
|
||||
stmt->NewBindingParamsArray(getter_AddRefs(paramsArray));
|
||||
for (PRInt32 i = 0; i < 2; i++) {
|
||||
nsCOMPtr<mozIStorageBindingParams> params;
|
||||
paramsArray->NewBindingParams(getter_AddRefs(params));
|
||||
params->BindInt32ByName(NS_LITERAL_CSTRING("param"), 1);
|
||||
paramsArray->AddParams(params);
|
||||
}
|
||||
stmt->BindParameters(paramsArray);
|
||||
paramsArray = nsnull;
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
stmt,
|
||||
};
|
||||
|
||||
check_transaction(db, stmts, NS_ARRAY_LENGTH(stmts), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that executing a single write AsyncStatement with multiple params
|
||||
* creates a transaction.
|
||||
*/
|
||||
void
|
||||
test_MultipleParamsAsyncWriteStatement()
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
|
||||
|
||||
// -- create a table for writes
|
||||
nsCOMPtr<mozIStorageStatement> tableStmt;
|
||||
db->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE test (id INTEGER PRIMARY KEY)"
|
||||
), getter_AddRefs(tableStmt));
|
||||
tableStmt->Execute();
|
||||
tableStmt->Finalize();
|
||||
|
||||
// -- create statements and execute them
|
||||
nsCOMPtr<mozIStorageAsyncStatement> stmt;
|
||||
db->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"DELETE FROM test WHERE id = :param"
|
||||
), getter_AddRefs(stmt));
|
||||
|
||||
// -- bind multiple BindingParams
|
||||
nsCOMPtr<mozIStorageBindingParamsArray> paramsArray;
|
||||
stmt->NewBindingParamsArray(getter_AddRefs(paramsArray));
|
||||
for (PRInt32 i = 0; i < 2; i++) {
|
||||
nsCOMPtr<mozIStorageBindingParams> params;
|
||||
paramsArray->NewBindingParams(getter_AddRefs(params));
|
||||
params->BindInt32ByName(NS_LITERAL_CSTRING("param"), 1);
|
||||
paramsArray->AddParams(params);
|
||||
}
|
||||
stmt->BindParameters(paramsArray);
|
||||
paramsArray = nsnull;
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
stmt,
|
||||
};
|
||||
|
||||
check_transaction(db, stmts, NS_ARRAY_LENGTH(stmts), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that executing a single write Statement with multiple params
|
||||
* creates a transaction.
|
||||
*/
|
||||
void
|
||||
test_MultipleParamsWriteStatement()
|
||||
{
|
||||
nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
|
||||
|
||||
// -- create a table for writes
|
||||
nsCOMPtr<mozIStorageStatement> tableStmt;
|
||||
db->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"CREATE TABLE test (id INTEGER PRIMARY KEY)"
|
||||
), getter_AddRefs(tableStmt));
|
||||
tableStmt->Execute();
|
||||
tableStmt->Finalize();
|
||||
|
||||
// -- create statements and execute them
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
db->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"DELETE FROM test WHERE id = :param"
|
||||
), getter_AddRefs(stmt));
|
||||
|
||||
// -- bind multiple BindingParams
|
||||
nsCOMPtr<mozIStorageBindingParamsArray> paramsArray;
|
||||
stmt->NewBindingParamsArray(getter_AddRefs(paramsArray));
|
||||
for (PRInt32 i = 0; i < 2; i++) {
|
||||
nsCOMPtr<mozIStorageBindingParams> params;
|
||||
paramsArray->NewBindingParams(getter_AddRefs(params));
|
||||
params->BindInt32ByName(NS_LITERAL_CSTRING("param"), 1);
|
||||
paramsArray->AddParams(params);
|
||||
}
|
||||
stmt->BindParameters(paramsArray);
|
||||
paramsArray = nsnull;
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
stmt,
|
||||
};
|
||||
|
||||
check_transaction(db, stmts, NS_ARRAY_LENGTH(stmts), true);
|
||||
}
|
||||
|
||||
void (*gTests[])(void) = {
|
||||
test_MultipleAsyncReadStatements,
|
||||
test_MultipleReadStatements,
|
||||
test_MultipleAsyncReadWriteStatements,
|
||||
test_MultipleReadWriteStatements,
|
||||
test_MultipleAsyncWriteStatements,
|
||||
test_MultipleWriteStatements,
|
||||
test_SingleAsyncReadStatement,
|
||||
test_SingleReadStatement,
|
||||
test_SingleAsyncWriteStatement,
|
||||
test_SingleWriteStatement,
|
||||
test_MultipleParamsAsyncReadStatement,
|
||||
test_MultipleParamsReadStatement,
|
||||
test_MultipleParamsAsyncWriteStatement,
|
||||
test_MultipleParamsWriteStatement,
|
||||
};
|
||||
|
||||
const char *file = __FILE__;
|
||||
#define TEST_NAME "async statement execution transaction"
|
||||
#define TEST_FILE file
|
||||
#include "storage_test_harness_tail.h"
|
|
@ -11,19 +11,6 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Async Helpers
|
||||
|
||||
/**
|
||||
* Invoke AsyncClose on the given connection, blocking the main thread until we
|
||||
* get the completion notification.
|
||||
*/
|
||||
void
|
||||
blocking_async_close(mozIStorageConnection *db)
|
||||
{
|
||||
nsRefPtr<AsyncStatementSpinner> spinner(new AsyncStatementSpinner());
|
||||
|
||||
db->AsyncClose(spinner);
|
||||
spinner->SpinUntilCompleted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Spins the events loop for current thread until aCondition is true.
|
||||
*/
|
||||
|
|
|
@ -171,33 +171,6 @@ private:
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Async Helpers
|
||||
|
||||
/**
|
||||
* Execute an async statement, blocking the main thread until we get the
|
||||
* callback completion notification.
|
||||
*/
|
||||
void
|
||||
blocking_async_execute(mozIStorageBaseStatement *stmt)
|
||||
{
|
||||
nsRefPtr<AsyncStatementSpinner> spinner(new AsyncStatementSpinner());
|
||||
|
||||
nsCOMPtr<mozIStoragePendingStatement> pendy;
|
||||
(void)stmt->ExecuteAsync(spinner, getter_AddRefs(pendy));
|
||||
spinner->SpinUntilCompleted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke AsyncClose on the given connection, blocking the main thread until we
|
||||
* get the completion notification.
|
||||
*/
|
||||
void
|
||||
blocking_async_close(mozIStorageConnection *db)
|
||||
{
|
||||
nsRefPtr<AsyncStatementSpinner> spinner(new AsyncStatementSpinner());
|
||||
|
||||
db->AsyncClose(spinner);
|
||||
spinner->SpinUntilCompleted();
|
||||
}
|
||||
|
||||
/**
|
||||
* A horrible hack to figure out what the connection's async thread is. By
|
||||
* creating a statement and async dispatching we can tell from the mutex who
|
||||
|
|
|
@ -131,39 +131,6 @@ function test_create_and_add()
|
|||
stmts[1].finalize();
|
||||
}
|
||||
|
||||
function test_transaction_created()
|
||||
{
|
||||
let stmts = [];
|
||||
stmts[0] = getOpenedDatabase().createAsyncStatement(
|
||||
"BEGIN"
|
||||
);
|
||||
stmts[1] = getOpenedDatabase().createStatement(
|
||||
"SELECT * FROM test"
|
||||
);
|
||||
|
||||
getOpenedDatabase().executeAsync(stmts, stmts.length, {
|
||||
handleResult: function(aResultSet)
|
||||
{
|
||||
dump("handleResults("+aResultSet+")\n");
|
||||
do_throw("unexpected results obtained!");
|
||||
},
|
||||
handleError: function(aError)
|
||||
{
|
||||
dump("handleError("+aError.result+")\n");
|
||||
},
|
||||
handleCompletion: function(aReason)
|
||||
{
|
||||
dump("handleCompletion("+aReason+")\n");
|
||||
do_check_eq(Ci.mozIStorageStatementCallback.REASON_ERROR, aReason);
|
||||
|
||||
// Run the next test.
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
stmts[0].finalize();
|
||||
stmts[1].finalize();
|
||||
}
|
||||
|
||||
function test_multiple_bindings_on_statements()
|
||||
{
|
||||
// This tests to make sure that we pass all the statements multiply bound
|
||||
|
@ -309,7 +276,6 @@ function test_double_asyncClose_throws()
|
|||
|
||||
[
|
||||
test_create_and_add,
|
||||
test_transaction_created,
|
||||
test_multiple_bindings_on_statements,
|
||||
test_asyncClose_does_not_complete_before_statements,
|
||||
test_asyncClose_does_not_throw_no_callback,
|
||||
|
|
Загрузка…
Ссылка в новой задаче