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 ((NEW.flag&0x02=0x02) AND (" + subscribeCondition + "))\n" // filter locally changed data
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_EKEYREVOKED;
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", static_cast<int>(mode),
176 errCode);
177 return errCode;
178 }
179 std::string sql = FormatSubscribeTriggerSql(subscribeId, subscribeCondition, mode);
180 errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql);
181 if (errCode != E_OK) {
182 LOGE("Add subscribe trigger failed. mode: %d, errCode: %d", static_cast<int>(mode), errCode);
183 return errCode;
184 }
185 }
186 return E_OK;
187 }
188
RemoveSubscribeTrigger(const std::vector<std::string> & subscribeIds)189 int SQLiteSingleVerStorageExecutor::RemoveSubscribeTrigger(const std::vector<std::string> &subscribeIds)
190 {
191 int errCode = E_OK;
192 for (const auto &id : subscribeIds) {
193 for (auto mode : {TriggerModeEnum::INSERT, TriggerModeEnum::UPDATE}) {
194 const std::string trigger = DBConstant::SUBSCRIBE_QUERY_PREFIX + id + "_ON_" + GetTriggerModeString(mode);
195 errCode = SQLiteUtils::DropTriggerByName(dbHandle_, trigger);
196 if (errCode != E_OK) {
197 LOGE("remove subscribe trigger failed. %d", errCode);
198 break;
199 }
200 }
201 if (errCode != E_OK) {
202 LOGE("remove subscribe trigger for id %s failed. %d", id.c_str(), errCode);
203 break;
204 }
205 }
206 return errCode;
207 }
208
RemoveTrigger(const std::vector<std::string> & triggers)209 int SQLiteSingleVerStorageExecutor::RemoveTrigger(const std::vector<std::string> &triggers)
210 {
211 int errCode = E_OK;
212 for (const auto &trigger : triggers) {
213 errCode = SQLiteUtils::DropTriggerByName(dbHandle_, trigger);
214 if (errCode != E_OK) {
215 LOGE("remove trigger failed. %d", errCode);
216 break;
217 }
218 }
219 return errCode;
220 }
221
RemoveSubscribeTriggerWaterMark(const std::vector<std::string> & subscribeIds)222 int SQLiteSingleVerStorageExecutor::RemoveSubscribeTriggerWaterMark(const std::vector<std::string> &subscribeIds)
223 {
224 sqlite3_stmt *statement = nullptr;
225 const std::string sql = attachMetaMode_ ? REMOVE_ATTACH_META_VALUE_SQL : REMOVE_META_VALUE_SQL;
226 int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement);
227 if (errCode != E_OK) {
228 LOGE("Get remove trigger water mark statement failed. %d", errCode);
229 return errCode;
230 }
231 for (const auto &id : subscribeIds) {
232 errCode = SQLiteUtils::BindTextToStatement(statement, 1, DBConstant::SUBSCRIBE_QUERY_PREFIX + id);
233 if (errCode != E_OK) {
234 LOGE("Bind mark key to statement failed. %d", errCode);
235 break;
236 }
237 errCode = SQLiteUtils::StepWithRetry(statement, isMemDb_);
238 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
239 errCode = E_OK;
240 } else {
241 LOGE("Remove trigger water mark failed. %d", errCode);
242 break;
243 }
244 SQLiteUtils::ResetStatement(statement, false, errCode);
245 }
246 SQLiteUtils::ResetStatement(statement, true, errCode);
247 return errCode;
248 }
249
GetTriggers(const std::string & namePreFix,std::vector<std::string> & triggerNames)250 int SQLiteSingleVerStorageExecutor::GetTriggers(const std::string &namePreFix, std::vector<std::string> &triggerNames)
251 {
252 sqlite3_stmt *stmt = nullptr;
253 int errCode = SQLiteUtils::GetStatement(dbHandle_, GET_SYNC_DATA_TIRGGER_SQL, stmt);
254 if (errCode != E_OK) {
255 LOGE("Get trigger query statement failed. %d", errCode);
256 return errCode;
257 }
258
259 errCode = SQLiteUtils::BindTextToStatement(stmt, 1, namePreFix + "%");
260 if (errCode != E_OK) {
261 SQLiteUtils::ResetStatement(stmt, true, errCode);
262 LOGE("Bind trigger name prefix to statement failed. %d", errCode);
263 return errCode;
264 }
265
266 do {
267 errCode = SQLiteUtils::StepWithRetry(stmt, isMemDb_);
268 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
269 errCode = E_OK;
270 break;
271 } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
272 std::string name;
273 SQLiteUtils::GetColumnTextValue(stmt, 0, name);
274 triggerNames.emplace_back(name);
275 } else {
276 LOGE("Get trigger by name prefix failed. %d", errCode);
277 break;
278 }
279 } while (true);
280
281 SQLiteUtils::ResetStatement(stmt, true, errCode);
282 return errCode;
283 }
284 } // namespace DistributedDB
285