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