• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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