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_urls_database.h"
6
7 #include "base/logging.h"
8
9 namespace history {
10
AndroidURLsDatabase()11 AndroidURLsDatabase::AndroidURLsDatabase() {
12 }
13
~AndroidURLsDatabase()14 AndroidURLsDatabase::~AndroidURLsDatabase() {
15 }
16
CreateAndroidURLsTable()17 bool AndroidURLsDatabase::CreateAndroidURLsTable() {
18 const char* name = "android_urls";
19 if (!GetDB().DoesTableExist(name)) {
20 std::string sql;
21 sql.append("CREATE TABLE ");
22 sql.append(name);
23 sql.append("("
24 "id INTEGER PRIMARY KEY,"
25 "raw_url LONGVARCHAR," // Passed in raw url.
26 "url_id INTEGER NOT NULL" // url id in urls table.
27 ")");
28 if (!GetDB().Execute(sql.c_str())) {
29 LOG(ERROR) << GetDB().GetErrorMessage();
30 return false;
31 }
32
33 if (!GetDB().Execute("CREATE INDEX android_urls_raw_url_idx"
34 " ON android_urls(raw_url)")) {
35 LOG(ERROR) << GetDB().GetErrorMessage();
36 return false;
37 }
38
39 if (!GetDB().Execute("CREATE INDEX android_urls_url_id_idx"
40 " ON android_urls(url_id)")) {
41 LOG(ERROR) << GetDB().GetErrorMessage();
42 return false;
43 }
44 }
45 return true;
46 }
47
AddAndroidURLRow(const std::string & raw_url,URLID url_id)48 AndroidURLID AndroidURLsDatabase::AddAndroidURLRow(const std::string& raw_url,
49 URLID url_id) {
50 if (GetAndroidURLRow(url_id, NULL)) {
51 LOG(ERROR) << "url_id already exist";
52 return 0;
53 }
54
55 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
56 "INSERT INTO android_urls (raw_url, url_id) VALUES (?, ?)"));
57
58 statement.BindString(0, raw_url);
59 statement.BindInt64(1, static_cast<int64>(url_id));
60
61 if (!statement.Run()) {
62 LOG(ERROR) << GetDB().GetErrorMessage();
63 return 0;
64 }
65 return GetDB().GetLastInsertRowId();
66 }
67
GetAndroidURLRow(URLID url_id,AndroidURLRow * row)68 bool AndroidURLsDatabase::GetAndroidURLRow(URLID url_id, AndroidURLRow* row) {
69 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
70 "SELECT id, raw_url, url_id FROM android_urls WHERE url_id = ?"));
71
72 statement.BindInt64(0, url_id);
73
74 if (!statement.Step())
75 return false;
76 if (row) {
77 row->id = statement.ColumnInt64(0);
78 row->raw_url = statement.ColumnString(1);
79 row->url_id = statement.ColumnInt64(2);
80 }
81 return true;
82 }
83
DeleteAndroidURLRows(const std::vector<URLID> & url_ids)84 bool AndroidURLsDatabase::DeleteAndroidURLRows(
85 const std::vector<URLID>& url_ids) {
86 if (url_ids.empty())
87 return true;
88
89 std::string sql;
90 sql.append("DELETE FROM android_urls ");
91 std::ostringstream oss;
92 bool has_id = false;
93 for (std::vector<URLID>::const_iterator i = url_ids.begin();
94 i != url_ids.end(); ++i) {
95 if (has_id)
96 oss << ", ";
97 else
98 has_id = true;
99 oss << *i;
100 }
101
102 if (has_id) {
103 sql.append(" WHERE url_id in ( ");
104 sql.append(oss.str());
105 sql.append(" )");
106 }
107
108 if (!GetDB().Execute(sql.c_str())) {
109 LOG(ERROR) << GetDB().GetErrorMessage();
110 return false;
111 }
112 return true;
113 }
114
DeleteUnusedAndroidURLs()115 bool AndroidURLsDatabase::DeleteUnusedAndroidURLs() {
116 return GetDB().Execute("DELETE FROM android_urls WHERE url_id NOT IN ("
117 "SELECT id FROM urls)");
118 }
119
UpdateAndroidURLRow(AndroidURLID id,const std::string & raw_url,URLID url_id)120 bool AndroidURLsDatabase::UpdateAndroidURLRow(AndroidURLID id,
121 const std::string& raw_url,
122 URLID url_id) {
123 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
124 "UPDATE android_urls SET raw_url = ?, url_id = ? WHERE id = ?"));
125
126 statement.BindString(0, raw_url);
127 statement.BindInt64(1, url_id);
128 statement.BindInt64(2, id);
129
130 if (!statement.is_valid()) {
131 LOG(ERROR) << GetDB().GetErrorMessage();
132 return false;
133 }
134
135 if (!statement.Run()) {
136 LOG(ERROR) << GetDB().GetErrorMessage();
137 return false;
138 }
139
140 return true;
141 }
142
ClearAndroidURLRows()143 bool AndroidURLsDatabase::ClearAndroidURLRows() {
144 // The android_urls table might not exist if the Android content provider is
145 // never used, especially in the unit tests. See http://b/6385692.
146 if (GetDB().DoesTableExist("android_urls"))
147 return GetDB().Execute("DELETE FROM android_urls");
148
149 return true;
150 }
151
MigrateToVersion22()152 bool AndroidURLsDatabase::MigrateToVersion22() {
153 if (!GetDB().DoesTableExist("android_urls"))
154 return true;
155
156 if (!GetDB().Execute("ALTER TABLE android_urls RENAME TO android_urls_tmp"))
157 return false;
158
159 if (!GetDB().Execute("DROP INDEX android_urls_raw_url_idx"))
160 return false;
161
162 if (!GetDB().Execute("DROP INDEX android_urls_url_id_idx"))
163 return false;
164
165 if (!CreateAndroidURLsTable())
166 return false;
167
168 if (!GetDB().Execute(
169 "INSERT INTO android_urls (id, raw_url, url_id) "
170 "SELECT id, raw_url, url_id FROM android_urls_tmp"))
171 return false;
172
173 if (!GetDB().Execute("DROP TABLE android_urls_tmp"))
174 return false;
175
176 return true;
177 }
178
179 } // namespace history
180