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