• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &timestamp, 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 }