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_single_ver_storage_executor.h"
17
18 #include "log_print.h"
19 #include "db_common.h"
20 #include "db_errno.h"
21 #include "sqlite_single_ver_storage_executor_sql.h"
22
23 namespace DistributedDB {
24 using namespace TriggerMode;
25
CheckQueryObjectLegal(QueryObject & queryObj) const26 int SQLiteSingleVerStorageExecutor::CheckQueryObjectLegal(QueryObject &queryObj) const
27 {
28 int errCode = E_OK;
29 SqliteQueryHelper helper = queryObj.GetQueryHelper(errCode);
30 if (errCode != E_OK) {
31 LOGE("Get query helper failed [%d]!", errCode);
32 return errCode;
33 }
34
35 sqlite3_stmt *statement = nullptr;
36 errCode = helper.GetQuerySyncStatement(dbHandle_, 0, INT64_MAX, statement); // (0, INT64_MAX):max range
37 int ret = E_OK;
38 SQLiteUtils::ResetStatement(statement, true, ret);
39 if (ret != E_OK) {
40 LOGW("Failed to reset statement. error:%d", ret);
41 }
42 return CheckCorruptedStatus(errCode);
43 }
44
CheckMissQueryDataItem(sqlite3_stmt * stmt,const std::string & deviceName,DataItem & item)45 int SQLiteSingleVerStorageExecutor::CheckMissQueryDataItem(sqlite3_stmt *stmt, const std::string &deviceName,
46 DataItem &item)
47 {
48 int errCode = SQLiteUtils::StepWithRetry(stmt, isMemDb_);
49 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
50 // the value with same hashKey in DB matched the query
51 std::vector<uint8_t> dev;
52 errCode = SQLiteUtils::GetColumnBlobValue(stmt, SYNC_RES_DEVICE_INDEX, dev);
53 if (errCode != E_OK) {
54 LOGE("Get data device info failed. %d", errCode);
55 return errCode;
56 }
57 auto timeStamp = static_cast<TimeStamp>(sqlite3_column_int64(stmt, SYNC_RES_TIME_INDEX));
58 std::string device = std::string(dev.begin(), dev.end());
59 // this data item should be neglected when it's out of date of it's from same device
60 // otherwise, it should be erased after resolved the conflict
61 item.neglect = (timeStamp > item.timeStamp) ||
62 (timeStamp == item.timeStamp && device == DBCommon::TransferHashString(deviceName));
63 return E_OK;
64 } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
65 // the value with same hashKey in DB does not match the query, this data item should be neglected.
66 item.neglect = true;
67 return E_OK;
68 }
69 LOGE("Check sync data failed %d", errCode);
70 return errCode;
71 }
72
73 // check the data with REMOTE_DEVICE_DATA_MISS_QUERY flag need neglect or not
CheckMissQueryDataItems(sqlite3_stmt * & stmt,const SqliteQueryHelper & helper,const DeviceInfo & deviceInfo,std::vector<DataItem> & dataItems)74 int SQLiteSingleVerStorageExecutor::CheckMissQueryDataItems(sqlite3_stmt *&stmt, const SqliteQueryHelper &helper,
75 const DeviceInfo &deviceInfo, std::vector<DataItem> &dataItems)
76 {
77 int errCode = E_OK;
78 for (auto &item : dataItems) {
79 if ((item.flag & DataItem::REMOTE_DEVICE_DATA_MISS_QUERY) != 0 && !item.key.empty()) {
80 errCode = helper.BindSyncDataCheckStmt(stmt, item.key);
81 if (errCode != E_OK) {
82 LOGE("Bind sync data check statement failed %d", errCode);
83 break;
84 }
85 errCode = CheckMissQueryDataItem(stmt, deviceInfo.deviceName, item);
86 if (errCode != E_OK) {
87 LOGE("Check miss query data item failed. %d", errCode);
88 return errCode;
89 }
90 SQLiteUtils::ResetStatement(stmt, false, errCode);
91 }
92 }
93 return errCode;
94 }
95
CheckDataWithQuery(QueryObject query,std::vector<DataItem> & dataItems,const DeviceInfo & deviceInfo)96 int SQLiteSingleVerStorageExecutor::CheckDataWithQuery(QueryObject query, std::vector<DataItem> &dataItems,
97 const DeviceInfo &deviceInfo)
98 {
99 int errCode = E_OK;
100 if (query.Empty()) {
101 LOGD("Query is empty, skip check.");
102 return E_OK;
103 }
104 SqliteQueryHelper helper = query.GetQueryHelper(errCode);
105 if (errCode != E_OK) {
106 LOGE("Get query helper failed [%d]!", errCode);
107 return errCode;
108 }
109 std::string sql;
110 errCode = helper.GetSyncDataCheckSql(sql);
111 if (errCode != E_OK) {
112 LOGE("Get sync data check sql failed");
113 return errCode;
114 }
115 sqlite3_stmt *stmt = nullptr;
116 errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt);
117 if (errCode != E_OK) {
118 LOGE("Get statement fail. %d", errCode);
119 return -E_INVALID_QUERY_FORMAT;
120 }
121 errCode = CheckMissQueryDataItems(stmt, helper, deviceInfo, dataItems);
122 if (errCode != E_OK) {
123 LOGE("check data with query failed. %d", errCode);
124 }
125 SQLiteUtils::ResetStatement(stmt, true, errCode);
126 return CheckCorruptedStatus(errCode);
127 }
128
129 namespace {
FormatSubscribeTriggerSql(const std::string & subscribeId,const std::string & subscribeCondition,TriggerModeEnum mode)130 std::string FormatSubscribeTriggerSql(const std::string &subscribeId, const std::string &subscribeCondition,
131 TriggerModeEnum mode)
132 {
133 std::string triggerModeString = GetTriggerModeString(mode);
134 std::string accessString = ((mode == TriggerModeEnum::DELETE) ?
135 DBConstant::TRIGGER_REFERENCES_OLD : DBConstant::TRIGGER_REFERENCES_NEW);
136 std::string keyStr = DBConstant::SUBSCRIBE_QUERY_PREFIX + DBCommon::TransferHashString(subscribeId);
137 Key key {keyStr.begin(), keyStr.end()};
138 std::string hexKeyStr = DBCommon::VectorToHexString(key);
139 std::string triggerName = DBConstant::SUBSCRIBE_QUERY_PREFIX + subscribeId + "_ON_" + triggerModeString;
140 return "CREATE TRIGGER IF NOT EXISTS " + triggerName + " AFTER " + triggerModeString + " \n"
141 "ON sync_data\n"
142 "WHEN " + subscribeCondition + "\n"
143 "BEGIN\n"
144 " SELECT " + DBConstant::UPDATE_META_FUNC + "(x'" + hexKeyStr + "', NEW.TIMESTAMP);\n"
145 "END;";
146 }
147 }
148
AddSubscribeTrigger(QueryObject & query,const std::string & subscribeId)149 int SQLiteSingleVerStorageExecutor::AddSubscribeTrigger(QueryObject &query, const std::string &subscribeId)
150 {
151 if (executorState_ == ExecutorState::CACHEDB || executorState_ == ExecutorState::CACHE_ATTACH_MAIN) {
152 LOGE("Not support add subscribe in cache db.");
153 return -E_NOT_SUPPORT;
154 }
155 int errCode = E_OK;
156 SqliteQueryHelper helper = query.GetQueryHelper(errCode);
157 if (errCode != E_OK) {
158 LOGE("Get query helper failed. %d", errCode);
159 return errCode;
160 }
161 // check if sqlite function is registered or not
162 sqlite3_stmt *stmt = nullptr;
163 errCode = SQLiteUtils::GetStatement(dbHandle_, "SELECT " + DBConstant::UPDATE_META_FUNC + "('K', 0);", stmt);
164 if (errCode != E_OK) {
165 LOGE("sqlite function %s has not been created.", DBConstant::UPDATE_META_FUNC.c_str());
166 return -E_NOT_SUPPORT;
167 }
168 SQLiteUtils::ResetStatement(stmt, true, errCode);
169
170 // Delete data API is actually an update operation, there is no need for DELETE trigger
171 for (auto mode : {TriggerModeEnum::INSERT, TriggerModeEnum::UPDATE}) {
172 std::string subscribeCondition;
173 errCode = helper.GetSubscribeSql(subscribeId, mode, subscribeCondition);
174 if (errCode != E_OK) {
175 LOGE("Get subscribe trigger create sql failed. mode: %d, errCode: %d", mode, errCode);
176 return errCode;
177 }
178 std::string sql = FormatSubscribeTriggerSql(subscribeId, subscribeCondition, mode);
179 errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql);
180 if (errCode != E_OK) {
181 LOGE("Add subscribe trigger failed. mode: %d, errCode: %d", mode, errCode);
182 return errCode;
183 }
184 }
185 return E_OK;
186 }
187
RemoveSubscribeTrigger(const std::vector<std::string> & subscribeIds)188 int SQLiteSingleVerStorageExecutor::RemoveSubscribeTrigger(const std::vector<std::string> &subscribeIds)
189 {
190 int errCode = E_OK;
191 for (const auto &id : subscribeIds) {
192 for (auto mode : {TriggerModeEnum::INSERT, TriggerModeEnum::UPDATE}) {
193 const std::string trigger = DBConstant::SUBSCRIBE_QUERY_PREFIX + id + "_ON_" + GetTriggerModeString(mode);
194 errCode = SQLiteUtils::DropTriggerByName(dbHandle_, trigger);
195 if (errCode != E_OK) {
196 LOGE("remove subscribe trigger failed. %d", errCode);
197 break;
198 }
199 }
200 if (errCode != E_OK) {
201 LOGE("remove subscribe trigger for id %s failed. %d", id.c_str(), errCode);
202 break;
203 }
204 }
205 return errCode;
206 }
207
RemoveTrigger(const std::vector<std::string> & triggers)208 int SQLiteSingleVerStorageExecutor::RemoveTrigger(const std::vector<std::string> &triggers)
209 {
210 int errCode = E_OK;
211 for (const auto &trigger : triggers) {
212 errCode = SQLiteUtils::DropTriggerByName(dbHandle_, trigger);
213 if (errCode != E_OK) {
214 LOGE("remove trigger failed. %d", errCode);
215 break;
216 }
217 }
218 return errCode;
219 }
220
RemoveSubscribeTriggerWaterMark(const std::vector<std::string> & subscribeIds)221 int SQLiteSingleVerStorageExecutor::RemoveSubscribeTriggerWaterMark(const std::vector<std::string> &subscribeIds)
222 {
223 sqlite3_stmt *statement = nullptr;
224 const std::string sql = attachMetaMode_ ? REMOVE_ATTACH_META_VALUE_SQL : REMOVE_META_VALUE_SQL;
225 int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement);
226 if (errCode != E_OK) {
227 LOGE("Get remove trigger water mark statement failed. %d", errCode);
228 return errCode;
229 }
230 for (const auto &id : subscribeIds) {
231 errCode = SQLiteUtils::BindTextToStatement(statement, 1, DBConstant::SUBSCRIBE_QUERY_PREFIX + id);
232 if (errCode != E_OK) {
233 LOGE("Bind mark key to statement failed. %d", errCode);
234 break;
235 }
236 errCode = SQLiteUtils::StepWithRetry(statement, isMemDb_);
237 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
238 errCode = E_OK;
239 } else {
240 LOGE("Remove trigger water mark failed. %d", errCode);
241 break;
242 }
243 SQLiteUtils::ResetStatement(statement, false, errCode);
244 }
245 SQLiteUtils::ResetStatement(statement, true, errCode);
246 return errCode;
247 }
248
GetTriggers(const std::string & namePreFix,std::vector<std::string> & triggerNames)249 int SQLiteSingleVerStorageExecutor::GetTriggers(const std::string &namePreFix, std::vector<std::string> &triggerNames)
250 {
251 sqlite3_stmt *stmt = nullptr;
252 int errCode = SQLiteUtils::GetStatement(dbHandle_, GET_SYNC_DATA_TIRGGER_SQL, stmt);
253 if (errCode != E_OK) {
254 LOGE("Get trigger query statement failed. %d", errCode);
255 return errCode;
256 }
257
258 errCode = SQLiteUtils::BindTextToStatement(stmt, 1, namePreFix + "%");
259 if (errCode != E_OK) {
260 SQLiteUtils::ResetStatement(stmt, true, errCode);
261 LOGE("Bind trigger name prefix to statement failed. %d", errCode);
262 return errCode;
263 }
264
265 do {
266 errCode = SQLiteUtils::StepWithRetry(stmt, isMemDb_);
267 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
268 errCode = E_OK;
269 break;
270 } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
271 std::string name;
272 SQLiteUtils::GetColumnTextValue(stmt, 0, name);
273 triggerNames.emplace_back(name);
274 } else {
275 LOGE("Get trigger by name prefix failed. %d", errCode);
276 break;
277 }
278 } while (true);
279
280 SQLiteUtils::ResetStatement(stmt, true, errCode);
281 return errCode;
282 }
283 } // namespace DistributedDB
284