StatementCache.h (3901B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : 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_StatementCache_h 8 #define mozilla_storage_StatementCache_h 9 10 #include "mozIStorageConnection.h" 11 #include "mozIStorageStatement.h" 12 #include "mozIStorageAsyncStatement.h" 13 14 #include "nsHashKeys.h" 15 #include "nsInterfaceHashtable.h" 16 17 namespace mozilla { 18 namespace storage { 19 20 /** 21 * Class used to cache statements (mozIStorageStatement or 22 * mozIStorageAsyncStatement). 23 */ 24 template <typename StatementType> 25 class StatementCache { 26 public: 27 /** 28 * Constructor for the cache. 29 * 30 * @note a connection can have more than one cache. 31 * 32 * @param aConnection 33 * A reference to the nsCOMPtr for the connection this cache is to be 34 * used for. This nsCOMPtr must at least live as long as this class, 35 * otherwise crashes will happen. 36 */ 37 explicit StatementCache(nsCOMPtr<mozIStorageConnection>& aConnection) 38 : mConnection(aConnection) {} 39 40 /** 41 * Obtains a cached statement. If this statement is not yet created, it will 42 * be created and stored for later use. 43 * 44 * @param aQuery 45 * The SQL string (either a const char [] or nsACString) to get a 46 * cached query for. 47 * @return the cached statement, or null upon error. 48 */ 49 inline already_AddRefed<StatementType> GetCachedStatement( 50 const nsACString& aQuery) { 51 nsCOMPtr<StatementType> stmt; 52 if (!mCachedStatements.Get(aQuery, getter_AddRefs(stmt))) { 53 stmt = CreateStatement(aQuery); 54 NS_ENSURE_TRUE(stmt, nullptr); 55 56 mCachedStatements.InsertOrUpdate(aQuery, stmt); 57 } 58 return stmt.forget(); 59 } 60 61 template <int N> 62 MOZ_ALWAYS_INLINE already_AddRefed<StatementType> GetCachedStatement( 63 const char (&aQuery)[N]) { 64 nsDependentCString query(aQuery, N - 1); 65 return GetCachedStatement(query); 66 } 67 68 /** 69 * Finalizes all cached statements so the database can be safely closed. The 70 * behavior of this cache is unspecified after this method is called. 71 */ 72 inline void FinalizeStatements() { 73 for (const auto& data : mCachedStatements.Values()) { 74 (void)data->Finalize(); 75 } 76 77 // Clear the cache at this time too! 78 (void)mCachedStatements.Clear(); 79 } 80 81 private: 82 inline already_AddRefed<StatementType> CreateStatement( 83 const nsACString& aQuery); 84 85 nsInterfaceHashtable<nsCStringHashKey, StatementType> mCachedStatements; 86 nsCOMPtr<mozIStorageConnection>& mConnection; 87 }; 88 89 template <> 90 inline already_AddRefed<mozIStorageStatement> 91 StatementCache<mozIStorageStatement>::CreateStatement( 92 const nsACString& aQuery) { 93 NS_ENSURE_TRUE(mConnection, nullptr); 94 95 nsCOMPtr<mozIStorageStatement> stmt; 96 nsresult rv = mConnection->CreateStatement(aQuery, getter_AddRefs(stmt)); 97 if (NS_FAILED(rv)) { 98 nsCString error; 99 error.AppendLiteral("The statement '"); 100 error.Append(aQuery); 101 error.AppendLiteral("' failed to compile with the error message '"); 102 nsCString msg; 103 (void)mConnection->GetLastErrorString(msg); 104 error.Append(msg); 105 error.AppendLiteral("'."); 106 NS_ERROR(error.get()); 107 } 108 NS_ENSURE_SUCCESS(rv, nullptr); 109 110 return stmt.forget(); 111 } 112 113 template <> 114 inline already_AddRefed<mozIStorageAsyncStatement> 115 StatementCache<mozIStorageAsyncStatement>::CreateStatement( 116 const nsACString& aQuery) { 117 NS_ENSURE_TRUE(mConnection, nullptr); 118 119 nsCOMPtr<mozIStorageAsyncStatement> stmt; 120 nsresult rv = mConnection->CreateAsyncStatement(aQuery, getter_AddRefs(stmt)); 121 NS_ENSURE_SUCCESS(rv, nullptr); 122 123 return stmt.forget(); 124 } 125 126 } // namespace storage 127 } // namespace mozilla 128 129 #endif // mozilla_storage_StatementCache_h