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 int ret = E_OK;
72 SQLiteUtils::ResetStatement(statement, true, ret);
73 return CheckCorruptedStatus(errCode);
74 }
75
Clear()76 int SQLiteLocalStorageExecutor::Clear()
77 {
78 int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, CLEAR_SQL);
79 return CheckCorruptedStatus(errCode);
80 }
81
GetEntries(const Key & keyPrefix,std::vector<Entry> & entries) const82 int SQLiteLocalStorageExecutor::GetEntries(const Key &keyPrefix,
83 std::vector<Entry> &entries) const
84 {
85 sqlite3_stmt *statement = nullptr;
86 int errCode = SQLiteUtils::GetStatement(dbHandle_, SELECT_BATCH_SQL, statement);
87 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
88 return CheckCorruptedStatus(errCode);
89 }
90
91 Entry entry;
92 errCode = SQLiteUtils::BindPrefixKey(statement, SELECT_BIND_KEY_INDEX, keyPrefix); // first arg is prefix key
93 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
94 goto END;
95 }
96
97 do {
98 errCode = SQLiteUtils::StepWithRetry(statement);
99 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
100 errCode = SQLiteUtils::GetColumnBlobValue(statement, SELECT_RESULT_KEY_INDEX, entry.key);
101 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
102 goto END;
103 }
104
105 errCode = SQLiteUtils::GetColumnBlobValue(statement, SELECT_RESULT_VAL_INDEX, entry.value);
106 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
107 goto END;
108 }
109
110 entries.push_back(std::move(entry));
111 } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
112 break;
113 } else {
114 LOGE("SQLite step failed:%d", errCode);
115 goto END;
116 }
117 } while (true);
118
119 // if select no result, return the -E_NOT_FOUND.
120 if (entries.empty()) { // LCOV_EXCL_BR_LINE
121 errCode = -E_NOT_FOUND;
122 } else {
123 errCode = E_OK;
124 }
125
126 END:
127 int ret = E_OK;
128 SQLiteUtils::ResetStatement(statement, true, ret);
129 return CheckCorruptedStatus(errCode);
130 }
131
PutBatch(const std::vector<Entry> & entries)132 int SQLiteLocalStorageExecutor::PutBatch(const std::vector<Entry> &entries)
133 {
134 if (entries.empty()) { // LCOV_EXCL_BR_LINE
135 return -E_INVALID_ARGS;
136 }
137
138 for (const auto &entry : entries) {
139 // first argument is key and second argument is value.
140 int errCode = Put(entry.key, entry.value);
141 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
142 LOGE("PutBatch failed: %d", errCode);
143 return CheckCorruptedStatus(errCode);
144 }
145 }
146
147 return E_OK;
148 }
149
DeleteBatch(const std::vector<Key> & keys)150 int SQLiteLocalStorageExecutor::DeleteBatch(const std::vector<Key> &keys)
151 {
152 if (keys.empty()) { // LCOV_EXCL_BR_LINE
153 return -E_INVALID_ARGS;
154 }
155
156 bool isAllNoExisted = true;
157
158 for (const auto &key : keys) {
159 int errCode = Delete(key);
160 if (errCode != E_OK && errCode != -E_NOT_FOUND) { // LCOV_EXCL_BR_LINE
161 return CheckCorruptedStatus(errCode);
162 }
163 if (errCode != -E_NOT_FOUND && isAllNoExisted == true) { // LCOV_EXCL_BR_LINE
164 isAllNoExisted = false;
165 }
166 }
167
168 if (isAllNoExisted) { // LCOV_EXCL_BR_LINE
169 return -E_NOT_FOUND;
170 }
171
172 return E_OK;
173 }
174
StartTransaction()175 int SQLiteLocalStorageExecutor::StartTransaction()
176 {
177 int errCode = SQLiteUtils::BeginTransaction(dbHandle_);
178 return CheckCorruptedStatus(errCode);
179 }
180
Commit()181 int SQLiteLocalStorageExecutor::Commit()
182 {
183 int errCode = SQLiteUtils::CommitTransaction(dbHandle_);
184 return CheckCorruptedStatus(errCode);
185 }
186
RollBack()187 int SQLiteLocalStorageExecutor::RollBack()
188 {
189 int errCode = SQLiteUtils::RollbackTransaction(dbHandle_);
190 return CheckCorruptedStatus(errCode);
191 }
192
Put(const Key & key,const Value & value)193 int SQLiteLocalStorageExecutor::Put(const Key &key, const Value &value)
194 {
195 sqlite3_stmt *statement = nullptr;
196 int errCode = SQLiteUtils::GetStatement(dbHandle_, INSERT_SQL, statement);
197 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
198 return CheckCorruptedStatus(errCode);
199 }
200
201 errCode = SQLiteUtils::BindBlobToStatement(statement, BIND_KEY_INDEX, key, false);
202 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
203 LOGE("Failed to bind the key.");
204 goto END;
205 }
206
207 errCode = SQLiteUtils::BindBlobToStatement(statement, BIND_VAL_INDEX, value, true);
208 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
209 LOGE("Failed to bind the value");
210 goto END;
211 }
212
213 errCode = SQLiteUtils::StepWithRetry(statement);
214 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { // LCOV_EXCL_BR_LINE
215 errCode = E_OK;
216 } else {
217 errCode = SQLiteUtils::MapSQLiteErrno(errCode);
218 }
219
220 END:
221 int ret = E_OK;
222 SQLiteUtils::ResetStatement(statement, true, ret);
223 return CheckCorruptedStatus(errCode);
224 }
225
Delete(const Key & key)226 int SQLiteLocalStorageExecutor::Delete(const Key &key)
227 {
228 sqlite3_stmt *statement = nullptr;
229 int errCode = SQLiteUtils::GetStatement(dbHandle_, DELETE_SQL, statement);
230 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
231 LOGE("Failed to get the delete statememt.");
232 return CheckCorruptedStatus(errCode);
233 }
234
235 errCode = SQLiteUtils::BindBlobToStatement(statement, BIND_KEY_INDEX, key, false);
236 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
237 LOGE("Bind key failed");
238 goto END;
239 }
240
241 errCode = SQLiteUtils::StepWithRetry(statement);
242 if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { // LCOV_EXCL_BR_LINE
243 LOGE("Delete step error:%d", errCode);
244 } else {
245 if (sqlite3_changes(dbHandle_) > 0) { // LCOV_EXCL_BR_LINE
246 errCode = E_OK;
247 } else {
248 errCode = -E_NOT_FOUND;
249 }
250 }
251 END:
252 int ret = E_OK;
253 SQLiteUtils::ResetStatement(statement, true, ret);
254 return CheckCorruptedStatus(errCode);
255 }
256 } // namespace DistributedDB
257