1 /*
2 * Copyright (c) 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 "reminder_store.h"
17
18 #include <filesystem>
19 #include <sstream>
20 #include <sys/stat.h>
21 #include <unistd.h>
22
23 #include "fa_ability_context.h"
24 #include "ans_log_wrapper.h"
25 #include "reminder_table.h"
26 #include "reminder_table_old.h"
27 #include "reminder_request_alarm.h"
28 #include "reminder_request_timer.h"
29 #include "reminder_request_calendar.h"
30 #include "reminder_store_strategy.h"
31 #include "reminder_utils.h"
32
33 namespace OHOS {
34 namespace Notification {
35 namespace {
36 constexpr int32_t REMINDER_RDB_VERSION_V1 = 1;
37 constexpr int32_t REMINDER_RDB_VERSION_V2 = 2;
38 constexpr int32_t REMINDER_RDB_VERSION_V3 = 3;
39 constexpr int32_t REMINDER_RDB_VERSION_V4 = 4;
40 constexpr int32_t REMINDER_RDB_VERSION_V5 = 5;
41 constexpr int32_t REMINDER_RDB_VERSION_V6 = 6;
42 constexpr int32_t REMINDER_RDB_VERSION_V7 = 7;
43 constexpr int32_t REMINDER_RDB_VERSION_V8 = 8;
44 constexpr int32_t REMINDER_RDB_VERSION = 9;
45 constexpr int64_t DURATION_PRELOAD_TIME = 10 * 60 * 60 * 1000; // 10h, millisecond
46 }
47
48 const int32_t ReminderStore::STATE_OK = 0;
49 const int32_t ReminderStore::STATE_FAIL = -1;
50 const std::string ReminderStore::REMINDER_DB_DIR = "/data/service/el1/public/notification/";
51 const std::string ReminderStore::REMINDER_DB_NAME = "notification.db";
52
OnCreate(NativeRdb::RdbStore & store)53 int32_t ReminderStore::ReminderStoreDataCallBack::OnCreate(NativeRdb::RdbStore& store)
54 {
55 ANSR_LOGI("Create table");
56 return CreateTable(store);
57 }
58
OnUpgrade(NativeRdb::RdbStore & store,int32_t oldVersion,int32_t newVersion)59 int32_t ReminderStore::ReminderStoreDataCallBack::OnUpgrade(
60 NativeRdb::RdbStore& store, int32_t oldVersion, int32_t newVersion)
61 {
62 ANSR_LOGI("OnUpgrade oldVersion is %{public}d, newVersion is %{public}d", oldVersion, newVersion);
63 if (oldVersion < newVersion && newVersion == REMINDER_RDB_VERSION) {
64 switch (oldVersion) {
65 case REMINDER_RDB_VERSION_V1:
66 AddRdbColum(store, ReminderTable::TABLE_NAME, "groupId", "TEXT", "''");
67 [[fallthrough]];
68 case REMINDER_RDB_VERSION_V2:
69 AddRdbColum(store, ReminderTable::TABLE_NAME, "custom_ring_uri", "TEXT", "''");
70 AddRdbColum(store, ReminderTable::TABLE_NAME, "snooze_slot_id", "INT", "3");
71 [[fallthrough]];
72 case REMINDER_RDB_VERSION_V3:
73 AddRdbColum(store, ReminderTable::TABLE_NAME, "creator_bundle_name", "TEXT", "''");
74 [[fallthrough]];
75 case REMINDER_RDB_VERSION_V4:
76 CreateTable(store);
77 CopyData(store);
78 [[fallthrough]];
79 case REMINDER_RDB_VERSION_V5:
80 AddRdbColum(store, ReminderBaseTable::TABLE_NAME, ReminderBaseTable::CREATOR_UID, "INT", "-1");
81 [[fallthrough]];
82 case REMINDER_RDB_VERSION_V6:
83 AddRdbColum(store, ReminderCalendarTable::TABLE_NAME,
84 ReminderCalendarTable::CALENDAR_LAST_DATE_TIME, "BIGINT", "0");
85 [[fallthrough]];
86 case REMINDER_RDB_VERSION_V7:
87 AddRdbColum(store, ReminderBaseTable::TABLE_NAME, ReminderBaseTable::TITLE_RESOURCE_ID, "INT", "0");
88 AddRdbColum(store, ReminderBaseTable::TABLE_NAME,
89 ReminderBaseTable::CONTENT_RESOURCE_ID, "INT", "0");
90 AddRdbColum(store, ReminderBaseTable::TABLE_NAME,
91 ReminderBaseTable::SNOOZE_CONTENT_RESOURCE_ID, "INT", "0");
92 AddRdbColum(store, ReminderBaseTable::TABLE_NAME,
93 ReminderBaseTable::EXPIRED_CONTENT_RESOURCE_ID, "INT", "0");
94 [[fallthrough]];
95 case REMINDER_RDB_VERSION_V8:
96 AddRdbColum(store, ReminderBaseTable::TABLE_NAME, ReminderBaseTable::RING_CHANNEL, "INT", "0");
97 [[fallthrough]];
98 default:
99 break;
100 }
101 }
102 store.SetVersion(newVersion);
103 return NativeRdb::E_OK;
104 }
105
OnDowngrade(NativeRdb::RdbStore & store,int32_t currentVersion,int32_t targetVersion)106 int32_t ReminderStore::ReminderStoreDataCallBack::OnDowngrade(
107 NativeRdb::RdbStore& store, int32_t currentVersion, int32_t targetVersion)
108 {
109 ANSR_LOGI("OnDowngrade currentVersion is %{public}d, targetVersion is %{public}d", currentVersion, targetVersion);
110 if (currentVersion > targetVersion && targetVersion <= REMINDER_RDB_VERSION_V4) {
111 std::string createSql = "CREATE TABLE IF NOT EXISTS " + ReminderTable::TABLE_NAME + " ("
112 + ReminderTable::ADD_COLUMNS + ")";
113 int32_t ret = store.ExecuteSql(createSql);
114 if (ret != NativeRdb::E_OK) {
115 ANSR_LOGE("Create reminder table failed:%{public}d", ret);
116 }
117 return ret;
118 }
119 store.SetVersion(targetVersion);
120 return NativeRdb::E_OK;
121 }
122
CreateTable(NativeRdb::RdbStore & store)123 int32_t ReminderStore::ReminderStoreDataCallBack::CreateTable(NativeRdb::RdbStore& store)
124 {
125 std::string createSql = "CREATE TABLE IF NOT EXISTS " + ReminderBaseTable::TABLE_NAME + " ("
126 + ReminderBaseTable::ADD_COLUMNS + ")";
127 int32_t ret = store.ExecuteSql(createSql);
128 if (ret != NativeRdb::E_OK) {
129 ANSR_LOGE("Create reminder_base table failed:%{public}d", ret);
130 return ret;
131 }
132
133 createSql = "CREATE TABLE IF NOT EXISTS " + ReminderAlarmTable::TABLE_NAME + " ("
134 + ReminderAlarmTable::ADD_COLUMNS + ")";
135 ret = store.ExecuteSql(createSql);
136 if (ret != NativeRdb::E_OK) {
137 ANSR_LOGE("Create reminder_alarm table failed:%{public}d", ret);
138 return ret;
139 }
140
141 createSql = "CREATE TABLE IF NOT EXISTS " + ReminderCalendarTable::TABLE_NAME + " ("
142 + ReminderCalendarTable::ADD_COLUMNS + ")";
143 ret = store.ExecuteSql(createSql);
144 if (ret != NativeRdb::E_OK) {
145 ANSR_LOGE("Create reminder_calendar table failed:%{public}d", ret);
146 return ret;
147 }
148
149 createSql = "CREATE TABLE IF NOT EXISTS " + ReminderTimerTable::TABLE_NAME + " ("
150 + ReminderTimerTable::ADD_COLUMNS + ")";
151 ret = store.ExecuteSql(createSql);
152 if (ret != NativeRdb::E_OK) {
153 ANSR_LOGE("Create reminder_timer table failed:%{public}d", ret);
154 return ret;
155 }
156 return ret;
157 }
158
CopyData(NativeRdb::RdbStore & store)159 int32_t ReminderStore::ReminderStoreDataCallBack::CopyData(NativeRdb::RdbStore& store)
160 {
161 // select old data
162 auto reminders = GetOldReminders(store);
163 // insert new data
164 if (!reminders.empty()) {
165 InsertNewReminders(store, reminders);
166 }
167 // delete old table
168 std::string sql = "DELETE FROM " + ReminderTable::TABLE_NAME;
169 store.ExecuteSql(sql);
170 return NativeRdb::E_OK;
171 }
172
GetOldReminders(NativeRdb::RdbStore & store)173 std::vector<sptr<ReminderRequest>> ReminderStore::ReminderStoreDataCallBack::GetOldReminders(NativeRdb::RdbStore& store)
174 {
175 std::string sql = "SELECT " + ReminderTable::SELECT_COLUMNS + " FROM "
176 + ReminderTable::TABLE_NAME;
177 std::vector<sptr<ReminderRequest>> reminders;
178 std::vector<std::string> whereArgs;
179 auto queryResult = store.QuerySql(sql, whereArgs);
180 if (queryResult == nullptr) {
181 return reminders;
182 }
183
184 while (queryResult->GoToNextRow() == NativeRdb::E_OK) {
185 int32_t reminderId;
186 int32_t reminderType;
187 GetInt32Val(queryResult, ReminderTable::REMINDER_ID, reminderId);
188 GetInt32Val(queryResult, ReminderTable::REMINDER_TYPE, reminderType);
189
190 sptr<ReminderRequest> reminderReq = nullptr;
191 switch (reminderType) {
192 case (static_cast<int32_t>(ReminderRequest::ReminderType::TIMER)): {
193 reminderReq = new (std::nothrow) ReminderRequestTimer(reminderId);
194 ReminderTimerStrategy::RecoverFromOldVersion(reminderReq, queryResult);
195 break;
196 }
197 case (static_cast<int32_t>(ReminderRequest::ReminderType::CALENDAR)): {
198 reminderReq = new (std::nothrow) ReminderRequestCalendar(reminderId);
199 ReminderCalendarStrategy::RecoverFromOldVersion(reminderReq, queryResult);
200 break;
201 }
202 case (static_cast<int32_t>(ReminderRequest::ReminderType::ALARM)): {
203 reminderReq = new (std::nothrow) ReminderRequestAlarm(reminderId);
204 ReminderAlarmStrategy::RecoverFromOldVersion(reminderReq, queryResult);
205 break;
206 }
207 default: {
208 break;
209 }
210 }
211 if (reminderReq != nullptr) {
212 reminders.push_back(reminderReq);
213 }
214 }
215 return reminders;
216 }
217
InsertNewReminders(NativeRdb::RdbStore & store,const std::vector<sptr<ReminderRequest>> & reminders)218 void ReminderStore::ReminderStoreDataCallBack::InsertNewReminders(NativeRdb::RdbStore& store,
219 const std::vector<sptr<ReminderRequest>>& reminders)
220 {
221 for (auto reminder : reminders) {
222 int64_t rowId = STATE_FAIL;
223 NativeRdb::ValuesBucket baseValues;
224 ReminderStrategy::AppendValuesBucket(reminder, baseValues, true);
225
226 store.BeginTransaction();
227 // insert reminder_base
228 int32_t ret = store.Insert(rowId, ReminderBaseTable::TABLE_NAME, baseValues);
229 if (ret != NativeRdb::E_OK) {
230 ANSR_LOGE("Insert reminder_base operation failed, result: %{public}d, reminderId=%{public}d.",
231 ret, reminder->GetReminderId());
232 store.RollBack();
233 continue;
234 }
235
236 // insert reminder_alarm or reminder_calendar
237 NativeRdb::ValuesBucket values;
238 rowId = STATE_FAIL;
239 switch (reminder->GetReminderType()) {
240 case ReminderRequest::ReminderType::CALENDAR:
241 ReminderCalendarStrategy::AppendValuesBucket(reminder, values);
242 ret = store.Insert(rowId, ReminderCalendarTable::TABLE_NAME, values);
243 break;
244 case ReminderRequest::ReminderType::ALARM:
245 ReminderAlarmStrategy::AppendValuesBucket(reminder, values);
246 ret = store.Insert(rowId, ReminderAlarmTable::TABLE_NAME, values);
247 break;
248 case ReminderRequest::ReminderType::TIMER:
249 ReminderTimerStrategy::AppendValuesBucket(reminder, values);
250 ret = store.Insert(rowId, ReminderTimerTable::TABLE_NAME, values);
251 break;
252 default:
253 ANSR_LOGE("Insert reminder_base operation failed, unkown type.");
254 ret = STATE_FAIL;
255 break;
256 }
257 if (ret != NativeRdb::E_OK) {
258 ANSR_LOGE("Insert operation failed, result: %{public}d, reminderId=%{public}d.",
259 ret, reminder->GetReminderId());
260 store.RollBack();
261 continue;
262 }
263 store.Commit();
264 ANSR_LOGD("Insert successfully, reminderId=%{public}d.", reminder->GetReminderId());
265 }
266 }
267
AddRdbColum(NativeRdb::RdbStore & store,const std::string & tableName,const std::string & columnName,const std::string & columnType,const std::string & defValue)268 void ReminderStore::ReminderStoreDataCallBack::AddRdbColum(NativeRdb::RdbStore& store, const std::string& tableName,
269 const std::string& columnName, const std::string& columnType, const std::string& defValue)
270 {
271 std::string sqlStr = "";
272 sqlStr = "ALTER TABLE " + tableName + " ADD " + columnName + " " + columnType + " DEFAULT " + defValue + ";";
273 ANSR_LOGD("AddRdbColum sqlStr = %{public}s", sqlStr.c_str());
274 int errorCode = store.ExecuteSql(sqlStr);
275 if (errorCode != NativeRdb::E_OK) {
276 ANSR_LOGE("AddRdbColum error,errorCode is = %{public}d", errorCode);
277 }
278 }
279
Init()280 __attribute__((no_sanitize("cfi"))) int32_t ReminderStore::Init()
281 {
282 ANSR_LOGD("Reminder store init.");
283 std::lock_guard<std::mutex> lock(initMutex_);
284 if (access(REMINDER_DB_DIR.c_str(), F_OK) != 0) {
285 int createDir = mkdir(REMINDER_DB_DIR.c_str(), S_IRWXU);
286 if (createDir != 0) {
287 ANSR_LOGE("Failed to create directory %{private}s", REMINDER_DB_DIR.c_str());
288 return STATE_FAIL;
289 }
290 }
291 ReminderTable::InitDbColumns();
292 ReminderBaseTable::InitDbColumns();
293 ReminderTimerTable::InitDbColumns();
294 ReminderAlarmTable::InitDbColumns();
295 ReminderCalendarTable::InitDbColumns();
296
297 std::string dbConfig = REMINDER_DB_DIR + REMINDER_DB_NAME;
298 NativeRdb::RdbStoreConfig config(dbConfig);
299 config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
300
301 ReminderStoreDataCallBack rdbDataCallBack;
302 int32_t errCode = STATE_FAIL;
303 rdbStore_ = NativeRdb::RdbHelper::GetRdbStore(config, REMINDER_RDB_VERSION, rdbDataCallBack, errCode);
304 if (rdbStore_ == nullptr) {
305 ANSR_LOGE("ReminderStore init fail, errCode %{public}d.", errCode);
306 return STATE_FAIL;
307 }
308 int32_t result = InitData();
309
310 return result;
311 }
312
Delete(const int32_t reminderId)313 __attribute__((no_sanitize("cfi"))) int32_t ReminderStore::Delete(const int32_t reminderId)
314 {
315 if (rdbStore_ == nullptr) {
316 ANSR_LOGE("Rdb store is not initialized.");
317 return STATE_FAIL;
318 }
319 std::string condition = ReminderBaseTable::REMINDER_ID + " = " + std::to_string(reminderId);
320 rdbStore_->BeginTransaction();
321 int32_t delRows = STATE_FAIL;
322 std::vector<std::string> whereArgs;
323 int32_t ret = rdbStore_->Delete(delRows, ReminderBaseTable::TABLE_NAME, condition, whereArgs);
324 if (ret != NativeRdb::E_OK) {
325 ANSR_LOGE("Delete from %{public}s failed, reminderId = %{public}d",
326 ReminderBaseTable::TABLE_NAME.c_str(), reminderId);
327 rdbStore_->RollBack();
328 return STATE_FAIL;
329 }
330 delRows = STATE_FAIL;
331 ret = rdbStore_->Delete(delRows, ReminderAlarmTable::TABLE_NAME, condition, whereArgs);
332 if (ret != NativeRdb::E_OK) {
333 ANSR_LOGE("Delete from %{public}s failed, reminderId = %{public}d",
334 ReminderAlarmTable::TABLE_NAME.c_str(), reminderId);
335 rdbStore_->RollBack();
336 return STATE_FAIL;
337 }
338 delRows = STATE_FAIL;
339 ret = rdbStore_->Delete(delRows, ReminderCalendarTable::TABLE_NAME, condition, whereArgs);
340 if (ret != NativeRdb::E_OK) {
341 ANSR_LOGE("Delete from %{public}s failed, reminderId = %{public}d",
342 ReminderCalendarTable::TABLE_NAME.c_str(), reminderId);
343 rdbStore_->RollBack();
344 return STATE_FAIL;
345 }
346 delRows = STATE_FAIL;
347 ret = rdbStore_->Delete(delRows, ReminderTimerTable::TABLE_NAME, condition, whereArgs);
348 if (ret != NativeRdb::E_OK) {
349 ANSR_LOGE("Delete from %{public}s failed, reminderId = %{public}d",
350 ReminderTimerTable::TABLE_NAME.c_str(), reminderId);
351 rdbStore_->RollBack();
352 return STATE_FAIL;
353 }
354 rdbStore_->Commit();
355 return STATE_OK;
356 }
357
Delete(const std::string & pkg,const int32_t userId,const int32_t uid)358 __attribute__((no_sanitize("cfi"))) int32_t ReminderStore::Delete(const std::string& pkg, const int32_t userId,
359 const int32_t uid)
360 {
361 std::string assoConditon = "(SELECT " + ReminderBaseTable::REMINDER_ID + " FROM " + ReminderBaseTable::TABLE_NAME
362 + " WHERE " + ReminderBaseTable::TABLE_NAME + "." + ReminderBaseTable::PACKAGE_NAME + " = '" + pkg
363 + "' AND " + ReminderBaseTable::TABLE_NAME + "." + ReminderBaseTable::USER_ID + " = " + std::to_string(userId);
364
365 std::string baseCondtion = ReminderBaseTable::PACKAGE_NAME + " = '" + pkg + "' AND "
366 + ReminderBaseTable::USER_ID + " = " + std::to_string(userId);
367
368 if (uid != -1) {
369 assoConditon += " AND " + ReminderBaseTable::TABLE_NAME + "." + ReminderBaseTable::UID
370 + " = " + std::to_string(uid);
371 baseCondtion += " AND " + ReminderBaseTable::UID + " = " + std::to_string(uid);
372 }
373 assoConditon += ")";
374 return Delete(baseCondtion, assoConditon);
375 }
376
DeleteUser(const int32_t userId)377 __attribute__((no_sanitize("cfi"))) int32_t ReminderStore::DeleteUser(const int32_t userId)
378 {
379 std::string assoConditon = "(SELECT " + ReminderBaseTable::REMINDER_ID + " FROM " + ReminderBaseTable::TABLE_NAME
380 + " WHERE " + ReminderBaseTable::TABLE_NAME + "." + ReminderBaseTable::USER_ID + " = "
381 + std::to_string(userId) + ")";
382
383 std::string baseCondtion = ReminderBaseTable::USER_ID + " = " + std::to_string(userId);
384 return Delete(baseCondtion, assoConditon);
385 }
386
UpdateOrInsert(const sptr<ReminderRequest> & reminder)387 int32_t ReminderStore::UpdateOrInsert(
388 const sptr<ReminderRequest>& reminder)
389 {
390 if (rdbStore_ == nullptr) {
391 ANSR_LOGE("Rdb store is not initialized.");
392 return STATE_FAIL;
393 }
394 if (reminder != nullptr && reminder->IsShare()) {
395 return STATE_OK;
396 }
397 if (IsReminderExist(reminder)) {
398 return Update(reminder);
399 } else {
400 return Insert(reminder);
401 }
402 }
403
GetMaxId()404 int32_t ReminderStore::GetMaxId()
405 {
406 if (rdbStore_ == nullptr) {
407 ANSR_LOGE("Rdb store is not initialized.");
408 return STATE_FAIL;
409 }
410 std::string queryCondition = "SELECT " + ReminderBaseTable::REMINDER_ID
411 + " FROM " + ReminderBaseTable::TABLE_NAME + " ORDER BY "
412 + ReminderBaseTable::REMINDER_ID + " DESC";
413 auto queryResultSet = Query(queryCondition);
414 if (queryResultSet == nullptr) {
415 ANSR_LOGE("QueryResultSet is null.");
416 return STATE_FAIL;
417 }
418 int32_t resultNum = 0;
419 queryResultSet->GetRowCount(resultNum);
420 if (resultNum == 0) {
421 ANSR_LOGI("QueryResultSet is zero.");
422 return STATE_FAIL;
423 }
424 queryResultSet->GoToNextRow();
425 int32_t maxId = STATE_FAIL;
426 int32_t result = queryResultSet->GetInt(0, maxId);
427 if (result != NativeRdb::E_OK) {
428 ANSR_LOGE("Query operation failed, result %{public}d.", result);
429 }
430 ANSR_LOGD("MaxId: %{public}d.", maxId);
431 return maxId;
432 }
433
GetAllValidReminders()434 __attribute__((no_sanitize("cfi"))) std::vector<sptr<ReminderRequest>> ReminderStore::GetAllValidReminders()
435 {
436 std::string sql = "SELECT " + ReminderBaseTable::SELECT_COLUMNS + " FROM "
437 + ReminderBaseTable::TABLE_NAME + " WHERE "
438 + ReminderBaseTable::IS_EXPIRED + " = 'false' ORDER BY "
439 + ReminderBaseTable::TRIGGER_TIME + " ASC";
440 ANSR_LOGD("GetAllValidReminders sql =%{public}s", sql.c_str());
441 return GetReminders(sql);
442 }
443
GetHalfHourReminders()444 __attribute__((no_sanitize("cfi"))) std::vector<sptr<ReminderRequest>> ReminderStore::GetHalfHourReminders()
445 {
446 int64_t nowTime = GetCurrentTime();
447 std::string sql = "SELECT * FROM " +
448 ReminderBaseTable::TABLE_NAME + " WHERE (" +
449 ReminderBaseTable::TABLE_NAME + "." + ReminderBaseTable::IS_EXPIRED + " = 'false' AND " +
450 ReminderBaseTable::TABLE_NAME + "." + ReminderBaseTable::REMINDER_TYPE + " != 1 AND " +
451 ReminderBaseTable::TABLE_NAME + "." + ReminderBaseTable::TRIGGER_TIME + " < " +
452 std::to_string(nowTime + DURATION_PRELOAD_TIME) + ") OR " +
453 ReminderBaseTable::TABLE_NAME + "." + ReminderBaseTable::REMINDER_ID + " IN " +
454 "(SELECT " + ReminderBaseTable::REMINDER_ID + " FROM " + ReminderCalendarTable::TABLE_NAME + " WHERE (" +
455 ReminderCalendarTable::TABLE_NAME + "." + ReminderCalendarTable::CALENDAR_DATE_TIME + " <= " +
456 std::to_string(nowTime + DURATION_PRELOAD_TIME) + " AND " +
457 ReminderCalendarTable::TABLE_NAME + "." + ReminderCalendarTable::CALENDAR_END_DATE_TIME + " >= " +
458 std::to_string(nowTime) + ") OR (" + (ReminderCalendarTable::CALENDAR_DATE_TIME) + " < " +
459 std::to_string(nowTime + DURATION_PRELOAD_TIME) + " AND " + ReminderCalendarTable::CALENDAR_END_DATE_TIME +
460 " = " + ReminderCalendarTable::CALENDAR_DATE_TIME + ")) ORDER BY " +
461 ReminderBaseTable::TRIGGER_TIME + " ASC";
462 ANSR_LOGD("GetHalfHourReminders sql =%{public}s", sql.c_str());
463 return GetReminders(sql);
464 }
465
GetUInt8Val(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,const std::string & name,uint8_t & value)466 void ReminderStore::GetUInt8Val(const std::shared_ptr<NativeRdb::ResultSet>& resultSet,
467 const std::string& name, uint8_t& value)
468 {
469 int32_t val;
470 GetInt32Val(resultSet, name, val);
471 value = static_cast<uint8_t>(val);
472 }
473
GetUInt16Val(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,const std::string & name,uint16_t & value)474 void ReminderStore::GetUInt16Val(const std::shared_ptr<NativeRdb::ResultSet>& resultSet,
475 const std::string& name, uint16_t& value)
476 {
477 int32_t val;
478 GetInt32Val(resultSet, name, val);
479 value = static_cast<uint16_t>(val);
480 }
481
GetInt32Val(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,const std::string & name,int32_t & value)482 void ReminderStore::GetInt32Val(const std::shared_ptr<NativeRdb::ResultSet>& resultSet,
483 const std::string& name, int32_t& value)
484 {
485 value = 0;
486 int32_t columnIndex = -1;
487 resultSet->GetColumnIndex(name, columnIndex);
488 if (columnIndex == -1) {
489 ANSR_LOGE("the column %{public}s does not exsit.", name.c_str());
490 return;
491 }
492 resultSet->GetInt(columnIndex, value);
493 }
494
GetInt64Val(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,const std::string & name,int64_t & value)495 void ReminderStore::GetInt64Val(const std::shared_ptr<NativeRdb::ResultSet>& resultSet,
496 const std::string& name, int64_t& value)
497 {
498 value = 0;
499 int32_t columnIndex = -1;
500 resultSet->GetColumnIndex(name, columnIndex);
501 if (columnIndex == -1) {
502 ANSR_LOGE("the column %{public}s does not exsit.", name.c_str());
503 return;
504 }
505 resultSet->GetLong(columnIndex, value);
506 }
507
GetUInt64Val(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,const std::string & name,uint64_t & value)508 void ReminderStore::GetUInt64Val(const std::shared_ptr<NativeRdb::ResultSet>& resultSet,
509 const std::string& name, uint64_t& value)
510 {
511 int64_t val;
512 GetInt64Val(resultSet, name, val);
513 value = static_cast<uint64_t>(val);
514 }
515
GetStringVal(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,const std::string & name,std::string & value)516 void ReminderStore::GetStringVal(const std::shared_ptr<NativeRdb::ResultSet>& resultSet,
517 const std::string& name, std::string& value)
518 {
519 int32_t columnIndex = -1;
520 resultSet->GetColumnIndex(name, columnIndex);
521 if (columnIndex == -1) {
522 ANSR_LOGE("the column %{public}s does not exsit.", name.c_str());
523 return;
524 }
525 resultSet->GetString(columnIndex, value);
526 }
527
InitData()528 __attribute__((no_sanitize("cfi"))) int32_t ReminderStore::InitData()
529 {
530 ANSR_LOGD("Reminder data init.");
531 if (rdbStore_ == nullptr) {
532 ANSR_LOGE("Rdb store is not initialized.");
533 return STATE_FAIL;
534 }
535 // delete all the reminders which IS_EXPIRED is true.
536 std::string deleteCondition = ReminderBaseTable::IS_EXPIRED + " is true";
537 DeleteBase(deleteCondition);
538
539 // set all the value of STATE to ReminderRequest::REMINDER_STATUS_INACTIVE
540 NativeRdb::ValuesBucket statusValues;
541 statusValues.PutInt(ReminderBaseTable::STATE, ReminderRequest::REMINDER_STATUS_INACTIVE);
542 int32_t statusChangedRows = STATE_FAIL;
543 int32_t ret = rdbStore_->Update(statusChangedRows, ReminderBaseTable::TABLE_NAME, statusValues);
544 ANSR_LOGD("Change status to inactive, changed rows: %{public}d.", statusChangedRows);
545 if (ret != NativeRdb::E_OK) {
546 ANSR_LOGE("Init data failed.");
547 return STATE_FAIL;
548 }
549 return STATE_OK;
550 }
551
DeleteBase(const std::string & deleteCondition)552 __attribute__((no_sanitize("cfi"))) int32_t ReminderStore::DeleteBase(const std::string& deleteCondition)
553 {
554 if (rdbStore_ == nullptr) {
555 ANSR_LOGE("Rdb store is not initialized.");
556 return STATE_FAIL;
557 }
558 int32_t deletedRows = STATE_FAIL;
559 std::vector<std::string> whereArgs;
560 int32_t ret = rdbStore_->Delete(deletedRows, ReminderBaseTable::TABLE_NAME, deleteCondition, whereArgs);
561 if (ret != NativeRdb::E_OK) {
562 ANSR_LOGE("Delete operation failed, deleteConditon: %{public}s," \
563 "result: %{public}d.", deleteCondition.c_str(), ret);
564 }
565 ANSR_LOGD("Delete operation done, deleteConditon: %{public}s," \
566 "deleted rows: %{public}d.", deleteCondition.c_str(), deletedRows);
567 return deletedRows;
568 }
569
Delete(const std::string & baseCondition,const std::string & assoConditon)570 __attribute__((no_sanitize("cfi"))) int32_t ReminderStore::Delete(const std::string& baseCondition,
571 const std::string& assoConditon)
572 {
573 if (rdbStore_ == nullptr) {
574 ANSR_LOGE("Rdb store is not initialized.");
575 return STATE_FAIL;
576 }
577 rdbStore_->BeginTransaction();
578 // delete reminder_calendar
579 std::string sql = "DELETE FROM " + ReminderCalendarTable::TABLE_NAME + " WHERE "
580 + ReminderCalendarTable::TABLE_NAME + "." + ReminderCalendarTable::REMINDER_ID
581 + " IN " + assoConditon;
582 int32_t ret = rdbStore_->ExecuteSql(sql);
583 if (ret != NativeRdb::E_OK) {
584 ANSR_LOGE("Delete from %{public}s failed", ReminderCalendarTable::TABLE_NAME.c_str());
585 rdbStore_->RollBack();
586 return STATE_FAIL;
587 }
588
589 // delete reminder_alarm
590 sql = "DELETE FROM " + ReminderAlarmTable::TABLE_NAME + " WHERE "
591 + ReminderAlarmTable::TABLE_NAME + "." + ReminderAlarmTable::REMINDER_ID
592 + " IN " + assoConditon;
593 ret = rdbStore_->ExecuteSql(sql);
594 if (ret != NativeRdb::E_OK) {
595 ANSR_LOGE("Delete from %{public}s failed", ReminderCalendarTable::TABLE_NAME.c_str());
596 rdbStore_->RollBack();
597 return STATE_FAIL;
598 }
599
600 // delete reminder_timer
601 sql = "DELETE FROM " + ReminderTimerTable::TABLE_NAME + " WHERE "
602 + ReminderTimerTable::TABLE_NAME + "." + ReminderTimerTable::REMINDER_ID
603 + " IN " + assoConditon;
604 ret = rdbStore_->ExecuteSql(sql);
605 if (ret != NativeRdb::E_OK) {
606 ANSR_LOGE("Delete from %{public}s failed", ReminderTimerTable::TABLE_NAME.c_str());
607 rdbStore_->RollBack();
608 return STATE_FAIL;
609 }
610
611 // delete reminder_base
612 sql = "DELETE FROM " + ReminderBaseTable::TABLE_NAME + " WHERE " + baseCondition;
613 ret = rdbStore_->ExecuteSql(sql);
614 if (ret != NativeRdb::E_OK) {
615 ANSR_LOGE("Delete from %{public}s failed", ReminderCalendarTable::TABLE_NAME.c_str());
616 rdbStore_->RollBack();
617 return STATE_FAIL;
618 }
619 rdbStore_->Commit();
620 return STATE_OK;
621 }
622
Insert(const sptr<ReminderRequest> & reminder)623 int32_t ReminderStore::Insert(const sptr<ReminderRequest>& reminder)
624 {
625 if (rdbStore_ == nullptr) {
626 ANSR_LOGE("Rdb store is not initialized.");
627 return STATE_FAIL;
628 }
629 int64_t rowId = STATE_FAIL;
630 NativeRdb::ValuesBucket baseValues;
631 ReminderStrategy::AppendValuesBucket(reminder, baseValues);
632
633 rdbStore_->BeginTransaction();
634 // insert reminder_base
635 int32_t ret = rdbStore_->Insert(rowId, ReminderBaseTable::TABLE_NAME, baseValues);
636 if (ret != NativeRdb::E_OK) {
637 ANSR_LOGE("Insert reminder_base operation failed, result: %{public}d, reminderId=%{public}d.",
638 ret, reminder->GetReminderId());
639 rdbStore_->RollBack();
640 return STATE_FAIL;
641 }
642
643 // insert reminder_alarm or reminder_calendar
644 NativeRdb::ValuesBucket values;
645 rowId = STATE_FAIL;
646 switch (reminder->GetReminderType()) {
647 case ReminderRequest::ReminderType::CALENDAR: {
648 ReminderCalendarStrategy::AppendValuesBucket(reminder, values);
649 ret = rdbStore_->Insert(rowId, ReminderCalendarTable::TABLE_NAME, values);
650 break;
651 }
652 case ReminderRequest::ReminderType::ALARM: {
653 ReminderAlarmStrategy::AppendValuesBucket(reminder, values);
654 ret = rdbStore_->Insert(rowId, ReminderAlarmTable::TABLE_NAME, values);
655 break;
656 }
657 case ReminderRequest::ReminderType::TIMER: {
658 ReminderTimerStrategy::AppendValuesBucket(reminder, values);
659 ret = rdbStore_->Insert(rowId, ReminderTimerTable::TABLE_NAME, values);
660 break;
661 }
662 default: {
663 ANSR_LOGE("Insert reminder_base operation failed, unkown type.");
664 ret = STATE_FAIL;
665 break;
666 }
667 }
668 if (ret != NativeRdb::E_OK) {
669 ANSR_LOGE("Insert operation failed, result: %{public}d, reminderId=%{public}d.",
670 ret, reminder->GetReminderId());
671 rdbStore_->RollBack();
672 return STATE_FAIL;
673 }
674 rdbStore_->Commit();
675 ANSR_LOGD("Insert successfully, reminderId=%{public}d.", reminder->GetReminderId());
676 return STATE_OK;
677 }
678
Update(const sptr<ReminderRequest> & reminder)679 int32_t ReminderStore::Update(
680 const sptr<ReminderRequest>& reminder)
681 {
682 if (rdbStore_ == nullptr) {
683 ANSR_LOGE("Rdb store is not initialized.");
684 return STATE_FAIL;
685 }
686 int32_t rowId = STATE_FAIL;
687 NativeRdb::ValuesBucket baseValues;
688 ReminderStrategy::AppendValuesBucket(reminder, baseValues);
689
690 std::string updateCondition = ReminderBaseTable::REMINDER_ID
691 + " = " + std::to_string(reminder->GetReminderId());
692
693 rdbStore_->BeginTransaction();
694 // update reminder_base
695 std::vector<std::string> whereArgs;
696 int32_t ret = rdbStore_->Update(rowId, ReminderBaseTable::TABLE_NAME, baseValues, updateCondition, whereArgs);
697 if (ret != NativeRdb::E_OK) {
698 ANSR_LOGE("Update reminder_base operation failed, result: %{public}d, reminderId=%{public}d.",
699 ret, reminder->GetReminderId());
700 rdbStore_->RollBack();
701 return STATE_FAIL;
702 }
703
704 // update reminder_alarm or reminder_calendar
705 NativeRdb::ValuesBucket values;
706 rowId = STATE_FAIL;
707 switch (reminder->GetReminderType()) {
708 case ReminderRequest::ReminderType::CALENDAR:
709 ReminderCalendarStrategy::AppendValuesBucket(reminder, values);
710 ret = rdbStore_->Update(rowId, ReminderCalendarTable::TABLE_NAME, values, updateCondition, whereArgs);
711 break;
712 case ReminderRequest::ReminderType::ALARM:
713 ReminderAlarmStrategy::AppendValuesBucket(reminder, values);
714 ret = rdbStore_->Update(rowId, ReminderAlarmTable::TABLE_NAME, values, updateCondition, whereArgs);
715 break;
716 case ReminderRequest::ReminderType::TIMER:
717 ReminderTimerStrategy::AppendValuesBucket(reminder, values);
718 ret = rdbStore_->Update(rowId, ReminderTimerTable::TABLE_NAME, values, updateCondition, whereArgs);
719 break;
720 default:
721 ANSR_LOGE("Insert reminder_base operation failed, unkown type.");
722 ret = STATE_FAIL;
723 break;
724 }
725 if (ret != NativeRdb::E_OK) {
726 ANSR_LOGE("Update operation failed, result: %{public}d, reminderId=%{public}d.",
727 ret, reminder->GetReminderId());
728 rdbStore_->RollBack();
729 return STATE_FAIL;
730 }
731 rdbStore_->Commit();
732 ANSR_LOGD("Update successfully, reminderId=%{public}d.", reminder->GetReminderId());
733 return STATE_OK;
734 }
735
IsReminderExist(const sptr<ReminderRequest> & reminder)736 bool ReminderStore::IsReminderExist(const sptr<ReminderRequest>& reminder)
737 {
738 NativeRdb::AbsRdbPredicates absRdbPredicates(ReminderBaseTable::TABLE_NAME);
739 absRdbPredicates.EqualTo(ReminderBaseTable::REMINDER_ID, std::to_string(reminder->GetReminderId()));
740 auto queryResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
741 if (queryResultSet == nullptr) {
742 ANSR_LOGE("QueryResultSet is null.");
743 return false;
744 }
745 int32_t resultNum;
746 queryResultSet->GetRowCount(resultNum);
747 return resultNum != 0;
748 }
749
IsReminderExist(const int32_t reminderId,const int32_t uid)750 bool ReminderStore::IsReminderExist(const int32_t reminderId, const int32_t uid)
751 {
752 NativeRdb::AbsRdbPredicates absRdbPredicates(ReminderBaseTable::TABLE_NAME);
753 absRdbPredicates.EqualTo(ReminderBaseTable::REMINDER_ID, std::to_string(reminderId));
754 absRdbPredicates.EqualTo(ReminderBaseTable::CREATOR_UID, std::to_string(uid));
755 auto queryResultSet = rdbStore_->Query(absRdbPredicates, std::vector<std::string>());
756 if (queryResultSet == nullptr) {
757 ANSR_LOGE("QueryResultSet is null.");
758 return false;
759 }
760 int32_t resultNum;
761 queryResultSet->GetRowCount(resultNum);
762 return resultNum != 0;
763 }
764
GetReminders(const std::string & queryCondition)765 std::vector<sptr<ReminderRequest>> ReminderStore::GetReminders(const std::string& queryCondition)
766 {
767 std::vector<sptr<ReminderRequest>> reminders;
768 if (rdbStore_ == nullptr) {
769 ANSR_LOGE("Rdb store is not initialized.");
770 return reminders;
771 }
772 auto queryResultSet = Query(queryCondition);
773 if (queryResultSet == nullptr) {
774 return reminders;
775 }
776 while (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
777 sptr<ReminderRequest> reminder = BuildReminder(queryResultSet);
778 if (reminder != nullptr) {
779 reminders.push_back(reminder);
780 }
781 }
782 ANSR_LOGD("Size=%{public}zu", reminders.size());
783 return reminders;
784 }
785
BuildReminder(const std::shared_ptr<NativeRdb::ResultSet> & resultBase)786 sptr<ReminderRequest> ReminderStore::BuildReminder(const std::shared_ptr<NativeRdb::ResultSet>& resultBase)
787 {
788 int32_t reminderId;
789 int32_t reminderType;
790 GetInt32Val(resultBase, ReminderBaseTable::REMINDER_ID, reminderId);
791 GetInt32Val(resultBase, ReminderBaseTable::REMINDER_TYPE, reminderType);
792
793 sptr<ReminderRequest> reminder = nullptr;
794 std::shared_ptr<NativeRdb::ResultSet> resultSet;
795 switch (reminderType) {
796 case (static_cast<int32_t>(ReminderRequest::ReminderType::TIMER)): {
797 reminder = new (std::nothrow) ReminderRequestTimer(reminderId);
798 resultSet = Query(ReminderTimerTable::TABLE_NAME, ReminderTimerTable::SELECT_COLUMNS, reminderId);
799 ReminderTimerStrategy::RecoverFromDb(reminder, resultBase, resultSet);
800 break;
801 }
802 case (static_cast<int32_t>(ReminderRequest::ReminderType::CALENDAR)): {
803 reminder = new (std::nothrow) ReminderRequestCalendar(reminderId);
804 resultSet = Query(ReminderCalendarTable::TABLE_NAME, ReminderCalendarTable::SELECT_COLUMNS, reminderId);
805 ReminderCalendarStrategy::RecoverFromDb(reminder, resultBase, resultSet);
806 break;
807 }
808 case (static_cast<int32_t>(ReminderRequest::ReminderType::ALARM)): {
809 reminder = new (std::nothrow) ReminderRequestAlarm(reminderId);
810 resultSet = Query(ReminderAlarmTable::TABLE_NAME, ReminderAlarmTable::SELECT_COLUMNS, reminderId);
811 ReminderAlarmStrategy::RecoverFromDb(reminder, resultBase, resultSet);
812 break;
813 }
814 default: {
815 ANSR_LOGE("ReminderType from database is error, reminderType %{public}d.", reminderType);
816 break;
817 }
818 }
819 if (reminder == nullptr) {
820 ANSR_LOGW("BuildReminder fail.");
821 }
822 return reminder;
823 }
824
Query(const std::string & tableName,const std::string & colums,const int32_t reminderId)825 std::shared_ptr<NativeRdb::ResultSet> ReminderStore::Query(const std::string& tableName, const std::string& colums,
826 const int32_t reminderId)
827 {
828 if (rdbStore_ == nullptr) {
829 ANSR_LOGE("Rdb store is not initialized.");
830 return nullptr;
831 }
832 std::string queryCondition = "SELECT " + colums + " FROM " + tableName
833 + " WHERE " + ReminderBaseTable::REMINDER_ID + " = " + std::to_string(reminderId);
834 auto queryResultSet = Query(queryCondition);
835 if (queryResultSet == nullptr) {
836 return nullptr;
837 }
838 int32_t resultNum = 0;
839 queryResultSet->GetRowCount(resultNum);
840 if (resultNum == 0) {
841 return nullptr;
842 }
843 queryResultSet->GoToNextRow();
844 return queryResultSet;
845 }
846
Query(const std::string & queryCondition) const847 std::shared_ptr<NativeRdb::ResultSet> ReminderStore::Query(const std::string& queryCondition) const
848 {
849 if (rdbStore_ == nullptr) {
850 ANSR_LOGE("Rdb store is not initialized.");
851 return nullptr;
852 }
853 std::vector<std::string> whereArgs;
854 return rdbStore_->QuerySql(queryCondition, whereArgs);
855 }
856
QueryActiveReminderCount()857 int32_t ReminderStore::QueryActiveReminderCount()
858 {
859 if (rdbStore_ == nullptr) {
860 ANSR_LOGE("Rdb store is not initialized.");
861 return 0;
862 }
863 std::string queryCondition = "SELECT * FROM ";
864 queryCondition.append(ReminderBaseTable::TABLE_NAME).append(" WHERE ").append(ReminderBaseTable::IS_EXPIRED)
865 .append(" = 'false' AND ").append(ReminderTable::REMINDER_TYPE).append(" != 1");
866 std::vector<std::string> whereArgs;
867 auto resultSet = rdbStore_->QuerySql(queryCondition, whereArgs);
868 int32_t baseTableNum = 0;
869 resultSet->GetRowCount(baseTableNum);
870
871 queryCondition = "SELECT * FROM ";
872 int64_t nowTime = GetCurrentTime();
873 queryCondition.append(ReminderCalendarTable::TABLE_NAME).append(" WHERE (")
874 .append(ReminderCalendarTable::CALENDAR_DATE_TIME).append(" < ").append(std::to_string(nowTime)).append(" AND ")
875 .append(ReminderCalendarTable::CALENDAR_END_DATE_TIME)
876 .append(" > ").append(std::to_string(nowTime)).append(" ) OR ")
877 .append(ReminderCalendarTable::CALENDAR_DATE_TIME).append("> ").append(std::to_string(nowTime)).append(" OR (")
878 .append(ReminderCalendarTable::CALENDAR_DATE_TIME).append("< ").append(std::to_string(nowTime)).append(" AND ")
879 .append(ReminderCalendarTable::CALENDAR_DATE_TIME).append(" = ")
880 .append(ReminderCalendarTable::CALENDAR_END_DATE_TIME).append(")");
881 resultSet = rdbStore_->QuerySql(queryCondition, whereArgs);
882 int32_t calenderTableNum = 0;
883 resultSet->GetRowCount(calenderTableNum);
884 return baseTableNum + calenderTableNum;
885 }
886
887 } // namespace Notification
888 } // namespace OHOS
889