1cf69771bSopenharmony_ci/*
2cf69771bSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3cf69771bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4cf69771bSopenharmony_ci * you may not use this file except in compliance with the License.
5cf69771bSopenharmony_ci * You may obtain a copy of the License at
6cf69771bSopenharmony_ci *
7cf69771bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8cf69771bSopenharmony_ci *
9cf69771bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10cf69771bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11cf69771bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cf69771bSopenharmony_ci * See the License for the specific language governing permissions and
13cf69771bSopenharmony_ci * limitations under the License.
14cf69771bSopenharmony_ci */
15cf69771bSopenharmony_ci#include "timer_database.h"
16cf69771bSopenharmony_ci#include "time_hilog.h"
17cf69771bSopenharmony_ci#include "time_common.h"
18cf69771bSopenharmony_ci
19cf69771bSopenharmony_cinamespace OHOS {
20cf69771bSopenharmony_cinamespace MiscServices {
21cf69771bSopenharmony_ciconstexpr const char *CREATE_TIME_TIMER_HOLD_ON_REBOOT = "CREATE TABLE IF NOT EXISTS hold_on_reboot "
22cf69771bSopenharmony_ci                                                         "(timerId INTEGER PRIMARY KEY, "
23cf69771bSopenharmony_ci                                                         "type INTEGER, "
24cf69771bSopenharmony_ci                                                         "flag INTEGER, "
25cf69771bSopenharmony_ci                                                         "windowLength INTEGER, "
26cf69771bSopenharmony_ci                                                         "interval INTEGER, "
27cf69771bSopenharmony_ci                                                         "uid INTEGER, "
28cf69771bSopenharmony_ci                                                         "bundleName TEXT, "
29cf69771bSopenharmony_ci                                                         "wantAgent TEXT, "
30cf69771bSopenharmony_ci                                                         "state INTEGER, "
31cf69771bSopenharmony_ci                                                         "triggerTime INTEGER, "
32cf69771bSopenharmony_ci                                                         "pid INTEGER)";
33cf69771bSopenharmony_ci
34cf69771bSopenharmony_ciconstexpr const char *CREATE_TIME_TIMER_DROP_ON_REBOOT = "CREATE TABLE IF NOT EXISTS drop_on_reboot "
35cf69771bSopenharmony_ci                                                         "(timerId INTEGER PRIMARY KEY, "
36cf69771bSopenharmony_ci                                                         "type INTEGER, "
37cf69771bSopenharmony_ci                                                         "flag INTEGER, "
38cf69771bSopenharmony_ci                                                         "windowLength INTEGER, "
39cf69771bSopenharmony_ci                                                         "interval INTEGER, "
40cf69771bSopenharmony_ci                                                         "uid INTEGER, "
41cf69771bSopenharmony_ci                                                         "bundleName TEXT, "
42cf69771bSopenharmony_ci                                                         "wantAgent TEXT, "
43cf69771bSopenharmony_ci                                                         "state INTEGER, "
44cf69771bSopenharmony_ci                                                         "triggerTime INTEGER, "
45cf69771bSopenharmony_ci                                                         "pid INTEGER)";
46cf69771bSopenharmony_ci
47cf69771bSopenharmony_ciconstexpr const char *HOLD_ON_REBOOT_ADD_COLUMN = "ALTER TABLE hold_on_reboot ADD COLUMN pid INTEGER";
48cf69771bSopenharmony_ci
49cf69771bSopenharmony_ciconstexpr const char *DROP_ON_REBOOT_ADD_COLUMN = "ALTER TABLE drop_on_reboot ADD COLUMN pid INTEGER";
50cf69771bSopenharmony_ci
51cf69771bSopenharmony_ciTimeDatabase::TimeDatabase()
52cf69771bSopenharmony_ci{
53cf69771bSopenharmony_ci    int errCode = OHOS::NativeRdb::E_OK;
54cf69771bSopenharmony_ci    OHOS::NativeRdb::RdbStoreConfig config(DB_NAME);
55cf69771bSopenharmony_ci    config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
56cf69771bSopenharmony_ci    config.SetEncryptStatus(false);
57cf69771bSopenharmony_ci    config.SetReadConSize(1);
58cf69771bSopenharmony_ci    TimeDBOpenCallback timeDBOpenCallback;
59cf69771bSopenharmony_ci    store_ = OHOS::NativeRdb::RdbHelper::GetRdbStore(config, DATABASE_OPEN_VERSION_2, timeDBOpenCallback, errCode);
60cf69771bSopenharmony_ci    TIME_HILOGI(TIME_MODULE_SERVICE, "Gets time database, ret: %{public}d", errCode);
61cf69771bSopenharmony_ci    if (errCode == OHOS::NativeRdb::E_SQLITE_CORRUPT) {
62cf69771bSopenharmony_ci        auto ret = OHOS::NativeRdb::RdbHelper::DeleteRdbStore(config);
63cf69771bSopenharmony_ci        if (ret != OHOS::NativeRdb::E_OK) {
64cf69771bSopenharmony_ci            TIME_HILOGE(TIME_MODULE_SERVICE, "delete corrupt database failed, ret: %{public}d", ret);
65cf69771bSopenharmony_ci            return;
66cf69771bSopenharmony_ci        }
67cf69771bSopenharmony_ci        store_ = OHOS::NativeRdb::RdbHelper::GetRdbStore(config, DATABASE_OPEN_VERSION_2, timeDBOpenCallback, errCode);
68cf69771bSopenharmony_ci    }
69cf69771bSopenharmony_ci}
70cf69771bSopenharmony_ci
71cf69771bSopenharmony_ciTimeDatabase &TimeDatabase::GetInstance()
72cf69771bSopenharmony_ci{
73cf69771bSopenharmony_ci    static TimeDatabase timeDatabase;
74cf69771bSopenharmony_ci    return timeDatabase;
75cf69771bSopenharmony_ci}
76cf69771bSopenharmony_ci
77cf69771bSopenharmony_cibool TimeDatabase::RecoverDataBase()
78cf69771bSopenharmony_ci{
79cf69771bSopenharmony_ci    OHOS::NativeRdb::RdbStoreConfig config(DB_NAME);
80cf69771bSopenharmony_ci    config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
81cf69771bSopenharmony_ci    config.SetEncryptStatus(false);
82cf69771bSopenharmony_ci    config.SetReadConSize(1);
83cf69771bSopenharmony_ci    auto ret = OHOS::NativeRdb::RdbHelper::DeleteRdbStore(config);
84cf69771bSopenharmony_ci    if (ret != OHOS::NativeRdb::E_OK) {
85cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "delete corrupt database failed, ret: %{public}d", ret);
86cf69771bSopenharmony_ci        return false;
87cf69771bSopenharmony_ci    }
88cf69771bSopenharmony_ci    TimeDBOpenCallback timeDbOpenCallback;
89cf69771bSopenharmony_ci    int errCode;
90cf69771bSopenharmony_ci    store_ = OHOS::NativeRdb::RdbHelper::GetRdbStore(config, DATABASE_OPEN_VERSION_2, timeDbOpenCallback, errCode);
91cf69771bSopenharmony_ci    return true;
92cf69771bSopenharmony_ci}
93cf69771bSopenharmony_ci
94cf69771bSopenharmony_ciint GetInt(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, int line)
95cf69771bSopenharmony_ci{
96cf69771bSopenharmony_ci    int value = 0;
97cf69771bSopenharmony_ci    resultSet->GetInt(line, value);
98cf69771bSopenharmony_ci    return value;
99cf69771bSopenharmony_ci}
100cf69771bSopenharmony_ci
101cf69771bSopenharmony_ciint64_t GetLong(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, int line)
102cf69771bSopenharmony_ci{
103cf69771bSopenharmony_ci    int64_t value = 0;
104cf69771bSopenharmony_ci    resultSet->GetLong(line, value);
105cf69771bSopenharmony_ci    return value;
106cf69771bSopenharmony_ci}
107cf69771bSopenharmony_ci
108cf69771bSopenharmony_cistd::string GetString(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, int line)
109cf69771bSopenharmony_ci{
110cf69771bSopenharmony_ci    std::string value = "";
111cf69771bSopenharmony_ci    resultSet->GetString(line, value);
112cf69771bSopenharmony_ci    return value;
113cf69771bSopenharmony_ci}
114cf69771bSopenharmony_ci
115cf69771bSopenharmony_cibool TimeDatabase::Insert(const std::string &table, const OHOS::NativeRdb::ValuesBucket &insertValues)
116cf69771bSopenharmony_ci{
117cf69771bSopenharmony_ci    if (store_ == nullptr) {
118cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
119cf69771bSopenharmony_ci        return false;
120cf69771bSopenharmony_ci    }
121cf69771bSopenharmony_ci
122cf69771bSopenharmony_ci    int64_t outRowId = 0;
123cf69771bSopenharmony_ci    int ret = store_->Insert(outRowId, table, insertValues);
124cf69771bSopenharmony_ci    if (ret != OHOS::NativeRdb::E_OK) {
125cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "insert values failed, ret: %{public}d", ret);
126cf69771bSopenharmony_ci        if (ret != OHOS::NativeRdb::E_SQLITE_CORRUPT) {
127cf69771bSopenharmony_ci            return false;
128cf69771bSopenharmony_ci        }
129cf69771bSopenharmony_ci        if (!RecoverDataBase()) {
130cf69771bSopenharmony_ci            return false;
131cf69771bSopenharmony_ci        }
132cf69771bSopenharmony_ci        ret = store_->Insert(outRowId, table, insertValues);
133cf69771bSopenharmony_ci        if (ret != OHOS::NativeRdb::E_OK) {
134cf69771bSopenharmony_ci            TIME_HILOGE(TIME_MODULE_SERVICE, "Insert values after RecoverDataBase failed, ret: %{public}d", ret);
135cf69771bSopenharmony_ci        }
136cf69771bSopenharmony_ci    }
137cf69771bSopenharmony_ci    return true;
138cf69771bSopenharmony_ci}
139cf69771bSopenharmony_ci
140cf69771bSopenharmony_cibool TimeDatabase::Update(
141cf69771bSopenharmony_ci    const OHOS::NativeRdb::ValuesBucket values, const OHOS::NativeRdb::AbsRdbPredicates &predicates)
142cf69771bSopenharmony_ci{
143cf69771bSopenharmony_ci    if (store_ == nullptr) {
144cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
145cf69771bSopenharmony_ci        return false;
146cf69771bSopenharmony_ci    }
147cf69771bSopenharmony_ci
148cf69771bSopenharmony_ci    int changedRows = 0;
149cf69771bSopenharmony_ci    int ret = store_->Update(changedRows, values, predicates);
150cf69771bSopenharmony_ci    if (ret != OHOS::NativeRdb::E_OK) {
151cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "update values failed, ret: %{public}d", ret);
152cf69771bSopenharmony_ci        if (ret != OHOS::NativeRdb::E_SQLITE_CORRUPT) {
153cf69771bSopenharmony_ci            return false;
154cf69771bSopenharmony_ci        }
155cf69771bSopenharmony_ci        if (!RecoverDataBase()) {
156cf69771bSopenharmony_ci            return false;
157cf69771bSopenharmony_ci        }
158cf69771bSopenharmony_ci        ret = store_->Update(changedRows, values, predicates);
159cf69771bSopenharmony_ci        if (ret != OHOS::NativeRdb::E_OK) {
160cf69771bSopenharmony_ci            TIME_HILOGE(TIME_MODULE_SERVICE, "Update values after RecoverDataBase failed, ret: %{public}d", ret);
161cf69771bSopenharmony_ci        }
162cf69771bSopenharmony_ci    }
163cf69771bSopenharmony_ci    return true;
164cf69771bSopenharmony_ci}
165cf69771bSopenharmony_ci
166cf69771bSopenharmony_cistd::shared_ptr<OHOS::NativeRdb::ResultSet> TimeDatabase::Query(
167cf69771bSopenharmony_ci    const OHOS::NativeRdb::AbsRdbPredicates &predicates, const std::vector<std::string> &columns)
168cf69771bSopenharmony_ci{
169cf69771bSopenharmony_ci    if (store_ == nullptr) {
170cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
171cf69771bSopenharmony_ci        return nullptr;
172cf69771bSopenharmony_ci    }
173cf69771bSopenharmony_ci    auto result = store_->Query(predicates, columns);
174cf69771bSopenharmony_ci    int count;
175cf69771bSopenharmony_ci    if (result->GetRowCount(count) == OHOS::NativeRdb::E_SQLITE_CORRUPT) {
176cf69771bSopenharmony_ci        RecoverDataBase();
177cf69771bSopenharmony_ci        return nullptr;
178cf69771bSopenharmony_ci    }
179cf69771bSopenharmony_ci    return result;
180cf69771bSopenharmony_ci}
181cf69771bSopenharmony_ci
182cf69771bSopenharmony_cibool TimeDatabase::Delete(const OHOS::NativeRdb::AbsRdbPredicates &predicates)
183cf69771bSopenharmony_ci{
184cf69771bSopenharmony_ci    if (store_ == nullptr) {
185cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
186cf69771bSopenharmony_ci        return false;
187cf69771bSopenharmony_ci    }
188cf69771bSopenharmony_ci
189cf69771bSopenharmony_ci    int deletedRows = 0;
190cf69771bSopenharmony_ci    int ret = store_->Delete(deletedRows, predicates);
191cf69771bSopenharmony_ci    if (ret != OHOS::NativeRdb::E_OK) {
192cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "delete values failed, ret: %{public}d", ret);
193cf69771bSopenharmony_ci        if (ret != OHOS::NativeRdb::E_SQLITE_CORRUPT) {
194cf69771bSopenharmony_ci            return false;
195cf69771bSopenharmony_ci        }
196cf69771bSopenharmony_ci        if (!RecoverDataBase()) {
197cf69771bSopenharmony_ci            return false;
198cf69771bSopenharmony_ci        }
199cf69771bSopenharmony_ci        ret = store_->Delete(deletedRows, predicates);
200cf69771bSopenharmony_ci        if (ret != OHOS::NativeRdb::E_OK) {
201cf69771bSopenharmony_ci            TIME_HILOGE(TIME_MODULE_SERVICE, "Delete values after RecoverDataBase failed, ret: %{public}d", ret);
202cf69771bSopenharmony_ci        }
203cf69771bSopenharmony_ci    }
204cf69771bSopenharmony_ci    return true;
205cf69771bSopenharmony_ci}
206cf69771bSopenharmony_ci
207cf69771bSopenharmony_civoid TimeDatabase::ClearDropOnReboot()
208cf69771bSopenharmony_ci{
209cf69771bSopenharmony_ci    TIME_HILOGI(TIME_MODULE_SERVICE, "Clears drop_on_reboot table");
210cf69771bSopenharmony_ci    if (store_ == nullptr) {
211cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "store_ is nullptr");
212cf69771bSopenharmony_ci        return;
213cf69771bSopenharmony_ci    }
214cf69771bSopenharmony_ci    int ret = store_->ExecuteSql("DELETE FROM drop_on_reboot");
215cf69771bSopenharmony_ci    if (ret != OHOS::NativeRdb::E_OK) {
216cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "Clears drop_on_reboot table failed");
217cf69771bSopenharmony_ci        if (ret != OHOS::NativeRdb::E_SQLITE_CORRUPT) {
218cf69771bSopenharmony_ci            return;
219cf69771bSopenharmony_ci        }
220cf69771bSopenharmony_ci        if (!RecoverDataBase()) {
221cf69771bSopenharmony_ci            return;
222cf69771bSopenharmony_ci        }
223cf69771bSopenharmony_ci        ret = store_->ExecuteSql("DELETE FROM drop_on_reboot");
224cf69771bSopenharmony_ci        if (ret != OHOS::NativeRdb::E_OK) {
225cf69771bSopenharmony_ci            TIME_HILOGE(TIME_MODULE_SERVICE, "Clears after RecoverDataBase failed, ret: %{public}d", ret);
226cf69771bSopenharmony_ci        }
227cf69771bSopenharmony_ci    }
228cf69771bSopenharmony_ci}
229cf69771bSopenharmony_ci
230cf69771bSopenharmony_ciint TimeDBCreateTables(OHOS::NativeRdb::RdbStore &store)
231cf69771bSopenharmony_ci{
232cf69771bSopenharmony_ci    TIME_HILOGI(TIME_MODULE_SERVICE, "Creates hold_on_reboot table");
233cf69771bSopenharmony_ci    // Creates hold_on_reboot table.
234cf69771bSopenharmony_ci    int ret = store.ExecuteSql(CREATE_TIME_TIMER_HOLD_ON_REBOOT);
235cf69771bSopenharmony_ci    if (ret != OHOS::NativeRdb::E_OK) {
236cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "Creates hold_on_reboot table failed, ret: %{public}d", ret);
237cf69771bSopenharmony_ci        return ret;
238cf69771bSopenharmony_ci    }
239cf69771bSopenharmony_ci
240cf69771bSopenharmony_ci    TIME_HILOGI(TIME_MODULE_SERVICE, "Creates drop_on_reboot table");
241cf69771bSopenharmony_ci    // Creates drop_on_reboot table.
242cf69771bSopenharmony_ci    ret = store.ExecuteSql(CREATE_TIME_TIMER_DROP_ON_REBOOT);
243cf69771bSopenharmony_ci    if (ret != OHOS::NativeRdb::E_OK) {
244cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "Creates drop_on_reboot table failed, ret: %{public}d", ret);
245cf69771bSopenharmony_ci        return ret;
246cf69771bSopenharmony_ci    }
247cf69771bSopenharmony_ci    return ret;
248cf69771bSopenharmony_ci}
249cf69771bSopenharmony_ci
250cf69771bSopenharmony_ciint TimeDBOpenCallback::OnCreate(OHOS::NativeRdb::RdbStore &store)
251cf69771bSopenharmony_ci{
252cf69771bSopenharmony_ci    TIME_HILOGI(TIME_MODULE_SERVICE, "OnCreate");
253cf69771bSopenharmony_ci    auto initRet = TimeDBCreateTables(store);
254cf69771bSopenharmony_ci    if (initRet != OHOS::NativeRdb::E_OK) {
255cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "Init database failed: %{public}d", initRet);
256cf69771bSopenharmony_ci        return initRet;
257cf69771bSopenharmony_ci    }
258cf69771bSopenharmony_ci    return OHOS::NativeRdb::E_OK;
259cf69771bSopenharmony_ci}
260cf69771bSopenharmony_ci
261cf69771bSopenharmony_ciint TimeDBOpenCallback::OnOpen(OHOS::NativeRdb::RdbStore &store)
262cf69771bSopenharmony_ci{
263cf69771bSopenharmony_ci    return OHOS::NativeRdb::E_OK;
264cf69771bSopenharmony_ci}
265cf69771bSopenharmony_ci
266cf69771bSopenharmony_ciint TimeDBOpenCallback::OnUpgrade(OHOS::NativeRdb::RdbStore &store, int oldVersion, int newVersion)
267cf69771bSopenharmony_ci{
268cf69771bSopenharmony_ci    if (oldVersion == DATABASE_OPEN_VERSION && newVersion == DATABASE_OPEN_VERSION_2) {
269cf69771bSopenharmony_ci        int ret = store.ExecuteSql(HOLD_ON_REBOOT_ADD_COLUMN);
270cf69771bSopenharmony_ci        if (ret != OHOS::NativeRdb::E_OK) {
271cf69771bSopenharmony_ci            TIME_HILOGE(TIME_MODULE_SERVICE, "hold_on_reboot add column failed, ret: %{public}d", ret);
272cf69771bSopenharmony_ci            return ret;
273cf69771bSopenharmony_ci        }
274cf69771bSopenharmony_ci        ret = store.ExecuteSql(DROP_ON_REBOOT_ADD_COLUMN);
275cf69771bSopenharmony_ci        if (ret != OHOS::NativeRdb::E_OK) {
276cf69771bSopenharmony_ci            TIME_HILOGE(TIME_MODULE_SERVICE, "drop_on_reboot add column failed, ret: %{public}d", ret);
277cf69771bSopenharmony_ci            return ret;
278cf69771bSopenharmony_ci        }
279cf69771bSopenharmony_ci    }
280cf69771bSopenharmony_ci    return OHOS::NativeRdb::E_OK;
281cf69771bSopenharmony_ci}
282cf69771bSopenharmony_ci
283cf69771bSopenharmony_ciint TimeDBOpenCallback::OnDowngrade(OHOS::NativeRdb::RdbStore &store, int oldVersion, int newVersion)
284cf69771bSopenharmony_ci{
285cf69771bSopenharmony_ci    return OHOS::NativeRdb::E_OK;
286cf69771bSopenharmony_ci}
287cf69771bSopenharmony_ci}
288cf69771bSopenharmony_ci}