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 #include <mutex>
16 #include <openssl/sha.h>
17 #include <string>
18 #include <sys/time.h>
19 #include <thread>
20 #include <variant>
21 #include <vector>
22 
23 #include "cloud/cloud_db_constant.h"
24 #include "concurrent_adapter.h"
25 #include "db_common.h"
26 #include "db_constant.h"
27 #include "kv_store_errno.h"
28 #include "param_check_utils.h"
29 #include "platform_specific.h"
30 #include "relational_store_client.h"
31 #include "runtime_context.h"
32 #include "sqlite_utils.h"
33 
34 // using the "sqlite3sym.h" in OHOS
35 #ifndef USE_SQLITE_SYMBOLS
36 #include "sqlite3.h"
37 #else
38 #include "sqlite3sym.h"
39 #endif
40 
41 #if defined _WIN32
42 #ifndef RUNNING_ON_WIN
43 #define RUNNING_ON_WIN
44 #endif
45 #else
46 #ifndef RUNNING_ON_LINUX
47 #define RUNNING_ON_LINUX
48 #endif
49 #endif
50 
51 #if defined(RUNNING_ON_LINUX)
52 #include <unistd.h>
53 #elif defined RUNNING_ON_WIN
54 #include <io.h>
55 #else
56 #error "PLATFORM NOT SPECIFIED!"
57 #endif
58 
59 #ifdef DB_DEBUG_ENV
60 #include "system_time.h"
61 
62 using namespace DistributedDB::OS;
63 #endif
64 using namespace DistributedDB;
65 
66 namespace {
67 constexpr int E_OK = 0;
68 constexpr int E_ERROR = 1;
69 constexpr int STR_TO_LL_BY_DEVALUE = 10;
70 constexpr int BUSY_TIMEOUT = 2000;  // 2s.
71 constexpr int MAX_BLOB_READ_SIZE = 5 * 1024 * 1024; // 5M limit
72 const std::string DEVICE_TYPE = "device";
73 const std::string SYNC_TABLE_TYPE = "sync_table_type_";
74 class ValueHashCalc {
75 public:
ValueHashCalc()76     ValueHashCalc() {};
~ValueHashCalc()77     ~ValueHashCalc()
78     {
79         delete context_;
80         context_ = nullptr;
81     }
82 
Initialize()83     int Initialize()
84     {
85         context_ = new (std::nothrow) SHA256_CTX;
86         if (context_ == nullptr) {
87             return -E_ERROR;
88         }
89 
90         int errCode = SHA256_Init(context_);
91         if (errCode == 0) {
92             return -E_ERROR;
93         }
94         return E_OK;
95     }
96 
Update(const std::vector<uint8_t> & value)97     int Update(const std::vector<uint8_t> &value)
98     {
99         if (context_ == nullptr) {
100             return -E_ERROR;
101         }
102         int errCode = SHA256_Update(context_, value.data(), value.size());
103         if (errCode == 0) {
104             return -E_ERROR;
105         }
106         return E_OK;
107     }
108 
GetResult(std::vector<uint8_t> & value)109     int GetResult(std::vector<uint8_t> &value)
110     {
111         if (context_ == nullptr) {
112             return -E_ERROR;
113         }
114 
115         value.resize(SHA256_DIGEST_LENGTH);
116         int errCode = SHA256_Final(value.data(), context_);
117         if (errCode == 0) {
118             return -E_ERROR;
119         }
120 
121         return E_OK;
122     }
123 
124 private:
125     SHA256_CTX *context_ = nullptr;
126 };
127 
128 using Timestamp = uint64_t;
129 using TimeOffset = int64_t;
130 
131 class TimeHelper {
132 public:
133     // 10000 year 100ns
134     static constexpr int64_t BASE_OFFSET = 10000LL * 365LL * 24LL * 3600LL * 1000LL * 1000LL * 10L;
135 
136     static constexpr int64_t MAX_VALID_TIME = BASE_OFFSET * 2; // 20000 year 100ns
137 
138     static constexpr uint64_t TO_100_NS = 10; // 1us to 100ns
139 
140     static constexpr Timestamp INVALID_TIMESTAMP = 0;
141 
142     static constexpr uint64_t MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS = 1000000;
143 
144     static constexpr int64_t MAX_NOISE = 9 * 100 * 1000; // 900ms
145 
146     static constexpr uint64_t MAX_INC_COUNT = 9; // last bit from 0-9
147 
GetSysCurrentRawTime(uint64_t & curTime)148     static int GetSysCurrentRawTime(uint64_t &curTime)
149     {
150         static uint64_t lastCurTime = 0u;
151         int errCode = GetCurrentSysTimeInMicrosecond(curTime);
152         if (errCode != E_OK) {
153             return errCode;
154         }
155         curTime *= TO_100_NS;
156 
157         std::lock_guard<std::mutex> lock(systemTimeLock_);
158         int64_t timeDiff = static_cast<int64_t>(curTime) - static_cast<int64_t>(lastCurTime);
159         if (std::abs(timeDiff) > 1000u) { // 1000 is us
160             lastCurTime = curTime;
161             return E_OK;
162         }
163         if (curTime <= lastCurTime) {
164             curTime = lastCurTime + 1;
165         }
166         lastCurTime = curTime;
167         return E_OK;
168     }
169 
170     // Init the TimeHelper for time skew
Initialize()171     void Initialize()
172     {
173         // it maybe a rebuild db when initialize with localTimeOffset is TimeHelper::BASE_OFFSET
174         // reinitialize for this db
175         if (isInitialized_) {
176             return;
177         }
178         (void)GetCurrentSysTimeInMicrosecond(lastSystemTime_);
179         (void)OS::GetMonotonicRelativeTimeInMicrosecond(lastMonotonicTime_);
180         LOGD("Initialize time helper skew: %" PRIu64 " %" PRIu64, lastSystemTime_, lastMonotonicTime_);
181         isInitialized_ = true;
182     }
183 
GetTime(TimeOffset timeOffset,const std::function<Timestamp ()> & getDbMaxTimestamp,const std::function<Timestamp ()> & getDbLocalTimeOffset)184     Timestamp GetTime(TimeOffset timeOffset, const std::function<Timestamp()> &getDbMaxTimestamp,
185         const std::function<Timestamp()> &getDbLocalTimeOffset)
186     {
187         if (!isLoaded_) { // First use, load max time stamp and local time offset from db;
188             if (getDbMaxTimestamp != nullptr) {
189                 lastLocalTime_ = getDbMaxTimestamp();
190             }
191             if (getDbLocalTimeOffset != nullptr) {
192                 localTimeOffset_ = getDbLocalTimeOffset();
193             }
194             LOGD("Use time helper with maxTimestamp:%" PRIu64 " localTimeOffset:%" PRIu64 " first time", lastLocalTime_,
195                 localTimeOffset_);
196             isLoaded_ = true;
197         }
198         Timestamp currentSystemTime = 0u;
199         (void)GetCurrentSysTimeInMicrosecond(currentSystemTime);
200         Timestamp currentMonotonicTime = 0u;
201         (void)OS::GetMonotonicRelativeTimeInMicrosecond(currentMonotonicTime);
202         auto deltaTime = static_cast<int64_t>(currentMonotonicTime - lastMonotonicTime_);
203         Timestamp currentSysTime = GetSysCurrentTime();
204         Timestamp currentLocalTime = currentSysTime + timeOffset + localTimeOffset_;
205         if (currentLocalTime <= lastLocalTime_ || currentLocalTime > MAX_VALID_TIME) {
206             LOGD("Ext invalid time: lastLocalTime_: %" PRIu64 ", currentLocalTime: %" PRIu64 ", deltaTime: %" PRId64,
207                 lastLocalTime_, currentLocalTime, deltaTime);
208             lastLocalTime_ = static_cast<Timestamp>(static_cast<int64_t>(lastLocalTime_) +
209                 deltaTime * static_cast<int64_t>(TO_100_NS));
210             currentLocalTime = lastLocalTime_;
211         } else {
212             lastLocalTime_ = currentLocalTime;
213         }
214 
215         lastSystemTime_ = currentSystemTime;
216         lastMonotonicTime_ = currentMonotonicTime;
217         return currentLocalTime;
218     }
219 
TimeSkew(const std::function<Timestamp ()> & getLocalTimeOffsetFromDB,Timestamp timeOffset)220     bool TimeSkew(const std::function<Timestamp()> &getLocalTimeOffsetFromDB, Timestamp timeOffset)
221     {
222         Timestamp currentSystemTime = 0u;
223         (void)GetCurrentSysTimeInMicrosecond(currentSystemTime);
224         Timestamp currentMonotonicTime = 0u;
225         (void)OS::GetMonotonicRelativeTimeInMicrosecond(currentMonotonicTime);
226 
227         auto systemTimeOffset = static_cast<int64_t>(currentSystemTime - lastSystemTime_);
228         auto monotonicTimeOffset = static_cast<int64_t>(currentMonotonicTime - lastMonotonicTime_);
229         if (std::abs(systemTimeOffset - monotonicTimeOffset) > MAX_NOISE) {
230             // time skew detected
231             Timestamp localTimeOffset = getLocalTimeOffsetFromDB();
232             Timestamp currentSysTime = GetSysCurrentTime();
233             Timestamp currentLocalTime = currentSysTime + timeOffset + localTimeOffset;
234             auto virtualTimeOffset = static_cast<int64_t>(currentLocalTime - lastLocalTime_);
235             auto changedOffset = static_cast<int64_t>(virtualTimeOffset - monotonicTimeOffset * TO_100_NS);
236             if (std::abs(changedOffset) > static_cast<int64_t>(MAX_NOISE * TO_100_NS)) { // LCOV_EXCL_BR_LINE
237                 // localTimeOffset was not flushed, use temporary calculated value
238                 localTimeOffset_ = static_cast<Timestamp>(static_cast<int64_t>(localTimeOffset_) -
239                     (systemTimeOffset - monotonicTimeOffset) * static_cast<int64_t>(TO_100_NS));
240                 LOGD("Save ext local time offset: %" PRIu64 ", changedOffset: %" PRId64, localTimeOffset_,
241                     changedOffset);
242             } else {
243                 localTimeOffset_ = localTimeOffset;
244                 LOGD("Save ext local time offset: %" PRIu64, localTimeOffset_);
245             }
246         }
247         lastSystemTime_ = currentSystemTime;
248         lastMonotonicTime_ = currentMonotonicTime;
249         return std::abs(systemTimeOffset - monotonicTimeOffset) > MAX_NOISE;
250     }
251 
GetLastTime() const252     Timestamp GetLastTime() const
253     {
254         return lastLocalTime_;
255     }
256 
257     // Get current system time
GetSysCurrentTime()258     static Timestamp GetSysCurrentTime()
259     {
260         uint64_t curTime = 0;
261         int errCode = GetCurrentSysTimeInMicrosecond(curTime);
262         if (errCode != E_OK) {
263             return INVALID_TIMESTAMP;
264         }
265 
266         std::lock_guard<std::mutex> lock(systemTimeLock_);
267         // If GetSysCurrentTime in 1us, we need increase the currentIncCount_
268         if (curTime == lastSystemTimeUs_) {
269             // if the currentIncCount_ has been increased MAX_INC_COUNT, keep the currentIncCount_
270             if (currentIncCount_ < MAX_INC_COUNT) { // LCOV_EXCL_BR_LINE
271                 currentIncCount_++;
272             }
273         } else {
274             lastSystemTimeUs_ = curTime;
275             currentIncCount_ = 0;
276         }
277         return (curTime * TO_100_NS) + currentIncCount_; // Currently Timestamp is uint64_t
278     }
279 
280 #ifndef DB_DEBUG_ENV
GetCurrentSysTimeInMicrosecond(uint64_t & outTime)281     static int GetCurrentSysTimeInMicrosecond(uint64_t &outTime)
282     {
283         struct timeval rawTime;
284         int errCode = gettimeofday(&rawTime, nullptr);
285         if (errCode < 0) {
286             return -E_ERROR;
287         }
288         outTime = static_cast<uint64_t>(rawTime.tv_sec) * MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS +
289             static_cast<uint64_t>(rawTime.tv_usec);
290         return E_OK;
291     }
292 #endif
293 
294     static std::mutex systemTimeLock_;
295     static Timestamp lastSystemTimeUs_;
296     static Timestamp currentIncCount_;
297 
298     Timestamp lastLocalTime_ = 0;
299     Timestamp localTimeOffset_ = TimeHelper::BASE_OFFSET;
300     bool isLoaded_ = false;
301 
302     Timestamp lastSystemTime_ = 0;
303     Timestamp lastMonotonicTime_ = 0;
304     bool isInitialized_ = false;
305 };
306 
307 class TimeHelperManager {
308 public:
GetInstance()309     static TimeHelperManager *GetInstance()
310     {
311         static auto instance = new TimeHelperManager();
312         return instance;
313     }
314 
AddStore(const std::string & storeId)315     void AddStore(const std::string &storeId)
316     {
317         std::lock_guard<std::mutex> lock(metaDataLock_);
318         if (metaData_.find(storeId) != metaData_.end()) {
319             return;
320         }
321         TimeHelper timeHelper;
322         timeHelper.Initialize();
323         metaData_[storeId] = timeHelper;
324     }
325 
Restore(const std::string & storeId)326     void Restore(const std::string &storeId)
327     {
328         std::lock_guard<std::mutex> lock(metaDataLock_);
329         if (metaData_.find(storeId) != metaData_.end()) {
330             LOGD("Restore time helper");
331             metaData_.erase(storeId);
332         }
333     }
334 
GetLastTime(const std::string & storeId)335     Timestamp GetLastTime(const std::string &storeId)
336     {
337         std::lock_guard<std::mutex> lock(metaDataLock_);
338         auto it = metaData_.find(storeId);
339         if (it == metaData_.end()) {
340             return TimeHelper::INVALID_TIMESTAMP;
341         }
342         return it->second.GetLastTime();
343     }
344 
TimeSkew(const std::string & storeId,const std::function<Timestamp ()> & getLocalTimeOffsetFromDB,Timestamp timeOffset)345     bool TimeSkew(const std::string &storeId, const std::function<Timestamp()> &getLocalTimeOffsetFromDB,
346         Timestamp timeOffset)
347     {
348         std::lock_guard<std::mutex> lock(metaDataLock_);
349         auto it = metaData_.find(storeId);
350         if (it == metaData_.end()) {
351             return false;
352         }
353         return it->second.TimeSkew(getLocalTimeOffsetFromDB, timeOffset);
354     }
355 
GetTime(const std::string & storeId,TimeOffset timeOffset,const std::function<Timestamp ()> & getDbMaxTimestamp,const std::function<Timestamp ()> & getDbLocalTimeOffset)356     Timestamp GetTime(const std::string &storeId, TimeOffset timeOffset,
357         const std::function<Timestamp()> &getDbMaxTimestamp, const std::function<Timestamp()> &getDbLocalTimeOffset)
358     {
359         std::lock_guard<std::mutex> lock(metaDataLock_);
360         auto it = metaData_.find(storeId);
361         if (it == metaData_.end()) {
362             return TimeHelper::INVALID_TIMESTAMP;
363         }
364         return it->second.GetTime(timeOffset, getDbMaxTimestamp, getDbLocalTimeOffset);
365     }
366 private:
367     TimeHelperManager() = default;
368     std::mutex metaDataLock_;
369     std::map<std::string, TimeHelper> metaData_;
370 };
371 
372 std::mutex TimeHelper::systemTimeLock_;
373 Timestamp TimeHelper::lastSystemTimeUs_ = 0;
374 Timestamp TimeHelper::currentIncCount_ = 0;
375 
376 int GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt *&stmt);
377 int ResetStatement(sqlite3_stmt *&stmt);
378 int BindBlobToStatement(sqlite3_stmt *stmt, int index, const std::vector<uint8_t> &value, bool permEmpty = false);
379 int StepWithRetry(sqlite3_stmt *stmt);
380 int GetColumnBlobValue(sqlite3_stmt *stmt, int index, std::vector<uint8_t> &value);
381 int GetColumnTextValue(sqlite3_stmt *stmt, int index, std::string &value);
382 int GetDBIdentity(sqlite3 *db, std::string &identity);
383 
384 struct TransactFunc {
385     void (*xFunc)(sqlite3_context*, int, sqlite3_value**) = nullptr;
386     void (*xStep)(sqlite3_context*, int, sqlite3_value**) = nullptr;
387     void (*xFinal)(sqlite3_context*) = nullptr;
388     void(*xDestroy)(void*) = nullptr;
389 };
390 
391 std::mutex g_clientObserverMutex;
392 std::map<std::string, ClientObserver> g_clientObserverMap;
393 std::mutex g_clientChangedDataMutex;
394 std::map<std::string, ClientChangedData> g_clientChangedDataMap;
395 
396 std::mutex g_storeObserverMutex;
397 std::map<std::string, std::list<std::shared_ptr<StoreObserver>>> g_storeObserverMap;
398 std::mutex g_storeChangedDataMutex;
399 std::map<std::string, std::vector<ChangedData>> g_storeChangedDataMap;
400 
401 std::mutex g_clientCreateTableMutex;
402 std::set<std::string> g_clientCreateTable;
403 
RegisterFunction(sqlite3 * db,const std::string & funcName,int nArg,void * uData,TransactFunc & func)404 int RegisterFunction(sqlite3 *db, const std::string &funcName, int nArg, void *uData, TransactFunc &func)
405 {
406     if (db == nullptr) {
407         return -E_ERROR;
408     }
409     return sqlite3_create_function_v2(db, funcName.c_str(), nArg, SQLITE_UTF8 | SQLITE_DETERMINISTIC, uData,
410         func.xFunc, func.xStep, func.xFinal, func.xDestroy);
411 }
412 
CalcValueHash(const std::vector<uint8_t> & value,std::vector<uint8_t> & hashValue)413 int CalcValueHash(const std::vector<uint8_t> &value, std::vector<uint8_t> &hashValue)
414 {
415     ValueHashCalc hashCalc;
416     int errCode = hashCalc.Initialize();
417     if (errCode != E_OK) {
418         return -E_ERROR;
419     }
420 
421     errCode = hashCalc.Update(value);
422     if (errCode != E_OK) {
423         return -E_ERROR;
424     }
425 
426     errCode = hashCalc.GetResult(hashValue);
427     if (errCode != E_OK) {
428         return -E_ERROR;
429     }
430 
431     return E_OK;
432 }
433 
StringToUpper(std::string & str)434 void StringToUpper(std::string &str)
435 {
436     std::transform(str.cbegin(), str.cend(), str.begin(), [](unsigned char c) {
437         return std::toupper(c);
438     });
439 }
440 
CalcHashKey(sqlite3_context * ctx,int argc,sqlite3_value ** argv)441 void CalcHashKey(sqlite3_context *ctx, int argc, sqlite3_value **argv)
442 {
443     // 1 means that the function only needs one parameter, namely key
444     if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 is params count
445         return;
446     }
447 
448     int errCode;
449     std::vector<uint8_t> hashValue;
450     DistributedDB::CollateType collateType = static_cast<DistributedDB::CollateType>(sqlite3_value_int(argv[1]));
451     if (collateType == DistributedDB::CollateType::COLLATE_NOCASE) {
452         auto colChar = reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
453         if (colChar == nullptr) {
454             return;
455         }
456         std::string colStr(colChar);
457         StringToUpper(colStr);
458         std::vector<uint8_t> value;
459         value.assign(colStr.begin(), colStr.end());
460         errCode = CalcValueHash(value, hashValue);
461     } else if (collateType == DistributedDB::CollateType::COLLATE_RTRIM) {
462         auto colChar = reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
463         if (colChar == nullptr) {
464             return;
465         }
466         std::string colStr(colChar);
467         DBCommon::RTrim(colStr);
468         std::vector<uint8_t> value;
469         value.assign(colStr.begin(), colStr.end());
470         errCode = CalcValueHash(value, hashValue);
471     } else {
472             auto keyBlob = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0]));
473             if (keyBlob == nullptr) {
474                 sqlite3_result_error(ctx, "Parameters is invalid.", -1);
475                 return;
476             }
477 
478             int blobLen = sqlite3_value_bytes(argv[0]);
479             std::vector<uint8_t> value(keyBlob, keyBlob + blobLen);
480             errCode = CalcValueHash(value, hashValue);
481     }
482 
483     if (errCode != E_OK) {
484         sqlite3_result_error(ctx, "Get hash value error.", -1);
485         return;
486     }
487     sqlite3_result_blob(ctx, hashValue.data(), hashValue.size(), SQLITE_TRANSIENT);
488 }
489 
RegisterCalcHash(sqlite3 * db)490 int RegisterCalcHash(sqlite3 *db)
491 {
492     TransactFunc func;
493     func.xFunc = &CalcHashKey;
494     return RegisterFunction(db, "calc_hash", 2, nullptr, func); // 2 is params count
495 }
496 
GetLocalTimeOffsetFromMeta(sqlite3 * db,TimeOffset & offset)497 int GetLocalTimeOffsetFromMeta(sqlite3 *db, TimeOffset &offset)
498 {
499     if (db == nullptr) {
500         return -E_ERROR;
501     }
502 
503     sqlite3_stmt *stmt = nullptr;
504     int errCode = GetStatement(db, "SELECT value FROM naturalbase_rdb_aux_metadata WHERE key = ?", stmt);
505     if (errCode != E_OK) {
506         LOGE("Prepare meta data stmt failed. %d", errCode);
507         return -E_ERROR;
508     }
509 
510     std::string keyStr = "localTimeOffset";
511     std::vector<uint8_t> key(keyStr.begin(), keyStr.end());
512     errCode = BindBlobToStatement(stmt, 1, key);
513     if (errCode != E_OK) {
514         (void)ResetStatement(stmt);
515         LOGE("Bind meta data stmt failed, Key: %s. %d", keyStr.c_str(), errCode);
516         return -E_ERROR;
517     }
518 
519     std::vector<uint8_t> value;
520     errCode = StepWithRetry(stmt);
521     if (errCode == SQLITE_ROW) {
522         GetColumnBlobValue(stmt, 0, value);
523     } else if (errCode == SQLITE_DONE) {
524         (void)ResetStatement(stmt);
525         LOGE("Get meta data not found, Key: %s. %d", keyStr.c_str(), errCode);
526         return E_OK;
527     } else {
528         (void)ResetStatement(stmt);
529         LOGE("Get meta data failed, Key: %s. %d", keyStr.c_str(), errCode);
530         return -E_ERROR;
531     }
532 
533     std::string valueStr(value.begin(), value.end());
534     int64_t result = std::strtoll(valueStr.c_str(), nullptr, STR_TO_LL_BY_DEVALUE);
535     if (errno != ERANGE && result != LLONG_MIN && result != LLONG_MAX) {
536         offset = result;
537     }
538     (void)ResetStatement(stmt);
539     LOGD("Get local time offset from meta: %" PRId64, offset);
540     return E_OK;
541 }
542 
543 int GetCurrentMaxTimestamp(sqlite3 *db, Timestamp &maxTimestamp);
544 
GetSysTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)545 void GetSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
546 {
547     if (ctx == nullptr || argc != 1 || argv == nullptr) { // 1: function need one parameter
548         return;
549     }
550 
551     auto *db = static_cast<sqlite3 *>(sqlite3_user_data(ctx));
552     if (db == nullptr) {
553         sqlite3_result_error(ctx, "Sqlite context is invalid.", -1);
554         return;
555     }
556 
557     std::function<Timestamp()> getDbMaxTimestamp = [db]() -> Timestamp {
558         Timestamp maxTimestamp = 0;
559         (void)GetCurrentMaxTimestamp(db, maxTimestamp);
560         return maxTimestamp;
561     };
562     std::function<Timestamp()> getDbLocalTimeOffset = [db]() -> Timestamp {
563         TimeOffset localTimeOffset = TimeHelper::BASE_OFFSET;
564         (void)GetLocalTimeOffsetFromMeta(db, localTimeOffset);
565         return localTimeOffset;
566     };
567 
568     std::string identity;
569     GetDBIdentity(db, identity);
570     auto timeOffset = static_cast<TimeOffset>(sqlite3_value_int64(argv[0]));
571     (void)TimeHelperManager::GetInstance()->TimeSkew(identity, getDbLocalTimeOffset, timeOffset);
572     Timestamp currentTime = TimeHelperManager::GetInstance()->GetTime(identity, timeOffset, getDbMaxTimestamp,
573         getDbLocalTimeOffset);
574     sqlite3_result_int64(ctx, (sqlite3_int64)currentTime);
575 }
576 
GetRawSysTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)577 void GetRawSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
578 {
579     if (ctx == nullptr || argc != 0 || argv == nullptr) { // 0: function need zero parameter
580         return;
581     }
582 
583     uint64_t curTime = 0;
584     int errCode = TimeHelper::GetSysCurrentRawTime(curTime);
585     if (errCode != E_OK) {
586         sqlite3_result_error(ctx, "get raw sys time failed.", errCode);
587         return;
588     }
589     sqlite3_result_int64(ctx, (sqlite3_int64)(curTime));
590 }
591 
GetLastTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)592 void GetLastTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
593 {
594     if (ctx == nullptr || argc != 0 || argv == nullptr) { // 0: function need zero parameter
595         return;
596     }
597 
598     auto *db = static_cast<sqlite3 *>(sqlite3_user_data(ctx));
599     if (db == nullptr) {
600         sqlite3_result_error(ctx, "Sqlite context is invalid.", -1);
601         return;
602     }
603     std::string identity;
604     GetDBIdentity(db, identity);
605 
606     sqlite3_result_int64(ctx, (sqlite3_int64)TimeHelperManager::GetInstance()->GetLastTime(identity));
607 }
608 
GetHashString(const std::string & str,std::string & dst)609 int GetHashString(const std::string &str, std::string &dst)
610 {
611     std::vector<uint8_t> strVec;
612     strVec.assign(str.begin(), str.end());
613     std::vector<uint8_t> hashVec;
614     int errCode = CalcValueHash(strVec, hashVec);
615     if (errCode != E_OK) {
616         LOGE("calc hash value fail, %d", errCode);
617         return errCode;
618     }
619     dst.assign(hashVec.begin(), hashVec.end());
620     return E_OK;
621 }
622 
GetDbFileName(sqlite3 * db,std::string & fileName)623 static bool GetDbFileName(sqlite3 *db, std::string &fileName)
624 {
625     if (db == nullptr) {
626         return false;
627     }
628 
629     auto dbFilePath = sqlite3_db_filename(db, nullptr);
630     if (dbFilePath == nullptr) {
631         return false;
632     }
633     fileName = std::string(dbFilePath);
634     return true;
635 }
636 
GetDbHashString(sqlite3 * db,std::string & hashFileName)637 static bool GetDbHashString(sqlite3 *db, std::string &hashFileName)
638 {
639     std::string fileName;
640     if (!GetDbFileName(db, fileName)) {
641         LOGE("Get db fileName failed.");
642         return false;
643     }
644     return GetHashString(fileName, hashFileName) == E_OK;
645 }
646 
CloudDataChangedObserver(sqlite3_context * ctx,int argc,sqlite3_value ** argv)647 void CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv)
648 {
649     if (ctx == nullptr || argc != 4 || argv == nullptr) { // 4 is param counts
650         return;
651     }
652     sqlite3 *db = static_cast<sqlite3 *>(sqlite3_user_data(ctx));
653     std::string hashFileName = "";
654     if (!GetDbHashString(db, hashFileName)) {
655         return;
656     }
657     auto tableNameChar = reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
658     if (tableNameChar == nullptr) {
659         return;
660     }
661     std::string tableName = static_cast<std::string>(tableNameChar);
662 
663     uint64_t isTrackerChange = static_cast<uint64_t>(sqlite3_value_int(argv[3])); // 3 is param index
664     bool isExistObserver = false;
665     {
666         std::lock_guard<std::mutex> lock(g_clientObserverMutex);
667         auto it = g_clientObserverMap.find(hashFileName);
668         isExistObserver = (it != g_clientObserverMap.end());
669     }
670     {
671         std::lock_guard<std::mutex> lock(g_clientChangedDataMutex);
672         if (isExistObserver) {
673             auto itTable = g_clientChangedDataMap[hashFileName].tableData.find(tableName);
674             if (itTable != g_clientChangedDataMap[hashFileName].tableData.end()) {
675                 itTable->second.isTrackedDataChange =
676                     (static_cast<uint8_t>(itTable->second.isTrackedDataChange) | isTrackerChange) > 0;
677             } else {
678                 DistributedDB::ChangeProperties properties = { .isTrackedDataChange = (isTrackerChange > 0) };
679                 g_clientChangedDataMap[hashFileName].tableData.insert_or_assign(tableName, properties);
680             }
681         }
682     }
683     sqlite3_result_int64(ctx, static_cast<sqlite3_int64>(1));
684 }
685 
JudgeIfGetRowid(sqlite3 * db,const std::string & tableName,std::string & type,bool & isRowid)686 int JudgeIfGetRowid(sqlite3 *db, const std::string &tableName, std::string &type, bool &isRowid)
687 {
688     if (db == nullptr) {
689         return -E_ERROR;
690     }
691     std::string checkPrimaryKeySql = "SELECT count(1), type FROM pragma_table_info('" + tableName;
692     checkPrimaryKeySql += "') WHERE pk = 1";
693     sqlite3_stmt *checkPrimaryKeyStmt = nullptr;
694     int errCode = GetStatement(db, checkPrimaryKeySql, checkPrimaryKeyStmt);
695     if (errCode != E_OK) {
696         LOGE("Prepare get primarykey info statement failed. err=%d", errCode);
697         return -E_ERROR;
698     }
699     errCode = SQLiteUtils::StepWithRetry(checkPrimaryKeyStmt);
700     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
701         int count = sqlite3_column_int(checkPrimaryKeyStmt, 0);
702         GetColumnTextValue(checkPrimaryKeyStmt, 1, type);
703         isRowid = (count != 1) || (type != "TEXT" && type != "INT" && type != "INTEGER");
704         errCode = E_OK;
705     } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
706         errCode = E_OK;
707     } else {
708         errCode = SQLiteUtils::MapSQLiteErrno(errCode);
709     }
710     ResetStatement(checkPrimaryKeyStmt);
711     return errCode;
712 }
713 
SaveChangedData(const std::string & hashFileName,const std::string & tableName,const std::string & columnName,const DistributedDB::Type & data,ChangeType option)714 void SaveChangedData(const std::string &hashFileName, const std::string &tableName, const std::string &columnName,
715     const DistributedDB::Type &data, ChangeType option)
716 {
717     if (option < ChangeType::OP_INSERT || option >= ChangeType::OP_BUTT) {
718         return;
719     }
720     std::lock_guard<std::mutex> lock(g_storeChangedDataMutex);
721     auto itTable = std::find_if(g_storeChangedDataMap[hashFileName].begin(), g_storeChangedDataMap[hashFileName].end(),
722         [tableName](DistributedDB::ChangedData changedData) {
723             return tableName == changedData.tableName;
724         });
725     if (itTable != g_storeChangedDataMap[hashFileName].end()) {
726         std::vector<Type> dataVec;
727         dataVec.push_back(data);
728         itTable->primaryData[option].push_back(dataVec);
729     } else {
730         DistributedDB::ChangedData changedData;
731         changedData.tableName = tableName;
732         changedData.field.push_back(columnName);
733         std::vector<DistributedDB::Type> dataVec;
734         dataVec.push_back(data);
735         changedData.primaryData[option].push_back(dataVec);
736         g_storeChangedDataMap[hashFileName].push_back(changedData);
737     }
738 }
739 
DataChangedObserver(sqlite3_context * ctx,int argc,sqlite3_value ** argv)740 void DataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv)
741 {
742     if (ctx == nullptr || argc != 4 || argv == nullptr) { // 4 is param counts
743         return;
744     }
745     sqlite3 *db = static_cast<sqlite3 *>(sqlite3_user_data(ctx));
746     std::string hashFileName = "";
747     if (!GetDbHashString(db, hashFileName)) {
748         return;
749     }
750     bool isExistObserver = false;
751     {
752         std::lock_guard<std::mutex> lock(g_storeObserverMutex);
753         auto it = g_storeObserverMap.find(hashFileName);
754         isExistObserver = (it != g_storeObserverMap.end());
755     }
756     if (!isExistObserver) {
757         return;
758     }
759     auto tableNameChar = reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
760     if (tableNameChar == nullptr) {
761         return;
762     }
763     std::string tableName = static_cast<std::string>(tableNameChar);
764     auto columnNameChar = reinterpret_cast<const char *>(sqlite3_value_text(argv[1])); // 1 is param index
765     if (columnNameChar == nullptr) {
766         return;
767     }
768     std::string columnName = static_cast<std::string>(columnNameChar);
769     DistributedDB::Type data;
770     std::string type = "";
771     bool isRowid = false;
772     int errCode = JudgeIfGetRowid(db, tableName, type, isRowid);
773     if (errCode != E_OK) {
774         sqlite3_result_error(ctx, "Get primary key info error.", -1);
775         return;
776     }
777     if (!isRowid && type == "TEXT") {
778         auto dataChar = reinterpret_cast<const char *>(sqlite3_value_text(argv[2])); // 2 is param index
779         if (dataChar == nullptr) {
780             return;
781         }
782         data = static_cast<std::string>(dataChar);
783     } else {
784         data = static_cast<int64_t>(sqlite3_value_int64(argv[2])); // 2 is param index
785     }
786     ChangeType option = static_cast<ChangeType>(sqlite3_value_int64(argv[3])); // 3 is param index
787     SaveChangedData(hashFileName, tableName, columnName, data, option);
788     sqlite3_result_int64(ctx, static_cast<sqlite3_int64>(1)); // 1 is result ok
789 }
790 
GetInsertTrigger(const std::string & tableName,bool isRowid,const std::string & primaryKey)791 std::string GetInsertTrigger(const std::string &tableName, bool isRowid, const std::string &primaryKey)
792 {
793     std::string insertTrigger = "CREATE TEMP TRIGGER IF NOT EXISTS ";
794     insertTrigger += "naturalbase_rdb_" + tableName + "_local_ON_INSERT AFTER INSERT\n";
795     insertTrigger += "ON '" + tableName + "'\n";
796     insertTrigger += "BEGIN\n";
797     if (isRowid || primaryKey.empty()) { // LCOV_EXCL_BR_LINE
798         insertTrigger += "SELECT data_change('" + tableName + "', 'rowid', NEW._rowid_, 0);\n";
799     } else {
800         insertTrigger += "SELECT data_change('" + tableName + "', ";
801         insertTrigger += "(SELECT name as a FROM pragma_table_info('" + tableName + "') WHERE pk=1), ";
802         insertTrigger += "NEW." + primaryKey + ", 0);\n";
803     }
804     insertTrigger += "END;";
805     return insertTrigger;
806 }
807 
GetUpdateTrigger(const std::string & tableName,bool isRowid,const std::string & primaryKey)808 std::string GetUpdateTrigger(const std::string &tableName, bool isRowid, const std::string &primaryKey)
809 {
810     std::string updateTrigger = "CREATE TEMP TRIGGER IF NOT EXISTS ";
811     updateTrigger += "naturalbase_rdb_" + tableName + "_local_ON_UPDATE AFTER UPDATE\n";
812     updateTrigger += "ON '" + tableName + "'\n";
813     updateTrigger += "BEGIN\n";
814     if (isRowid || primaryKey.empty()) { // LCOV_EXCL_BR_LINE
815         updateTrigger += "SELECT data_change('" + tableName + "', 'rowid', NEW._rowid_, 1);\n";
816     } else {
817         updateTrigger += "SELECT data_change('" + tableName + "', ";
818         updateTrigger += "(SELECT name as a FROM pragma_table_info('" + tableName + "') WHERE pk=1), ";
819         updateTrigger += "NEW." + primaryKey + ", 1);\n";
820     }
821     updateTrigger += "END;";
822     return updateTrigger;
823 }
824 
GetDeleteTrigger(const std::string & tableName,bool isRowid,const std::string & primaryKey)825 std::string GetDeleteTrigger(const std::string &tableName, bool isRowid, const std::string &primaryKey)
826 {
827     std::string deleteTrigger = "CREATE TEMP TRIGGER IF NOT EXISTS ";
828     deleteTrigger += "naturalbase_rdb_" + tableName + "_local_ON_DELETE AFTER DELETE\n";
829     deleteTrigger += "ON '" + tableName + "'\n";
830     deleteTrigger += "BEGIN\n";
831     if (isRowid || primaryKey.empty()) { // LCOV_EXCL_BR_LINE
832         deleteTrigger += "SELECT data_change('" + tableName + "', 'rowid', OLD._rowid_, 2);\n";
833     } else {
834         deleteTrigger += "SELECT data_change('" + tableName + "', ";
835         deleteTrigger += "(SELECT name as a FROM pragma_table_info('" + tableName + "') WHERE pk=1), ";
836         deleteTrigger += "OLD." + primaryKey + ", 2);\n";
837     }
838     deleteTrigger += "END;";
839     return deleteTrigger;
840 }
841 
GetPrimaryKeyName(sqlite3 * db,const std::string & tableName,std::string & primaryKey)842 int GetPrimaryKeyName(sqlite3 *db, const std::string &tableName, std::string &primaryKey)
843 {
844     if (db == nullptr) {
845         return -E_ERROR;
846     }
847     std::string sql = "SELECT name FROM pragma_table_info('";
848     sql += tableName + "') WHERE pk = 1";
849     sqlite3_stmt *stmt = nullptr;
850     int errCode = GetStatement(db, sql, stmt);
851     if (errCode != E_OK) {
852         LOGE("Prepare get primary key name statement failed. err=%d", errCode);
853         return -E_ERROR;
854     }
855     while ((errCode = StepWithRetry(stmt)) != SQLITE_DONE) {
856         if (errCode != SQLITE_ROW) {
857             ResetStatement(stmt);
858             LOGE("Get primary key name step statement failed.");
859             return -E_ERROR;
860         }
861         GetColumnTextValue(stmt, 0, primaryKey);
862     }
863     ResetStatement(stmt);
864     return E_OK;
865 }
866 
GetTriggerSqls(sqlite3 * db,const std::map<std::string,bool> & tableInfos,std::vector<std::string> & triggerSqls)867 int GetTriggerSqls(sqlite3 *db, const std::map<std::string, bool> &tableInfos, std::vector<std::string> &triggerSqls)
868 {
869     for (const auto &tableInfo : tableInfos) {
870         std::string primaryKey = "";
871         if (!tableInfo.second) {
872             int errCode = GetPrimaryKeyName(db, tableInfo.first, primaryKey);
873             if (errCode != E_OK) {
874                 return errCode;
875             }
876         }
877         std::string sql = GetInsertTrigger(tableInfo.first, tableInfo.second, primaryKey);
878         triggerSqls.push_back(sql);
879         sql = GetUpdateTrigger(tableInfo.first, tableInfo.second, primaryKey);
880         triggerSqls.push_back(sql);
881         sql = GetDeleteTrigger(tableInfo.first, tableInfo.second, primaryKey);
882         triggerSqls.push_back(sql);
883     }
884     return E_OK;
885 }
886 
AuthorizerCallback(void * data,int operation,const char * tableNameChar,const char *,const char *,const char *)887 int AuthorizerCallback(void *data, int operation, const char *tableNameChar, const char *, const char *, const char *)
888 {
889     if (operation != SQLITE_CREATE_TABLE || tableNameChar == nullptr) {
890         return SQLITE_OK;
891     }
892     std::lock_guard<std::mutex> clientCreateTableLock(g_clientCreateTableMutex);
893     std::string tableName = static_cast<std::string>(tableNameChar);
894     if (ParamCheckUtils::CheckRelationalTableName(tableName) && tableName.find("sqlite_") != 0 &&
895         tableName.find("naturalbase_") != 0) {
896         g_clientCreateTable.insert(tableName);
897     }
898     return SQLITE_OK;
899 }
900 
ClientObserverCallback(const std::string & hashFileName)901 void ClientObserverCallback(const std::string &hashFileName)
902 {
903     ClientObserver clientObserver;
904     {
905         std::lock_guard<std::mutex> clientObserverLock(g_clientObserverMutex);
906         auto it = g_clientObserverMap.find(hashFileName);
907         if (it != g_clientObserverMap.end() && it->second != nullptr) {
908             clientObserver = it->second;
909         } else {
910             return;
911         }
912     }
913     std::lock_guard<std::mutex> clientChangedDataLock(g_clientChangedDataMutex);
914     auto it = g_clientChangedDataMap.find(hashFileName);
915     if (it != g_clientChangedDataMap.end() && !it->second.tableData.empty()) {
916         ClientChangedData clientChangedData = g_clientChangedDataMap[hashFileName];
917         ConcurrentAdapter::ScheduleTask([clientObserver, clientChangedData] {
918             ClientChangedData taskClientChangedData = clientChangedData;
919             clientObserver(taskClientChangedData);
920         });
921         g_clientChangedDataMap[hashFileName].tableData.clear();
922     }
923 }
924 
TriggerObserver(const std::vector<std::shared_ptr<StoreObserver>> & storeObservers,const std::string & hashFileName)925 void TriggerObserver(const std::vector<std::shared_ptr<StoreObserver>> &storeObservers, const std::string &hashFileName)
926 {
927     std::lock_guard<std::mutex> storeChangedDataLock(g_storeChangedDataMutex);
928     for (const auto &storeObserver : storeObservers) {
929         auto it = g_storeChangedDataMap.find(hashFileName);
930         if (it != g_storeChangedDataMap.end() && !it->second.empty()) {
931             std::vector<DistributedDB::ChangedData> storeChangedData = g_storeChangedDataMap[hashFileName];
932             storeObserver->OnChange(std::move(storeChangedData));
933         }
934     }
935     g_storeChangedDataMap[hashFileName].clear();
936 }
937 
StoreObserverCallback(sqlite3 * db,const std::string & hashFileName)938 void StoreObserverCallback(sqlite3 *db, const std::string &hashFileName)
939 {
940     std::vector<std::shared_ptr<StoreObserver>> storeObserver;
941     {
942         std::lock_guard<std::mutex> storeObserverLock(g_storeObserverMutex);
943         auto it = g_storeObserverMap.find(hashFileName);
944         if (it != g_storeObserverMap.end() && !it->second.empty()) {
945             std::copy(it->second.begin(), it->second.end(), std::back_inserter(storeObserver));
946         } else {
947             return;
948         }
949     }
950     TriggerObserver(storeObserver, hashFileName);
951     std::map<std::string, bool> tableInfos;
952     {
953         std::lock_guard<std::mutex> clientCreateTableLock(g_clientCreateTableMutex);
954         if (g_clientCreateTable.empty()) {
955             return;
956         }
957         for (const auto &tableName : g_clientCreateTable) {
958             bool isRowid = true;
959             std::string type = "";
960             JudgeIfGetRowid(db, tableName, type, isRowid);
961             tableInfos.insert(std::make_pair(tableName, isRowid));
962         }
963         g_clientCreateTable.clear();
964     }
965     std::vector<std::string> triggerSqls;
966     int errCode = GetTriggerSqls(db, tableInfos, triggerSqls);
967     if (errCode != E_OK) {
968         LOGE("Get data change trigger sql failed %d", errCode);
969         return;
970     }
971     for (const auto &sql : triggerSqls) {
972         errCode = SQLiteUtils::ExecuteRawSQL(db, sql);
973         if (errCode != E_OK) {
974             LOGE("Create data change trigger failed %d", errCode);
975             return;
976         }
977     }
978     return;
979 }
980 
LogCommitHookCallback(void * data,sqlite3 * db,const char * zDb,int size)981 int LogCommitHookCallback(void *data, sqlite3 *db, const char *zDb, int size)
982 {
983     std::string fileName;
984     if (!GetDbFileName(db, fileName)) {
985         return 0;
986     }
987     std::string hashFileName;
988     int errCode = GetHashString(fileName, hashFileName);
989     if (errCode != E_OK) {
990         return 0;
991     }
992     ClientObserverCallback(hashFileName);
993     StoreObserverCallback(db, hashFileName);
994     return 0;
995 }
996 
RollbackHookCallback(void * data)997 void RollbackHookCallback(void* data)
998 {
999     sqlite3 *db = static_cast<sqlite3 *>(data);
1000     std::string fileName;
1001     if (!GetDbFileName(db, fileName)) {
1002         return;
1003     }
1004     std::string hashFileName;
1005     int errCode = GetHashString(fileName, hashFileName);
1006     if (errCode != E_OK) {
1007         return;
1008     }
1009     std::lock_guard<std::mutex> clientChangedDataLock(g_clientChangedDataMutex);
1010     auto it = g_clientChangedDataMap.find(hashFileName);
1011     if (it != g_clientChangedDataMap.end() && !it->second.tableData.empty()) {
1012         g_clientChangedDataMap[hashFileName].tableData.clear();
1013     }
1014 }
1015 
RegisterGetSysTime(sqlite3 * db)1016 int RegisterGetSysTime(sqlite3 *db)
1017 {
1018     TransactFunc func;
1019     func.xFunc = &GetSysTime;
1020     return RegisterFunction(db, "get_sys_time", 1, db, func);
1021 }
1022 
RegisterGetLastTime(sqlite3 * db)1023 int RegisterGetLastTime(sqlite3 *db)
1024 {
1025     TransactFunc func;
1026     func.xFunc = &GetLastTime;
1027     return RegisterFunction(db, "get_last_time", 0, db, func);
1028 }
1029 
RegisterGetRawSysTime(sqlite3 * db)1030 int RegisterGetRawSysTime(sqlite3 *db)
1031 {
1032     TransactFunc func;
1033     func.xFunc = &GetRawSysTime;
1034     return RegisterFunction(db, "get_raw_sys_time", 0, nullptr, func);
1035 }
1036 
RegisterCloudDataChangeObserver(sqlite3 * db)1037 int RegisterCloudDataChangeObserver(sqlite3 *db)
1038 {
1039     TransactFunc func;
1040     func.xFunc = &CloudDataChangedObserver;
1041     return RegisterFunction(db, "client_observer", 4, db, func); // 4 is param counts
1042 }
1043 
RegisterDataChangeObserver(sqlite3 * db)1044 int RegisterDataChangeObserver(sqlite3 *db)
1045 {
1046     TransactFunc func;
1047     func.xFunc = &DataChangedObserver;
1048     return RegisterFunction(db, "data_change", 4, db, func); // 4 is param counts
1049 }
1050 
RegisterCommitAndRollbackHook(sqlite3 * db)1051 void RegisterCommitAndRollbackHook(sqlite3 *db)
1052 {
1053     sqlite3_set_authorizer(db, AuthorizerCallback, nullptr);
1054     sqlite3_wal_hook(db, LogCommitHookCallback, db);
1055     sqlite3_rollback_hook(db, RollbackHookCallback, db);
1056 }
1057 
ResetStatement(sqlite3_stmt * & stmt)1058 int ResetStatement(sqlite3_stmt *&stmt)
1059 {
1060     if (stmt == nullptr || sqlite3_finalize(stmt) != SQLITE_OK) { // LCOV_EXCL_BR_LINE
1061         return -E_ERROR;
1062     }
1063     stmt = nullptr;
1064     return E_OK;
1065 }
1066 
GetStatement(sqlite3 * db,const std::string & sql,sqlite3_stmt * & stmt)1067 int GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt *&stmt)
1068 {
1069     int errCode = sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr);
1070     if (errCode != SQLITE_OK) {
1071         (void)ResetStatement(stmt);
1072         LOGE("Get stmt failed. %d", errCode);
1073         return -E_ERROR;
1074     }
1075     return E_OK;
1076 }
1077 
ExecuteRawSQL(sqlite3 * db,const std::string & sql)1078 int ExecuteRawSQL(sqlite3 *db, const std::string &sql)
1079 {
1080     if (db == nullptr) {
1081         return -E_ERROR;
1082     }
1083     char *errMsg = nullptr;
1084     int errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &errMsg);
1085     if (errCode != SQLITE_OK) {
1086         errCode = -E_ERROR;
1087     }
1088 
1089     if (errMsg != nullptr) {
1090         sqlite3_free(errMsg);
1091         errMsg = nullptr;
1092     }
1093     return errCode;
1094 }
1095 
StepWithRetry(sqlite3_stmt * stmt)1096 int StepWithRetry(sqlite3_stmt *stmt)
1097 {
1098     if (stmt == nullptr) {
1099         return -E_ERROR;
1100     }
1101     int errCode = sqlite3_step(stmt);
1102     if (errCode != SQLITE_DONE && errCode != SQLITE_ROW) {
1103         return -E_ERROR;
1104     }
1105     return errCode;
1106 }
1107 
BindBlobToStatement(sqlite3_stmt * stmt,int index,const std::vector<uint8_t> & value,bool permEmpty)1108 int BindBlobToStatement(sqlite3_stmt *stmt, int index, const std::vector<uint8_t> &value, bool permEmpty)
1109 {
1110     if (stmt == nullptr || (value.empty() && !permEmpty)) { // LCOV_EXCL_BR_LINE
1111         return -E_ERROR;
1112     }
1113     int errCode;
1114     if (value.empty()) {
1115         errCode = sqlite3_bind_zeroblob(stmt, index, -1); // -1: zero-length blob
1116     } else {
1117         errCode = sqlite3_bind_blob(stmt, index, static_cast<const void*>(value.data()), value.size(),
1118             SQLITE_TRANSIENT);
1119     }
1120     return errCode == E_OK ? E_OK : -E_ERROR;
1121 }
1122 
GetColumnTextValue(sqlite3_stmt * stmt,int index,std::string & value)1123 int GetColumnTextValue(sqlite3_stmt *stmt, int index, std::string &value)
1124 {
1125     if (stmt == nullptr) {
1126         return -E_ERROR;
1127     }
1128     const unsigned char *val = sqlite3_column_text(stmt, index);
1129     value = (val != nullptr) ? std::string(reinterpret_cast<const char *>(val)) : std::string();
1130     return E_OK;
1131 }
1132 
GetColumnBlobValue(sqlite3_stmt * stmt,int index,std::vector<uint8_t> & value)1133 int GetColumnBlobValue(sqlite3_stmt *stmt, int index, std::vector<uint8_t> &value)
1134 {
1135     if (stmt == nullptr) {
1136         return -E_ERROR;
1137     }
1138 
1139     int keySize = sqlite3_column_bytes(stmt, index);
1140     if (keySize < 0) {
1141         value.resize(0);
1142         return E_OK;
1143     }
1144     auto keyRead = static_cast<const uint8_t *>(sqlite3_column_blob(stmt, index));
1145     if (keySize == 0 || keyRead == nullptr) {
1146         value.resize(0);
1147     } else {
1148         if (keySize > MAX_BLOB_READ_SIZE) {
1149             keySize = MAX_BLOB_READ_SIZE + 1;
1150         }
1151         value.resize(keySize);
1152         value.assign(keyRead, keyRead + keySize);
1153     }
1154     return E_OK;
1155 }
1156 
GetCurrentMaxTimestamp(sqlite3 * db,Timestamp & maxTimestamp)1157 int GetCurrentMaxTimestamp(sqlite3 *db, Timestamp &maxTimestamp)
1158 {
1159     if (db == nullptr) {
1160         return -E_ERROR;
1161     }
1162     std::string checkTableSql = "SELECT name FROM sqlite_master WHERE type = 'table' AND " \
1163         "name LIKE 'naturalbase_rdb_aux_%_log';";
1164     sqlite3_stmt *checkTableStmt = nullptr;
1165     int errCode = GetStatement(db, checkTableSql, checkTableStmt);
1166     if (errCode != E_OK) {
1167         LOGE("Prepare get max log timestamp statement failed. err=%d", errCode);
1168         return -E_ERROR;
1169     }
1170     while ((errCode = StepWithRetry(checkTableStmt)) != SQLITE_DONE) {
1171         if (errCode != SQLITE_ROW) {
1172             ResetStatement(checkTableStmt);
1173             return -E_ERROR;
1174         }
1175         std::string logTableName;
1176         GetColumnTextValue(checkTableStmt, 0, logTableName);
1177         if (logTableName.empty()) {
1178             continue;
1179         }
1180 
1181         std::string getMaxTimestampSql = "SELECT MAX(timestamp) FROM " + logTableName + ";";
1182         sqlite3_stmt *getTimeStmt = nullptr;
1183         errCode = GetStatement(db, getMaxTimestampSql, getTimeStmt);
1184         if (errCode != E_OK) {
1185             continue;
1186         }
1187         errCode = StepWithRetry(getTimeStmt);
1188         if (errCode != SQLITE_ROW) {
1189             ResetStatement(getTimeStmt);
1190             continue;
1191         }
1192         auto tableMaxTimestamp = static_cast<Timestamp>(sqlite3_column_int64(getTimeStmt, 0));
1193         maxTimestamp = (maxTimestamp > tableMaxTimestamp) ? maxTimestamp : tableMaxTimestamp;
1194         ResetStatement(getTimeStmt);
1195     }
1196     ResetStatement(checkTableStmt);
1197     return E_OK;
1198 }
1199 
CheckTableExists(sqlite3 * db,const std::string & tableName)1200 bool CheckTableExists(sqlite3 *db, const std::string &tableName)
1201 {
1202     sqlite3_stmt *stmt = nullptr;
1203     std::string sql = "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='" + tableName + "';";
1204     if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) { // LCOV_EXCL_BR_LINE
1205         (void)sqlite3_finalize(stmt);
1206         return false;
1207     }
1208 
1209     bool isLogTblExists = false;
1210     if (sqlite3_step(stmt) == SQLITE_ROW && static_cast<bool>(sqlite3_column_int(stmt, 0))) { // LCOV_EXCL_BR_LINE
1211         isLogTblExists = true;
1212     }
1213     (void)sqlite3_finalize(stmt);
1214     return isLogTblExists;
1215 }
1216 
GetTableSyncType(sqlite3 * db,const std::string & tableName,std::string & tableType)1217 int GetTableSyncType(sqlite3 *db, const std::string &tableName, std::string &tableType)
1218 {
1219     const char *selectSql = "SELECT value FROM naturalbase_rdb_aux_metadata WHERE key=?;";
1220     sqlite3_stmt *statement = nullptr;
1221     int errCode = sqlite3_prepare_v2(db, selectSql, -1, &statement, nullptr);
1222     if (errCode != SQLITE_OK) {
1223         (void)sqlite3_finalize(statement);
1224         return -E_ERROR;
1225     }
1226 
1227     std::string keyStr = SYNC_TABLE_TYPE + tableName;
1228     std::vector<uint8_t> key(keyStr.begin(), keyStr.end());
1229     if (sqlite3_bind_blob(statement, 1, static_cast<const void *>(key.data()), key.size(),
1230         SQLITE_TRANSIENT) != SQLITE_OK) { // LCOV_EXCL_BR_LINE
1231         return -E_ERROR;
1232     }
1233 
1234     if (sqlite3_step(statement) == SQLITE_ROW) {
1235         std::vector<uint8_t> value;
1236         if (GetColumnBlobValue(statement, 0, value) == E_OK) {
1237             tableType.assign(value.begin(), value.end());
1238             (void)sqlite3_finalize(statement);
1239             return E_OK;
1240         } else {
1241             (void)sqlite3_finalize(statement);
1242             return -E_ERROR;
1243         }
1244     } else if (sqlite3_step(statement) != SQLITE_DONE) {
1245         (void)sqlite3_finalize(statement);
1246         return -E_ERROR;
1247     }
1248     (void)sqlite3_finalize(statement);
1249     tableType = DEVICE_TYPE;
1250     return E_OK;
1251 }
1252 
HandleDropCloudSyncTable(sqlite3 * db,const std::string & tableName)1253 void HandleDropCloudSyncTable(sqlite3 *db, const std::string &tableName)
1254 {
1255     std::string logTblName = "naturalbase_rdb_aux_" + tableName + "_log";
1256     std::string sql = "UPDATE " + logTblName + " SET data_key=-1, flag=0x03, timestamp=get_raw_sys_time();";
1257     (void)sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr);
1258     std::string keyStr = SYNC_TABLE_TYPE + tableName;
1259     std::vector<uint8_t> key(keyStr.begin(), keyStr.end());
1260     sql = "DELETE FROM naturalbase_rdb_aux_metadata WHERE key = ?;";
1261     sqlite3_stmt *statement = nullptr;
1262     int errCode = sqlite3_prepare_v2(db, sql.c_str(), -1, &statement, nullptr);
1263     if (errCode != SQLITE_OK) {
1264         (void)sqlite3_finalize(statement);
1265         return;
1266     }
1267 
1268     if (sqlite3_bind_blob(statement, 1, static_cast<const void *>(key.data()), key.size(),
1269         SQLITE_TRANSIENT) != SQLITE_OK) { // LCOV_EXCL_BR_LINE
1270         (void)sqlite3_finalize(statement);
1271         return;
1272     }
1273     (void)sqlite3_step(statement);
1274     (void)sqlite3_finalize(statement);
1275 }
1276 
HandleDropLogicDeleteData(sqlite3 * db,const std::string & tableName,uint64_t cursor)1277 int HandleDropLogicDeleteData(sqlite3 *db, const std::string &tableName, uint64_t cursor)
1278 {
1279     std::string logTblName = DBCommon::GetLogTableName(tableName);
1280     std::string sql = "INSERT OR REPLACE INTO " + DBConstant::RELATIONAL_PREFIX + "metadata" +
1281         " VALUES ('log_trigger_switch', 'false')";
1282     int errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr);
1283     if (errCode != SQLITE_OK) {
1284         LOGE("close log_trigger_switch failed. %d", errCode);
1285         return errCode;
1286     }
1287     sql = "DELETE FROM " + tableName + " WHERE _rowid_ IN (SELECT data_key FROM " + logTblName + " WHERE "
1288         " flag&0x08=0x08" + (cursor == 0 ? ");" : " AND cursor <= '" + std::to_string(cursor) + "');");
1289     errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr);
1290     if (errCode != SQLITE_OK) {
1291         LOGE("delete logic deletedData failed. %d", errCode);
1292         return errCode;
1293     }
1294     sql = "DELETE FROM " + logTblName + " WHERE (flag&0x08=0x08 " +
1295          (cursor == 0 ? ");" : " AND cursor <= '" + std::to_string(cursor) + "');");
1296     errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr);
1297     if (errCode != SQLITE_OK) {
1298         LOGE("delete logic delete log failed. %d", errCode);
1299         return errCode;
1300     }
1301     sql = "INSERT OR REPLACE INTO " + DBConstant::RELATIONAL_PREFIX + "metadata" +
1302         " VALUES ('log_trigger_switch', 'true')";
1303     errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr);
1304     if (errCode != SQLITE_OK) {
1305         LOGE("open log_trigger_switch failed. %d", errCode);
1306     }
1307     return errCode;
1308 }
1309 
SaveDeleteFlagToDB(sqlite3 * db,const std::string & tableName)1310 int SaveDeleteFlagToDB(sqlite3 *db, const std::string &tableName)
1311 {
1312     std::string keyStr = DBConstant::TABLE_IS_DROPPED + tableName;
1313     Key key;
1314     DBCommon::StringToVector(keyStr, key);
1315     Value value;
1316     DBCommon::StringToVector("1", value); // 1 means delete
1317     std::string sql = "INSERT OR REPLACE INTO naturalbase_rdb_aux_metadata VALUES(?, ?);";
1318     sqlite3_stmt *statement = nullptr;
1319     int errCode = sqlite3_prepare_v2(db, sql.c_str(), -1, &statement, nullptr);
1320     if (errCode != SQLITE_OK) {
1321         LOGE("[SaveDeleteFlagToDB] prepare statement failed, %d", errCode);
1322         return -E_ERROR;
1323     }
1324 
1325     if (sqlite3_bind_blob(statement, 1, static_cast<const void *>(key.data()), key.size(),
1326         SQLITE_TRANSIENT) != SQLITE_OK) { // LCOV_EXCL_BR_LINE
1327         (void)sqlite3_finalize(statement);
1328         LOGE("[SaveDeleteFlagToDB] bind key failed, %d", errCode);
1329         return -E_ERROR;
1330     }
1331     if (sqlite3_bind_blob(statement, 2, static_cast<const void *>(value.data()), value.size(), // 2 is column index
1332         SQLITE_TRANSIENT) != SQLITE_OK) { // LCOV_EXCL_BR_LINE
1333         (void)sqlite3_finalize(statement);
1334         LOGE("[SaveDeleteFlagToDB] bind value failed, %d", errCode);
1335         return -E_ERROR;
1336     }
1337     errCode = sqlite3_step(statement);
1338     if (errCode != SQLITE_DONE) {
1339         LOGE("[SaveDeleteFlagToDB] step failed, %d", errCode);
1340         (void)sqlite3_finalize(statement);
1341         return -E_ERROR;
1342     }
1343     (void)sqlite3_finalize(statement);
1344     return E_OK;
1345 }
1346 
ClearTheLogAfterDropTable(sqlite3 * db,const char * tableName,const char * schemaName)1347 void ClearTheLogAfterDropTable(sqlite3 *db, const char *tableName, const char *schemaName)
1348 {
1349     if (db == nullptr || tableName == nullptr || schemaName == nullptr) {
1350         return;
1351     }
1352     auto filePath = sqlite3_db_filename(db, schemaName);
1353     if (filePath == nullptr) {
1354         return;
1355     }
1356     std::string fileName = std::string(filePath);
1357     Timestamp dropTimeStamp = TimeHelperManager::GetInstance()->GetTime(fileName, 0, nullptr, nullptr);
1358     std::string tableStr = std::string(tableName);
1359     std::string logTblName = DBCommon::GetLogTableName(tableStr);
1360     if (CheckTableExists(db, logTblName)) {
1361         if (SaveDeleteFlagToDB(db, tableStr) != E_OK) {
1362             // the failure of this step does not affect the following step, so we just write log
1363             LOGW("[ClearTheLogAfterDropTable] save delete flag failed.");
1364         }
1365         std::string tableType = DEVICE_TYPE;
1366         if (GetTableSyncType(db, tableStr, tableType) != E_OK) {
1367             return;
1368         }
1369         if (tableType == DEVICE_TYPE) {
1370             RegisterGetSysTime(db);
1371             RegisterGetLastTime(db);
1372             std::string sql = "UPDATE " + logTblName + " SET data_key=-1, flag=0x03, timestamp=get_sys_time(0) "
1373                 "WHERE flag&0x03=0x02 AND timestamp<" + std::to_string(dropTimeStamp);
1374             (void)sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr);
1375         } else {
1376             HandleDropCloudSyncTable(db, tableStr);
1377         }
1378     }
1379 }
1380 
CheckUnLockingDataExists(sqlite3 * db,const std::string & tableName)1381 bool CheckUnLockingDataExists(sqlite3 *db, const std::string &tableName)
1382 {
1383     sqlite3_stmt *stmt = nullptr;
1384     std::string sql = "SELECT count(1) FROM " + tableName + " WHERE status=1";
1385     if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) { // LCOV_EXCL_BR_LINE
1386         return false;
1387     }
1388 
1389     bool isExists = false;
1390     if ((sqlite3_step(stmt) == SQLITE_ROW) && (sqlite3_column_int(stmt, 0) > 0)) { // LCOV_EXCL_BR_LINE
1391         isExists = true;
1392     }
1393     (void)sqlite3_finalize(stmt);
1394     return isExists;
1395 }
1396 
HandleDataStatus(sqlite3 * db,const std::string & tableName,const std::vector<std::vector<uint8_t>> & hashKey,bool isLock)1397 int HandleDataStatus(sqlite3 *db, const std::string &tableName, const std::vector<std::vector<uint8_t>> &hashKey,
1398     bool isLock)
1399 {
1400     std::string sql = "UPDATE " + tableName + " SET " + (isLock ? CloudDbConstant::TO_LOCK :
1401         CloudDbConstant::TO_UNLOCK) + " WHERE hash_key in (";
1402     for (size_t i = 0; i < hashKey.size(); i++) {
1403         sql += "?,";
1404     }
1405     sql.pop_back();
1406     sql += ");";
1407 
1408     sqlite3_stmt *stmt = nullptr;
1409     int errCode = GetStatement(db, sql, stmt);
1410     if (errCode != E_OK) {
1411         LOGE("Prepare handle status stmt failed:%d, isLock:%d", errCode, isLock);
1412         return errCode;
1413     }
1414     int index = 1;
1415     for (const auto &hash: hashKey) {
1416         errCode = BindBlobToStatement(stmt, index++, hash);
1417         if (errCode != E_OK) {
1418             (void)ResetStatement(stmt);
1419             LOGE("Bind handle status stmt failed:%d, index:%d, isLock:%d", errCode, index, isLock);
1420             return errCode;
1421         }
1422     }
1423     errCode = StepWithRetry(stmt);
1424     (void)ResetStatement(stmt);
1425     if (errCode == SQLITE_DONE) {
1426         if (!isLock && CheckUnLockingDataExists(db, tableName)) {
1427             return -E_WAIT_COMPENSATED_SYNC;
1428         }
1429         if (sqlite3_changes(db) == 0) {
1430             return -E_NOT_FOUND;
1431         }
1432     } else {
1433         LOGE("step handle status failed:%d, isLock:%d", errCode, isLock);
1434         return -E_ERROR;
1435     }
1436     return E_OK;
1437 }
1438 
HandleDataLock(const std::string & tableName,const std::vector<std::vector<uint8_t>> & hashKey,sqlite3 * db,bool isLock)1439 DistributedDB::DBStatus HandleDataLock(const std::string &tableName, const std::vector<std::vector<uint8_t>> &hashKey,
1440     sqlite3 *db, bool isLock)
1441 {
1442     std::string fileName;
1443     if (!GetDbFileName(db, fileName) || tableName.empty() || hashKey.empty()) {
1444         return DistributedDB::INVALID_ARGS;
1445     }
1446     std::string logTblName = DBCommon::GetLogTableName(tableName);
1447     if (!CheckTableExists(db, logTblName)) {
1448         return DistributedDB::INVALID_ARGS;
1449     }
1450     int errCode = SQLiteUtils::BeginTransaction(db, TransactType::IMMEDIATE);
1451     if (errCode != DistributedDB::E_OK) {
1452         LOGE("begin transaction failed before lock data:%d, isLock:%d", errCode, isLock);
1453         return DistributedDB::TransferDBErrno(errCode);
1454     }
1455     errCode = HandleDataStatus(db, logTblName, hashKey, isLock);
1456     if (errCode != DistributedDB::E_OK && errCode != -DistributedDB::E_NOT_FOUND &&
1457         errCode != -DistributedDB::E_WAIT_COMPENSATED_SYNC) {
1458         int ret = SQLiteUtils::RollbackTransaction(db);
1459         if (ret != DistributedDB::E_OK) {
1460             LOGE("rollback failed when lock data:%d, isLock:%d", ret, isLock);
1461         }
1462         return DistributedDB::TransferDBErrno(errCode);
1463     }
1464     int ret = SQLiteUtils::CommitTransaction(db);
1465     if (ret != DistributedDB::E_OK) {
1466         LOGE("commit failed when lock data:%d, isLock:%d", ret, isLock);
1467     }
1468     return errCode == DistributedDB::E_OK ? DistributedDB::TransferDBErrno(ret) :
1469         DistributedDB::TransferDBErrno(errCode);
1470 }
1471 
GetDBIdentity(sqlite3 * db,std::string & identity)1472 int GetDBIdentity(sqlite3 *db, std::string &identity)
1473 {
1474     auto filePath = sqlite3_db_filename(db, "main");
1475     if (filePath == nullptr) {
1476         return -E_ERROR;
1477     }
1478     identity = std::string(filePath);
1479     return E_OK;
1480 }
1481 
PostHandle(bool isExists,sqlite3 * db)1482 void PostHandle(bool isExists, sqlite3 *db)
1483 {
1484     std::string dbIdentity;
1485     (void)GetDBIdentity(db, dbIdentity);
1486     if (!isExists) { // first create db, clean old time helper
1487         TimeHelperManager::GetInstance()->Restore(dbIdentity);
1488     }
1489     TimeHelperManager::GetInstance()->AddStore(dbIdentity);
1490     RegisterCalcHash(db);
1491     RegisterGetSysTime(db);
1492     RegisterGetLastTime(db);
1493     RegisterGetRawSysTime(db);
1494     RegisterCloudDataChangeObserver(db);
1495     RegisterDataChangeObserver(db);
1496     RegisterCommitAndRollbackHook(db);
1497     (void)sqlite3_set_droptable_handle(db, &ClearTheLogAfterDropTable);
1498     (void)sqlite3_busy_timeout(db, BUSY_TIMEOUT);
1499     std::string recursiveTrigger = "PRAGMA recursive_triggers = ON;";
1500     (void)ExecuteRawSQL(db, recursiveTrigger);
1501 }
1502 
GetTableInfos(sqlite3 * db,std::map<std::string,bool> & tableInfos)1503 int GetTableInfos(sqlite3 *db, std::map<std::string, bool> &tableInfos)
1504 {
1505     if (db == nullptr) {
1506         return -E_ERROR;
1507     }
1508     std::string sql = "SELECT name FROM main.sqlite_master WHERE type = 'table'";
1509     sqlite3_stmt *stmt = nullptr;
1510     int errCode = GetStatement(db, sql, stmt);
1511     if (errCode != E_OK) {
1512         LOGE("Prepare get table and primary key statement failed. err=%d", errCode);
1513         return -E_ERROR;
1514     }
1515     while ((errCode = StepWithRetry(stmt)) != SQLITE_DONE) {
1516         if (errCode != SQLITE_ROW) {
1517             ResetStatement(stmt);
1518             return -E_ERROR;
1519         }
1520         std::string tableName;
1521         GetColumnTextValue(stmt, 0, tableName);
1522         if (tableName.empty() || !ParamCheckUtils::CheckRelationalTableName(tableName) ||
1523             tableName.find("sqlite_") == 0 || tableName.find("naturalbase_") == 0) {
1524             continue;
1525         }
1526         tableInfos.insert(std::make_pair(tableName, true));
1527     }
1528     ResetStatement(stmt);
1529     for (auto &tableInfo : tableInfos) {
1530         std::string type = "";
1531         JudgeIfGetRowid(db, tableInfo.first, type, tableInfo.second);
1532     }
1533     return E_OK;
1534 }
1535 
CreateTempTrigger(sqlite3 * db)1536 int CreateTempTrigger(sqlite3 *db)
1537 {
1538     std::map<std::string, bool> tableInfos;
1539     int errCode = GetTableInfos(db, tableInfos);
1540     if (errCode != E_OK) {
1541         return errCode;
1542     }
1543     std::vector<std::string> triggerSqls;
1544     errCode = GetTriggerSqls(db, tableInfos, triggerSqls);
1545     if (errCode != E_OK) {
1546         return errCode;
1547     }
1548     for (const auto &sql : triggerSqls) {
1549         errCode = SQLiteUtils::ExecuteRawSQL(db, sql);
1550         if (errCode != E_OK) {
1551             LOGE("Create data change trigger failed %d", errCode);
1552             return errCode;
1553         }
1554     }
1555     return errCode;
1556 }
1557 }
1558 
sqlite3_open_relational(const char * filename,sqlite3 ** ppDb)1559 SQLITE_API int sqlite3_open_relational(const char *filename, sqlite3 **ppDb)
1560 {
1561     bool isExists = (access(filename, 0) == 0);
1562     int err = sqlite3_open(filename, ppDb);
1563     if (err != SQLITE_OK) {
1564         return err;
1565     }
1566     PostHandle(isExists, *ppDb);
1567     return err;
1568 }
1569 
sqlite3_open16_relational(const void * filename,sqlite3 ** ppDb)1570 SQLITE_API int sqlite3_open16_relational(const void *filename, sqlite3 **ppDb)
1571 {
1572     bool isExists = (access(static_cast<const char *>(filename), 0) == 0);
1573     int err = sqlite3_open16(filename, ppDb);
1574     if (err != SQLITE_OK) { // LCOV_EXCL_BR_LINE
1575         return err;
1576     }
1577     PostHandle(isExists, *ppDb);
1578     return err;
1579 }
1580 
sqlite3_open_v2_relational(const char * filename,sqlite3 ** ppDb,int flags,const char * zVfs)1581 SQLITE_API int sqlite3_open_v2_relational(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs)
1582 {
1583     bool isExists = (access(filename, 0) == 0);
1584     int err = sqlite3_open_v2(filename, ppDb, flags, zVfs);
1585     if (err != SQLITE_OK) {
1586         return err;
1587     }
1588     PostHandle(isExists, *ppDb);
1589     return err;
1590 }
1591 
RegisterClientObserver(sqlite3 * db,const ClientObserver & clientObserver)1592 DB_API DistributedDB::DBStatus RegisterClientObserver(sqlite3 *db, const ClientObserver &clientObserver)
1593 {
1594     std::string fileName;
1595     if (clientObserver == nullptr || !GetDbFileName(db, fileName)) {
1596         return DistributedDB::INVALID_ARGS;
1597     }
1598 
1599     std::string hashFileName;
1600     int errCode = GetHashString(fileName, hashFileName);
1601     if (errCode != DistributedDB::E_OK) {
1602         return DistributedDB::DB_ERROR;
1603     }
1604 
1605     std::lock_guard<std::mutex> lock(g_clientObserverMutex);
1606     g_clientObserverMap[hashFileName] = clientObserver;
1607     return DistributedDB::OK;
1608 }
1609 
UnRegisterClientObserver(sqlite3 * db)1610 DB_API DistributedDB::DBStatus UnRegisterClientObserver(sqlite3 *db)
1611 {
1612     std::string fileName;
1613     if (!GetDbFileName(db, fileName)) {
1614         return DistributedDB::INVALID_ARGS;
1615     }
1616 
1617     std::string hashFileName;
1618     int errCode = GetHashString(fileName, hashFileName);
1619     if (errCode != DistributedDB::E_OK) {
1620         return DistributedDB::DB_ERROR;
1621     }
1622 
1623     std::lock_guard<std::mutex> lock(g_clientObserverMutex);
1624     auto it = g_clientObserverMap.find(hashFileName);
1625     if (it != g_clientObserverMap.end()) {
1626         g_clientObserverMap.erase(it);
1627     }
1628     return DistributedDB::OK;
1629 }
1630 
RegisterStoreObserver(sqlite3 * db,const std::shared_ptr<StoreObserver> & storeObserver)1631 DB_API DistributedDB::DBStatus RegisterStoreObserver(sqlite3 *db, const std::shared_ptr<StoreObserver> &storeObserver)
1632 {
1633     if (storeObserver == nullptr) {
1634         LOGE("[RegisterStoreObserver] StoreObserver is invalid.");
1635         return DistributedDB::INVALID_ARGS;
1636     }
1637 
1638     std::string fileName;
1639     if (!GetDbFileName(db, fileName)) {
1640         LOGE("[RegisterStoreObserver] Get db filename failed.");
1641         return DistributedDB::INVALID_ARGS;
1642     }
1643 
1644     std::string hashFileName;
1645     int errCode = GetHashString(fileName, hashFileName);
1646     if (errCode != DistributedDB::E_OK) {
1647         LOGE("[RegisterStoreObserver] Get db filename hash string failed.");
1648         return DistributedDB::DB_ERROR;
1649     }
1650 
1651     errCode = CreateTempTrigger(db);
1652     if (errCode != DistributedDB::E_OK) {
1653         LOGE("[RegisterStoreObserver] Create trigger failed.");
1654         return DistributedDB::DB_ERROR;
1655     }
1656 
1657     std::lock_guard<std::mutex> lock(g_storeObserverMutex);
1658     if (std::find(g_storeObserverMap[hashFileName].begin(), g_storeObserverMap[hashFileName].end(), storeObserver) !=
1659         g_storeObserverMap[hashFileName].end()) {
1660         LOGE("[RegisterStoreObserver] Duplicate observer.");
1661         return DistributedDB::INVALID_ARGS;
1662     }
1663     g_storeObserverMap[hashFileName].push_back(storeObserver);
1664     return DistributedDB::OK;
1665 }
1666 
UnregisterStoreObserver(sqlite3 * db,const std::shared_ptr<StoreObserver> & storeObserver)1667 DB_API DistributedDB::DBStatus UnregisterStoreObserver(sqlite3 *db, const std::shared_ptr<StoreObserver> &storeObserver)
1668 {
1669     if (storeObserver == nullptr) {
1670         LOGE("[UnregisterStoreObserver] StoreObserver is invalid.");
1671         return DistributedDB::INVALID_ARGS;
1672     }
1673 
1674     std::string fileName;
1675     if (!GetDbFileName(db, fileName)) {
1676         LOGE("[UnregisterStoreObserver] Get db filename failed.");
1677         return DistributedDB::INVALID_ARGS;
1678     }
1679 
1680     std::string hashFileName;
1681     int errCode = GetHashString(fileName, hashFileName);
1682     if (errCode != DistributedDB::E_OK) {
1683         LOGE("[UnregisterStoreObserver] Get db filename hash string failed.");
1684         return DistributedDB::DB_ERROR;
1685     }
1686 
1687     std::lock_guard<std::mutex> lock(g_storeObserverMutex);
1688     auto it = g_storeObserverMap.find(hashFileName);
1689     if (it != g_storeObserverMap.end()) {
1690         it->second.remove(storeObserver);
1691         if (it->second.empty()) {
1692             g_storeObserverMap.erase(it);
1693         }
1694     }
1695 
1696     return DistributedDB::OK;
1697 }
1698 
UnregisterStoreObserver(sqlite3 * db)1699 DB_API DistributedDB::DBStatus UnregisterStoreObserver(sqlite3 *db)
1700 {
1701     std::string fileName;
1702     if (!GetDbFileName(db, fileName)) {
1703         LOGE("[UnregisterAllStoreObserver] StoreObserver is invalid.");
1704         return DistributedDB::INVALID_ARGS;
1705     }
1706 
1707     std::string hashFileName;
1708     int errCode = GetHashString(fileName, hashFileName);
1709     if (errCode != DistributedDB::E_OK) {
1710         LOGE("[UnregisterAllStoreObserver] Get db filename hash string failed.");
1711         return DistributedDB::DB_ERROR;
1712     }
1713 
1714     std::lock_guard<std::mutex> lock(g_storeObserverMutex);
1715     auto it = g_storeObserverMap.find(hashFileName);
1716     if (it != g_storeObserverMap.end()) {
1717         g_storeObserverMap.erase(it);
1718     }
1719     return DistributedDB::OK;
1720 }
1721 
DropLogicDeletedData(sqlite3 * db,const std::string & tableName,uint64_t cursor)1722 DB_API DistributedDB::DBStatus DropLogicDeletedData(sqlite3 *db, const std::string &tableName, uint64_t cursor)
1723 {
1724     std::string fileName;
1725     if (!GetDbFileName(db, fileName)) {
1726         return DistributedDB::INVALID_ARGS;
1727     }
1728     if (tableName.empty()) {
1729         return DistributedDB::INVALID_ARGS;
1730     }
1731     int errCode = SQLiteUtils::BeginTransaction(db, TransactType::IMMEDIATE);
1732     if (errCode != DistributedDB::E_OK) {
1733         LOGE("begin transaction failed before drop logic deleted data. %d", errCode);
1734         return DistributedDB::TransferDBErrno(errCode);
1735     }
1736     errCode = HandleDropLogicDeleteData(db, tableName, cursor);
1737     if (errCode != SQLITE_OK) {
1738         int ret = SQLiteUtils::RollbackTransaction(db);
1739         if (ret != DistributedDB::E_OK) {
1740             LOGE("rollback failed when drop logic deleted data. %d", ret);
1741         }
1742         return DistributedDB::TransferDBErrno(errCode);
1743     }
1744     int ret = SQLiteUtils::CommitTransaction(db);
1745     if (ret != DistributedDB::E_OK) {
1746         LOGE("commit failed when drop logic deleted data. %d", ret);
1747     }
1748     return ret == DistributedDB::E_OK ? DistributedDB::OK : DistributedDB::TransferDBErrno(ret);
1749 }
1750 
Lock(const std::string & tableName,const std::vector<std::vector<uint8_t>> & hashKey,sqlite3 * db)1751 DB_API DistributedDB::DBStatus Lock(const std::string &tableName, const std::vector<std::vector<uint8_t>> &hashKey,
1752     sqlite3 *db)
1753 {
1754     return HandleDataLock(tableName, hashKey, db, true);
1755 }
1756 
UnLock(const std::string & tableName,const std::vector<std::vector<uint8_t>> & hashKey,sqlite3 * db)1757 DB_API DistributedDB::DBStatus UnLock(const std::string &tableName, const std::vector<std::vector<uint8_t>> &hashKey,
1758     sqlite3 *db)
1759 {
1760     return HandleDataLock(tableName, hashKey, db, false);
1761 }
1762 
1763 // hw export the symbols
1764 #ifdef SQLITE_DISTRIBUTE_RELATIONAL
1765 #if defined(__GNUC__)
1766 #  define EXPORT_SYMBOLS  __attribute__ ((visibility ("default")))
1767 #elif defined(_MSC_VER)
1768     #  define EXPORT_SYMBOLS  __declspec(dllexport)
1769 #else
1770 #  define EXPORT_SYMBOLS
1771 #endif
1772 
1773 struct sqlite3_api_routines_relational {
1774     int (*open)(const char *, sqlite3 **);
1775     int (*open16)(const void *, sqlite3 **);
1776     int (*open_v2)(const char *, sqlite3 **, int, const char *);
1777 };
1778 
1779 typedef struct sqlite3_api_routines_relational sqlite3_api_routines_relational;
1780 static const sqlite3_api_routines_relational sqlite3HwApis = {
1781 #ifdef SQLITE_DISTRIBUTE_RELATIONAL
1782     sqlite3_open_relational,
1783     sqlite3_open16_relational,
1784     sqlite3_open_v2_relational
1785 #else
1786     0,
1787     0,
1788     0
1789 #endif
1790 };
1791 
1792 EXPORT_SYMBOLS const sqlite3_api_routines_relational *sqlite3_export_relational_symbols = &sqlite3HwApis;
1793 #endif
1794