1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "calllog_database.h"
17
18 #include "common.h"
19 #include "contacts_database.h"
20 #include "contacts_type.h"
21
22 namespace OHOS {
23 namespace Contacts {
24 std::shared_ptr<CallLogDataBase> CallLogDataBase::callLogDataBase_ = nullptr;
25 std::shared_ptr<OHOS::NativeRdb::RdbStore> CallLogDataBase::store_ = nullptr;
26
CallLogDataBase()27 CallLogDataBase::CallLogDataBase()
28 {
29 std::string g_databaseName = ContactsPath::RDB_EL1_PATH + "calls.db";
30 HILOG_INFO("CallLogDataBase g_databaseName :%{public}s", g_databaseName.c_str());
31 int errCode = OHOS::NativeRdb::E_OK;
32 OHOS::NativeRdb::RdbStoreConfig config(g_databaseName);
33 SqliteOpenHelperCallLogCallback sqliteOpenHelperCallback;
34 store_ = OHOS::NativeRdb::RdbHelper::GetRdbStore(config, DATABASE_OPEN_VERSION, sqliteOpenHelperCallback, errCode);
35 if (errCode != OHOS::NativeRdb::E_OK) {
36 HILOG_ERROR("CallLogDataBase errCode :%{public}d", errCode);
37 } else {
38 HILOG_INFO("CallLogDataBase errCode :%{public}d", errCode);
39 }
40 }
41
GetInstance()42 std::shared_ptr<CallLogDataBase> CallLogDataBase::GetInstance()
43 {
44 if (callLogDataBase_ == nullptr) {
45 callLogDataBase_.reset(new CallLogDataBase());
46 return callLogDataBase_;
47 }
48 return callLogDataBase_;
49 }
50
BeginTransaction()51 int CallLogDataBase::BeginTransaction()
52 {
53 if (store_ == nullptr) {
54 HILOG_ERROR("CallLogDataBase BeginTransaction store_ is nullptr");
55 return RDB_OBJECT_EMPTY;
56 }
57 int ret = store_->BeginTransaction();
58 if (ret != OHOS::NativeRdb::E_OK) {
59 HILOG_ERROR("CallLogDataBase BeginTransaction fail :%{public}d", ret);
60 }
61 return ret;
62 }
63
Commit()64 int CallLogDataBase::Commit()
65 {
66 if (store_ == nullptr) {
67 HILOG_ERROR(" CallLogDataBase Commit store_ is nullptr");
68 return RDB_OBJECT_EMPTY;
69 }
70 int ret = store_->Commit();
71 if (ret != OHOS::NativeRdb::E_OK) {
72 HILOG_ERROR(" CallLogDataBase Commit fail :%{public}d", ret);
73 }
74 return ret;
75 }
76
RollBack()77 int CallLogDataBase::RollBack()
78 {
79 if (store_ == nullptr) {
80 HILOG_ERROR(" CallLogDataBase RollBack store_ is nullptr");
81 return RDB_OBJECT_EMPTY;
82 }
83 int ret = store_->RollBack();
84 if (ret != OHOS::NativeRdb::E_OK) {
85 HILOG_ERROR(" CallLogDataBase RollBack fail :%{public}d", ret);
86 }
87 return ret;
88 }
89
OnCreate(OHOS::NativeRdb::RdbStore & store)90 int SqliteOpenHelperCallLogCallback::OnCreate(OHOS::NativeRdb::RdbStore &store)
91 {
92 std::vector<int> judgeSuccess;
93 judgeSuccess.push_back(store.ExecuteSql(CREATE_VOICEMAIL));
94 judgeSuccess.push_back(store.ExecuteSql(CREATE_CALLLOG));
95 judgeSuccess.push_back(store.ExecuteSql(CREATE_REPLYING));
96 judgeSuccess.push_back(store.ExecuteSql(CREATE_DATABASE_BACKUP_TASK));
97 judgeSuccess.push_back(store.ExecuteSql(CREATE_INSERT_BACKUP_TIME));
98 judgeSuccess.push_back(store.ExecuteSql(CALL_LOG_PHONE_NUMBER_INDEX));
99 unsigned int size = judgeSuccess.size();
100 for (unsigned int i = 0; i < size; i++) {
101 if (judgeSuccess[i] != OHOS::NativeRdb::E_OK) {
102 HILOG_ERROR("SqliteOpenHelperCallLogCallback create table error : %{public}d", judgeSuccess[i]);
103 }
104 }
105 return OHOS::NativeRdb::E_OK;
106 }
107
OnUpgrade(OHOS::NativeRdb::RdbStore & store,int oldVersion,int newVersion)108 int SqliteOpenHelperCallLogCallback::OnUpgrade(OHOS::NativeRdb::RdbStore &store, int oldVersion, int newVersion)
109 {
110 HILOG_INFO("OnUpgrade oldVersion is %{public}d , newVersion is %{public}d", oldVersion, newVersion);
111 if (oldVersion < newVersion && newVersion == DATABASE_NEW_VERSION) {
112 store.ExecuteSql("ALTER TABLE database_backup_task ADD COLUMN sync TEXT");
113 }
114 if (oldVersion < newVersion && newVersion == DATABASE_VERSION_2) {
115 UpgradeToV2(store, oldVersion, newVersion);
116 }
117 store.SetVersion(newVersion);
118 return OHOS::NativeRdb::E_OK;
119 }
120
UpgradeToV2(OHOS::NativeRdb::RdbStore & store,int oldVersion,int newVersion)121 void SqliteOpenHelperCallLogCallback::UpgradeToV2(OHOS::NativeRdb::RdbStore &store, int oldVersion, int newVersion)
122 {
123 if (oldVersion >= newVersion || newVersion != DATABASE_VERSION_2) {
124 return;
125 }
126 store.ExecuteSql("ALTER TABLE callog ADD COLUMN features INTEGERT DEFAULT 0;");
127 }
128
OnDowngrade(OHOS::NativeRdb::RdbStore & store,int oldVersion,int newVersion)129 int SqliteOpenHelperCallLogCallback::OnDowngrade(OHOS::NativeRdb::RdbStore &store, int oldVersion, int newVersion)
130 {
131 HILOG_INFO("OnDowngrade oldVersion is %{public}d , newVersion is %{public}d", oldVersion, newVersion);
132 if (oldVersion > newVersion && newVersion == DATABASE_OPEN_VERSION) {
133 store.ExecuteSql(
134 "CREATE TABLE IF NOT EXISTS database_backup (id INTEGER PRIMARY KEY AUTOINCREMENT, backup_time "
135 "TEXT, backup_path TEXT, remarks TEXT)");
136 store.ExecuteSql(
137 "INSERT INTO database_backup(id, backup_time, backup_path, remarks) SELECT id, "
138 "backup_time, backup_path, remarks FROM database_backup_task");
139 store.ExecuteSql("DROP table database_backup_task");
140 store.ExecuteSql("ALTER table database_backup RENAME TO database_backup_task");
141 store.ExecuteSql(CREATE_INSERT_BACKUP_TIME);
142 }
143 int ret = store.SetVersion(newVersion);
144 return ret;
145 }
146
147 /**
148 * @brief InsertCallLog operation
149 *
150 * @param insertValues Conditions for update operation
151 *
152 * @return InsertCallLog operation results
153 */
InsertCallLog(OHOS::NativeRdb::ValuesBucket insertValues)154 int64_t CallLogDataBase::InsertCallLog(OHOS::NativeRdb::ValuesBucket insertValues)
155 {
156 int64_t outRowId = RDB_EXECUTE_FAIL;
157 if (store_ == nullptr) {
158 HILOG_ERROR("CallLogDataBase Insert store_ is nullptr");
159 return RDB_OBJECT_EMPTY;
160 }
161 QueryContactsByInsertCalls(insertValues);
162 int ret = store_->Insert(outRowId, CallsTableName::CALLLOG, insertValues);
163 if (ret != OHOS::NativeRdb::E_OK) {
164 HILOG_ERROR("CallLogDataBase InsertCallLog ret :%{public}d", ret);
165 return RDB_EXECUTE_FAIL;
166 }
167 return outRowId;
168 }
169
170 /**
171 * @brief UpdateCallLog operation
172 *
173 * @param values Conditions for update operation
174 * @param predicates Conditions for update operation
175 *
176 * @return UpdateCallLog operation results
177 */
UpdateCallLog(OHOS::NativeRdb::ValuesBucket values,OHOS::NativeRdb::RdbPredicates & predicates)178 int CallLogDataBase::UpdateCallLog(OHOS::NativeRdb::ValuesBucket values, OHOS::NativeRdb::RdbPredicates &predicates)
179 {
180 if (store_ == nullptr) {
181 HILOG_ERROR("CallLogDataBase Update store_ is nullptr");
182 return RDB_OBJECT_EMPTY;
183 }
184 if (values.HasColumn(CallLogColumns::PHONE_NUMBER)) {
185 QueryContactsByInsertCalls(values);
186 }
187 int changeRow;
188 int ret = store_->Update(changeRow, values, predicates);
189 if (ret != OHOS::NativeRdb::E_OK) {
190 HILOG_ERROR("CallLogDataBase UpdateCallLog ret :%{public}d", ret);
191 return RDB_EXECUTE_FAIL;
192 }
193 return ret;
194 }
195
196 /**
197 * @brief DeleteCallLog operation
198 *
199 * @param predicates Conditions for delete operation
200 *
201 * @return DeleteCallLog operation results
202 */
DeleteCallLog(OHOS::NativeRdb::RdbPredicates & predicates)203 int CallLogDataBase::DeleteCallLog(OHOS::NativeRdb::RdbPredicates &predicates)
204 {
205 if (store_ == nullptr) {
206 HILOG_ERROR("CallLogDataBase Delete store_ is nullptr");
207 return RDB_OBJECT_EMPTY;
208 }
209 int deleteRow;
210 int ret = store_->Delete(deleteRow, predicates);
211 if (ret != OHOS::NativeRdb::E_OK) {
212 HILOG_ERROR("CallLogDataBase DeleteCallLog ret :%{public}d", ret);
213 return RDB_EXECUTE_FAIL;
214 }
215 return ret;
216 }
217
218 /**
219 * @brief QueryContacts operation
220 *
221 * @param predicates Conditions for query operation
222 * @param columns Conditions for query operation
223 *
224 * @return Query database results
225 */
Query(OHOS::NativeRdb::RdbPredicates & predicates,std::vector<std::string> columns)226 std::shared_ptr<OHOS::NativeRdb::ResultSet> CallLogDataBase::Query(
227 OHOS::NativeRdb::RdbPredicates &predicates, std::vector<std::string> columns)
228 {
229 if (store_ == nullptr) {
230 HILOG_ERROR("CallLogDataBase Delete store_ is nullptr");
231 return nullptr;
232 }
233
234 return store_->Query(predicates, columns);
235 }
236
237 /**
238 * @brief QueryContacts By InsertCallLog get name and phone to UpdateTopContact
239 *
240 * @param insertValues Inserted data values
241 *
242 * @return void
243 */
QueryContactsByInsertCalls(OHOS::NativeRdb::ValuesBucket & insertValues)244 void CallLogDataBase::QueryContactsByInsertCalls(OHOS::NativeRdb::ValuesBucket &insertValues)
245 {
246 if (!insertValues.HasColumn(CallLogColumns::PHONE_NUMBER)) {
247 HILOG_ERROR("QueryContactsByInsertCalls phone_number is required");
248 return;
249 }
250 OHOS::NativeRdb::ValueObject value;
251 insertValues.GetObject(CallLogColumns::PHONE_NUMBER, value);
252 std::string phoneNumber;
253 value.GetString(phoneNumber);
254 ContactsType contactsType;
255 static std::shared_ptr<ContactsDataBase> contactsDataBase = ContactsDataBase::GetInstance();
256 if (contactsDataBase == nullptr || contactsDataBase->contactStore_ == nullptr) {
257 HILOG_ERROR("ContactsDataBase is nullptr or ContactsDataBase->contactStore_ is nullptr");
258 return;
259 }
260 int typeNameId = contactsType.LookupTypeId(contactsDataBase->contactStore_, ContentTypeData::PHONE);
261 std::string sql = "SELECT display_name, contact_id FROM ";
262 sql.append(ViewName::VIEW_CONTACT_DATA)
263 .append(" WHERE raw_contact_id = ")
264 .append("(SELECT min(raw_contact_id) FROM ")
265 .append(ViewName::VIEW_CONTACT_DATA)
266 .append(" WHERE detail_info = ?")
267 .append(" AND is_deleted = 0")
268 .append(") AND type_id = ")
269 .append(std::to_string(typeNameId))
270 .append(" AND is_deleted = 0");
271 std::vector<std::string> selectionArgs;
272 selectionArgs.push_back(phoneNumber);
273 auto resultSet = contactsDataBase->contactStore_->QuerySql(sql, selectionArgs);
274 if (resultSet->GoToFirstRow() == OHOS::NativeRdb::E_OK) {
275 std::string quickSearchKey;
276 std::string name;
277 resultSet->GetString(0, name);
278 resultSet->GetString(1, quickSearchKey);
279 resultSet->GoToNextRow();
280 insertValues.Delete(CallLogColumns::DISPLAY_NAME);
281 insertValues.PutString(CallLogColumns::DISPLAY_NAME, name);
282 insertValues.Delete(CallLogColumns::QUICK_SEARCH_KEY);
283 insertValues.PutString(CallLogColumns::QUICK_SEARCH_KEY, quickSearchKey);
284 }
285 resultSet->Close();
286 int ret = UpdateTopContact(insertValues);
287 if (ret != OHOS::NativeRdb::E_OK) {
288 HILOG_ERROR("QueryContactsByInsertCalls UpdateTopContact is error");
289 }
290 }
291
292 /**
293 * @brief Update the callLog contact frequency and contact time
294 *
295 * @param insertValues Get contact time
296 * @param phoneNumber phoneNumber To select callLog
297 *
298 * @return update frequency and time result code
299 */
UpdateTopContact(OHOS::NativeRdb::ValuesBucket & insertValues)300 int CallLogDataBase::UpdateTopContact(OHOS::NativeRdb::ValuesBucket &insertValues)
301 {
302 if (!insertValues.HasColumn(CallLogColumns::BEGIN_TIME)) {
303 return RDB_EXECUTE_FAIL;
304 }
305 OHOS::NativeRdb::ValueObject value;
306 insertValues.GetObject(CallLogColumns::BEGIN_TIME, value);
307 int contactedTime;
308 value.GetInt(contactedTime);
309 std::string sqlBuild = "UPDATE ";
310 sqlBuild.append(ContactTableName::RAW_CONTACT)
311 .append(" SET lastest_contacted_time = ")
312 .append(std::to_string(contactedTime))
313 .append(", contacted_count = (contacted_count + 1) ")
314 .append(" WHERE contact_id = ")
315 .append("(SELECT DISTINCT min(contact_id) FROM ")
316 .append(ViewName::VIEW_CONTACT_DATA)
317 .append(" WHERE detail_info = ? ")
318 .append(")");
319 std::vector<OHOS::NativeRdb::ValueObject> bindArgs;
320 OHOS::NativeRdb::ValueObject phone;
321 insertValues.GetObject(CallLogColumns::PHONE_NUMBER, phone);
322 bindArgs.push_back(phone);
323 int ret = ContactsDataBase::GetInstance()->contactStore_->ExecuteSql(sqlBuild, bindArgs);
324 if (ret != OHOS::NativeRdb::E_OK) {
325 HILOG_ERROR("store ExecuteSql error");
326 return RDB_EXECUTE_FAIL;
327 }
328 return RDB_EXECUTE_OK;
329 }
330 } // namespace Contacts
331 } // namespace OHOS