void basicFunctionHelper(sqlite3_context *aCtx, int aArgc, sqlite3_value **aArgv) { void *userData = ::sqlite3_user_data(aCtx); mozIStorageFunction *func = static_cast<mozIStorageFunction *>(userData); nsRefPtr<ArgValueArray> arguments(new ArgValueArray(aArgc, aArgv)); if (!arguments) return; nsCOMPtr<nsIVariant> result; if (NS_FAILED(func->OnFunctionCall(arguments, getter_AddRefs(result)))) { NS_WARNING("User function returned error code!"); ::sqlite3_result_error(aCtx, "User function returned error code", -1); return; } int retcode = variantToSQLiteT(aCtx, result); if (retcode == SQLITE_IGNORE) { ::sqlite3_result_int(aCtx, SQLITE_IGNORE); } else if (retcode != SQLITE_OK) { NS_WARNING("User function returned invalid data type!"); ::sqlite3_result_error(aCtx, "User function returned invalid data type", -1); } }
already_AddRefed<mozIStorageError> AsyncBindingParams::bind(sqlite3_stmt * aStatement) { // We should bind by index using the super-class if there is nothing in our // hashtable. if (!mNamedParameters.Count()) return BindingParams::bind(aStatement); nsCOMPtr<mozIStorageError> err; for (auto iter = mNamedParameters.Iter(); !iter.Done(); iter.Next()) { const nsACString &key = iter.Key(); // We do not accept any forms of names other than ":name", but we need to // add the colon for SQLite. nsAutoCString name(":"); name.Append(key); int oneIdx = ::sqlite3_bind_parameter_index(aStatement, name.get()); if (oneIdx == 0) { nsAutoCString errMsg(key); errMsg.AppendLiteral(" is not a valid named parameter."); err = new Error(SQLITE_RANGE, errMsg.get()); break; } // XPCVariant's AddRef and Release are not thread-safe and so we must not // do anything that would invoke them here on the async thread. As such we // can't cram aValue into mParameters using ReplaceObjectAt so that // we can freeload off of the BindingParams::Bind implementation. int rc = variantToSQLiteT(BindingColumnData(aStatement, oneIdx - 1), iter.UserData()); if (rc != SQLITE_OK) { // We had an error while trying to bind. Now we need to create an error // object with the right message. Note that we special case // SQLITE_MISMATCH, but otherwise get the message from SQLite. const char *msg = "Could not covert nsIVariant to SQLite type."; if (rc != SQLITE_MISMATCH) { msg = ::sqlite3_errmsg(::sqlite3_db_handle(aStatement)); } err = new Error(rc, msg); break; } } return err.forget(); }
PLDHashOperator AsyncBindingParams::iterateOverNamedParameters(const nsACString &aName, nsIVariant *aValue, void *voidClosureThunk) { NamedParameterIterationClosureThunk *closureThunk = static_cast<NamedParameterIterationClosureThunk *>(voidClosureThunk); // We do not accept any forms of names other than ":name", but we need to add // the colon for SQLite. nsAutoCString name(":"); name.Append(aName); int oneIdx = ::sqlite3_bind_parameter_index(closureThunk->statement, name.get()); if (oneIdx == 0) { nsAutoCString errMsg(aName); errMsg.Append(NS_LITERAL_CSTRING(" is not a valid named parameter.")); closureThunk->err = new Error(SQLITE_RANGE, errMsg.get()); return PL_DHASH_STOP; } // XPCVariant's AddRef and Release are not thread-safe and so we must not do // anything that would invoke them here on the async thread. As such we can't // cram aValue into self->mParameters using ReplaceObjectAt so that we can // freeload off of the BindingParams::Bind implementation. int rc = variantToSQLiteT(BindingColumnData(closureThunk->statement, oneIdx - 1), aValue); if (rc != SQLITE_OK) { // We had an error while trying to bind. Now we need to create an error // object with the right message. Note that we special case // SQLITE_MISMATCH, but otherwise get the message from SQLite. const char *msg = "Could not covert nsIVariant to SQLite type."; if (rc != SQLITE_MISMATCH) msg = ::sqlite3_errmsg(::sqlite3_db_handle(closureThunk->statement)); closureThunk->err = new Error(rc, msg); return PL_DHASH_STOP; } return PL_DHASH_NEXT; }
already_AddRefed<mozIStorageError> BindingParams::bind(sqlite3_stmt *aStatement) { // Iterate through all of our stored data, and bind it. for (size_t i = 0; i < mParameters.Length(); i++) { int rc = variantToSQLiteT(BindingColumnData(aStatement, i), mParameters[i]); if (rc != SQLITE_OK) { // We had an error while trying to bind. Now we need to create an error // object with the right message. Note that we special case // SQLITE_MISMATCH, but otherwise get the message from SQLite. const char *msg = "Could not covert nsIVariant to SQLite type."; if (rc != SQLITE_MISMATCH) msg = ::sqlite3_errmsg(::sqlite3_db_handle(aStatement)); nsCOMPtr<mozIStorageError> err(new Error(rc, msg)); return err.forget(); } } return nullptr; }
void aggregateFunctionFinalHelper(sqlite3_context *aCtx) { void *userData = ::sqlite3_user_data(aCtx); mozIStorageAggregateFunction *func = static_cast<mozIStorageAggregateFunction *>(userData); nsRefPtr<nsIVariant> result; if (NS_FAILED(func->OnFinal(getter_AddRefs(result)))) { NS_WARNING("User aggregate final function returned error code!"); ::sqlite3_result_error(aCtx, "User aggregate final function returned error code", -1); return; } if (variantToSQLiteT(aCtx, result) != SQLITE_OK) { NS_WARNING("User aggregate final function returned invalid data type!"); ::sqlite3_result_error(aCtx, "User aggregate final function returned invalid data type", -1); } }