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