OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/history/android/android_cache_database.h" | |
6 | |
7 #include "base/file_util.h" | |
8 #include "sql/statement.h" | |
9 | |
10 using base::Time; | |
11 using base::TimeDelta; | |
12 | |
13 namespace history { | |
14 | |
15 namespace { | |
16 | |
17 int64 ToMilliseconds(const Time& time) { | |
18 TimeDelta delta = time - Time::UnixEpoch(); | |
19 return delta.InMilliseconds(); | |
20 } | |
21 | |
22 } // namespace. | |
23 | |
24 AndroidCacheDatabase::AndroidCacheDatabase() { | |
sky
2012/03/02 15:59:50
You should either initialize db_attached_, or nuke
michaelbai
2012/03/02 20:04:43
That needs nuked, thanks
On 2012/03/02 15:59:50,
| |
25 } | |
26 | |
27 AndroidCacheDatabase::~AndroidCacheDatabase() { | |
28 if (file_util::PathExists(db_name_)) { | |
sky
2012/03/02 15:59:50
Don't you need to close first?
michaelbai
2012/03/02 20:04:43
Thank for finding this, I shouldn't delete the fil
| |
29 bool result = file_util::Delete(db_name_, false); | |
sky
2012/03/02 15:59:50
spacing
michaelbai
2012/03/02 20:04:43
Code removed.
On 2012/03/02 15:59:50, sky wrote:
| |
30 DCHECK(result); | |
31 } | |
32 } | |
33 | |
34 sql::InitStatus AndroidCacheDatabase::InitAndroidCacheDatabase( | |
35 const FilePath& db_name) { | |
36 if (!CreateDatabase(db_name)) | |
37 return sql::INIT_FAILURE; | |
38 | |
39 if (!Attach()) | |
40 return sql::INIT_FAILURE; | |
41 | |
42 if (!CreateBookmarkCacheTable()) | |
43 return sql::INIT_FAILURE; | |
44 | |
45 return sql::INIT_OK; | |
46 } | |
47 | |
48 bool AndroidCacheDatabase::AddBookmarkCacheRow(const Time& created_time, | |
49 const Time& last_visit_time, | |
50 URLID url_id) { | |
51 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | |
52 "INSERT INTO android_cache_db.bookmark_cache (created_time, " | |
53 "last_visit_time, url_id) VALUES (?, ?, ?)")); | |
54 | |
55 statement.BindInt64(0, ToMilliseconds(created_time)); | |
sky
2012/03/02 15:59:50
Why are you using milliseconds instead of Internal
michaelbai
2012/03/02 20:04:43
It because the Android use the milliseconds to que
sky
2012/03/02 20:51:28
Can't you convert when necessary? If not, add a co
michaelbai
2012/03/02 21:16:14
I can't, as the client could just write a SQL as '
| |
56 statement.BindInt64(1, ToMilliseconds(last_visit_time)); | |
57 statement.BindInt64(2, url_id); | |
58 | |
59 if (!statement.Run()) { | |
60 LOG(ERROR) << GetDB().GetErrorMessage(); | |
61 return 0; | |
62 } | |
63 | |
64 return GetDB().GetLastInsertRowId(); | |
sky
2012/03/02 15:59:50
Do you want the return value to be a bool or the I
michaelbai
2012/03/02 20:04:43
Return true
On 2012/03/02 15:59:50, sky wrote:
| |
65 } | |
66 | |
67 bool AndroidCacheDatabase::ClearAllBookmarkCacheRow() { | |
68 if (!GetDB().Execute("DELETE FROM android_cache_db.bookmark_cache")) { | |
sky
2012/03/02 15:59:50
Don't you want a cached statement?
michaelbai
2012/03/02 20:04:43
Done.
| |
69 LOG(ERROR) << GetDB().GetErrorMessage(); | |
70 return false; | |
71 } | |
72 return true; | |
73 } | |
74 | |
75 bool AndroidCacheDatabase::CacheBookmarkBits( | |
76 const std::vector<URLID>& url_ids) { | |
77 bool has_id = false; | |
78 std::ostringstream oss; | |
sky
2012/03/02 15:59:50
Why not just build up a string?
michaelbai
2012/03/02 20:04:43
Did you mean use 'string.append()', if so, I need
| |
79 for (std::vector<URLID>::const_iterator i = url_ids.begin(); | |
80 i != url_ids.end(); ++i) { | |
81 if (has_id) | |
82 oss << ", "; | |
83 else | |
84 has_id = true; | |
85 oss << *i; | |
86 } | |
87 | |
88 if (!has_id) | |
89 return true; | |
90 | |
91 std::string sql("UPDATE android_cache_db.bookmark_cache " | |
92 "SET bookmark = 1 WHERE url_id in ("); | |
93 sql.append(oss.str()); | |
94 sql.append(")"); | |
95 if (!GetDB().Execute(sql.c_str())) { | |
96 LOG(ERROR) << GetDB().GetErrorMessage(); | |
97 return false; | |
98 } | |
99 return true; | |
100 } | |
101 | |
102 bool AndroidCacheDatabase::CacheFaviconID(URLID url_id, FaviconID favicon_id) { | |
103 sql::Statement update_statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | |
104 "UPDATE android_cache_db.bookmark_cache " | |
105 "SET favicon_id = ? WHERE url_id = ? ")); | |
106 | |
107 update_statement.BindInt64(0, favicon_id); | |
108 update_statement.BindInt64(1, url_id); | |
109 if (!update_statement.Run()) { | |
110 LOG(ERROR) << GetDB().GetErrorMessage(); | |
111 return false; | |
112 } | |
113 return true; | |
114 } | |
115 | |
116 bool AndroidCacheDatabase::CreateDatabase(const FilePath& db_name) { | |
117 db_name_ = db_name; | |
118 if (file_util::PathExists(db_name_)) | |
119 file_util::Delete(db_name_, false); | |
120 | |
121 // Using a new connection, otherwise we can not create the database. | |
122 sql::Connection connection; | |
123 | |
124 // The db doesn't store too much data, so we don't need that big a page | |
125 // size or cache. | |
126 connection.set_page_size(2048); | |
127 connection.set_cache_size(32); | |
128 | |
129 // Run the database in exclusive mode. Nobody else should be accessing the | |
130 // database while we're running, and this will give somewhat improved perf. | |
131 connection.set_exclusive_locking(); | |
132 | |
133 if (!connection.Open(db_name_)) { | |
134 LOG(ERROR) << connection.GetErrorMessage(); | |
135 return false; | |
136 } | |
137 connection.Close(); | |
138 return true; | |
139 } | |
140 | |
141 bool AndroidCacheDatabase::CreateBookmarkCacheTable() { | |
142 const char* name = "android_cache_db.bookmark_cache"; | |
143 DCHECK(!GetDB().DoesTableExist(name)); | |
144 | |
145 std::string sql; | |
146 sql.append("CREATE TABLE "); | |
147 sql.append(name); | |
148 sql.append("(" | |
149 "id INTEGER PRIMARY KEY," | |
150 "created_time INTEGER NOT NULL," // Time in millisecond. | |
151 "last_visit_time INTEGER NOT NULL," // Time in millisecond. | |
152 "url_id INTEGER NOT NULL," // url id in urls table. | |
153 "favicon_id INTEGER DEFAULT NULL," // favicon id. | |
sky
2012/03/02 15:59:50
Don't you want 0 here?
michaelbai
2012/03/02 20:04:43
No, this is the tricky thing. The client think the
| |
154 "bookmark INTEGER DEFAULT 0" // whether is bookmark. | |
155 ")"); | |
156 if (!GetDB().Execute(sql.c_str())) { | |
157 LOG(ERROR) << GetDB().GetErrorMessage(); | |
158 return false; | |
159 } | |
160 | |
161 sql.assign("CREATE INDEX "); | |
162 sql.append("android_cache_db.bookmark_cache_url_id_idx ON " | |
163 "bookmark_cache(url_id)"); | |
164 if (!GetDB().Execute(sql.c_str())) { | |
165 LOG(ERROR) << GetDB().GetErrorMessage(); | |
166 return false; | |
167 } | |
168 return true; | |
169 } | |
170 | |
171 bool AndroidCacheDatabase::Attach() { | |
172 if (GetDB().transaction_nesting()) | |
173 GetDB().CommitTransaction(); | |
sky
2012/03/02 15:59:50
Document why this is needed.
michaelbai
2012/03/02 20:04:43
Done.
| |
174 | |
175 // Attach AndroidCacheDatabase. | |
176 { | |
177 // This block is needed because otherwise the attach statement is | |
178 // never cleared from cache and we can't close the DB :P | |
179 std::string sql("ATTACH ? AS android_cache_db"); | |
180 sql::Statement attach(GetDB().GetUniqueStatement(sql.c_str())); | |
181 if (!attach.is_valid()) { | |
182 // Keep the transaction open, even though we failed. | |
183 GetDB().BeginTransaction(); | |
sky
2012/03/02 15:59:50
This code is fragile because of having to open the
michaelbai
2012/03/02 20:04:43
FYI, This code was copied from ThumbnailDatabase.
sky
2012/03/02 20:51:28
Now is your chance to fix it;)
| |
184 return false; | |
185 } | |
186 | |
187 attach.BindString(0, db_name_.value()); | |
188 if (!attach.Run()) { | |
189 GetDB().BeginTransaction(); | |
190 return false; | |
191 } | |
192 } | |
193 GetDB().BeginTransaction(); | |
194 db_attached_ = true; | |
195 return true; | |
196 } | |
197 | |
198 } // namespace history | |
OLD | NEW |