tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

mozStorageStatementData.h (4481B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: sw=2 ts=2 sts=2 et
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozStorageStatementData_h
      8 #define mozStorageStatementData_h
      9 
     10 #include "sqlite3.h"
     11 
     12 #include "nsTArray.h"
     13 
     14 #include "mozStorageBindingParamsArray.h"
     15 #include "mozStorageConnection.h"
     16 #include "StorageBaseStatementInternal.h"
     17 #include "mozStoragePrivateHelpers.h"
     18 
     19 struct sqlite3_stmt;
     20 
     21 namespace mozilla::storage {
     22 
     23 class StatementData {
     24 public:
     25  StatementData(sqlite3_stmt* aStatement,
     26                already_AddRefed<BindingParamsArray> aParamsArray,
     27                StorageBaseStatementInternal* aStatementOwner)
     28      : mStatement(aStatement),
     29        mParamsArray(aParamsArray),
     30        mQueryStatusRecorded(false),
     31        mStatementOwner(aStatementOwner) {
     32    MOZ_ASSERT(mStatementOwner, "Must have a statement owner!");
     33  }
     34  StatementData(const StatementData& aSource)
     35      : mStatement(aSource.mStatement),
     36        mParamsArray(aSource.mParamsArray),
     37        mQueryStatusRecorded(false),
     38        mStatementOwner(aSource.mStatementOwner) {
     39    MOZ_ASSERT(mStatementOwner, "Must have a statement owner!");
     40  }
     41  StatementData() : mStatement(nullptr), mQueryStatusRecorded(false) {}
     42 
     43  /**
     44   * Return the sqlite statement, fetching it from the storage statement.  In
     45   * the case of AsyncStatements this may actually create the statement
     46   */
     47  inline int getSqliteStatement(sqlite3_stmt** _stmt) {
     48    if (!mStatement) {
     49      int rc = mStatementOwner->getAsyncStatement(&mStatement);
     50      MaybeRecordQueryStatus(rc);
     51      NS_ENSURE_TRUE(rc == SQLITE_OK, rc);
     52    }
     53    *_stmt = mStatement;
     54    return SQLITE_OK;
     55  }
     56 
     57  operator BindingParamsArray*() const { return mParamsArray; }
     58 
     59  /**
     60   * NULLs out our sqlite3_stmt (it is held by the owner) after reseting it and
     61   * clear all bindings to it.  This is expected to occur on the async thread.
     62   */
     63  inline void reset() {
     64    MOZ_ASSERT(mStatementOwner, "Must have a statement owner!");
     65    // In the AsyncStatement case we may never have populated mStatement if the
     66    // AsyncExecuteStatements got canceled or a failure occurred in constructing
     67    // the statement.
     68    if (mStatement) {
     69      (void)::sqlite3_reset(mStatement);
     70      (void)::sqlite3_clear_bindings(mStatement);
     71      mStatement = nullptr;
     72 
     73      if (!mQueryStatusRecorded) {
     74        mStatementOwner->getOwner()->RecordQueryStatus(SQLITE_OK);
     75      }
     76    }
     77  }
     78 
     79  /**
     80   * Indicates if this statement has parameters to be bound before it is
     81   * executed.
     82   *
     83   * @return true if the statement has parameters to bind against, false
     84   *         otherwise.
     85   */
     86  inline bool hasParametersToBeBound() const { return !!mParamsArray; }
     87  /**
     88   * Indicates the number of implicit statements generated by this statement
     89   * requiring a transaction for execution.  For example a single statement
     90   * with N BindingParams will execute N implicit staments.
     91   *
     92   * @return number of statements requiring a transaction for execution.
     93   *
     94   * @note In the case of AsyncStatements this may actually create the
     95   *       statement.
     96   */
     97  inline uint32_t needsTransaction() {
     98    MOZ_ASSERT(!NS_IsMainThread());
     99    // Be sure to use the getSqliteStatement helper, since sqlite3_stmt_readonly
    100    // can only analyze prepared statements and AsyncStatements are prepared
    101    // lazily.
    102    sqlite3_stmt* stmt;
    103    int rc = getSqliteStatement(&stmt);
    104    if (SQLITE_OK != rc || ::sqlite3_stmt_readonly(stmt)) {
    105      return 0;
    106    }
    107    return mParamsArray ? mParamsArray->length() : 1;
    108  }
    109 
    110  void MaybeRecordQueryStatus(int srv) {
    111    if (mQueryStatusRecorded || !isErrorCode(srv)) {
    112      return;
    113    }
    114 
    115    mStatementOwner->getOwner()->RecordQueryStatus(srv);
    116    mQueryStatusRecorded = true;
    117  }
    118 
    119 private:
    120  sqlite3_stmt* mStatement;
    121 
    122  /**
    123   * It's safe to release this on any thread, as it holds `BindingParams` that
    124   * can only contain thread-safe derivates of `Variant_base`.
    125   */
    126  RefPtr<BindingParamsArray> mParamsArray;
    127 
    128  bool mQueryStatusRecorded;
    129 
    130  /**
    131   * We hold onto a reference of the statement's owner so it doesn't get
    132   * destroyed out from under us.
    133   */
    134  nsCOMPtr<StorageBaseStatementInternal> mStatementOwner;
    135 };
    136 
    137 }  // namespace mozilla::storage
    138 
    139 #endif  // mozStorageStatementData_h