1 /*
2  * Copyright (c) 2021 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 "sqlite_local_storage_executor.h"
17 
18 #include "log_print.h"
19 #include "db_errno.h"
20 #include "sqlite_utils.h"
21 
22 namespace DistributedDB {
23 namespace {
24     const std::string CLEAR_SQL = "DELETE FROM data;";
25     const std::string SELECT_SQL = "SELECT value FROM data WHERE key=?;";
26     const std::string SELECT_BATCH_SQL =
27         "SELECT key, value FROM data WHERE key>=? AND key<=? ORDER BY key ASC;";
28     const std::string INSERT_SQL = "INSERT OR REPLACE INTO data VALUES(?,?);";
29     const std::string DELETE_SQL = "DELETE FROM data WHERE key=?;";
30 
31     const int BIND_KEY_INDEX = 1;
32     const int BIND_VAL_INDEX = 2;
33 
34     const int SELECT_BIND_KEY_INDEX = 1; // index of the binding key index for select one entry.
35 
36     const int SELECT_RESULT_KEY_INDEX = 0;
37     const int SELECT_RESULT_VAL_INDEX = 1;
38 }
39 
SQLiteLocalStorageExecutor(sqlite3 * dbHandle,bool writable,bool isMemDb)40 SQLiteLocalStorageExecutor::SQLiteLocalStorageExecutor(sqlite3 *dbHandle, bool writable, bool isMemDb)
41     : SQLiteStorageExecutor(dbHandle, writable, isMemDb)
42 {}
43 
~SQLiteLocalStorageExecutor()44 SQLiteLocalStorageExecutor::~SQLiteLocalStorageExecutor()
45 {}
46 
Get(const Key & key,Value & value) const47 int SQLiteLocalStorageExecutor::Get(const Key &key, Value &value) const
48 {
49     sqlite3_stmt *statement = nullptr;
50     int errCode = SQLiteUtils::GetStatement(dbHandle_, SELECT_SQL, statement);
51     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
52         return CheckCorruptedStatus(errCode);
53     }
54 
55     errCode = SQLiteUtils::BindBlobToStatement(statement, SELECT_BIND_KEY_INDEX, key, false);
56     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
57         goto END;
58     }
59 
60     errCode = SQLiteUtils::StepWithRetry(statement);
61     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { // LCOV_EXCL_BR_LINE
62         errCode = -E_NOT_FOUND;
63         goto END;
64     } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
65         goto END;
66     }
67 
68     errCode = SQLiteUtils::GetColumnBlobValue(statement, 0, value);
69 
70 END:
71     SQLiteUtils::ResetStatement(statement, true, errCode);
72     return CheckCorruptedStatus(errCode);
73 }
74 
Clear()75 int SQLiteLocalStorageExecutor::Clear()
76 {
77     int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, CLEAR_SQL);
78     return CheckCorruptedStatus(errCode);
79 }
80 
GetEntries(const Key & keyPrefix,std::vector<Entry> & entries) const81 int SQLiteLocalStorageExecutor::GetEntries(const Key &keyPrefix,
82     std::vector<Entry> &entries) const
83 {
84     sqlite3_stmt *statement = nullptr;
85     int errCode = SQLiteUtils::GetStatement(dbHandle_, SELECT_BATCH_SQL, statement);
86     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
87         return CheckCorruptedStatus(errCode);
88     }
89 
90     Entry entry;
91     errCode = SQLiteUtils::BindPrefixKey(statement, SELECT_BIND_KEY_INDEX, keyPrefix); // first arg is prefix key
92     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
93         goto END;
94     }
95 
96     do {
97         errCode = SQLiteUtils::StepWithRetry(statement);
98         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
99             errCode = SQLiteUtils::GetColumnBlobValue(statement, SELECT_RESULT_KEY_INDEX, entry.key);
100             if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
101                 goto END;
102             }
103 
104             errCode = SQLiteUtils::GetColumnBlobValue(statement, SELECT_RESULT_VAL_INDEX, entry.value);
105             if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
106                 goto END;
107             }
108 
109             entries.push_back(std::move(entry));
110         } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
111             break;
112         } else {
113             LOGE("SQLite step failed:%d", errCode);
114             goto END;
115         }
116     } while (true);
117 
118     // if select no result, return the -E_NOT_FOUND.
119     if (entries.empty()) { // LCOV_EXCL_BR_LINE
120         errCode = -E_NOT_FOUND;
121     } else {
122         errCode = E_OK;
123     }
124 
125 END:
126     SQLiteUtils::ResetStatement(statement, true, errCode);
127     return CheckCorruptedStatus(errCode);
128 }
129 
PutBatch(const std::vector<Entry> & entries)130 int SQLiteLocalStorageExecutor::PutBatch(const std::vector<Entry> &entries)
131 {
132     if (entries.empty()) { // LCOV_EXCL_BR_LINE
133         return -E_INVALID_ARGS;
134     }
135 
136     for (const auto &entry : entries) {
137         // first argument is key and second argument is value.
138         int errCode = Put(entry.key, entry.value);
139         if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
140             LOGE("PutBatch failed: %d", errCode);
141             return CheckCorruptedStatus(errCode);
142         }
143     }
144 
145     return E_OK;
146 }
147 
DeleteBatch(const std::vector<Key> & keys)148 int SQLiteLocalStorageExecutor::DeleteBatch(const std::vector<Key> &keys)
149 {
150     if (keys.empty()) { // LCOV_EXCL_BR_LINE
151         return -E_INVALID_ARGS;
152     }
153 
154     bool isAllNoExisted = true;
155 
156     for (const auto &key : keys) {
157         int errCode = Delete(key);
158         if (errCode != E_OK && errCode != -E_NOT_FOUND) { // LCOV_EXCL_BR_LINE
159             return CheckCorruptedStatus(errCode);
160         }
161         if (errCode != -E_NOT_FOUND && isAllNoExisted == true) { // LCOV_EXCL_BR_LINE
162             isAllNoExisted = false;
163         }
164     }
165 
166     if (isAllNoExisted) { // LCOV_EXCL_BR_LINE
167         return -E_NOT_FOUND;
168     }
169 
170     return E_OK;
171 }
172 
StartTransaction()173 int SQLiteLocalStorageExecutor::StartTransaction()
174 {
175     int errCode = SQLiteUtils::BeginTransaction(dbHandle_);
176     return CheckCorruptedStatus(errCode);
177 }
178 
Commit()179 int SQLiteLocalStorageExecutor::Commit()
180 {
181     int errCode = SQLiteUtils::CommitTransaction(dbHandle_);
182     return CheckCorruptedStatus(errCode);
183 }
184 
RollBack()185 int SQLiteLocalStorageExecutor::RollBack()
186 {
187     int errCode = SQLiteUtils::RollbackTransaction(dbHandle_);
188     return CheckCorruptedStatus(errCode);
189 }
190 
Put(const Key & key,const Value & value)191 int SQLiteLocalStorageExecutor::Put(const Key &key, const Value &value)
192 {
193     sqlite3_stmt *statement = nullptr;
194     int errCode = SQLiteUtils::GetStatement(dbHandle_, INSERT_SQL, statement);
195     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
196         return CheckCorruptedStatus(errCode);
197     }
198 
199     errCode = SQLiteUtils::BindBlobToStatement(statement, BIND_KEY_INDEX, key, false);
200     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
201         LOGE("Failed to bind the key.");
202         goto END;
203     }
204 
205     errCode = SQLiteUtils::BindBlobToStatement(statement, BIND_VAL_INDEX, value, true);
206     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
207         LOGE("Failed to bind the value");
208         goto END;
209     }
210 
211     errCode = SQLiteUtils::StepWithRetry(statement);
212     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { // LCOV_EXCL_BR_LINE
213         errCode = E_OK;
214     } else {
215         errCode = SQLiteUtils::MapSQLiteErrno(errCode);
216     }
217 
218 END:
219     SQLiteUtils::ResetStatement(statement, true, errCode);
220     return CheckCorruptedStatus(errCode);
221 }
222 
Delete(const Key & key)223 int SQLiteLocalStorageExecutor::Delete(const Key &key)
224 {
225     sqlite3_stmt *statement = nullptr;
226     int errCode = SQLiteUtils::GetStatement(dbHandle_, DELETE_SQL, statement);
227     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
228         LOGE("Failed to get the delete statememt.");
229         return CheckCorruptedStatus(errCode);
230     }
231 
232     errCode = SQLiteUtils::BindBlobToStatement(statement, BIND_KEY_INDEX, key, false);
233     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
234         LOGE("Bind key failed");
235         goto END;
236     }
237 
238     errCode = SQLiteUtils::StepWithRetry(statement);
239     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { // LCOV_EXCL_BR_LINE
240         LOGE("Delete step error:%d", errCode);
241     } else {
242         if (sqlite3_changes(dbHandle_) > 0) { // LCOV_EXCL_BR_LINE
243             errCode = E_OK;
244         } else {
245             errCode = -E_NOT_FOUND;
246         }
247     }
248 END:
249     SQLiteUtils::ResetStatement(statement, true, errCode);
250     return CheckCorruptedStatus(errCode);
251 }
252 } // namespace DistributedDB
253