1 /*
2 * Copyright (c) 2023 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_store_executor_impl.h"
17
18 #include "check_common.h"
19 #include "rd_db_constant.h"
20 #include "doc_errno.h"
21 #include "document_key.h"
22 #include "rd_log_print.h"
23 #include "rd_sqlite_utils.h"
24
25 namespace DocumentDB {
26 constexpr const uint8_t KEY_TYPE = uint8_t(DocIdType::STRING);
CreateDatabase(const std::string & path,const DBConfig & config,sqlite3 * & db)27 int SqliteStoreExecutorImpl::CreateDatabase(const std::string &path, const DBConfig &config, sqlite3 *&db)
28 {
29 if (db != nullptr) {
30 return -E_INVALID_ARGS;
31 }
32
33 int errCode = RDSQLiteUtils::CreateDataBase(path, 0, db);
34 if (errCode != E_OK || db == nullptr) {
35 GLOGE("Open or create database failed. %d", errCode);
36 return errCode;
37 }
38
39 std::string pageSizeSql = "PRAGMA page_size=" + std::to_string(config.GetPageSize() * 1024);
40 errCode = RDSQLiteUtils::ExecSql(db, pageSizeSql);
41 if (errCode != E_OK) {
42 GLOGE("Set db page size failed. %d", errCode);
43 goto END;
44 }
45
46 errCode = RDSQLiteUtils::ExecSql(db, "PRAGMA journal_mode=WAL;");
47 if (errCode != E_OK) {
48 GLOGE("Set db journal_mode failed. %d", errCode);
49 goto END;
50 }
51
52 errCode = RDSQLiteUtils::ExecSql(db, "CREATE TABLE IF NOT EXISTS grd_meta (key BLOB PRIMARY KEY, value BLOB);");
53 if (errCode != E_OK) {
54 GLOGE("Create meta table failed. %d", errCode);
55 goto END;
56 }
57
58 return E_OK;
59
60 END:
61 sqlite3_close_v2(db);
62 db = nullptr;
63 return errCode;
64 }
65
SqliteStoreExecutorImpl(sqlite3 * handle)66 SqliteStoreExecutorImpl::SqliteStoreExecutorImpl(sqlite3 *handle) : dbHandle_(handle) {}
67
~SqliteStoreExecutorImpl()68 SqliteStoreExecutorImpl::~SqliteStoreExecutorImpl()
69 {
70 sqlite3_close_v2(dbHandle_);
71 dbHandle_ = nullptr;
72 }
73
GetDBConfig(std::string & config)74 int SqliteStoreExecutorImpl::GetDBConfig(std::string &config)
75 {
76 std::string dbConfigKeyStr = "DB_CONFIG";
77 Key dbConfigKey = { dbConfigKeyStr.begin(), dbConfigKeyStr.end() };
78 Value dbConfigVal;
79 int errCode = GetDataByKey("grd_meta", dbConfigKey, dbConfigVal);
80 config.assign(dbConfigVal.begin(), dbConfigVal.end());
81 return errCode;
82 }
83
SetDBConfig(const std::string & config)84 int SqliteStoreExecutorImpl::SetDBConfig(const std::string &config)
85 {
86 std::string dbConfigKeyStr = "DB_CONFIG";
87 Key dbConfigKey = { dbConfigKeyStr.begin(), dbConfigKeyStr.end() };
88 Value dbConfigVal = { config.begin(), config.end() };
89 return PutData("grd_meta", dbConfigKey, dbConfigVal, false); // dont need to add Key type;
90 }
91
StartTransaction()92 int SqliteStoreExecutorImpl::StartTransaction()
93 {
94 return RDSQLiteUtils::BeginTransaction(dbHandle_, TransactType::IMMEDIATE);
95 }
96
Commit()97 int SqliteStoreExecutorImpl::Commit()
98 {
99 return RDSQLiteUtils::CommitTransaction(dbHandle_);
100 }
101
Rollback()102 int SqliteStoreExecutorImpl::Rollback()
103 {
104 return RDSQLiteUtils::RollbackTransaction(dbHandle_);
105 }
106
PutData(const std::string & collName,Key & key,const Value & value,bool isNeedAddKeyType)107 int SqliteStoreExecutorImpl::PutData(const std::string &collName, Key &key, const Value &value, bool isNeedAddKeyType)
108 {
109 if (dbHandle_ == nullptr) {
110 return -E_ERROR;
111 }
112 if (isNeedAddKeyType) {
113 key.push_back(KEY_TYPE); // Stitching ID type
114 }
115 std::string sql = "INSERT OR REPLACE INTO '" + collName + "' VALUES (?,?);";
116 int errCode = RDSQLiteUtils::ExecSql(
117 dbHandle_, sql,
118 [key, value](sqlite3_stmt *stmt) {
119 RDSQLiteUtils::BindBlobToStatement(stmt, 1, key);
120 RDSQLiteUtils::BindBlobToStatement(stmt, 2, value);
121 return E_OK;
122 },
123 nullptr);
124 if (errCode != E_OK) {
125 GLOGE("[sqlite executor] Put data failed. err=%d", errCode);
126 if (errCode == -E_ERROR) {
127 GLOGE("Cant find the collection");
128 return -E_INVALID_ARGS;
129 }
130 return errCode;
131 }
132 return E_OK;
133 }
134
InsertData(const std::string & collName,Key & key,const Value & value,bool isNeedAddKeyType)135 int SqliteStoreExecutorImpl::InsertData(const std::string &collName, Key &key, const Value &value,
136 bool isNeedAddKeyType)
137 {
138 if (dbHandle_ == nullptr) {
139 return -E_ERROR;
140 }
141 if (isNeedAddKeyType) {
142 key.push_back(KEY_TYPE); // Stitching ID type
143 }
144 std::string sql = "INSERT INTO '" + collName + "' VALUES (?,?);";
145 int errCode = RDSQLiteUtils::ExecSql(
146 dbHandle_, sql,
147 [key, value](sqlite3_stmt *stmt) {
148 RDSQLiteUtils::BindBlobToStatement(stmt, 1, key);
149 RDSQLiteUtils::BindBlobToStatement(stmt, 2, value);
150 return E_OK;
151 },
152 nullptr);
153 if (errCode != E_OK) {
154 GLOGE("[sqlite executor] Put data failed. err=%d", errCode);
155 if (errCode == -E_ERROR) {
156 GLOGE("have same ID before");
157 return -E_DATA_CONFLICT;
158 }
159 return errCode;
160 }
161 return E_OK;
162 }
163
GetDataByKey(const std::string & collName,Key & key,Value & value) const164 int SqliteStoreExecutorImpl::GetDataByKey(const std::string &collName, Key &key, Value &value) const
165 {
166 if (dbHandle_ == nullptr) {
167 GLOGE("Invalid db handle.");
168 return -E_ERROR;
169 }
170 int innerErrorCode = -E_NOT_FOUND;
171 std::string sql = "SELECT value FROM '" + collName + "' WHERE key=?;";
172 int errCode = RDSQLiteUtils::ExecSql(
173 dbHandle_, sql,
174 [key](sqlite3_stmt *stmt) {
175 RDSQLiteUtils::BindBlobToStatement(stmt, 1, key);
176 return E_OK;
177 },
178 [&value, &innerErrorCode](sqlite3_stmt *stmt, bool &isMatchOneData) {
179 RDSQLiteUtils::GetColumnBlobValue(stmt, 0, value);
180 innerErrorCode = E_OK;
181 return E_OK;
182 });
183 if (errCode != E_OK) {
184 GLOGE("[sqlite executor] Get data failed. err=%d", errCode);
185 return errCode;
186 }
187 return innerErrorCode;
188 }
189
GetDataById(const std::string & collName,Key & key,Value & value) const190 int SqliteStoreExecutorImpl::GetDataById(const std::string &collName, Key &key, Value &value) const
191 {
192 if (dbHandle_ == nullptr) {
193 GLOGE("Invalid db handle.");
194 return -E_ERROR;
195 }
196 key.push_back(KEY_TYPE); // Stitching ID type
197 int innerErrorCode = -E_NOT_FOUND;
198 std::string sql = "SELECT value FROM '" + collName + "' WHERE key=?;";
199 int errCode = RDSQLiteUtils::ExecSql(
200 dbHandle_, sql,
201 [key](sqlite3_stmt *stmt) {
202 RDSQLiteUtils::BindBlobToStatement(stmt, 1, key);
203 return E_OK;
204 },
205 [&value, &innerErrorCode](sqlite3_stmt *stmt, bool &isMatchOneData) {
206 RDSQLiteUtils::GetColumnBlobValue(stmt, 0, value);
207 innerErrorCode = E_OK;
208 return E_OK;
209 });
210 if (errCode != E_OK) {
211 GLOGE("[sqlite executor] Get data failed. err=%d", errCode);
212 return errCode;
213 }
214 return innerErrorCode;
215 }
216
GeneralInsertSql(const std::string & collName,Key & key,int isIdExist)217 std::string GeneralInsertSql(const std::string &collName, Key &key, int isIdExist)
218 {
219 std::string sqlEqual = "SELECT key, value FROM '" + collName + "' WHERE key=?;";
220 std::string sqlOrder = "SELECT key, value FROM '" + collName + "' ORDER BY KEY;";
221 std::string sqlLarger = "SELECT key, value FROM '" + collName + "' WHERE key>?;";
222 if (isIdExist) {
223 return sqlEqual;
224 } else {
225 return (key.empty()) ? sqlOrder : sqlLarger;
226 }
227 }
228
AssignValueToData(std::string & keyStr,const std::string & valueStr,std::pair<std::string,std::string> & values,int & innerErrorCode,bool & isMatchOneData)229 void AssignValueToData(std::string &keyStr, const std::string &valueStr, std::pair<std::string, std::string> &values,
230 int &innerErrorCode, bool &isMatchOneData)
231 {
232 keyStr.pop_back(); // get id from really key.
233 values.first = keyStr;
234 values.second = valueStr;
235 innerErrorCode = E_OK;
236 isMatchOneData = true; // this args work in ExecSql fuction
237 }
238
GetDataByFilter(const std::string & collName,Key & key,const JsonObject & filterObj,std::pair<std::string,std::string> & values,int isIdExist) const239 int SqliteStoreExecutorImpl::GetDataByFilter(const std::string &collName, Key &key, const JsonObject &filterObj,
240 std::pair<std::string, std::string> &values, int isIdExist) const
241 {
242 if (dbHandle_ == nullptr) {
243 GLOGE("Invalid db handle.");
244 return -E_ERROR;
245 }
246 Value keyResult;
247 Value valueResult;
248 bool isFindMatch = false;
249 int innerErrorCode = -E_NOT_FOUND;
250 std::string sql = GeneralInsertSql(collName, key, isIdExist);
251 key.push_back(KEY_TYPE);
252 std::string keyStr(key.begin(), key.end());
253 int errCode = RDSQLiteUtils::ExecSql(
254 dbHandle_, sql,
255 [key](sqlite3_stmt *stmt) {
256 if (!key.empty()) {
257 RDSQLiteUtils::BindBlobToStatement(stmt, 1, key);
258 }
259 return E_OK;
260 },
261 [&keyResult, &innerErrorCode, &valueResult, &filterObj, &values, &isFindMatch](sqlite3_stmt *stmt,
262 bool &isMatchOneData) {
263 RDSQLiteUtils::GetColumnBlobValue(stmt, 0, keyResult);
264 RDSQLiteUtils::GetColumnBlobValue(stmt, 1, valueResult);
265 std::string keyStr(keyResult.begin(), keyResult.end());
266 std::string valueStr(valueResult.begin(), valueResult.end());
267 JsonObject srcObj = JsonObject::Parse(valueStr, innerErrorCode, true);
268 if (innerErrorCode != E_OK) {
269 GLOGE("srcObj Parsed failed");
270 return innerErrorCode;
271 }
272 if (JsonCommon::IsJsonNodeMatch(srcObj, filterObj, innerErrorCode)) {
273 isFindMatch = true; // this args work in this function
274 (void)AssignValueToData(keyStr, valueStr, values, innerErrorCode, isMatchOneData);
275 return E_OK; // match count;
276 }
277 innerErrorCode = E_OK;
278 return E_OK;
279 });
280 if (errCode != E_OK) {
281 GLOGE("[sqlite executor] Get data failed. err=%d", errCode);
282 return errCode;
283 }
284 if (!isFindMatch) {
285 return -E_NOT_FOUND;
286 }
287 return innerErrorCode;
288 }
289
DelData(const std::string & collName,Key & key)290 int SqliteStoreExecutorImpl::DelData(const std::string &collName, Key &key)
291 {
292 if (dbHandle_ == nullptr) {
293 GLOGE("Invalid db handle.");
294 return -E_ERROR;
295 }
296 key.push_back(KEY_TYPE);
297 int errCode = 0;
298 Value valueRet;
299 if (GetDataByKey(collName, key, valueRet) != E_OK) {
300 return -E_NO_DATA;
301 }
302 std::string sql = "DELETE FROM '" + collName + "' WHERE key=?;";
303 errCode = RDSQLiteUtils::ExecSql(
304 dbHandle_, sql,
305 [key](sqlite3_stmt *stmt) {
306 RDSQLiteUtils::BindBlobToStatement(stmt, 1, key);
307 return E_OK;
308 },
309 nullptr);
310 if (errCode != E_OK) {
311 GLOGE("[sqlite executor] Delete data failed. err=%d", errCode);
312 if (errCode == -E_ERROR) {
313 GLOGE("Cant find the collection");
314 return -E_NO_DATA;
315 }
316 }
317 return errCode;
318 }
319
CreateCollection(const std::string & name,const std::string & option,bool ignoreExists)320 int SqliteStoreExecutorImpl::CreateCollection(const std::string &name, const std::string &option, bool ignoreExists)
321 {
322 if (dbHandle_ == nullptr) {
323 return -E_ERROR;
324 }
325 std::string collName = RdDBConstant::COLL_PREFIX + name;
326 int errCode = E_OK;
327 bool isExists = IsCollectionExists(collName, errCode);
328 if (errCode != E_OK) {
329 return errCode;
330 }
331
332 if (isExists) {
333 GLOGW("[sqlite executor] Create collection failed, collection already exists.");
334 return ignoreExists ? E_OK : -E_COLLECTION_CONFLICT;
335 }
336
337 std::string sql = "CREATE TABLE IF NOT EXISTS '" + collName + "' (key BLOB PRIMARY KEY, value BLOB);";
338 errCode = RDSQLiteUtils::ExecSql(dbHandle_, sql);
339 if (errCode != E_OK) {
340 GLOGE("[sqlite executor] Create collection failed. err=%d", errCode);
341 return errCode;
342 }
343
344 errCode = SetCollectionOption(name, option);
345 if (errCode != E_OK) {
346 GLOGE("[sqlite executor] Set collection option failed. err=%d", errCode);
347 }
348 return errCode;
349 }
350
DropCollection(const std::string & name,bool ignoreNonExists)351 int SqliteStoreExecutorImpl::DropCollection(const std::string &name, bool ignoreNonExists)
352 {
353 if (dbHandle_ == nullptr) {
354 return -E_ERROR;
355 }
356
357 std::string collName = RdDBConstant::COLL_PREFIX + name;
358 if (!ignoreNonExists) {
359 int errCode = E_OK;
360 bool isExists = IsCollectionExists(collName, errCode);
361 if (errCode != E_OK) {
362 return errCode;
363 }
364 if (!isExists) {
365 GLOGE("[sqlite executor] Drop collection failed, collection not exists.");
366 return -E_INVALID_ARGS;
367 }
368 }
369
370 std::string sql = "DROP TABLE IF EXISTS '" + collName + "';";
371 int errCode = RDSQLiteUtils::ExecSql(dbHandle_, sql);
372 if (errCode != E_OK) {
373 GLOGE("[sqlite executor] Drop collection failed. err=%d", errCode);
374 }
375 return errCode;
376 }
377
IsCollectionExists(const std::string & name,int & errCode)378 bool SqliteStoreExecutorImpl::IsCollectionExists(const std::string &name, int &errCode)
379 {
380 bool isExists = false;
381 std::string sql = "SELECT tbl_name FROM sqlite_master WHERE tbl_name=?;";
382 errCode = RDSQLiteUtils::ExecSql(
383 dbHandle_, sql,
384 [name](sqlite3_stmt *stmt) {
385 RDSQLiteUtils::BindTextToStatement(stmt, 1, name);
386 return E_OK;
387 },
388 [&isExists](sqlite3_stmt *stmt, bool &isMatchOneData) {
389 isExists = true;
390 return E_OK;
391 });
392 if (errCode != E_OK) {
393 GLOGE("Check collection exist failed. %d", errCode);
394 }
395 return isExists;
396 }
397
SetCollectionOption(const std::string & name,const std::string & option)398 int SqliteStoreExecutorImpl::SetCollectionOption(const std::string &name, const std::string &option)
399 {
400 std::string collOptKeyStr = "COLLECTION_OPTION_" + name;
401 Key collOptKey = { collOptKeyStr.begin(), collOptKeyStr.end() };
402 Value collOptVal = { option.begin(), option.end() };
403 return PutData("grd_meta", collOptKey, collOptVal, false); // dont need to add key type;
404 }
405
CleanCollectionOption(const std::string & name)406 int SqliteStoreExecutorImpl::CleanCollectionOption(const std::string &name)
407 {
408 std::string collOptKeyStr = "COLLECTION_OPTION_" + name;
409 Key collOptKey = { collOptKeyStr.begin(), collOptKeyStr.end() };
410 return DelData("grd_meta", collOptKey);
411 }
412 } // namespace DocumentDB