Line data Source code
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 0 : 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 5 : explicit StatementCache(nsCOMPtr<mozIStorageConnection>& aConnection)
39 5 : : mConnection(aConnection)
40 : {
41 5 : }
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 12 : GetCachedStatement(const nsACString& aQuery)
55 : {
56 24 : nsCOMPtr<StatementType> stmt;
57 12 : if (!mCachedStatements.Get(aQuery, getter_AddRefs(stmt))) {
58 10 : stmt = CreateStatement(aQuery);
59 10 : NS_ENSURE_TRUE(stmt, nullptr);
60 :
61 10 : mCachedStatements.Put(aQuery, stmt);
62 : }
63 12 : return stmt.forget();
64 : }
65 :
66 : template<int N>
67 : MOZ_ALWAYS_INLINE already_AddRefed<StatementType>
68 3 : GetCachedStatement(const char (&aQuery)[N])
69 : {
70 6 : nsDependentCString query(aQuery, N - 1);
71 6 : 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 0 : FinalizeStatements()
81 : {
82 0 : for (auto iter = mCachedStatements.Iter(); !iter.Done(); iter.Next()) {
83 0 : (void)iter.Data()->Finalize();
84 : }
85 :
86 : // Clear the cache at this time too!
87 0 : (void)mCachedStatements.Clear();
88 0 : }
89 :
90 : private:
91 : inline
92 : already_AddRefed<StatementType>
93 : CreateStatement(const nsACString& aQuery);
94 :
95 : nsInterfaceHashtable<nsCStringHashKey, StatementType> mCachedStatements;
96 : nsCOMPtr<mozIStorageConnection>& mConnection;
97 : };
98 :
99 : template< >
100 : inline
101 : already_AddRefed<mozIStorageStatement>
102 9 : StatementCache<mozIStorageStatement>::CreateStatement(const nsACString& aQuery)
103 : {
104 9 : NS_ENSURE_TRUE(mConnection, nullptr);
105 :
106 18 : nsCOMPtr<mozIStorageStatement> stmt;
107 9 : nsresult rv = mConnection->CreateStatement(aQuery, getter_AddRefs(stmt));
108 9 : if (NS_FAILED(rv)) {
109 0 : nsCString error;
110 0 : error.AppendLiteral("The statement '");
111 0 : error.Append(aQuery);
112 0 : error.AppendLiteral("' failed to compile with the error message '");
113 0 : nsCString msg;
114 0 : (void)mConnection->GetLastErrorString(msg);
115 0 : error.Append(msg);
116 0 : error.AppendLiteral("'.");
117 0 : NS_ERROR(error.get());
118 : }
119 9 : NS_ENSURE_SUCCESS(rv, nullptr);
120 :
121 9 : return stmt.forget();
122 : }
123 :
124 : template< >
125 : inline
126 : already_AddRefed<mozIStorageAsyncStatement>
127 1 : StatementCache<mozIStorageAsyncStatement>::CreateStatement(const nsACString& aQuery)
128 : {
129 1 : NS_ENSURE_TRUE(mConnection, nullptr);
130 :
131 2 : nsCOMPtr<mozIStorageAsyncStatement> stmt;
132 1 : nsresult rv = mConnection->CreateAsyncStatement(aQuery, getter_AddRefs(stmt));
133 1 : NS_ENSURE_SUCCESS(rv, nullptr);
134 :
135 1 : return stmt.forget();
136 : }
137 :
138 : } // namespace storage
139 : } // namespace mozilla
140 :
141 : #endif // mozilla_storage_StatementCache_h
|