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