tor-browser

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

StorageBaseStatementInternal.h (15213B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: sw=2 ts=2 sts=2 expandtab
      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 mozilla_storage_StorageBaseStatementInternal_h_
      8 #define mozilla_storage_StorageBaseStatementInternal_h_
      9 
     10 #include "nsISupports.h"
     11 #include "nsCOMPtr.h"
     12 #include "mozStorageHelper.h"
     13 
     14 struct sqlite3;
     15 struct sqlite3_stmt;
     16 class mozIStorageBindingParamsArray;
     17 class mozIStorageBindingParams;
     18 class mozIStorageStatementCallback;
     19 class mozIStoragePendingStatement;
     20 
     21 namespace mozilla {
     22 namespace storage {
     23 
     24 #define STORAGEBASESTATEMENTINTERNAL_IID \
     25  {0xd18856c9, 0xbf07, 0x4ae2, {0x94, 0x5b, 0x1a, 0xdd, 0x49, 0x19, 0x55, 0x2a}}
     26 
     27 class Connection;
     28 class StatementData;
     29 
     30 class AsyncStatementFinalizer;
     31 
     32 /**
     33 * Implementation-only interface and shared logix mix-in corresponding to
     34 * mozIStorageBaseStatement.  Both Statement and AsyncStatement inherit from
     35 * this. The interface aspect makes them look the same to implementation innards
     36 * that aren't publicly accessible.  The mix-in avoids code duplication in
     37 * common implementations of mozIStorageBaseStatement, albeit with some minor
     38 * performance/space overhead because we have to use defines to officially
     39 * implement the methods on Statement/AsyncStatement (and proxy to this base
     40 * class.)
     41 */
     42 class StorageBaseStatementInternal : public nsISupports {
     43 public:
     44  NS_INLINE_DECL_STATIC_IID(STORAGEBASESTATEMENTINTERNAL_IID)
     45 
     46  /**
     47   * @return the connection that this statement belongs to.
     48   */
     49  Connection* getOwner() { return mDBConnection; }
     50 
     51  /**
     52   * Return the asynchronous statement, creating it if required.
     53   *
     54   * This is for use by the asynchronous execution code for StatementData
     55   * created by AsyncStatements.  Statement internally uses this method to
     56   * prepopulate StatementData with the sqlite3_stmt.
     57   *
     58   * @param[out] stmt
     59   *             The sqlite3_stmt for asynchronous use.
     60   * @return The SQLite result code for creating the statement if created,
     61   *         SQLITE_OK if creation was not required.
     62   */
     63  virtual int getAsyncStatement(sqlite3_stmt** _stmt) = 0;
     64 
     65  /**
     66   * Obtains the StatementData needed for asynchronous execution.
     67   *
     68   * This is for use by Connection to retrieve StatementData from statements
     69   * when executeAsync is invoked.
     70   *
     71   * @param[out] _data
     72   *             A reference to a StatementData object that will be populated
     73   *             upon successful execution of this method.
     74   * @return NS_OK if we were able to assemble the data, failure otherwise.
     75   */
     76  virtual nsresult getAsynchronousStatementData(StatementData& _data) = 0;
     77 
     78  /**
     79   * Construct a new BindingParams to be owned by the provided binding params
     80   * array.  This method exists so that BindingParamsArray does not need
     81   * factory logic to determine what type of BindingParams to instantiate.
     82   *
     83   * @param aOwner
     84   *        The binding params array to own the newly created binding params.
     85   * @return The new mozIStorageBindingParams instance appropriate to the
     86   *         underlying statement type.
     87   */
     88  virtual already_AddRefed<mozIStorageBindingParams> newBindingParams(
     89      mozIStorageBindingParamsArray* aOwner) = 0;
     90 
     91 protected:  // mix-in bits are protected
     92  StorageBaseStatementInternal();
     93 
     94  RefPtr<Connection> mDBConnection;
     95  sqlite3* mNativeConnection;
     96 
     97  /**
     98   * Our asynchronous statement.
     99   *
    100   * For Statement this is populated by the first invocation to
    101   * getAsyncStatement.
    102   *
    103   * For AsyncStatement, this is null at creation time and initialized by the
    104   * async thread when it calls getAsyncStatement the first time the statement
    105   * is executed.  (Or in the event of badly formed SQL, every time.)
    106   */
    107  sqlite3_stmt* mAsyncStatement;
    108 
    109  /**
    110   * Initiate asynchronous finalization by dispatching an event to the
    111   * asynchronous thread to finalize mAsyncStatement.  This acquires a reference
    112   * to this statement and proxies it back to the connection's owning thread
    113   * for release purposes.
    114   *
    115   * In the event the asynchronous thread is already gone or we otherwise fail
    116   * to dispatch an event to it we failover to invoking internalAsyncFinalize
    117   * directly.  (That's what the asynchronous finalizer would have called.)
    118   *
    119   * @note You must not call this method from your destructor because its
    120   *       operation assumes we are still alive.  Call internalAsyncFinalize
    121   *       directly in that case.
    122   */
    123  void asyncFinalize();
    124 
    125  /**
    126   * Cleanup the async sqlite3_stmt stored in mAsyncStatement if it exists by
    127   * attempting to dispatch to the asynchronous thread if available, finalizing
    128   * on this thread if it is not.
    129   *
    130   * @note Call this from your destructor, call asyncFinalize otherwise.
    131   */
    132  void destructorAsyncFinalize();
    133 
    134  NS_IMETHOD NewBindingParamsArray(mozIStorageBindingParamsArray** _array);
    135  NS_IMETHOD ExecuteAsync(mozIStorageStatementCallback* aCallback,
    136                          mozIStoragePendingStatement** _stmt);
    137  NS_IMETHOD EscapeStringForLIKE(const nsAString& aValue, char16_t aEscapeChar,
    138                                 nsAString& _escapedString);
    139  NS_IMETHOD EscapeUTF8StringForLIKE(const nsACString& aValue, char aEscapeChar,
    140                                     nsACString& _escapedString);
    141 
    142  // Needs access to internalAsyncFinalize
    143  friend class AsyncStatementFinalizer;
    144 };
    145 
    146 #define NS_DECL_STORAGEBASESTATEMENTINTERNAL                           \
    147  virtual Connection* getOwner();                                      \
    148  virtual int getAsyncStatement(sqlite3_stmt** _stmt) override;        \
    149  virtual nsresult getAsynchronousStatementData(StatementData& _data)  \
    150      override;                                                        \
    151  virtual already_AddRefed<mozIStorageBindingParams> newBindingParams( \
    152      mozIStorageBindingParamsArray* aOwner) override;
    153 
    154 /**
    155 * Helper macro to implement the proxying implementations.  Because we are
    156 * implementing methods that are part of mozIStorageBaseStatement and the
    157 * implementation classes already use NS_DECL_MOZISTORAGEBASESTATEMENT we don't
    158 * need to provide declaration support.
    159 */
    160 #define MIX_IMPL(_class, _optionalGuard, _method, _declArgs, _invokeArgs)    \
    161  NS_IMETHODIMP _class::_method _declArgs {                                  \
    162    _optionalGuard return StorageBaseStatementInternal::_method _invokeArgs; \
    163  }
    164 
    165 /**
    166 * Define proxying implementation for the given _class.  If a state invariant
    167 * needs to be checked and an early return possibly performed, pass the clause
    168 * to use as _optionalGuard.
    169 */
    170 #define MIXIN_IMPL_STORAGEBASESTATEMENTINTERNAL(_class, _optionalGuard) \
    171  MIX_IMPL(_class, _optionalGuard, NewBindingParamsArray,               \
    172           (mozIStorageBindingParamsArray * *_array), (_array))         \
    173  MIX_IMPL(_class, _optionalGuard, ExecuteAsync,                        \
    174           (mozIStorageStatementCallback * aCallback,                   \
    175            mozIStoragePendingStatement * *_stmt),                      \
    176           (aCallback, _stmt))                                          \
    177  MIX_IMPL(_class, _optionalGuard, EscapeStringForLIKE,                 \
    178           (const nsAString& aValue, char16_t aEscapeChar,              \
    179            nsAString& _escapedString),                                 \
    180           (aValue, aEscapeChar, _escapedString))                       \
    181  MIX_IMPL(_class, _optionalGuard, EscapeUTF8StringForLIKE,             \
    182           (const nsACString& aValue, char aEscapeChar,                 \
    183            nsACString& _escapedString),                                \
    184           (aValue, aEscapeChar, _escapedString))
    185 
    186 /**
    187 * Name-building helper for BIND_GEN_IMPL.
    188 */
    189 #define BIND_NAME_CONCAT(_nameBit, _concatBit) Bind##_nameBit##_concatBit
    190 
    191 /**
    192 * We have type-specific convenience methods for C++ implementations in
    193 * two different forms; by index and by name.  The following macro allows
    194 * us to avoid having to define repetitive things by hand.
    195 *
    196 * Because of limitations of macros and our desire to avoid requiring special
    197 * permutations for the null and blob cases (whose argument count varies),
    198 * we require that the argument declarations and corresponding invocation
    199 * usages are passed in.
    200 *
    201 * @param _class
    202 *        The class name.
    203 * @param _guard
    204 *        The guard clause to inject.
    205 * @param _declName
    206 *        The argument list (with parens) for the ByName variants.
    207 * @param _declIndex
    208 *        The argument list (with parens) for the ByIndex variants.
    209 * @param _invArgs
    210 *        The invocation argumment list.
    211 */
    212 #define BIND_GEN_IMPL(_class, _guard, _name, _declName, _declIndex, _invArgs) \
    213  NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, ByName) _declName {           \
    214    _guard mozIStorageBindingParams* params = getParams();                    \
    215    NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);                           \
    216    return params->BIND_NAME_CONCAT(_name, ByName) _invArgs;                  \
    217  }                                                                           \
    218  NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, ByIndex) _declIndex {         \
    219    _guard mozIStorageBindingParams* params = getParams();                    \
    220    NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);                           \
    221    return params->BIND_NAME_CONCAT(_name, ByIndex) _invArgs;                 \
    222  }
    223 
    224 /**
    225 * Implement BindByName/BindByIndex for the given class.
    226 *
    227 * @param _class The class name.
    228 * @param _optionalGuard The guard clause to inject.
    229 */
    230 #define BIND_BASE_IMPLS(_class, _optionalGuard)                            \
    231  NS_IMETHODIMP _class::BindByName(const nsACString& aName,                \
    232                                   nsIVariant* aValue) {                   \
    233    _optionalGuard mozIStorageBindingParams* params = getParams();         \
    234    NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);                        \
    235    return params->BindByName(aName, aValue);                              \
    236  }                                                                        \
    237  NS_IMETHODIMP _class::BindByIndex(uint32_t aIndex, nsIVariant* aValue) { \
    238    _optionalGuard mozIStorageBindingParams* params = getParams();         \
    239    NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);                        \
    240    return params->BindByIndex(aIndex, aValue);                            \
    241  }
    242 
    243 /**
    244 * Define the various Bind*ByIndex, Bind*ByName stubs that just end up proxying
    245 * to the params object.
    246 */
    247 #define BOILERPLATE_BIND_PROXIES(_class, _optionalGuard)                       \
    248  BIND_BASE_IMPLS(_class, _optionalGuard)                                      \
    249  BIND_GEN_IMPL(_class, _optionalGuard, UTF8String,                            \
    250                (const nsACString& aWhere, const nsACString& aValue),          \
    251                (uint32_t aWhere, const nsACString& aValue), (aWhere, aValue)) \
    252  BIND_GEN_IMPL(_class, _optionalGuard, String,                                \
    253                (const nsACString& aWhere, const nsAString& aValue),           \
    254                (uint32_t aWhere, const nsAString& aValue), (aWhere, aValue))  \
    255  BIND_GEN_IMPL(_class, _optionalGuard, Double,                                \
    256                (const nsACString& aWhere, double aValue),                     \
    257                (uint32_t aWhere, double aValue), (aWhere, aValue))            \
    258  BIND_GEN_IMPL(_class, _optionalGuard, Int32,                                 \
    259                (const nsACString& aWhere, int32_t aValue),                    \
    260                (uint32_t aWhere, int32_t aValue), (aWhere, aValue))           \
    261  BIND_GEN_IMPL(_class, _optionalGuard, Int64,                                 \
    262                (const nsACString& aWhere, int64_t aValue),                    \
    263                (uint32_t aWhere, int64_t aValue), (aWhere, aValue))           \
    264  BIND_GEN_IMPL(_class, _optionalGuard, Null, (const nsACString& aWhere),      \
    265                (uint32_t aWhere), (aWhere))                                   \
    266  BIND_GEN_IMPL(                                                               \
    267      _class, _optionalGuard, Blob,                                            \
    268      (const nsACString& aWhere, const uint8_t* aValue, uint32_t aValueSize),  \
    269      (uint32_t aWhere, const uint8_t* aValue, uint32_t aValueSize),           \
    270      (aWhere, aValue, aValueSize))                                            \
    271  BIND_GEN_IMPL(_class, _optionalGuard, BlobArray,                             \
    272                (const nsACString& aWhere, const nsTArray<uint8_t>& aValue),   \
    273                (uint32_t aWhere, const nsTArray<uint8_t>& aValue),            \
    274                (aWhere, aValue))                                              \
    275  BIND_GEN_IMPL(_class, _optionalGuard, StringAsBlob,                          \
    276                (const nsACString& aWhere, const nsAString& aValue),           \
    277                (uint32_t aWhere, const nsAString& aValue), (aWhere, aValue))  \
    278  BIND_GEN_IMPL(_class, _optionalGuard, UTF8StringAsBlob,                      \
    279                (const nsACString& aWhere, const nsACString& aValue),          \
    280                (uint32_t aWhere, const nsACString& aValue), (aWhere, aValue)) \
    281  BIND_GEN_IMPL(                                                               \
    282      _class, _optionalGuard, AdoptedBlob,                                     \
    283      (const nsACString& aWhere, uint8_t* aValue, uint32_t aValueSize),        \
    284      (uint32_t aWhere, uint8_t* aValue, uint32_t aValueSize),                 \
    285      (aWhere, aValue, aValueSize))                                            \
    286  BIND_GEN_IMPL(_class, _optionalGuard, ArrayOfIntegers,                       \
    287                (const nsACString& aWhere, const nsTArray<int64_t>& aValue),   \
    288                (uint32_t aWhere, const nsTArray<int64_t>& aValue),            \
    289                (aWhere, aValue))                                              \
    290  BIND_GEN_IMPL(_class, _optionalGuard, ArrayOfDoubles,                        \
    291                (const nsACString& aWhere, const nsTArray<double>& aValue),    \
    292                (uint32_t aWhere, const nsTArray<double>& aValue),             \
    293                (aWhere, aValue))                                              \
    294  BIND_GEN_IMPL(_class, _optionalGuard, ArrayOfStrings,                        \
    295                (const nsACString& aWhere, const nsTArray<nsString>& aValue),  \
    296                (uint32_t aWhere, const nsTArray<nsString>& aValue),           \
    297                (aWhere, aValue))                                              \
    298  BIND_GEN_IMPL(_class, _optionalGuard, ArrayOfUTF8Strings,                    \
    299                (const nsACString& aWhere, const nsTArray<nsCString>& aValue), \
    300                (uint32_t aWhere, const nsTArray<nsCString>& aValue),          \
    301                (aWhere, aValue))
    302 
    303 }  // namespace storage
    304 }  // namespace mozilla
    305 
    306 #endif  // mozilla_storage_StorageBaseStatementInternal_h_