NS_IMETHODIMP AsyncExecuteStatements::Run() { // Do not run if we have been canceled. { MutexAutoLock lockedScope(mMutex); if (mCancelRequested) mState = CANCELED; } 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. mTransactionManager = new mozStorageTransaction(mConnection, PR_FALSE, mozIStorageConnection::TRANSACTION_IMMEDIATE); } // Execute each statement, giving the callback results if it returns any. for (PRUint32 i = 0; i < mStatements.Length(); i++) { bool finished = (i == (mStatements.Length() - 1)); // If we have parameters to bind, bind them, execute, and process. if (mStatements[i].hasParametersToBeBound()) { if (!bindExecuteAndProcessStatement(mStatements[i], finished)) break; } // Otherwise, just execute and process the statement. else if (!executeAndProcessStatement(mStatements[i], finished)) { break; } } // If we still have results that we haven't notified about, take care of // them now. if (mResultSet) (void)notifyResults(); // Notify about completion return notifyComplete(); }
bool AsyncExecuteStatements::bindExecuteAndProcessStatement(StatementData &aData, bool aLastStatement) { mMutex.AssertNotCurrentThreadOwns(); sqlite3_stmt *aStatement = nullptr; // This cannot fail; we are only called if it's available. (void)aData.getSqliteStatement(&aStatement); NS_ASSERTION(aStatement, "You broke the code; do not call here like that!"); BindingParamsArray *paramsArray(aData); // Iterate through all of our parameters, bind them, and execute. bool continueProcessing = true; BindingParamsArray::iterator itr = paramsArray->begin(); BindingParamsArray::iterator end = paramsArray->end(); while (itr != end && continueProcessing) { // Bind the data to our statement. nsCOMPtr<IStorageBindingParamsInternal> bindingInternal = do_QueryInterface(*itr); nsCOMPtr<mozIStorageError> error = bindingInternal->bind(aStatement); if (error) { // Set our error state. mState = ERROR; // And notify. (void)notifyError(error); return false; } // Advance our iterator, execute, and then process the statement. itr++; bool lastStatement = aLastStatement && itr == end; continueProcessing = executeAndProcessStatement(aStatement, lastStatement); // Always reset our statement. (void)::sqlite3_reset(aStatement); } return continueProcessing; }
bool AsyncExecuteStatements::bindExecuteAndProcessStatement(StatementData &aData, bool aLastStatement) { mMutex.AssertNotCurrentThreadOwns(); sqlite3_stmt *stmt(aData); BindingParamsArray *paramsArray(aData); // Iterate through all of our parameters, bind them, and execute. bool continueProcessing = true; BindingParamsArray::iterator itr = paramsArray->begin(); BindingParamsArray::iterator end = paramsArray->end(); while (itr != end && continueProcessing) { // Bind the data to our statement. nsCOMPtr<mozIStorageError> error; error = (*itr)->bind(stmt); if (error) { // Set our error state. mState = ERROR; // And notify. (void)notifyError(error); return false; } // Advance our iterator, execute, and then process the statement. itr++; bool lastStatement = aLastStatement && itr == end; continueProcessing = executeAndProcessStatement(stmt, lastStatement); // Always reset our statement. (void)::sqlite3_reset(stmt); } return continueProcessing; }
NS_IMETHODIMP AsyncExecuteStatements::Run() { MOZ_ASSERT(!mConnection->isClosed()); // Do not run if we have been canceled. { MutexAutoLock lockedScope(mMutex); if (mCancelRequested) mState = CANCELED; } if (mState == CANCELED) return notifyComplete(); if (statementsNeedTransaction() && mConnection->getAutocommit()) { if (NS_SUCCEEDED(mConnection->beginTransactionInternal(mNativeConnection, mozIStorageConnection::TRANSACTION_IMMEDIATE))) { mHasTransaction = true; } #ifdef DEBUG else { NS_WARNING("Unable to create a transaction for async execution."); } #endif } // Execute each statement, giving the callback results if it returns any. for (uint32_t i = 0; i < mStatements.Length(); i++) { bool finished = (i == (mStatements.Length() - 1)); sqlite3_stmt *stmt; { // lock the sqlite mutex so sqlite3_errmsg cannot change SQLiteMutexAutoLock lockedScope(mDBMutex); int rc = mStatements[i].getSqliteStatement(&stmt); if (rc != SQLITE_OK) { // Set our error state. mState = ERROR; // Build the error object; can't call notifyError with the lock held nsCOMPtr<mozIStorageError> errorObj( new Error(rc, ::sqlite3_errmsg(mNativeConnection)) ); { // We cannot hold the DB mutex and call notifyError. SQLiteMutexAutoUnlock unlockedScope(mDBMutex); (void)notifyError(errorObj); } break; } } // If we have parameters to bind, bind them, execute, and process. if (mStatements[i].hasParametersToBeBound()) { if (!bindExecuteAndProcessStatement(mStatements[i], finished)) break; } // Otherwise, just execute and process the statement. else if (!executeAndProcessStatement(stmt, finished)) { break; } } // If we still have results that we haven't notified about, take care of // them now. if (mResultSet) (void)notifyResults(); // Notify about completion return notifyComplete(); }
NS_IMETHODIMP AsyncExecuteStatements::Run() { // Do not run if we have been canceled. { MutexAutoLock lockedScope(mMutex); if (mCancelRequested) mState = CANCELED; } if (mState == CANCELED) return notifyComplete(); if (statementsNeedTransaction()) { mTransactionManager = new mozStorageTransaction(mConnection, false, mozIStorageConnection::TRANSACTION_IMMEDIATE); } // Execute each statement, giving the callback results if it returns any. for (PRUint32 i = 0; i < mStatements.Length(); i++) { bool finished = (i == (mStatements.Length() - 1)); sqlite3_stmt *stmt; { // lock the sqlite mutex so sqlite3_errmsg cannot change SQLiteMutexAutoLock lockedScope(mDBMutex); int rc = mStatements[i].getSqliteStatement(&stmt); if (rc != SQLITE_OK) { // Set our error state. mState = ERROR; // Build the error object; can't call notifyError with the lock held sqlite3 *db = mConnection->GetNativeConnection(); nsCOMPtr<mozIStorageError> errorObj( new Error(rc, ::sqlite3_errmsg(db)) ); { // We cannot hold the DB mutex and call notifyError. SQLiteMutexAutoUnlock unlockedScope(mDBMutex); (void)notifyError(errorObj); } break; } } // If we have parameters to bind, bind them, execute, and process. if (mStatements[i].hasParametersToBeBound()) { if (!bindExecuteAndProcessStatement(mStatements[i], finished)) break; } // Otherwise, just execute and process the statement. else if (!executeAndProcessStatement(stmt, finished)) { break; } } // If we still have results that we haven't notified about, take care of // them now. if (mResultSet) (void)notifyResults(); // Notify about completion return notifyComplete(); }