storage/public/StatementCache.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/storage/public/StatementCache.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,148 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef mozilla_storage_StatementCache_h
    1.11 +#define mozilla_storage_StatementCache_h
    1.12 +
    1.13 +#include "mozIStorageConnection.h"
    1.14 +#include "mozIStorageStatement.h"
    1.15 +#include "mozIStorageAsyncStatement.h"
    1.16 +
    1.17 +#include "nsAutoPtr.h"
    1.18 +#include "nsHashKeys.h"
    1.19 +#include "nsInterfaceHashtable.h"
    1.20 +
    1.21 +namespace mozilla {
    1.22 +namespace storage {
    1.23 +
    1.24 +/**
    1.25 + * Class used to cache statements (mozIStorageStatement or
    1.26 + * mozIStorageAsyncStatement).
    1.27 + */
    1.28 +template<typename StatementType>
    1.29 +class StatementCache {
    1.30 +public:
    1.31 +  /**
    1.32 +   * Constructor for the cache.
    1.33 +   *
    1.34 +   * @note a connection can have more than one cache.
    1.35 +   *
    1.36 +   * @param aConnection
    1.37 +   *        A reference to the nsCOMPtr for the connection this cache is to be
    1.38 +   *        used for.  This nsCOMPtr must at least live as long as this class,
    1.39 +   *        otherwise crashes will happen.
    1.40 +   */
    1.41 +  StatementCache(nsCOMPtr<mozIStorageConnection>& aConnection)
    1.42 +  : mConnection(aConnection)
    1.43 +  {
    1.44 +  }
    1.45 +
    1.46 +  /**
    1.47 +   * Obtains a cached statement.  If this statement is not yet created, it will
    1.48 +   * be created and stored for later use.
    1.49 +   *
    1.50 +   * @param aQuery
    1.51 +   *        The SQL string (either a const char [] or nsACString) to get a
    1.52 +   *        cached query for.
    1.53 +   * @return the cached statement, or null upon error.
    1.54 +   */
    1.55 +  inline
    1.56 +  already_AddRefed<StatementType>
    1.57 +  GetCachedStatement(const nsACString& aQuery)
    1.58 +  {
    1.59 +    nsCOMPtr<StatementType> stmt;
    1.60 +    if (!mCachedStatements.Get(aQuery, getter_AddRefs(stmt))) {
    1.61 +      stmt = CreateStatement(aQuery);
    1.62 +      NS_ENSURE_TRUE(stmt, nullptr);
    1.63 +
    1.64 +      mCachedStatements.Put(aQuery, stmt);
    1.65 +    }
    1.66 +    return stmt.forget();
    1.67 +  }
    1.68 +
    1.69 +  template<int N>
    1.70 +  MOZ_ALWAYS_INLINE already_AddRefed<StatementType>
    1.71 +  GetCachedStatement(const char (&aQuery)[N])
    1.72 +  {
    1.73 +    nsDependentCString query(aQuery, N - 1);
    1.74 +    return GetCachedStatement(query);
    1.75 +  }
    1.76 +
    1.77 +  /**
    1.78 +   * Finalizes all cached statements so the database can be safely closed.  The
    1.79 +   * behavior of this cache is unspecified after this method is called.
    1.80 +   */
    1.81 +  inline
    1.82 +  void
    1.83 +  FinalizeStatements()
    1.84 +  {
    1.85 +    (void)mCachedStatements.Enumerate(FinalizeCachedStatements, nullptr);
    1.86 +
    1.87 +    // Clear the cache at this time too!
    1.88 +    (void)mCachedStatements.Clear();
    1.89 +  }
    1.90 +
    1.91 +private:
    1.92 +  inline
    1.93 +  already_AddRefed<StatementType>
    1.94 +  CreateStatement(const nsACString& aQuery);
    1.95 +  static
    1.96 +  PLDHashOperator
    1.97 +  FinalizeCachedStatements(const nsACString& aKey,
    1.98 +                           nsCOMPtr<StatementType>& aStatement,
    1.99 +                           void*)
   1.100 +  {
   1.101 +    (void)aStatement->Finalize();
   1.102 +    return PL_DHASH_NEXT;
   1.103 +  }
   1.104 +
   1.105 +  nsInterfaceHashtable<nsCStringHashKey, StatementType> mCachedStatements;
   1.106 +  nsCOMPtr<mozIStorageConnection>& mConnection;
   1.107 +};
   1.108 +
   1.109 +template< >
   1.110 +inline
   1.111 +already_AddRefed<mozIStorageStatement>
   1.112 +StatementCache<mozIStorageStatement>::CreateStatement(const nsACString& aQuery)
   1.113 +{
   1.114 +  NS_ENSURE_TRUE(mConnection, nullptr);
   1.115 +
   1.116 +  nsCOMPtr<mozIStorageStatement> stmt;
   1.117 +  nsresult rv = mConnection->CreateStatement(aQuery, getter_AddRefs(stmt));
   1.118 +  if (NS_FAILED(rv)) {
   1.119 +    nsCString error;
   1.120 +    error.AppendLiteral("The statement '");
   1.121 +    error.Append(aQuery);
   1.122 +    error.AppendLiteral("' failed to compile with the error message '");
   1.123 +    nsCString msg;
   1.124 +    (void)mConnection->GetLastErrorString(msg);
   1.125 +    error.Append(msg);
   1.126 +    error.AppendLiteral("'.");
   1.127 +    NS_ERROR(error.get());
   1.128 +  }
   1.129 +  NS_ENSURE_SUCCESS(rv, nullptr);
   1.130 +
   1.131 +  return stmt.forget();
   1.132 +}
   1.133 +
   1.134 +template< >
   1.135 +inline
   1.136 +already_AddRefed<mozIStorageAsyncStatement>
   1.137 +StatementCache<mozIStorageAsyncStatement>::CreateStatement(const nsACString& aQuery)
   1.138 +{
   1.139 +  NS_ENSURE_TRUE(mConnection, nullptr);
   1.140 +
   1.141 +  nsCOMPtr<mozIStorageAsyncStatement> stmt;
   1.142 +  nsresult rv = mConnection->CreateAsyncStatement(aQuery, getter_AddRefs(stmt));
   1.143 +  NS_ENSURE_SUCCESS(rv, nullptr);
   1.144 +
   1.145 +  return stmt.forget();
   1.146 +}
   1.147 +
   1.148 +} // namespace storage
   1.149 +} // namespace mozilla
   1.150 +
   1.151 +#endif // mozilla_storage_StatementCache_h

mercurial