• 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 const int32_t REMINDER_RDB_VERSION_V1 = 1;
37 const int32_t REMINDER_RDB_VERSION_V2 = 2;
38 const int32_t REMINDER_RDB_VERSION_V3 = 3;
39 const int32_t REMINDER_RDB_VERSION_V4 = 4;
40 const int32_t REMINDER_RDB_VERSION_V5 = 5;
41 const int32_t REMINDER_RDB_VERSION_V6 = 6;
42 const int32_t REMINDER_RDB_VERSION_V7 = 7;
43 const int32_t REMINDER_RDB_VERSION = 8;
44 constexpr int64_t DURATION_PRELOAD_TIME = 10 * 60 * 60 * 1000;  // 10h, millisecond
45 }
46 
47 const int32_t ReminderStore::STATE_OK = 0;
48 const int32_t ReminderStore::STATE_FAIL = -1;
49 const std::string ReminderStore::REMINDER_DB_DIR = "/data/service/el1/public/notification/";
50 const std::string ReminderStore::REMINDER_DB_NAME = "notification.db";
51 
OnCreate(NativeRdb::RdbStore & store)52 int32_t ReminderStore::ReminderStoreDataCallBack::OnCreate(NativeRdb::RdbStore& store)
53 {
54     ANSR_LOGI("Create table");
55     return CreateTable(store);
56 }
57 
OnUpgrade(NativeRdb::RdbStore & store,int32_t oldVersion,int32_t newVersion)58 int32_t ReminderStore::ReminderStoreDataCallBack::OnUpgrade(
59     NativeRdb::RdbStore& store, int32_t oldVersion, int32_t newVersion)
60 {
61     ANSR_LOGI("OnUpgrade oldVersion is %{public}d, newVersion is %{public}d", oldVersion, newVersion);
62     if (oldVersion < newVersion && newVersion == REMINDER_RDB_VERSION) {
63         switch (oldVersion) {
64             case REMINDER_RDB_VERSION_V1:
65                 AddRdbColum(store, ReminderTable::TABLE_NAME, "groupId", "TEXT", "''");
66                 [[fallthrough]];
67             case REMINDER_RDB_VERSION_V2:
68                 AddRdbColum(store, ReminderTable::TABLE_NAME, "custom_ring_uri", "TEXT", "''");
69                 AddRdbColum(store, ReminderTable::TABLE_NAME, "snooze_slot_id", "INT", "3");
70                 [[fallthrough]];
71             case REMINDER_RDB_VERSION_V3:
72                 AddRdbColum(store, ReminderTable::TABLE_NAME, "creator_bundle_name", "TEXT", "''");
73                 [[fallthrough]];
74             case REMINDER_RDB_VERSION_V4:
75                 CreateTable(store);
76                 CopyData(store);
77                 [[fallthrough]];
78             case REMINDER_RDB_VERSION_V5:
79                 AddRdbColum(store, ReminderBaseTable::TABLE_NAME, ReminderBaseTable::CREATOR_UID, "INT", "-1");
80                 [[fallthrough]];
81             case REMINDER_RDB_VERSION_V6:
82                 AddRdbColum(store, ReminderCalendarTable::TABLE_NAME,
83                     ReminderCalendarTable::CALENDAR_LAST_DATE_TIME, "BIGINT", "0");
84                 [[fallthrough]];
85             case REMINDER_RDB_VERSION_V7:
86                 AddRdbColum(store, ReminderBaseTable::TABLE_NAME, ReminderBaseTable::TITLE_RESOURCE_ID, "INT", "0");
87                 AddRdbColum(store, ReminderBaseTable::TABLE_NAME,
88                     ReminderBaseTable::CONTENT_RESOURCE_ID, "INT", "0");
89                 AddRdbColum(store, ReminderBaseTable::TABLE_NAME,
90                     ReminderBaseTable::SNOOZE_CONTENT_RESOURCE_ID, "INT", "0");
91                 AddRdbColum(store, ReminderBaseTable::TABLE_NAME,
92                     ReminderBaseTable::EXPIRED_CONTENT_RESOURCE_ID, "INT", "0");
93                 [[fallthrough]];
94             default:
95                 break;
96         }
97     }
98     store.SetVersion(newVersion);
99     return NativeRdb::E_OK;
100 }
101 
OnDowngrade(NativeRdb::RdbStore & store,int32_t currentVersion,int32_t targetVersion)102 int32_t ReminderStore::ReminderStoreDataCallBack::OnDowngrade(
103     NativeRdb::RdbStore& store, int32_t currentVersion, int32_t targetVersion)
104 {
105     ANSR_LOGI("OnDowngrade currentVersion is %{public}d, targetVersion is %{public}d", currentVersion, targetVersion);
106     if (currentVersion > targetVersion && targetVersion <= REMINDER_RDB_VERSION_V4) {
107         std::string createSql = "CREATE TABLE IF NOT EXISTS " + ReminderTable::TABLE_NAME + " ("
108             + ReminderTable::ADD_COLUMNS + ")";
109         int32_t ret = store.ExecuteSql(createSql);
110         if (ret != NativeRdb::E_OK) {
111             ANSR_LOGE("Create reminder table failed:%{public}d", ret);
112         }
113         return ret;
114     }
115     store.SetVersion(targetVersion);
116     return NativeRdb::E_OK;
117 }
118 
CreateTable(NativeRdb::RdbStore & store)119 int32_t ReminderStore::ReminderStoreDataCallBack::CreateTable(NativeRdb::RdbStore& store)
120 {
121     std::string createSql = "CREATE TABLE IF NOT EXISTS " + ReminderBaseTable::TABLE_NAME + " ("
122         + ReminderBaseTable::ADD_COLUMNS + ")";
123     int32_t ret = store.ExecuteSql(createSql);
124     if (ret != NativeRdb::E_OK) {
125         ANSR_LOGE("Create reminder_base table failed:%{public}d", ret);
126         return ret;
127     }
128 
129     createSql = "CREATE TABLE IF NOT EXISTS " + ReminderAlarmTable::TABLE_NAME + " ("
130         + ReminderAlarmTable::ADD_COLUMNS + ")";
131     ret = store.ExecuteSql(createSql);
132     if (ret != NativeRdb::E_OK) {
133         ANSR_LOGE("Create reminder_alarm table failed:%{public}d", ret);
134         return ret;
135     }
136 
137     createSql = "CREATE TABLE IF NOT EXISTS " + ReminderCalendarTable::TABLE_NAME + " ("
138         + ReminderCalendarTable::ADD_COLUMNS + ")";
139     ret = store.ExecuteSql(createSql);
140     if (ret != NativeRdb::E_OK) {
141         ANSR_LOGE("Create reminder_calendar table failed:%{public}d", ret);
142         return ret;
143     }
144 
145     createSql = "CREATE TABLE IF NOT EXISTS " + ReminderTimerTable::TABLE_NAME + " ("
146         + ReminderTimerTable::ADD_COLUMNS + ")";
147     ret = store.ExecuteSql(createSql);
148     if (ret != NativeRdb::E_OK) {
149         ANSR_LOGE("Create reminder_timer table failed:%{public}d", ret);
150         return ret;
151     }
152     return ret;
153 }
154 
CopyData(NativeRdb::RdbStore & store)155 int32_t ReminderStore::ReminderStoreDataCallBack::CopyData(NativeRdb::RdbStore& store)
156 {
157     // select old data
158     auto reminders = GetOldReminders(store);
159     // insert new data
160     if (!reminders.empty()) {
161         InsertNewReminders(store, reminders);
162     }
163     // delete old table
164     std::string sql = "DELETE FROM " + ReminderTable::TABLE_NAME;
165     store.ExecuteSql(sql);
166     return NativeRdb::E_OK;
167 }
168 
GetOldReminders(NativeRdb::RdbStore & store)169 std::vector<sptr<ReminderRequest>> ReminderStore::ReminderStoreDataCallBack::GetOldReminders(NativeRdb::RdbStore& store)
170 {
171     std::string sql = "SELECT " + ReminderTable::SELECT_COLUMNS + " FROM "
172         + ReminderTable::TABLE_NAME;
173     std::vector<sptr<ReminderRequest>> reminders;
174     std::vector<std::string> whereArgs;
175     auto queryResult = store.QuerySql(sql, whereArgs);
176     if (queryResult == nullptr) {
177         return reminders;
178     }
179 
180     bool isLastRow = false;
181     queryResult->IsAtLastRow(isLastRow);
182     while (!isLastRow) {
183         queryResult->GoToNextRow();
184         int32_t reminderId;
185         int32_t reminderType;
186         GetInt32Val(queryResult, ReminderTable::REMINDER_ID, reminderId);
187         GetInt32Val(queryResult, ReminderTable::REMINDER_TYPE, reminderType);
188 
189         sptr<ReminderRequest> reminderReq = nullptr;
190         switch (reminderType) {
191             case (static_cast<int32_t>(ReminderRequest::ReminderType::TIMER)): {
192                 reminderReq = new (std::nothrow) ReminderRequestTimer(reminderId);
193                 ReminderTimerStrategy::RecoverFromOldVersion(reminderReq, queryResult);
194                 break;
195             }
196             case (static_cast<int32_t>(ReminderRequest::ReminderType::CALENDAR)): {
197                 reminderReq = new (std::nothrow) ReminderRequestCalendar(reminderId);
198                 ReminderCalendarStrategy::RecoverFromOldVersion(reminderReq, queryResult);
199                 break;
200             }
201             case (static_cast<int32_t>(ReminderRequest::ReminderType::ALARM)): {
202                 reminderReq = new (std::nothrow) ReminderRequestAlarm(reminderId);
203                 ReminderAlarmStrategy::RecoverFromOldVersion(reminderReq, queryResult);
204                 break;
205             }
206             default: {
207                 break;
208             }
209         }
210         if (reminderReq != nullptr) {
211             reminders.push_back(reminderReq);
212         }
213         queryResult->IsAtLastRow(isLastRow);
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 
GetReminders(const std::string & queryCondition)750 std::vector<sptr<ReminderRequest>> ReminderStore::GetReminders(const std::string& queryCondition)
751 {
752     std::vector<sptr<ReminderRequest>> reminders;
753     if (rdbStore_ == nullptr) {
754         ANSR_LOGE("Rdb store is not initialized.");
755         return reminders;
756     }
757     auto queryResultSet = Query(queryCondition);
758     if (queryResultSet == nullptr) {
759         return reminders;
760     }
761     bool isAtLastRow = false;
762     int32_t ret = queryResultSet->IsAtLastRow(isAtLastRow);
763     while (ret == NativeRdb::E_OK && !isAtLastRow) {
764         queryResultSet->GoToNextRow();
765         sptr<ReminderRequest> reminder = BuildReminder(queryResultSet);
766         if (reminder != nullptr) {
767             reminders.push_back(reminder);
768         }
769         ret = queryResultSet->IsAtLastRow(isAtLastRow);
770     }
771     ANSR_LOGD("Size=%{public}zu", reminders.size());
772     return reminders;
773 }
774 
BuildReminder(const std::shared_ptr<NativeRdb::ResultSet> & resultBase)775 sptr<ReminderRequest> ReminderStore::BuildReminder(const std::shared_ptr<NativeRdb::ResultSet>& resultBase)
776 {
777     int32_t reminderId;
778     int32_t reminderType;
779     GetInt32Val(resultBase, ReminderBaseTable::REMINDER_ID, reminderId);
780     GetInt32Val(resultBase, ReminderBaseTable::REMINDER_TYPE, reminderType);
781 
782     sptr<ReminderRequest> reminder = nullptr;
783     std::shared_ptr<NativeRdb::ResultSet> resultSet;
784     switch (reminderType) {
785         case (static_cast<int32_t>(ReminderRequest::ReminderType::TIMER)): {
786             reminder = new (std::nothrow) ReminderRequestTimer(reminderId);
787             resultSet = Query(ReminderTimerTable::TABLE_NAME, ReminderTimerTable::SELECT_COLUMNS, reminderId);
788             ReminderTimerStrategy::RecoverFromDb(reminder, resultBase, resultSet);
789             break;
790         }
791         case (static_cast<int32_t>(ReminderRequest::ReminderType::CALENDAR)): {
792             reminder = new (std::nothrow) ReminderRequestCalendar(reminderId);
793             resultSet = Query(ReminderCalendarTable::TABLE_NAME, ReminderCalendarTable::SELECT_COLUMNS, reminderId);
794             ReminderCalendarStrategy::RecoverFromDb(reminder, resultBase, resultSet);
795             break;
796         }
797         case (static_cast<int32_t>(ReminderRequest::ReminderType::ALARM)): {
798             reminder = new (std::nothrow) ReminderRequestAlarm(reminderId);
799             resultSet = Query(ReminderAlarmTable::TABLE_NAME, ReminderAlarmTable::SELECT_COLUMNS, reminderId);
800             ReminderAlarmStrategy::RecoverFromDb(reminder, resultBase, resultSet);
801             break;
802         }
803         default: {
804             ANSR_LOGE("ReminderType from database is error, reminderType %{public}d.", reminderType);
805             break;
806         }
807     }
808     if (reminder == nullptr) {
809         ANSR_LOGW("BuildReminder fail.");
810     }
811     return reminder;
812 }
813 
Query(const std::string & tableName,const std::string & colums,const int32_t reminderId)814 std::shared_ptr<NativeRdb::ResultSet> ReminderStore::Query(const std::string& tableName, const std::string& colums,
815     const int32_t reminderId)
816 {
817     if (rdbStore_ == nullptr) {
818         ANSR_LOGE("Rdb store is not initialized.");
819         return nullptr;
820     }
821     std::string queryCondition = "SELECT " + colums + " FROM " + tableName
822         + " WHERE " + ReminderBaseTable::REMINDER_ID + " = " + std::to_string(reminderId);
823     auto queryResultSet = Query(queryCondition);
824     if (queryResultSet == nullptr) {
825         return nullptr;
826     }
827     int32_t resultNum = 0;
828     queryResultSet->GetRowCount(resultNum);
829     if (resultNum == 0) {
830         return nullptr;
831     }
832     queryResultSet->GoToNextRow();
833     return queryResultSet;
834 }
835 
Query(const std::string & queryCondition) const836 std::shared_ptr<NativeRdb::ResultSet> ReminderStore::Query(const std::string& queryCondition) const
837 {
838     if (rdbStore_ == nullptr) {
839         ANSR_LOGE("Rdb store is not initialized.");
840         return nullptr;
841     }
842     std::vector<std::string> whereArgs;
843     return rdbStore_->QuerySql(queryCondition, whereArgs);
844 }
845 
QueryActiveReminderCount()846 int32_t ReminderStore::QueryActiveReminderCount()
847 {
848     if (rdbStore_ == nullptr) {
849         ANSR_LOGE("Rdb store is not initialized.");
850         return 0;
851     }
852     std::string queryCondition = "SELECT * FROM ";
853     queryCondition.append(ReminderBaseTable::TABLE_NAME).append(" WHERE ").append(ReminderBaseTable::IS_EXPIRED)
854         .append(" = 'false' AND ").append(ReminderTable::REMINDER_TYPE).append(" != 1");
855     std::vector<std::string> whereArgs;
856     auto resultSet = rdbStore_->QuerySql(queryCondition, whereArgs);
857     int32_t baseTableNum = 0;
858     resultSet->GetRowCount(baseTableNum);
859 
860     queryCondition = "SELECT * FROM ";
861     int64_t nowTime = GetCurrentTime();
862     queryCondition.append(ReminderCalendarTable::TABLE_NAME).append(" WHERE (")
863         .append(ReminderCalendarTable::CALENDAR_DATE_TIME).append(" < ").append(std::to_string(nowTime)).append(" AND ")
864         .append(ReminderCalendarTable::CALENDAR_END_DATE_TIME)
865         .append(" > ").append(std::to_string(nowTime)).append(" ) OR ")
866         .append(ReminderCalendarTable::CALENDAR_DATE_TIME).append("> ").append(std::to_string(nowTime)).append(" OR (")
867         .append(ReminderCalendarTable::CALENDAR_DATE_TIME).append("< ").append(std::to_string(nowTime)).append(" AND ")
868         .append(ReminderCalendarTable::CALENDAR_DATE_TIME).append(" = ")
869         .append(ReminderCalendarTable::CALENDAR_END_DATE_TIME).append(")");
870     resultSet = rdbStore_->QuerySql(queryCondition, whereArgs);
871     int32_t calenderTableNum = 0;
872     resultSet->GetRowCount(calenderTableNum);
873     return baseTableNum + calenderTableNum;
874 }
875 
876 }  // namespace Notification
877 }  // namespace OHOS
878