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 "sqlite_query_helper.h"
16
17 #include <iomanip>
18 #include <sstream>
19
20 #include "db_common.h"
21 #include "db_constant.h"
22 #include "db_errno.h"
23 #include "log_print.h"
24 #include "macro_utils.h"
25 #include "sqlite_utils.h"
26 #include "sqlite_single_ver_storage_executor_sql.h"
27 #include "cloud/cloud_storage_utils.h"
28 #include "res_finalizer.h"
29
30 namespace DistributedDB {
31 using namespace TriggerMode;
32 namespace {
33 const std::string PRE_QUERY_KV_SQL = "SELECT key, value FROM sync_data ";
34 const std::string PRE_QUERY_ITEM_SQL = "SELECT * FROM ";
35 const std::string PRE_QUERY_COUNT_ITEM_SQL = "SELECT count(*) FROM ";
36 const std::string PRE_QUERY_ROWID_SQL = "SELECT rowid FROM sync_data ";
37 const std::string PRE_GET_COUNT_SQL = "SELECT count(*) FROM sync_data ";
38 const std::string FILTER_NATIVE_DATA_SQL = "WHERE (flag&0x01=0) ";
39 const std::string FILTER_REMOTE_QUERY = "WHERE (flag&0x03=0x02)";
40 const std::string USING_INDEX = "INDEXED BY ";
41 const int MAX_SQL_LEN = 1024 * 1024; // 1M bytes
42 const int SINGLE_FIELD_VALUE_SIZE = 1;
43 const int MAX_CONDITIONS_SIZE = 128;
44 const int MAX_SQLITE_BIND_SIZE = 50000;
45 const uint32_t SYMBOL_TYPE_MASK = 0xff00;
46
47 const std::map<QueryObjType, std::string> RELATIONAL_SYMBOL_TO_SQL {
48 {QueryObjType::EQUALTO, "= "},
49 {QueryObjType::NOT_EQUALTO, "!= "},
50 {QueryObjType::GREATER_THAN, "> "},
51 {QueryObjType::LESS_THAN, "< "},
52 {QueryObjType::GREATER_THAN_OR_EQUALTO, ">= "},
53 {QueryObjType::LESS_THAN_OR_EQUALTO, "<= "},
54 {QueryObjType::LIKE, " LIKE "},
55 {QueryObjType::NOT_LIKE, " NOT LIKE "},
56 {QueryObjType::IS_NULL, " IS NULL "},
57 {QueryObjType::IS_NOT_NULL, " IS NOT NULL "},
58 {QueryObjType::IN, " IN ("},
59 {QueryObjType::NOT_IN, " NOT IN ("},
60 };
61
62 const std::map<QueryObjType, std::string> LOGIC_SYMBOL_TO_SQL {
63 {QueryObjType::AND, " AND "},
64 {QueryObjType::OR, " OR "},
65 {QueryObjType::BEGIN_GROUP, "("},
66 {QueryObjType::END_GROUP, ")"},
67 };
68
FieldValue2String(const FieldValue & val,QueryValueType type)69 std::string FieldValue2String(const FieldValue &val, QueryValueType type)
70 {
71 std::stringstream ss;
72 switch (type) {
73 case QueryValueType::VALUE_TYPE_NULL:
74 return "NULL";
75 case QueryValueType::VALUE_TYPE_BOOL:
76 return val.boolValue ? "1" : "0";
77 case QueryValueType::VALUE_TYPE_INTEGER:
78 return std::to_string(val.integerValue);
79 case QueryValueType::VALUE_TYPE_LONG:
80 return std::to_string(val.longValue);
81 case QueryValueType::VALUE_TYPE_DOUBLE:
82 ss << std::setprecision(DBConstant::DOUBLE_PRECISION) << val.doubleValue;
83 return ss.str();
84 case QueryValueType::VALUE_TYPE_STRING:
85 return "'" + val.stringValue + "'";
86 case QueryValueType::VALUE_TYPE_INVALID:
87 default:
88 return "";
89 }
90 }
91
GetSelectAndFromClauseForRDB(const std::string & tableName,const std::vector<std::string> & fieldNames)92 std::string GetSelectAndFromClauseForRDB(const std::string &tableName, const std::vector<std::string> &fieldNames)
93 {
94 std::string sql = "SELECT b.data_key,"
95 "b.device,"
96 "b.ori_device,"
97 "b.timestamp as ";
98 sql.append(DBConstant::TIMESTAMP_ALIAS);
99 sql += ","
100 "b.wtimestamp,"
101 "b.flag,"
102 "b.hash_key,";
103 if (fieldNames.empty()) { // For query check. If column count changed, can be discovered.
104 sql += "a.*";
105 } else {
106 for (const auto &fieldName : fieldNames) { // For query data.
107 sql += "a.'" + fieldName + "',";
108 }
109 sql.pop_back();
110 }
111 sql += " FROM '" + tableName + "' AS a INNER JOIN " + DBConstant::RELATIONAL_PREFIX + tableName + "_log AS b "
112 "ON a." + DBConstant::SQLITE_INNER_ROWID + "=b.data_key ";
113 return sql;
114 }
115
GetTimeRangeClauseForRDB()116 std::string GetTimeRangeClauseForRDB()
117 {
118 return " AND (" + std::string(DBConstant::TIMESTAMP_ALIAS) + ">=? AND " + DBConstant::TIMESTAMP_ALIAS + "<?) ";
119 }
120
GetOuterQueryClauseForRDB(const std::string & subQueryClause)121 std::string GetOuterQueryClauseForRDB(const std::string &subQueryClause)
122 {
123 return "SELECT * "
124 "FROM ( " + subQueryClause + " ) "
125 "WHERE (" + DBConstant::TIMESTAMP_ALIAS + ">=? AND " + DBConstant::TIMESTAMP_ALIAS + "<?) "
126 "ORDER BY " + DBConstant::TIMESTAMP_ALIAS + ";";
127 }
128
GetFlagClauseForRDB()129 std::string GetFlagClauseForRDB()
130 {
131 return "WHERE (b.flag&0x03=0x02)";
132 }
133
GetMissQueryFlagClauseForRDB()134 std::string GetMissQueryFlagClauseForRDB()
135 {
136 return "WHERE (b.flag&0x23=0x22)";
137 }
138 }
139
SqliteQueryHelper(const QueryObjInfo & info)140 SqliteQueryHelper::SqliteQueryHelper(const QueryObjInfo &info)
141 : schema_(info.schema_),
142 queryObjNodes_(info.queryObjNodes_),
143 prefixKey_(info.prefixKey_),
144 suggestIndex_(info.suggestIndex_),
145 tableName_(info.tableName_),
146 keys_(info.keys_),
147 orderByCounts_(info.orderByCounts_),
148 isValid_(info.isValid_),
149 transformed_(false),
150 hasOrderBy_(info.hasOrderBy_),
151 hasLimit_(info.hasLimit_),
152 isOrderByAppeared_(false),
153 hasPrefixKey_(info.hasPrefixKey_),
154 isNeedOrderbyKey_(false),
155 isRelationalQuery_(info.isRelationalQuery_),
156 sortType_(info.sortType_)
157 {}
158
GetSymbolType(const QueryObjType & queryObjType)159 SymbolType SqliteQueryHelper::GetSymbolType(const QueryObjType &queryObjType)
160 {
161 return static_cast<SymbolType>(static_cast<uint32_t>(queryObjType) & SYMBOL_TYPE_MASK);
162 }
163
FilterSymbolToAddBracketLink(std::string & querySql,bool isNeedLink) const164 bool SqliteQueryHelper::FilterSymbolToAddBracketLink(std::string &querySql, bool isNeedLink) const
165 {
166 bool isNeedEndBracket = false;
167 for (const auto &iter : queryObjNodes_) {
168 SymbolType symbolType = GetSymbolType(iter.operFlag);
169 if (symbolType == SymbolType::COMPARE_SYMBOL || symbolType == SymbolType::RELATIONAL_SYMBOL ||
170 symbolType == SymbolType::RANGE_SYMBOL) {
171 querySql += isNeedLink ? " AND (" : " (";
172 isNeedEndBracket = true;
173 break;
174 } else if (symbolType == SymbolType::LOGIC_SYMBOL || symbolType == SymbolType::PREFIXKEY_SYMBOL ||
175 symbolType == SymbolType::IN_KEYS_SYMBOL) {
176 continue;
177 } else {
178 break;
179 }
180 }
181 return isNeedEndBracket;
182 }
183
184
ParseQueryObjNodeToSQL(bool isQueryForSync)185 int SqliteQueryHelper::ParseQueryObjNodeToSQL(bool isQueryForSync)
186 {
187 if (queryObjNodes_.empty()) {
188 if (!isQueryForSync) {
189 querySql_ += ";";
190 }
191 return E_OK;
192 }
193
194 bool isNeedEndBracket = FilterSymbolToAddBracketLink(querySql_);
195
196 int errCode = E_OK;
197 for (const QueryObjNode &objNode : queryObjNodes_) {
198 SymbolType symbolType = GetSymbolType(objNode.operFlag);
199 if (symbolType == SymbolType::SPECIAL_SYMBOL && isNeedEndBracket) {
200 querySql_ += ") ";
201 isNeedEndBracket = false;
202 }
203 errCode = ParseQueryExpression(objNode, querySql_);
204 if (errCode != E_OK) {
205 querySql_.clear();
206 return errCode;
207 }
208 }
209
210 if (isNeedEndBracket) {
211 querySql_ += ") ";
212 }
213
214 return errCode;
215 }
216
ToQuerySql()217 int SqliteQueryHelper::ToQuerySql()
218 {
219 int errCode = ParseQueryObjNodeToSQL(false);
220 if (errCode != E_OK) {
221 return errCode;
222 }
223
224 // Limit needs to be placed after orderBy and processed separately in the limit branch
225 if (hasPrefixKey_ && !hasOrderBy_ && !hasLimit_ && isNeedOrderbyKey_) {
226 LOGD("Need add order by key at last when has prefixKey no need order by value and limit!");
227 querySql_ += "ORDER BY key ASC";
228 }
229 querySql_ += ";";
230 return errCode;
231 }
232
ToQuerySyncSql(bool hasSubQuery,bool useTimestampAlias)233 int SqliteQueryHelper::ToQuerySyncSql(bool hasSubQuery, bool useTimestampAlias)
234 {
235 int errCode = ParseQueryObjNodeToSQL(true);
236 if (errCode != E_OK) {
237 return errCode;
238 }
239
240 // Order by time when no order by and no limit and no need order by key.
241 if (!hasOrderBy_ && !hasLimit_ && !isNeedOrderbyKey_) {
242 querySql_ += (useTimestampAlias ?
243 ("ORDER BY " + std::string(DBConstant::TIMESTAMP_ALIAS) + " ASC") :
244 "ORDER BY timestamp ASC");
245 }
246
247 if (!hasSubQuery) {
248 querySql_ += ";";
249 }
250 return errCode;
251 }
252
ToGetCountSql()253 int SqliteQueryHelper::ToGetCountSql()
254 {
255 countSql_.clear();
256 if (queryObjNodes_.empty()) {
257 countSql_ += ";";
258 return E_OK;
259 }
260 bool isNeedEndBracket = FilterSymbolToAddBracketLink(countSql_);
261
262 int errCode = E_OK;
263 for (const QueryObjNode &objNode : queryObjNodes_) {
264 SymbolType symbolType = GetSymbolType(objNode.operFlag);
265 if (symbolType == SymbolType::SPECIAL_SYMBOL && isNeedEndBracket) {
266 countSql_ += ") ";
267 isNeedEndBracket = false;
268 }
269
270 if (objNode.operFlag == QueryObjType::LIMIT) {
271 hasLimit_ = true;
272 continue;
273 }
274 if (objNode.operFlag == QueryObjType::ORDERBY) {
275 hasOrderBy_ = true;
276 continue;
277 }
278 errCode = ParseQueryExpression(objNode, countSql_);
279 if (errCode != E_OK) {
280 countSql_.clear();
281 return errCode;
282 }
283 }
284
285 if (isNeedEndBracket) {
286 countSql_ += ") ";
287 }
288
289 // Limit needs to be placed after orderBy and processed separately in the limit branch
290 if (hasPrefixKey_ && !hasOrderBy_ && !hasLimit_ && isNeedOrderbyKey_) {
291 LOGD("Need add order by key at last when has prefixKey no need order by value and limit!");
292 countSql_ += "ORDER BY key ASC";
293 }
294 countSql_ += ";";
295 return errCode;
296 }
297
GetQuerySql(std::string & sql,bool onlyRowid)298 int SqliteQueryHelper::GetQuerySql(std::string &sql, bool onlyRowid)
299 {
300 if (!isValid_) {
301 return -E_INVALID_QUERY_FORMAT;
302 }
303
304 const std::string &querySqlForUse = (onlyRowid ? PRE_QUERY_ROWID_SQL : PRE_QUERY_KV_SQL);
305 sql = AssembleSqlForSuggestIndex(querySqlForUse, FILTER_NATIVE_DATA_SQL);
306 sql = !hasPrefixKey_ ? sql : (sql + " AND (key>=? AND key<=?) ");
307 sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size()));
308 sql += " AND (flag&0x200=0) ";
309 if (sortType_ != SortType::NONE) {
310 sql += (sortType_ == SortType::TIMESTAMP_ASC) ? "ORDER BY timestamp asc " : "ORDER BY timestamp desc ";
311 }
312 if (transformed_) {
313 LOGD("This query object has been parsed.");
314 sql += querySql_;
315 return E_OK;
316 }
317 int errCode = ToQuerySql();
318 if (errCode != E_OK) {
319 LOGE("Transfer to query sql failed! errCode[%d]", errCode);
320 return errCode;
321 }
322 transformed_ = true;
323 sql += querySql_;
324 return errCode;
325 }
326
GetSyncDataCheckSql(std::string & sql)327 int SqliteQueryHelper::GetSyncDataCheckSql(std::string &sql)
328 {
329 int errCode = E_OK;
330 if (!isValid_) {
331 return -E_INVALID_QUERY_FORMAT;
332 }
333 sql = PRE_QUERY_ITEM_SQL + tableName_ + " WHERE hash_key=? AND (flag&0x01=0) ";
334 sql += hasPrefixKey_ ? " AND (key>=? AND key<=?) " : "";
335 sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size()));
336 if (!transformed_) {
337 errCode = ToQuerySql();
338 if (errCode != E_OK) {
339 LOGE("Transfer query to sync data check sql failed! errCode[%d]", errCode);
340 return errCode;
341 }
342 transformed_ = true;
343 }
344 sql += querySql_;
345 return errCode;
346 }
347
BindSyncDataCheckStmt(sqlite3_stmt * statement,const Key & hashKey) const348 int SqliteQueryHelper::BindSyncDataCheckStmt(sqlite3_stmt *statement, const Key &hashKey) const
349 {
350 if (statement == nullptr) {
351 return -E_INVALID_ARGS;
352 }
353 int index = 1; // bind statement start index 1
354 int errCode = SQLiteUtils::BindBlobToStatement(statement, index++, hashKey, false);
355 if (errCode != E_OK) {
356 LOGE("Get sync data check statement failed when bind hash key, errCode = %d", errCode);
357 return errCode;
358 }
359 if (hasPrefixKey_) {
360 // bind the prefix key for the first and second args.
361 errCode = SQLiteUtils::BindPrefixKey(statement, index, prefixKey_);
362 if (errCode != E_OK) {
363 LOGE("Get sync data check statement failed when bind prefix key, errCode = %d", errCode);
364 return errCode;
365 }
366 index += 2; // prefixKey takes 2 position
367 }
368
369 errCode = BindKeysToStmt(keys_, statement, index);
370 if (errCode != E_OK) {
371 int ret = E_OK;
372 SQLiteUtils::ResetStatement(statement, true, ret);
373 return errCode;
374 }
375
376 for (const QueryObjNode &objNode : queryObjNodes_) {
377 errCode = BindFieldValue(statement, objNode, index);
378 if (errCode != E_OK) {
379 LOGE("Get sync data check statement failed when bind field value, errCode = %d", errCode);
380 return errCode;
381 }
382 }
383 return errCode;
384 }
385
GetCountQuerySql(std::string & sql)386 int SqliteQueryHelper::GetCountQuerySql(std::string &sql)
387 {
388 if (!isValid_) {
389 return -E_INVALID_QUERY_FORMAT;
390 }
391
392 int errCode = ToGetCountSql();
393 if (errCode != E_OK) {
394 return errCode;
395 }
396 sql = AssembleSqlForSuggestIndex(PRE_GET_COUNT_SQL, FILTER_NATIVE_DATA_SQL);
397 sql = !hasPrefixKey_ ? sql : (sql + " AND (key>=? AND key<=?) ");
398 sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size()));
399 sql += " AND (flag&0x200=0) ";
400 sql += countSql_;
401 return E_OK;
402 }
403
GetQuerySqlStatement(sqlite3 * dbHandle,const std::string & sql,sqlite3_stmt * & statement)404 int SqliteQueryHelper::GetQuerySqlStatement(sqlite3 *dbHandle, const std::string &sql, sqlite3_stmt *&statement)
405 {
406 int errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
407 if (errCode != E_OK) {
408 LOGE("[Query] Get statement fail!");
409 return -E_INVALID_QUERY_FORMAT;
410 }
411 int index = 1;
412 int ret = E_OK;
413 if (hasPrefixKey_) {
414 // bind the prefix key for the first and second args.
415 errCode = SQLiteUtils::BindPrefixKey(statement, 1, prefixKey_);
416 if (errCode != E_OK) {
417 SQLiteUtils::ResetStatement(statement, true, ret);
418 LOGE("[Query] Get statement when bind prefix key, errCode = %d", errCode);
419 return errCode;
420 }
421 index = 3; // begin from 3rd args
422 }
423
424 errCode = BindKeysToStmt(keys_, statement, index);
425 if (errCode != E_OK) {
426 SQLiteUtils::ResetStatement(statement, true, ret);
427 return errCode;
428 }
429
430 for (const QueryObjNode &objNode : queryObjNodes_) {
431 errCode = BindFieldValue(statement, objNode, index);
432 if (errCode != E_OK) {
433 SQLiteUtils::ResetStatement(statement, true, ret);
434 LOGE("[Query] Get statement fail when bind field value, errCode = %d", errCode);
435 return errCode;
436 }
437 }
438 return errCode;
439 }
440
GetQuerySqlStatement(sqlite3 * dbHandle,bool onlyRowid,sqlite3_stmt * & statement)441 int SqliteQueryHelper::GetQuerySqlStatement(sqlite3 *dbHandle, bool onlyRowid, sqlite3_stmt *&statement)
442 {
443 std::string sql;
444 int errCode = GetQuerySql(sql, onlyRowid);
445 if (errCode != E_OK) {
446 return errCode;
447 }
448
449 errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
450 if (errCode != E_OK) {
451 LOGE("[Query] Get statement fail!");
452 return -E_INVALID_QUERY_FORMAT;
453 }
454 int index = 1;
455 if (hasPrefixKey_) {
456 // bind the prefix key for the first and second args.
457 errCode = SQLiteUtils::BindPrefixKey(statement, 1, prefixKey_);
458 if (errCode != E_OK) {
459 LOGE("[Query] Get statement when bind prefix key, errCode = %d", errCode);
460 return errCode;
461 }
462 index = 3; // begin from 3rd args
463 }
464
465 errCode = BindKeysToStmt(keys_, statement, index);
466 if (errCode != E_OK) {
467 return errCode;
468 }
469
470 for (const QueryObjNode &objNode : queryObjNodes_) {
471 errCode = BindFieldValue(statement, objNode, index);
472 if (errCode != E_OK) {
473 LOGE("[Query] Get statement fail when bind field value, errCode = %d", errCode);
474 return errCode;
475 }
476 }
477 return errCode;
478 }
479
GetCountSqlStatement(sqlite3 * dbHandle,sqlite3_stmt * & countStmt)480 int SqliteQueryHelper::GetCountSqlStatement(sqlite3 *dbHandle, sqlite3_stmt *&countStmt)
481 {
482 std::string countSql;
483 int errCode = GetCountQuerySql(countSql);
484 if (errCode != E_OK) {
485 return errCode;
486 }
487
488 // bind statement for count
489 errCode = SQLiteUtils::GetStatement(dbHandle, countSql, countStmt);
490 if (errCode != E_OK) {
491 LOGE("Get count statement error:%d", errCode);
492 return -E_INVALID_QUERY_FORMAT;
493 }
494 int index = 1;
495 if (hasPrefixKey_) {
496 // bind the prefix key for the first and second args.
497 errCode = SQLiteUtils::BindPrefixKey(countStmt, 1, prefixKey_);
498 if (errCode != E_OK) {
499 LOGE("[Query] Get count statement fail when bind prefix key, errCode = %d", errCode);
500 return errCode;
501 }
502 index = 3; // begin from 3rd args
503 }
504
505 errCode = BindKeysToStmt(keys_, countStmt, index);
506 if (errCode != E_OK) {
507 return errCode;
508 }
509
510 for (const QueryObjNode &objNode : queryObjNodes_) {
511 if (GetSymbolType(objNode.operFlag) == SymbolType::SPECIAL_SYMBOL) {
512 continue;
513 }
514 errCode = BindFieldValue(countStmt, objNode, index);
515 if (errCode != E_OK) {
516 LOGE("[Query] Get count statement fail when bind field value, errCode = %d", errCode);
517 return errCode;
518 }
519 }
520 return errCode;
521 }
522
GetSyncDataQuerySql(std::string & sql,bool hasSubQuery,bool isCount)523 int SqliteQueryHelper::GetSyncDataQuerySql(std::string &sql, bool hasSubQuery, bool isCount)
524 {
525 if (!isValid_) {
526 return -E_INVALID_QUERY_FORMAT;
527 }
528
529 if (hasLimit_) {
530 hasSubQuery = true; // Need sub query.
531 } else {
532 isNeedOrderbyKey_ = false; // Need order by timestamp.
533 }
534
535 sql = AssembleSqlForSuggestIndex(((isCount && !hasSubQuery) ?
536 PRE_QUERY_COUNT_ITEM_SQL : PRE_QUERY_ITEM_SQL) + tableName_ + " ", FILTER_REMOTE_QUERY);
537 sql = !hasPrefixKey_ ? sql : (sql + " AND (key>=? AND key<=?) ");
538 sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size()));
539 sql = hasSubQuery ? sql : (sql + " AND (timestamp>=? AND timestamp<?) ");
540 sql += " AND (flag&0x200=0) ";
541
542 querySql_.clear(); // clear local query sql format
543 int errCode = ToQuerySyncSql(hasSubQuery);
544 if (errCode != E_OK) {
545 LOGE("To query sql fail! errCode[%d]", errCode);
546 return errCode;
547 }
548 sql += querySql_;
549 if (hasSubQuery) {
550 // The last timestamp in one query will be stored in continue token and used for next query.
551 // Therefore all query data must be ordered by timestamp.
552 // When there is limit in SQL, data should be ordered by key in sub query, and timestamp is ordered by outside.
553 std::string sqlHead = isCount ? PRE_QUERY_COUNT_ITEM_SQL : PRE_QUERY_ITEM_SQL;
554 sql = sqlHead + "( " + sql + " ) WHERE (timestamp >= ? AND timestamp < ?) ORDER BY timestamp;";
555 }
556 return errCode;
557 }
558
BindTimeRange(sqlite3_stmt * & statement,int & index,uint64_t beginTime,uint64_t endTime) const559 int SqliteQueryHelper::BindTimeRange(sqlite3_stmt *&statement, int &index, uint64_t beginTime, uint64_t endTime) const
560 {
561 int ret = E_OK;
562 int errCode = SQLiteUtils::BindInt64ToStatement(statement, index++, beginTime);
563 if (errCode != E_OK) {
564 SQLiteUtils::ResetStatement(statement, true, ret);
565 return errCode;
566 }
567
568 errCode = SQLiteUtils::BindInt64ToStatement(statement, index++, endTime);
569 if (errCode != E_OK) {
570 SQLiteUtils::ResetStatement(statement, true, ret);
571 }
572 return errCode;
573 }
574
BindObjNodes(sqlite3_stmt * & statement,int & index) const575 int SqliteQueryHelper::BindObjNodes(sqlite3_stmt *&statement, int &index) const
576 {
577 int errCode = E_OK;
578 int ret = E_OK;
579 for (const QueryObjNode &objNode : queryObjNodes_) {
580 errCode = BindFieldValue(statement, objNode, index);
581 if (errCode != E_OK) {
582 SQLiteUtils::ResetStatement(statement, true, ret);
583 LOGE("[Query] Get statement fail when bind field value, errCode = %d", errCode);
584 break;
585 }
586 }
587 return errCode;
588 }
589
GetQuerySyncStatement(sqlite3 * dbHandle,uint64_t beginTime,uint64_t endTime,sqlite3_stmt * & statement,bool isCount)590 int SqliteQueryHelper::GetQuerySyncStatement(sqlite3 *dbHandle, uint64_t beginTime, uint64_t endTime,
591 sqlite3_stmt *&statement, bool isCount)
592 {
593 bool hasSubQuery = false;
594 if (hasLimit_) {
595 hasSubQuery = true; // Need sub query.
596 } else {
597 isNeedOrderbyKey_ = false; // Need order by timestamp.
598 }
599 std::string sql;
600 int errCode = GetSyncDataQuerySql(sql, hasSubQuery, isCount);
601 if (errCode != E_OK) {
602 LOGE("[Query] Get SQL fail!");
603 return -E_INVALID_QUERY_FORMAT;
604 }
605
606 errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
607 if (errCode != E_OK) {
608 LOGE("[Query] Get statement fail!");
609 return -E_INVALID_QUERY_FORMAT;
610 }
611
612 int index = 1; // begin with 1.
613 int ret = E_OK;
614 if (hasPrefixKey_) {
615 // bind the prefix key for the first and second args.
616 errCode = SQLiteUtils::BindPrefixKey(statement, index, prefixKey_);
617 if (errCode != E_OK) {
618 SQLiteUtils::ResetStatement(statement, true, ret);
619 LOGE("[Query] Get statement when bind prefix key, errCode = %d", errCode);
620 return errCode;
621 }
622 index = 3; // begin with 3 next if prefix key exists.
623 }
624
625 errCode = BindKeysToStmt(keys_, statement, index);
626 if (errCode != E_OK) {
627 SQLiteUtils::ResetStatement(statement, true, ret);
628 return errCode;
629 }
630
631 if (hasSubQuery) {
632 // For sub query SQL, timestamp must be last : (prefix key), (objNodes), timestamp.
633 // SQL: SELECT * FROM ( SELECT * FROM sync_data WHERE (flag&0x03=0x02) LIMIT 10 OFFSET 0 ) WHERE (timestamp>=?
634 // AND timestamp<?) ORDER BY timestamp;
635 errCode = BindObjNodes(statement, index);
636 if (errCode != E_OK) {
637 return errCode;
638 }
639 errCode = BindTimeRange(statement, index, beginTime, endTime);
640 } else {
641 // For normal SQL(no sub query), timestamp is just behind prefix key : (prefix key), timestamp, (ojbNodes).
642 // SQL: SELECT * FROM sync_data WHERE (timestamp>=? AND timestamp<?) AND (flag&0x03=0x02) ORDER BY timestamp;
643 errCode = BindTimeRange(statement, index, beginTime, endTime);
644 if (errCode != E_OK) {
645 return errCode;
646 }
647 errCode = BindObjNodes(statement, index);
648 }
649 return errCode;
650 }
651
MapRelationalSymbolToSql(const QueryObjNode & queryNode,bool placeholder) const652 std::string SqliteQueryHelper::MapRelationalSymbolToSql(const QueryObjNode &queryNode, bool placeholder) const
653 {
654 if (RELATIONAL_SYMBOL_TO_SQL.find(queryNode.operFlag) == RELATIONAL_SYMBOL_TO_SQL.end()) {
655 return "";
656 };
657 std::string sql = RELATIONAL_SYMBOL_TO_SQL.at(queryNode.operFlag) + MapValueToSql(queryNode, placeholder);
658 if (GetSymbolType(queryNode.operFlag) == SymbolType::RANGE_SYMBOL) {
659 sql += ")";
660 }
661 return sql;
662 }
663
MapLogicSymbolToSql(const QueryObjNode & queryNode) const664 std::string SqliteQueryHelper::MapLogicSymbolToSql(const QueryObjNode &queryNode) const
665 {
666 if (LOGIC_SYMBOL_TO_SQL.find(queryNode.operFlag) == LOGIC_SYMBOL_TO_SQL.end()) {
667 return "";
668 }
669 return LOGIC_SYMBOL_TO_SQL.at(queryNode.operFlag);
670 }
671
MapKeywordSymbolToSql(const QueryObjNode & queryNode)672 std::string SqliteQueryHelper::MapKeywordSymbolToSql(const QueryObjNode &queryNode)
673 {
674 std::string sql;
675 switch (queryNode.operFlag) {
676 case QueryObjType::ORDERBY:
677 if (queryNode.fieldValue.size() == SINGLE_FIELD_VALUE_SIZE) {
678 if (!isOrderByAppeared_) {
679 sql += "ORDER BY ";
680 }
681 sql += GetFieldShape(queryNode);
682 sql += queryNode.fieldValue[0].boolValue ? "ASC," : "DESC,";
683 orderByCounts_--;
684 if (orderByCounts_ == 0) {
685 sql.pop_back();
686 }
687 isOrderByAppeared_ = true;
688 }
689 return sql;
690 case QueryObjType::LIMIT:
691 if (hasPrefixKey_ && !hasOrderBy_ && isNeedOrderbyKey_) {
692 sql += "ORDER BY key ASC ";
693 }
694 sql += " LIMIT " + std::to_string(queryNode.fieldValue[0].integerValue);
695 sql += " OFFSET " + std::to_string(queryNode.fieldValue[1].integerValue);
696 return sql;
697 default:
698 return "";
699 }
700 }
701
MapValueToSql(const QueryObjNode & queryNode,bool placeholder) const702 std::string SqliteQueryHelper::MapValueToSql(const QueryObjNode &queryNode, bool placeholder) const
703 {
704 std::string resultSql;
705 for (size_t i = 0; i < queryNode.fieldValue.size(); i++) {
706 if (i != 0) {
707 resultSql += ", ";
708 }
709 resultSql += placeholder ? "? " : FieldValue2String(queryNode.fieldValue[i], queryNode.type);
710 }
711 return resultSql;
712 }
713
IsNeedCastWitEmptyValue(const QueryObjNode & queryNode)714 static bool IsNeedCastWitEmptyValue(const QueryObjNode &queryNode)
715 {
716 return (queryNode.operFlag == QueryObjType::IS_NULL || queryNode.operFlag == QueryObjType::IS_NOT_NULL ||
717 queryNode.operFlag == QueryObjType::IN || queryNode.operFlag == QueryObjType::NOT_IN);
718 }
719
MapCastFuncSql(const QueryObjNode & queryNode,const std::string & accessStr)720 std::string SqliteQueryHelper::MapCastFuncSql(const QueryObjNode &queryNode, const std::string &accessStr)
721 {
722 std::string resultSql;
723 if (queryNode.fieldValue.empty() && !IsNeedCastWitEmptyValue(queryNode)) {
724 return resultSql;
725 }
726 // fieldPath and isQueryable had been checked ok in the previous code, So here parse path and get type won't fail.
727 FieldPath fieldPath;
728 SchemaUtils::ParseAndCheckFieldPath(queryNode.fieldName, fieldPath);
729 FieldType fieldType = FieldType::LEAF_FIELD_INTEGER;
730 schema_.CheckQueryableAndGetFieldType(fieldPath, fieldType);
731 resultSql += SchemaObject::GenerateExtractSQL(schema_.GetSchemaType(), fieldPath, fieldType,
732 schema_.GetSkipSize(), accessStr);
733 isNeedOrderbyKey_ = false; // When index by value, No need order by key!
734 return resultSql;
735 }
736
BindFieldValue(sqlite3_stmt * statement,const QueryObjNode & queryNode,int & index) const737 int SqliteQueryHelper::BindFieldValue(sqlite3_stmt *statement, const QueryObjNode &queryNode, int &index) const
738 {
739 SymbolType symbolType = GetSymbolType(queryNode.operFlag);
740 if (symbolType != SymbolType::COMPARE_SYMBOL && symbolType != SymbolType::RELATIONAL_SYMBOL &&
741 symbolType != SymbolType::RANGE_SYMBOL) {
742 return E_OK;
743 }
744
745 int errCode = SQLITE_OK;
746 for (size_t i = 0; i < queryNode.fieldValue.size(); i++) {
747 if (queryNode.type == QueryValueType::VALUE_TYPE_BOOL) {
748 errCode = sqlite3_bind_int(statement, index, queryNode.fieldValue[i].boolValue);
749 } else if (queryNode.type == QueryValueType::VALUE_TYPE_INTEGER) {
750 errCode = sqlite3_bind_int(statement, index, queryNode.fieldValue[i].integerValue);
751 } else if (queryNode.type == QueryValueType::VALUE_TYPE_LONG) {
752 errCode = sqlite3_bind_int64(statement, index, queryNode.fieldValue[i].longValue);
753 } else if (queryNode.type == QueryValueType::VALUE_TYPE_DOUBLE) {
754 errCode = sqlite3_bind_double(statement, index, queryNode.fieldValue[i].doubleValue);
755 } else {
756 if (queryNode.fieldValue[i].stringValue.size() > MAX_SQLITE_BIND_SIZE) {
757 return -E_MAX_LIMITS;
758 }
759 errCode = sqlite3_bind_text(statement, index, queryNode.fieldValue[i].stringValue.c_str(),
760 queryNode.fieldValue[i].stringValue.size(), SQLITE_TRANSIENT);
761 }
762 if (errCode != SQLITE_OK) {
763 break;
764 }
765 index++;
766 }
767 return SQLiteUtils::MapSQLiteErrno(errCode);
768 }
769
GetFieldShape(const QueryObjNode & queryNode,const std::string & accessStr)770 std::string SqliteQueryHelper::GetFieldShape(const QueryObjNode &queryNode, const std::string &accessStr)
771 {
772 if (isRelationalQuery_) {
773 // For relational query, $. prefix is not permitted, so need not extract json. Return directly will be OK.
774 return "a.'" + queryNode.fieldName + "' ";
775 }
776 return MapCastFuncSql(queryNode, accessStr);
777 }
778
ParseQueryExpression(const QueryObjNode & queryNode,std::string & querySql,const std::string & accessStr,bool placeholder)779 int SqliteQueryHelper::ParseQueryExpression(const QueryObjNode &queryNode, std::string &querySql,
780 const std::string &accessStr, bool placeholder)
781 {
782 SymbolType symbolType = GetSymbolType(queryNode.operFlag);
783 if (symbolType == SymbolType::RANGE_SYMBOL && queryNode.fieldValue.size() > MAX_CONDITIONS_SIZE) {
784 LOGE("[Query][Parse][Expression] conditions is too many!");
785 return -E_MAX_LIMITS;
786 }
787
788 if (symbolType == SymbolType::COMPARE_SYMBOL || symbolType == SymbolType::RELATIONAL_SYMBOL ||
789 symbolType == SymbolType::RANGE_SYMBOL) {
790 querySql += GetFieldShape(queryNode, accessStr);
791 querySql += MapRelationalSymbolToSql(queryNode, placeholder);
792 } else if (symbolType == SymbolType::LOGIC_SYMBOL || symbolType == SymbolType::LINK_SYMBOL) {
793 querySql += MapLogicSymbolToSql(queryNode);
794 } else {
795 querySql += MapKeywordSymbolToSql(queryNode);
796 }
797
798 if (querySql.size() > MAX_SQL_LEN) {
799 LOGE("[Query][Parse][Expression] Sql is too long!");
800 return -E_MAX_LIMITS;
801 }
802 return E_OK;
803 }
804
AssembleSqlForSuggestIndex(const std::string & baseSql,const std::string & filter) const805 std::string SqliteQueryHelper::AssembleSqlForSuggestIndex(const std::string &baseSql, const std::string &filter) const
806 {
807 std::string formatIndex = CheckAndFormatSuggestIndex();
808 if (formatIndex.empty()) {
809 return baseSql + filter;
810 }
811
812 return baseSql + USING_INDEX + "'" + formatIndex + "' " + filter;
813 }
814
CheckAndFormatSuggestIndex() const815 std::string SqliteQueryHelper::CheckAndFormatSuggestIndex() const
816 {
817 if (suggestIndex_.empty()) {
818 return "";
819 }
820 IndexName indexName;
821 int errCode = SchemaUtils::ParseAndCheckFieldPath(suggestIndex_, indexName);
822 if (errCode != E_OK) {
823 LOGW("Check and format suggest index failed! %d", errCode);
824 return "";
825 }
826
827 if (!schema_.IsIndexExist(indexName)) {
828 LOGW("The suggest index not exist!");
829 return "";
830 }
831 return SchemaUtils::FieldPathString(indexName);
832 }
833
MapKeysInSubCondition(const std::string & accessStr) const834 std::string SqliteQueryHelper::MapKeysInSubCondition(const std::string &accessStr) const
835 {
836 std::string resultStr = "hex(" + accessStr + "key) IN (";
837 for (auto iter = keys_.begin(); iter != keys_.end(); iter++) {
838 if (iter != keys_.begin()) {
839 resultStr += ", ";
840 }
841 resultStr += "'" + DBCommon::VectorToHexString(*iter) + "' ";
842 }
843 resultStr += ")";
844 return resultStr;
845 }
846
GetSubscribeCondition(const std::string & accessStr,std::string & conditionStr)847 int SqliteQueryHelper::GetSubscribeCondition(const std::string &accessStr, std::string &conditionStr)
848 {
849 if (queryObjNodes_.empty()) {
850 conditionStr += " (1 = 1) ";
851 return E_OK;
852 }
853
854 bool hasQueryByValue = std::any_of(queryObjNodes_.begin(), queryObjNodes_.end(), [](const QueryObjNode &it) {
855 return GetSymbolType(it.operFlag) == SymbolType::COMPARE_SYMBOL ||
856 GetSymbolType(it.operFlag) == SymbolType::RELATIONAL_SYMBOL ||
857 GetSymbolType(it.operFlag) == SymbolType::RANGE_SYMBOL;
858 });
859 if (hasQueryByValue) {
860 // json_extract_by_path function will return error when value is empty, check it before when query by value
861 conditionStr += "((length(" + accessStr + "value) != 0 AND " + accessStr + "value IS NOT NULL) AND ";
862 } else {
863 conditionStr += "(";
864 }
865
866 if (hasPrefixKey_) {
867 conditionStr += "(hex(" + accessStr + "key) LIKE '" + DBCommon::VectorToHexString(prefixKey_) + "%')";
868 }
869
870 if (!keys_.empty()) {
871 if (hasPrefixKey_) {
872 conditionStr += " AND ";
873 }
874 conditionStr += "(" + MapKeysInSubCondition(accessStr) + ")";
875 }
876
877 bool isNeedEndBracket = FilterSymbolToAddBracketLink(conditionStr, hasPrefixKey_ || !keys_.empty());
878 int errCode = E_OK;
879 for (const QueryObjNode &objNode : queryObjNodes_) {
880 SymbolType symbolType = GetSymbolType(objNode.operFlag);
881 if (symbolType == SymbolType::SPECIAL_SYMBOL && isNeedEndBracket) {
882 conditionStr += ") ";
883 isNeedEndBracket = false;
884 }
885 errCode = ParseQueryExpression(objNode, conditionStr, accessStr, false);
886 if (errCode != E_OK) {
887 conditionStr.clear();
888 return errCode;
889 }
890 }
891
892 if (isNeedEndBracket) {
893 conditionStr += ") ";
894 }
895 conditionStr += ")";
896 return errCode;
897 }
898
GetSubscribeSql(TriggerModeEnum mode,std::string & subscribeCondition)899 int SqliteQueryHelper::GetSubscribeSql(TriggerModeEnum mode, std::string &subscribeCondition)
900 {
901 if (!isValid_) {
902 return -E_INVALID_QUERY_FORMAT;
903 }
904 int errCode = E_OK;
905 switch (mode) {
906 case TriggerModeEnum::INSERT:
907 errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_NEW, subscribeCondition);
908 break;
909 case TriggerModeEnum::UPDATE:
910 errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_OLD, subscribeCondition);
911 if (errCode != E_OK) {
912 break;
913 }
914 subscribeCondition += " OR ";
915 errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_NEW, subscribeCondition);
916 break;
917 case TriggerModeEnum::DELETE:
918 errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_OLD, subscribeCondition);
919 break;
920 default:
921 errCode = -INVALID_ARGS;
922 }
923 if (errCode != E_OK) {
924 LOGD("Get subscribe query condition failed. %d", errCode);
925 }
926 return errCode;
927 }
928
GetRelationalMissQuerySql(const std::vector<std::string> & fieldNames,std::string & sql)929 int SqliteQueryHelper::GetRelationalMissQuerySql(const std::vector<std::string> &fieldNames, std::string &sql)
930 {
931 if (!isValid_) {
932 return -E_INVALID_QUERY_FORMAT;
933 }
934
935 if (hasPrefixKey_) {
936 LOGE("For relational DB query, prefix key is not supported.");
937 return -E_NOT_SUPPORT;
938 }
939
940 sql = GetSelectAndFromClauseForRDB(tableName_, fieldNames);
941 sql += GetMissQueryFlagClauseForRDB();
942 sql += GetTimeRangeClauseForRDB();
943 sql += "ORDER BY ";
944 sql.append(DBConstant::TIMESTAMP_ALIAS);
945 sql += " ASC;";
946 return E_OK;
947 }
948
GetRelationalSyncDataQuerySql(std::string & sql,bool hasSubQuery,const std::vector<std::string> & fieldNames)949 int SqliteQueryHelper::GetRelationalSyncDataQuerySql(std::string &sql, bool hasSubQuery,
950 const std::vector<std::string> &fieldNames)
951 {
952 if (!isValid_) {
953 return -E_INVALID_QUERY_FORMAT;
954 }
955
956 if (hasPrefixKey_) {
957 LOGE("For relational DB query, prefix key is not supported.");
958 return -E_NOT_SUPPORT;
959 }
960
961 sql = AssembleSqlForSuggestIndex(GetSelectAndFromClauseForRDB(tableName_, fieldNames), GetFlagClauseForRDB());
962 sql = hasSubQuery ? sql : (sql + GetTimeRangeClauseForRDB());
963
964 querySql_.clear(); // clear local query sql format
965 int errCode = ToQuerySyncSql(hasSubQuery, true);
966 if (errCode != E_OK) {
967 LOGE("To query sql fail! errCode[%d]", errCode);
968 return errCode;
969 }
970 sql += querySql_;
971 if (hasSubQuery) {
972 // The last timestamp in one query will be stored in continue token and used for next query.
973 // Therefore all query data must be ordered by timestamp.
974 // When there is limit in SQL, data should be ordered by key in sub query, and timestamp is ordered by outside.
975 sql = GetOuterQueryClauseForRDB(sql);
976 }
977 return errCode;
978 }
979
GetRelationalMissQueryStatement(sqlite3 * dbHandle,uint64_t beginTime,uint64_t endTime,const std::vector<std::string> & fieldNames,sqlite3_stmt * & statement)980 int SqliteQueryHelper::GetRelationalMissQueryStatement(sqlite3 *dbHandle, uint64_t beginTime, uint64_t endTime,
981 const std::vector<std::string> &fieldNames, sqlite3_stmt *&statement)
982 {
983 std::string sql;
984 int errCode = GetRelationalMissQuerySql(fieldNames, sql);
985 if (errCode != E_OK) {
986 LOGE("[Query] Get SQL fail!");
987 return -E_INVALID_QUERY_FORMAT;
988 }
989
990 errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
991 if (errCode != E_OK) {
992 LOGE("[Query] Get statement fail!");
993 return -E_INVALID_QUERY_FORMAT;
994 }
995
996 int index = 1; // begin with 1.
997 return BindTimeRange(statement, index, beginTime, endTime);
998 }
999
1000 namespace {
GetRelationalSyncDataQueryHeader(const std::vector<std::string> & fieldNames)1001 std::string GetRelationalSyncDataQueryHeader(const std::vector<std::string> &fieldNames)
1002 {
1003 std::string sql = "SELECT b.data_key,"
1004 "b.device,"
1005 "b.ori_device,"
1006 "b.timestamp as ";
1007 sql.append(DBConstant::TIMESTAMP_ALIAS);
1008 sql += ","
1009 "b.wtimestamp,"
1010 "b.flag,"
1011 "b.hash_key,";
1012 if (fieldNames.empty()) { // For query check. If column count changed, can be discovered.
1013 sql += "a.*";
1014 } else {
1015 for (const auto &fieldName : fieldNames) { // For query data.
1016 sql += "a." + fieldName + ",";
1017 }
1018 sql.pop_back();
1019 }
1020 return sql;
1021 }
1022
GetRelationalCloudSyncDataQueryHeader(const std::vector<Field> & fields)1023 std::string GetRelationalCloudSyncDataQueryHeader(const std::vector<Field> &fields)
1024 {
1025 std::string sql = "SELECT b.data_key,"
1026 "b.device,"
1027 "b.ori_device,"
1028 "b.timestamp as ";
1029 sql.append(DBConstant::TIMESTAMP_ALIAS);
1030 sql += ","
1031 "b.wtimestamp,"
1032 "b.flag,"
1033 "b.hash_key,"
1034 "b.cloud_gid,"
1035 "b.version,"
1036 "b.status,";
1037 if (fields.empty()) { // For query check. If column count changed, can be discovered.
1038 sql += "a.*";
1039 } else {
1040 for (const auto &field : fields) { // For query data.
1041 sql += "a." + field.colName + ",";
1042 }
1043 sql.pop_back();
1044 }
1045 return sql;
1046 }
1047 }
1048
GetRelationalSyncDataQuerySqlWithLimit(const std::vector<std::string> & fieldNames,std::string & sql)1049 int SqliteQueryHelper::GetRelationalSyncDataQuerySqlWithLimit(const std::vector<std::string> &fieldNames,
1050 std::string &sql)
1051 {
1052 if (!isValid_) {
1053 return -E_INVALID_QUERY_FORMAT;
1054 }
1055
1056 if (hasPrefixKey_) {
1057 LOGE("For relational DB query, prefix key is not supported.");
1058 return -E_NOT_SUPPORT;
1059 }
1060 sql = GetRelationalSyncDataQueryHeader(fieldNames);
1061 sql += " FROM '" + tableName_ + "' AS a INNER JOIN ";
1062 sql += DBConstant::RELATIONAL_PREFIX + tableName_ + "_log";
1063 sql += " AS b ON (a.";
1064 sql.append(DBConstant::SQLITE_INNER_ROWID);
1065 sql += " = b.data_key)";
1066 sql += " WHERE (b.flag&0x03=0x02)";
1067
1068 querySql_.clear(); // clear local query sql format
1069 int errCode = ToQuerySyncSql(true, true);
1070 if (errCode != E_OK) {
1071 LOGE("To query sql fail! errCode[%d]", errCode);
1072 return errCode;
1073 }
1074 sql += querySql_;
1075 return E_OK;
1076 }
1077
GetRelationalQueryStatement(sqlite3 * dbHandle,uint64_t beginTime,uint64_t endTime,const std::vector<std::string> & fieldNames,sqlite3_stmt * & statement)1078 int SqliteQueryHelper::GetRelationalQueryStatement(sqlite3 *dbHandle, uint64_t beginTime, uint64_t endTime,
1079 const std::vector<std::string> &fieldNames, sqlite3_stmt *&statement)
1080 {
1081 int errCode = E_OK;
1082 bool hasSubQuery = false;
1083 std::string sql;
1084 if (hasLimit_ && !hasOrderBy_) { // Query with limit and no order by
1085 hasSubQuery = true; // Need sub query.
1086 errCode = GetRelationalSyncDataQuerySqlWithLimit(fieldNames, sql);
1087 } else if (hasLimit_ || hasOrderBy_) {
1088 hasSubQuery = true; // Need sub query.
1089 errCode = GetRelationalSyncDataQuerySql(sql, hasSubQuery, fieldNames);
1090 } else {
1091 isNeedOrderbyKey_ = false; // Need order by timestamp.
1092 errCode = GetRelationalSyncDataQuerySql(sql, hasSubQuery, fieldNames);
1093 }
1094 if (errCode != E_OK) {
1095 LOGE("[Query] Get SQL fail!");
1096 return -E_INVALID_QUERY_FORMAT;
1097 }
1098
1099 errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
1100 if (errCode != E_OK) {
1101 LOGE("[Query] Get statement fail!");
1102 return -E_INVALID_QUERY_FORMAT;
1103 }
1104
1105 int index = 1; // begin with 1.
1106 if (hasSubQuery) {
1107 /**
1108 * SELECT b.data_key,b.device,b.ori_device,b.timestamp as naturalbase_rdb_timestamp,
1109 * b.wtimestamp,b.flag,b.hash_key,a.*
1110 * FROM tableName AS a INNER JOIN naturalbase_rdb_log AS b
1111 * ON a.rowid=b.data_key
1112 * WHERE (b.flag&0x03=0x02)
1113 * ORDER BY a.xxx
1114 * LIMIT ? OFFSET ? )
1115 */
1116 errCode = BindObjNodes(statement, index);
1117 if (errCode != E_OK) {
1118 return errCode;
1119 }
1120 if (!hasLimit_ || hasOrderBy_) {
1121 errCode = BindTimeRange(statement, index, beginTime, endTime);
1122 }
1123 } else {
1124 /**
1125 * SELECT b.data_key,b.device,b.ori_device,b.timestamp as naturalbase_rdb_timestamp,
1126 * b.wtimestamp,b.flag,b.hash_key,a.*
1127 * FROM tableName AS a INNER JOIN naturalbase_rdb_log AS b
1128 * ON a.rowid=b.data_key
1129 * WHERE (b.flag&0x03=0x02) AND (naturalbase_rdb_timestamp>=? AND naturalbase_rdb_timestamp<?)
1130 * ORDER BY naturalbase_rdb_timestamp ASC;
1131 */
1132 errCode = BindTimeRange(statement, index, beginTime, endTime);
1133 if (errCode != E_OK) {
1134 return errCode;
1135 }
1136 errCode = BindObjNodes(statement, index);
1137 }
1138 return errCode;
1139 }
1140
MapKeysInToSql(size_t keysNum) const1141 std::string SqliteQueryHelper::MapKeysInToSql(size_t keysNum) const
1142 {
1143 std::string resultSql = "key IN (";
1144 for (size_t i = 0; i < keysNum; i++) {
1145 if (i != 0) {
1146 resultSql += ", ";
1147 }
1148 resultSql += "? ";
1149 }
1150 resultSql += ") ";
1151 return resultSql;
1152 }
1153
BindKeysToStmt(const std::set<Key> & keys,sqlite3_stmt * & statement,int & index) const1154 int SqliteQueryHelper::BindKeysToStmt(const std::set<Key> &keys, sqlite3_stmt *&statement, int &index) const
1155 {
1156 if (!keys_.empty()) {
1157 int errCode = E_OK;
1158 for (const auto &key : keys) {
1159 errCode = SQLiteUtils::BindBlobToStatement(statement, index, key);
1160 if (errCode != E_OK) {
1161 LOGE("[Query] Get statement when bind keys failed, errCode = %d", errCode);
1162 return errCode;
1163 }
1164 index++;
1165 }
1166 }
1167 return E_OK;
1168 }
1169
GetRelationalCloudQuerySql(const std::vector<Field> & fields,const bool & isCloudForcePush,bool isCompensatedTask,CloudWaterType mode)1170 std::string SqliteQueryHelper::GetRelationalCloudQuerySql(const std::vector<Field> &fields,
1171 const bool &isCloudForcePush, bool isCompensatedTask, CloudWaterType mode)
1172 {
1173 std::string sql = GetRelationalCloudSyncDataQueryHeader(fields);
1174 AppendCloudQuery(isCloudForcePush, isCompensatedTask, sql, mode);
1175 AppendCloudQueryToGetDiffData(sql, mode);
1176 return sql;
1177 }
1178
GetCountRelationalCloudQuerySql(bool isCloudForcePush,bool isCompensatedTask,CloudWaterType mode)1179 std::string SqliteQueryHelper::GetCountRelationalCloudQuerySql(bool isCloudForcePush, bool isCompensatedTask,
1180 CloudWaterType mode)
1181 {
1182 std::string sql = "SELECT COUNT(*) ";
1183 AppendCloudQuery(isCloudForcePush, isCompensatedTask, sql, mode);
1184 return sql;
1185 }
1186
GetGidRelationalCloudQuerySql(const std::vector<Field> & fields,bool isCloudForcePush,bool isCompensatedTask)1187 std::string SqliteQueryHelper::GetGidRelationalCloudQuerySql(const std::vector<Field> &fields,
1188 bool isCloudForcePush, bool isCompensatedTask)
1189 {
1190 std::string sql = GetRelationalCloudSyncDataQueryHeader(fields);
1191 AppendCloudGidQuery(isCloudForcePush, isCompensatedTask, sql);
1192 return sql;
1193 }
1194
AppendCloudQuery(bool isCloudForcePush,bool isCompensatedTask,std::string & sql,CloudWaterType mode)1195 void SqliteQueryHelper::AppendCloudQuery(bool isCloudForcePush, bool isCompensatedTask, std::string &sql,
1196 CloudWaterType mode)
1197 {
1198 sql += CloudStorageUtils::GetLeftJoinLogSql(tableName_, false);
1199 sql += " WHERE ";
1200 // let data after remove device data at flag_only and logic delete mode and deleted by others to upload to cloud.
1201 if (mode == CloudWaterType::INSERT) {
1202 sql += "(b.cloud_gid == '' and (b.flag & 0x20 != 0) and (b.flag & 0x02 = 0) and (b.flag & 0x08 != 0x08) and";
1203 sql += " (b.flag & 0x01 = 0) and (b.status = 0)) OR ";
1204 }
1205 if (mode == CloudWaterType::DELETE && isCompensatedTask) {
1206 // deleted data does not have primary key, requires gid to compensate sync
1207 sql += "(b.status = 1 AND (b.flag & 0x01 = 0x01) AND b.cloud_gid != '') OR ";
1208 }
1209 if (mode == CloudWaterType::DELETE || mode == CloudWaterType::UPDATE) {
1210 if (queryObjNodes_.empty() && isCompensatedTask) {
1211 sql += "0 ";
1212 return;
1213 }
1214 if (!isCompensatedTask) {
1215 sql += "(b.status != 1) AND ";
1216 }
1217 }
1218 if (isCloudForcePush) {
1219 sql += " (b.flag & 0x04 != 0x04)";
1220 } else {
1221 sql += "(b.flag & 0x02 = 0x02)";
1222 if (!isCompensatedTask) {
1223 // local data and flag is not upload finished.
1224 sql += " AND (b.flag & 0x400 != 0x400)";
1225 }
1226 }
1227 sql += " AND (b.flag & 0x08 != 0x08) AND (b.cloud_gid != '' or"; // actually, b.cloud_gid will not be null.
1228 sql += " (b.cloud_gid == '' and (b.flag & 0x01 = 0))) ";
1229 }
1230
AppendCloudQueryToGetDiffData(std::string & sql,const CloudWaterType mode,bool isKv)1231 void SqliteQueryHelper::AppendCloudQueryToGetDiffData(std::string &sql, const CloudWaterType mode, bool isKv)
1232 {
1233 switch (mode) {
1234 case DistributedDB::CloudWaterType::DELETE:
1235 sql += isKv ? " AND (flag & 0x01 == 0x01) " :
1236 " AND (b.flag & 0x01 == 0x01) ";
1237 break;
1238 case DistributedDB::CloudWaterType::UPDATE:
1239 sql += isKv ? " AND (flag & 0x01 == 0 AND cloud_gid != '' AND cloud_gid IS NOT NULL) " :
1240 " AND (b.flag & 0x01 == 0 AND b.cloud_gid != '') ";
1241 break;
1242 case DistributedDB::CloudWaterType::INSERT:
1243 sql += isKv ? " AND (flag & 0x01 == 0 AND (cloud_gid == '' OR cloud_gid IS NULL)) " :
1244 " AND (b.flag & 0x01 == 0 AND b.cloud_gid == '') ";
1245 break;
1246 default:
1247 break;
1248 }
1249 }
1250
AppendCloudGidQuery(bool isCloudForcePush,bool isCompensatedTask,std::string & sql)1251 void SqliteQueryHelper::AppendCloudGidQuery(bool isCloudForcePush, bool isCompensatedTask, std::string &sql)
1252 {
1253 sql += CloudStorageUtils::GetLeftJoinLogSql(tableName_, false);
1254 sql += " WHERE ";
1255 if (isCompensatedTask) {
1256 // deleted data does not have primary key, requires gid to compensate sync
1257 sql += "(b.status = 1 AND (b.flag & 0x01 = 0x01)) ";
1258 if (queryObjNodes_.empty()) {
1259 return;
1260 }
1261 sql += "OR ";
1262 }
1263 // actually, b.cloud_gid will not be null.
1264 sql += isCloudForcePush ? " (b.flag & 0x04 != 0x04) AND (b.cloud_gid != '') " : " (b.cloud_gid != '') ";
1265 }
1266
GetCloudQueryStatement(bool useTimestampAlias,sqlite3 * dbHandle,std::string & sql,sqlite3_stmt * & statement)1267 int SqliteQueryHelper::GetCloudQueryStatement(bool useTimestampAlias, sqlite3 *dbHandle, std::string &sql,
1268 sqlite3_stmt *&statement)
1269 {
1270 querySql_.clear(); // clear local query sql format
1271 int errCode = ToQuerySyncSql(false, useTimestampAlias);
1272 if (errCode != E_OK) {
1273 LOGE("To query sql fail! errCode[%d]", errCode);
1274 return errCode;
1275 }
1276 sql += querySql_;
1277 errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
1278 if (errCode != E_OK) {
1279 LOGE("[Query] Get statement fail!");
1280 return -E_INVALID_QUERY_FORMAT;
1281 }
1282 int index = 1;
1283 errCode = BindObjNodes(statement, index);
1284 if (errCode != E_OK) {
1285 LOGE("[Query] BindObjNodes failed %d", errCode);
1286 int resetRet = E_OK;
1287 SQLiteUtils::ResetStatement(statement, true, resetRet);
1288 if (resetRet != E_OK) {
1289 LOGW("[Query] reset statement failed %d", resetRet);
1290 }
1291 }
1292 return errCode;
1293 }
1294
GetKvCloudQueryStmt(sqlite3 * db,bool forcePush,const CloudWaterType mode,int64_t timeStamp,const std::string & user)1295 std::pair<int, sqlite3_stmt *> SqliteQueryHelper::GetKvCloudQueryStmt(sqlite3 *db, bool forcePush,
1296 const CloudWaterType mode, int64_t timeStamp, const std::string &user)
1297 {
1298 std::pair<int, sqlite3_stmt *> res;
1299 sqlite3_stmt *&stmt = res.second;
1300 int &errCode = res.first;
1301 std::string sql = GetKvCloudQuerySql(false, forcePush);
1302 AppendCloudQueryToGetDiffData(sql, mode, true);
1303 AppendKvQueryObjectOnSql(sql);
1304 sql += "order by modify_time asc";
1305 errCode = SQLiteUtils::GetStatement(db, sql, stmt);
1306 if (errCode != E_OK) {
1307 LOGE("[SqliteQueryHelper] Get kv cloud query stmt failed %d", errCode);
1308 return res;
1309 }
1310 int ret = E_OK;
1311 errCode = SQLiteUtils::BindTextToStatement(stmt, BIND_CLOUD_USER, user);
1312 if (errCode != E_OK) {
1313 SQLiteUtils::ResetStatement(stmt, true, ret);
1314 LOGE("[SqliteQueryHelper] Bind user failed %d reset %d", errCode, ret);
1315 return res;
1316 }
1317 errCode = SQLiteUtils::BindInt64ToStatement(stmt, BIND_CLOUD_TIMESTAMP, timeStamp);
1318 if (errCode != E_OK) {
1319 SQLiteUtils::ResetStatement(stmt, true, ret);
1320 LOGE("[SqliteQueryHelper] Bind begin time failed %d reset %d", errCode, ret);
1321 return res;
1322 }
1323 int index = BIND_CLOUD_TIMESTAMP + 1;
1324 errCode = BindKeysToStmt(keys_, stmt, index);
1325 if (errCode != E_OK) {
1326 SQLiteUtils::ResetStatement(stmt, true, ret);
1327 LOGE("[SqliteQueryHelper] Bind user failed %d reset %d", errCode, ret);
1328 }
1329 return res;
1330 }
1331
GetKvCloudQuerySql(bool countOnly,bool forcePush)1332 std::string SqliteQueryHelper::GetKvCloudQuerySql(bool countOnly, bool forcePush)
1333 {
1334 std::string sql;
1335 if (countOnly) {
1336 sql = QUERY_COUNT_HEAD;
1337 } else {
1338 sql = QUERY_CLOUD_SYNC_DATA_HEAD;
1339 }
1340 sql += QUERY_CLOUD_SYNC_DATA_DETAIL;
1341 sql += QUERY_CLOUD_SYNC_DATA_CONDITION;
1342 sql += " AND flag & 0x02 != 0 "; // get all data which is local
1343 if (forcePush) {
1344 sql += " AND flag & 0x04 != 0x04 "; // get all data which hasn't pushed
1345 } else {
1346 sql += " AND (cloud_flag is null OR cloud_flag & " +
1347 std::to_string(static_cast<uint32_t>(LogInfoFlag::FLAG_UPLOAD_FINISHED)) + " = 0) ";
1348 }
1349 return sql;
1350 }
1351
GetKvCloudRecordSql()1352 std::string SqliteQueryHelper::GetKvCloudRecordSql()
1353 {
1354 std::string sql = QUERY_CLOUD_SYNC_DATA_HEAD;
1355 sql += QUERY_CLOUD_SYNC_DATA_DETAIL;
1356 sql += QUERY_CLOUD_VERSION_RECORD_CONDITION;
1357 return sql;
1358 }
1359
GetCloudVersionRecordSql(bool isDeviceEmpty)1360 std::string SqliteQueryHelper::GetCloudVersionRecordSql(bool isDeviceEmpty)
1361 {
1362 std::string sql = QUERY_CLOUD_VERSION_RECORD_SQL_HEAD;
1363 if (!isDeviceEmpty) {
1364 sql += QUERY_CLOUD_VERSION_RECORD_SQL_DEVICE_CONDITION;
1365 } else {
1366 sql += QUERY_CLOUD_VERSION_RECORD_SQL_EMPTY_DEVICE_CONDITION;
1367 }
1368 return sql;
1369 }
1370
GetAndBindGidKvCloudQueryStatement(const std::string & user,sqlite3 * dbHandle,sqlite3_stmt * & stmt)1371 int SqliteQueryHelper::GetAndBindGidKvCloudQueryStatement(const std::string &user, sqlite3 *dbHandle,
1372 sqlite3_stmt *&stmt)
1373 {
1374 std::string sql = SELECT_CLOUD_GID_SQL;
1375 AppendKvQueryObjectOnSql(sql);
1376 int errCode = SQLiteUtils::GetStatement(dbHandle, sql, stmt);
1377 if (errCode != E_OK) {
1378 LOGE("[SqliteQueryHelper] Get gid stmt failed %d", errCode);
1379 return errCode;
1380 }
1381 int index = 1;
1382 int ret = E_OK;
1383 errCode = SQLiteUtils::BindTextToStatement(stmt, index++, user);
1384 if (errCode != E_OK) {
1385 SQLiteUtils::ResetStatement(stmt, true, ret);
1386 LOGE("[SqliteQueryHelper] Bind user failed %d when query gid", errCode);
1387 return errCode;
1388 }
1389 errCode = BindKeysToStmt(keys_, stmt, index);
1390 if (errCode != E_OK) {
1391 LOGE("[SqliteQueryHelper] Bind keys to query gid stmt failed %d", errCode);
1392 SQLiteUtils::ResetStatement(stmt, true, ret);
1393 }
1394 return errCode;
1395 }
1396
GetCountKvCloudDataStatement(sqlite3 * db,bool forcePush,const CloudWaterType mode,sqlite3_stmt * & stmt)1397 int SqliteQueryHelper::GetCountKvCloudDataStatement(sqlite3 *db, bool forcePush, const CloudWaterType mode,
1398 sqlite3_stmt *&stmt)
1399 {
1400 std::string sql = SqliteQueryHelper::GetKvCloudQuerySql(true, forcePush);
1401 SqliteQueryHelper::AppendCloudQueryToGetDiffData(sql, mode, true);
1402 AppendKvQueryObjectOnSql(sql);
1403 int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
1404 if (errCode != E_OK) {
1405 LOGE("[SqliteQueryHelper] Count data stmt failed %d", errCode);
1406 }
1407 return errCode;
1408 }
1409
BindCountKvCloudDataStatement(sqlite3 * db,bool isMemory,const Timestamp & timestamp,const std::string & user,sqlite3_stmt * & stmt)1410 std::pair<int, int64_t> SqliteQueryHelper::BindCountKvCloudDataStatement(sqlite3 *db, bool isMemory,
1411 const Timestamp ×tamp, const std::string &user, sqlite3_stmt *&stmt)
1412 {
1413 ResFinalizer finalizer([stmt]() {
1414 sqlite3_stmt *statement = stmt;
1415 int ret = E_OK;
1416 SQLiteUtils::ResetStatement(statement, true, ret);
1417 if (ret != E_OK) {
1418 LOGW("[SqliteCloudKvExecutorUtils] Reset log stmt failed %d when get upload count", ret);
1419 }
1420 });
1421 std::pair<int, int64_t> res = { E_OK, 0 };
1422 auto &[errCode, count] = res;
1423 errCode = SQLiteUtils::BindTextToStatement(stmt, BIND_CLOUD_USER, user);
1424 if (errCode != E_OK) {
1425 LOGE("[SqliteQueryHelper] Bind user failed %d when get upload count", errCode);
1426 return res;
1427 }
1428 errCode = SQLiteUtils::BindInt64ToStatement(stmt, BIND_CLOUD_TIMESTAMP, static_cast<int64_t>(timestamp));
1429 if (errCode != E_OK) {
1430 LOGE("[SqliteQueryHelper] Bind begin time failed %d when get upload count", errCode);
1431 return res;
1432 }
1433 int keysIndex = BIND_CLOUD_TIMESTAMP + 1;
1434 errCode = BindKeysToStmt(keys_, stmt, keysIndex);
1435 if (errCode != E_OK) {
1436 LOGE("[SqliteQueryHelper] Bind keys failed %d when get upload count", errCode);
1437 return res;
1438 }
1439 errCode = SQLiteUtils::StepNext(stmt, isMemory);
1440 if (errCode == -E_FINISHED) {
1441 count = 0;
1442 return res;
1443 }
1444 count = sqlite3_column_int64(stmt, CLOUD_QUERY_COUNT_INDEX);
1445 LOGD("[SqliteCloudKvExecutorUtils] Get total upload count %" PRId64, count);
1446 return res;
1447 }
1448
AppendKvQueryObjectOnSql(std::string & sql)1449 void SqliteQueryHelper::AppendKvQueryObjectOnSql(std::string &sql)
1450 {
1451 if (!keys_.empty()) {
1452 sql += " AND " + MapKeysInToSql(keys_.size());
1453 }
1454 }
1455 }