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