• 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 
19 #include "db_common.h"
20 #include "db_constant.h"
21 #include "db_errno.h"
22 #include "log_print.h"
23 #include "macro_utils.h"
24 #include "sqlite_utils.h"
25 
26 namespace DistributedDB {
27 using namespace TriggerMode;
28 namespace {
29 const std::string PRE_QUERY_KV_SQL = "SELECT key, value FROM sync_data ";
30 const std::string PRE_QUERY_ITEM_SQL = "SELECT * FROM ";
31 const std::string PRE_QUERY_ROWID_SQL = "SELECT rowid FROM sync_data ";
32 const std::string PRE_GET_COUNT_SQL = "SELECT count(*) FROM sync_data ";
33 const std::string FILTER_NATIVE_DATA_SQL = "WHERE (flag&0x01=0) ";
34 const std::string FILTER_REMOTE_QUERY = "WHERE (flag&0x03=0x02)";
35 const std::string USING_INDEX = "INDEXED BY ";
36 const int MAX_SQL_LEN = 1024 * 1024; // 1M bytes
37 const int SINGLE_FIELD_VALUE_SIZE = 1;
38 const int MAX_CONDITIONS_SIZE = 128;
39 const int MAX_SQLITE_BIND_SIZE = 50000;
40 const uint32_t SYMBOL_TYPE_MASK = 0xff00;
41 
42 const std::map<QueryObjType, std::string> RELATIONAL_SYMBOL_TO_SQL {
43     {QueryObjType::EQUALTO, "= "},
44     {QueryObjType::NOT_EQUALTO, "!= "},
45     {QueryObjType::GREATER_THAN, "> "},
46     {QueryObjType::LESS_THAN, "< "},
47     {QueryObjType::GREATER_THAN_OR_EQUALTO, ">= "},
48     {QueryObjType::LESS_THAN_OR_EQUALTO, "<= "},
49     {QueryObjType::LIKE, " LIKE "},
50     {QueryObjType::NOT_LIKE, " NOT LIKE "},
51     {QueryObjType::IS_NULL, " IS NULL "},
52     {QueryObjType::IS_NOT_NULL, " IS NOT NULL "},
53     {QueryObjType::IN, " IN ("},
54     {QueryObjType::NOT_IN, " NOT IN ("},
55 };
56 
57 const std::map<QueryObjType, std::string> LOGIC_SYMBOL_TO_SQL {
58     {QueryObjType::AND, " AND "},
59     {QueryObjType::OR, " OR "},
60     {QueryObjType::BEGIN_GROUP, "("},
61     {QueryObjType::END_GROUP, ")"},
62 };
63 
FieldValue2String(const FieldValue & val,QueryValueType type)64 std::string FieldValue2String(const FieldValue &val, QueryValueType type)
65 {
66     std::stringstream ss;
67     switch (type) {
68         case QueryValueType::VALUE_TYPE_NULL:
69             return "NULL";
70         case QueryValueType::VALUE_TYPE_BOOL:
71             return val.boolValue ? "1" : "0";
72         case QueryValueType::VALUE_TYPE_INTEGER:
73             return std::to_string(val.integerValue);
74         case QueryValueType::VALUE_TYPE_LONG:
75             return std::to_string(val.longValue);
76         case QueryValueType::VALUE_TYPE_DOUBLE:
77             ss << std::setprecision(DBConstant::DOUBLE_PRECISION) << val.doubleValue;
78             return ss.str();
79         case QueryValueType::VALUE_TYPE_STRING:
80             return "'" + val.stringValue + "'";
81         case QueryValueType::VALUE_TYPE_INVALID:
82         default:
83             return "";
84     }
85 }
86 
GetSelectAndFromClauseForRDB(const std::string & tableName,const std::vector<std::string> & fieldNames)87 std::string GetSelectAndFromClauseForRDB(const std::string &tableName, const std::vector<std::string> &fieldNames)
88 {
89     std::string sql = "SELECT b.data_key,"
90         "b.device,"
91         "b.ori_device,"
92         "b.timestamp as " + DBConstant::TIMESTAMP_ALIAS + ","
93         "b.wtimestamp,"
94         "b.flag,"
95         "b.hash_key,";
96     if (fieldNames.empty()) {  // For query check. If column count changed, can be discovered.
97         sql += "a.*";
98     } else {
99         for (const auto &fieldName : fieldNames) {  // For query data.
100             sql += "a.'" + fieldName + "',";
101         }
102         sql.pop_back();
103     }
104     sql += " FROM '" + tableName + "' AS a INNER JOIN " + DBConstant::RELATIONAL_PREFIX + tableName + "_log AS b "
105         "ON a.rowid=b.data_key ";
106     return sql;
107 }
108 
GetTimeRangeClauseForRDB()109 std::string GetTimeRangeClauseForRDB()
110 {
111     return " AND (" + DBConstant::TIMESTAMP_ALIAS + ">=? AND " + DBConstant::TIMESTAMP_ALIAS + "<?) ";
112 }
113 
GetOuterQueryClauseForRDB(const std::string & subQueryClause)114 std::string GetOuterQueryClauseForRDB(const std::string &subQueryClause)
115 {
116     return "SELECT * "
117         "FROM ( " + subQueryClause + " ) "
118         "WHERE (" + DBConstant::TIMESTAMP_ALIAS + ">=? AND " + DBConstant::TIMESTAMP_ALIAS + "<?) "
119         "ORDER BY " + DBConstant::TIMESTAMP_ALIAS + ";";
120 }
121 
GetFlagClauseForRDB()122 std::string GetFlagClauseForRDB()
123 {
124     return "WHERE (b.flag&0x03=0x02)";
125 }
126 
GetMissQueryFlagClauseForRDB()127 std::string GetMissQueryFlagClauseForRDB()
128 {
129     return "WHERE (b.flag&0x23=0x22)";
130 }
131 }
132 
SqliteQueryHelper(const QueryObjInfo & info)133 SqliteQueryHelper::SqliteQueryHelper(const QueryObjInfo &info)
134     : schema_(info.schema_),
135       queryObjNodes_(info.queryObjNodes_),
136       prefixKey_(info.prefixKey_),
137       suggestIndex_(info.suggestIndex_),
138       tableName_(info.tableName_),
139       keys_(info.keys_),
140       orderByCounts_(info.orderByCounts_),
141       isValid_(info.isValid_),
142       transformed_(false),
143       hasOrderBy_(info.hasOrderBy_),
144       hasLimit_(info.hasLimit_),
145       isOrderByAppeared_(false),
146       hasPrefixKey_(info.hasPrefixKey_),
147       isNeedOrderbyKey_(false),
148       isRelationalQuery_(info.isRelationalQuery_),
149       sortType_(info.sortType_)
150 {}
151 
GetSymbolType(const QueryObjType & queryObjType)152 SymbolType SqliteQueryHelper::GetSymbolType(const QueryObjType &queryObjType)
153 {
154     return static_cast<SymbolType>(static_cast<uint32_t>(queryObjType) & SYMBOL_TYPE_MASK);
155 }
156 
FilterSymbolToAddBracketLink(std::string & querySql,bool isNeedLink) const157 bool SqliteQueryHelper::FilterSymbolToAddBracketLink(std::string &querySql, bool isNeedLink) const
158 {
159     bool isNeedEndBracket = false;
160     for (const auto &iter : queryObjNodes_) {
161         SymbolType symbolType = GetSymbolType(iter.operFlag);
162         if (symbolType == COMPARE_SYMBOL || symbolType == RELATIONAL_SYMBOL || symbolType == RANGE_SYMBOL) {
163             querySql += isNeedLink ? " AND (" : " (";
164             isNeedEndBracket = true;
165             break;
166         } else if (symbolType == LOGIC_SYMBOL || symbolType == PREFIXKEY_SYMBOL || symbolType == IN_KEYS_SYMBOL) {
167             continue;
168         } else {
169             break;
170         }
171     }
172     return isNeedEndBracket;
173 }
174 
175 
ParseQueryObjNodeToSQL(bool isQueryForSync)176 int SqliteQueryHelper::ParseQueryObjNodeToSQL(bool isQueryForSync)
177 {
178     if (queryObjNodes_.empty()) {
179         if (!isQueryForSync) {
180             querySql_ += ";";
181         }
182         return E_OK;
183     }
184 
185     bool isNeedEndBracket = FilterSymbolToAddBracketLink(querySql_);
186 
187     int errCode = E_OK;
188     for (const QueryObjNode &objNode : queryObjNodes_) {
189         SymbolType symbolType = GetSymbolType(objNode.operFlag);
190         if (symbolType == SPECIAL_SYMBOL && isNeedEndBracket) {
191             querySql_ += ") ";
192             isNeedEndBracket = false;
193         }
194         errCode = ParseQueryExpression(objNode, querySql_);
195         if (errCode != E_OK) {
196             querySql_.clear();
197             return errCode;
198         }
199     }
200 
201     if (isNeedEndBracket) {
202         querySql_ += ") ";
203     }
204 
205     return errCode;
206 }
207 
ToQuerySql()208 int SqliteQueryHelper::ToQuerySql()
209 {
210     int errCode = ParseQueryObjNodeToSQL(false);
211     if (errCode != E_OK) {
212         return errCode;
213     }
214 
215     // Limit needs to be placed after orderBy and processed separately in the limit branch
216     if (hasPrefixKey_ && !hasOrderBy_ && !hasLimit_ && isNeedOrderbyKey_) {
217         LOGD("Need add order by key at last when has prefixKey no need order by value and limit!");
218         querySql_ += "ORDER BY key ASC";
219     }
220     querySql_ += ";";
221     return errCode;
222 }
223 
ToQuerySyncSql(bool hasSubQuery,bool useTimestampAlias)224 int SqliteQueryHelper::ToQuerySyncSql(bool hasSubQuery, bool useTimestampAlias)
225 {
226     int errCode = ParseQueryObjNodeToSQL(true);
227     if (errCode != E_OK) {
228         return errCode;
229     }
230 
231     // Order by time when no order by and no limit and no need order by key.
232     if (!hasOrderBy_ && !hasLimit_ && !isNeedOrderbyKey_) {
233         querySql_ += (useTimestampAlias ?
234             ("ORDER BY " + DBConstant::TIMESTAMP_ALIAS + " ASC") :
235             "ORDER BY timestamp ASC");
236     }
237 
238     if (!hasSubQuery) {
239         querySql_ += ";";
240     }
241     return errCode;
242 }
243 
ToGetCountSql()244 int SqliteQueryHelper::ToGetCountSql()
245 {
246     countSql_.clear();
247     if (queryObjNodes_.empty()) {
248         countSql_ += ";";
249         return E_OK;
250     }
251     bool isNeedEndBracket = FilterSymbolToAddBracketLink(countSql_);
252 
253     int errCode = E_OK;
254     for (const QueryObjNode &objNode : queryObjNodes_) {
255         SymbolType symbolType = GetSymbolType(objNode.operFlag);
256         if (symbolType == SPECIAL_SYMBOL && isNeedEndBracket) {
257             countSql_ += ") ";
258             isNeedEndBracket = false;
259         }
260 
261         if (objNode.operFlag == QueryObjType::LIMIT) {
262             hasLimit_ = true;
263             continue;
264         }
265         if (objNode.operFlag == QueryObjType::ORDERBY) {
266             hasOrderBy_ = true;
267             continue;
268         }
269         errCode = ParseQueryExpression(objNode, countSql_);
270         if (errCode != E_OK) {
271             countSql_.clear();
272             return errCode;
273         }
274     }
275 
276     if (isNeedEndBracket) {
277         countSql_ += ") ";
278     }
279 
280     // Limit needs to be placed after orderBy and processed separately in the limit branch
281     if (hasPrefixKey_ && !hasOrderBy_ && !hasLimit_ && isNeedOrderbyKey_) {
282         LOGD("Need add order by key at last when has prefixKey no need order by value and limit!");
283         countSql_ += "ORDER BY key ASC";
284     }
285     countSql_ += ";";
286     return errCode;
287 }
288 
GetQuerySql(std::string & sql,bool onlyRowid)289 int SqliteQueryHelper::GetQuerySql(std::string &sql, bool onlyRowid)
290 {
291     if (!isValid_) {
292         return -E_INVALID_QUERY_FORMAT;
293     }
294 
295     const std::string &querySqlForUse = (onlyRowid ? PRE_QUERY_ROWID_SQL : PRE_QUERY_KV_SQL);
296     sql = AssembleSqlForSuggestIndex(querySqlForUse, FILTER_NATIVE_DATA_SQL);
297     sql = !hasPrefixKey_ ? sql : (sql + " AND (key>=? AND key<=?) ");
298     sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size()));
299     if (sortType_ != SortType::NONE) {
300         sql += (sortType_ == SortType::TIMESTAMP_ASC) ? "ORDER BY timestamp asc " : "ORDER BY timestamp desc ";
301     }
302     if (transformed_) {
303         LOGD("This query object has been parsed.");
304         sql += querySql_;
305         return E_OK;
306     }
307     int errCode = ToQuerySql();
308     if (errCode != E_OK) {
309         LOGE("Transfer to query sql failed! errCode[%d]", errCode);
310         return errCode;
311     }
312     transformed_ = true;
313     sql += querySql_;
314     return errCode;
315 }
316 
GetSyncDataCheckSql(std::string & sql)317 int SqliteQueryHelper::GetSyncDataCheckSql(std::string &sql)
318 {
319     int errCode = E_OK;
320     if (!isValid_) {
321         return -E_INVALID_QUERY_FORMAT;
322     }
323     sql = PRE_QUERY_ITEM_SQL + tableName_ + " WHERE hash_key=? AND (flag&0x01=0) ";
324     sql += hasPrefixKey_ ? " AND (key>=? AND key<=?) " : "";
325     sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size()));
326     if (!transformed_) {
327         errCode = ToQuerySql();
328         if (errCode != E_OK) {
329             LOGE("Transfer query to sync data check sql failed! errCode[%d]", errCode);
330             return errCode;
331         }
332         transformed_ = true;
333     }
334     sql += querySql_;
335     return errCode;
336 }
337 
BindSyncDataCheckStmt(sqlite3_stmt * statement,const Key & hashKey) const338 int SqliteQueryHelper::BindSyncDataCheckStmt(sqlite3_stmt *statement, const Key &hashKey) const
339 {
340     if (statement == nullptr) {
341         return -E_INVALID_ARGS;
342     }
343     int index = 1; // bind statement start index 1
344     int errCode = SQLiteUtils::BindBlobToStatement(statement, index++, hashKey, false);
345     if (errCode != E_OK) {
346         LOGE("Get sync data check statement failed when bind hash key, errCode = %d", errCode);
347         return errCode;
348     }
349     if (hasPrefixKey_) {
350         // bind the prefix key for the first and second args.
351         errCode = SQLiteUtils::BindPrefixKey(statement, index, prefixKey_);
352         if (errCode != E_OK) {
353             LOGE("Get sync data check statement failed when bind prefix key, errCode = %d", errCode);
354             return errCode;
355         }
356         index += 2; // prefixKey takes 2 position
357     }
358 
359     errCode = BindKeysToStmt(keys_, statement, index);
360     if (errCode != E_OK) {
361         SQLiteUtils::ResetStatement(statement, true, errCode);
362         return errCode;
363     }
364 
365     for (const QueryObjNode &objNode : queryObjNodes_) {
366         errCode = BindFieldValue(statement, objNode, index);
367         if (errCode != E_OK) {
368             LOGE("Get sync data check statement failed when bind field value, errCode = %d", errCode);
369             return errCode;
370         }
371     }
372     return errCode;
373 }
374 
GetCountQuerySql(std::string & sql)375 int SqliteQueryHelper::GetCountQuerySql(std::string &sql)
376 {
377     if (!isValid_) {
378         return -E_INVALID_QUERY_FORMAT;
379     }
380 
381     int errCode = ToGetCountSql();
382     if (errCode != E_OK) {
383         return errCode;
384     }
385     sql = AssembleSqlForSuggestIndex(PRE_GET_COUNT_SQL, FILTER_NATIVE_DATA_SQL);
386     sql = !hasPrefixKey_ ? sql : (sql + " AND (key>=? AND key<=?) ");
387     sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size()));
388     sql += countSql_;
389     return E_OK;
390 }
391 
GetQuerySqlStatement(sqlite3 * dbHandle,const std::string & sql,sqlite3_stmt * & statement)392 int SqliteQueryHelper::GetQuerySqlStatement(sqlite3 *dbHandle, const std::string &sql, sqlite3_stmt *&statement)
393 {
394     int errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
395     if (errCode != E_OK) {
396         LOGE("[Query] Get statement fail!");
397         return -E_INVALID_QUERY_FORMAT;
398     }
399     int index = 1;
400     if (hasPrefixKey_) {
401         // bind the prefix key for the first and second args.
402         errCode = SQLiteUtils::BindPrefixKey(statement, 1, prefixKey_);
403         if (errCode != E_OK) {
404             SQLiteUtils::ResetStatement(statement, true, errCode);
405             LOGE("[Query] Get statement when bind prefix key, errCode = %d", errCode);
406             return errCode;
407         }
408         index = 3; // begin from 3rd args
409     }
410 
411     errCode = BindKeysToStmt(keys_, statement, index);
412     if (errCode != E_OK) {
413         SQLiteUtils::ResetStatement(statement, true, errCode);
414         return errCode;
415     }
416 
417     for (const QueryObjNode &objNode : queryObjNodes_) {
418         errCode = BindFieldValue(statement, objNode, index);
419         if (errCode != E_OK) {
420             SQLiteUtils::ResetStatement(statement, true, errCode);
421             LOGE("[Query] Get statement fail when bind field value, errCode = %d", errCode);
422             return errCode;
423         }
424     }
425     return errCode;
426 }
427 
GetQuerySqlStatement(sqlite3 * dbHandle,bool onlyRowid,sqlite3_stmt * & statement)428 int SqliteQueryHelper::GetQuerySqlStatement(sqlite3 *dbHandle, bool onlyRowid, sqlite3_stmt *&statement)
429 {
430     std::string sql;
431     int errCode = GetQuerySql(sql, onlyRowid);
432     if (errCode != E_OK) {
433         return errCode;
434     }
435 
436     errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
437     if (errCode != E_OK) {
438         LOGE("[Query] Get statement fail!");
439         return -E_INVALID_QUERY_FORMAT;
440     }
441     int index = 1;
442     if (hasPrefixKey_) {
443         // bind the prefix key for the first and second args.
444         errCode = SQLiteUtils::BindPrefixKey(statement, 1, prefixKey_);
445         if (errCode != E_OK) {
446             LOGE("[Query] Get statement when bind prefix key, errCode = %d", errCode);
447             return errCode;
448         }
449         index = 3; // begin from 3rd args
450     }
451 
452     errCode = BindKeysToStmt(keys_, statement, index);
453     if (errCode != E_OK) {
454         return errCode;
455     }
456 
457     for (const QueryObjNode &objNode : queryObjNodes_) {
458         errCode = BindFieldValue(statement, objNode, index);
459         if (errCode != E_OK) {
460             LOGE("[Query] Get statement fail when bind field value, errCode = %d", errCode);
461             return errCode;
462         }
463     }
464     return errCode;
465 }
466 
GetCountSqlStatement(sqlite3 * dbHandle,sqlite3_stmt * & countStmt)467 int SqliteQueryHelper::GetCountSqlStatement(sqlite3 *dbHandle, sqlite3_stmt *&countStmt)
468 {
469     std::string countSql;
470     int errCode = GetCountQuerySql(countSql);
471     if (errCode != E_OK) {
472         return errCode;
473     }
474 
475     // bind statement for count
476     errCode = SQLiteUtils::GetStatement(dbHandle, countSql, countStmt);
477     if (errCode != E_OK) {
478         LOGE("Get count statement error:%d", errCode);
479         return -E_INVALID_QUERY_FORMAT;
480     }
481     int index = 1;
482     if (hasPrefixKey_) {
483         // bind the prefix key for the first and second args.
484         errCode = SQLiteUtils::BindPrefixKey(countStmt, 1, prefixKey_);
485         if (errCode != E_OK) {
486             LOGE("[Query] Get count statement fail when bind prefix key, errCode = %d", errCode);
487             return errCode;
488         }
489         index = 3; // begin from 3rd args
490     }
491 
492     errCode = BindKeysToStmt(keys_, countStmt, index);
493     if (errCode != E_OK) {
494         return errCode;
495     }
496 
497     for (const QueryObjNode &objNode : queryObjNodes_) {
498         if (GetSymbolType(objNode.operFlag) == SPECIAL_SYMBOL) {
499             continue;
500         }
501         errCode = BindFieldValue(countStmt, objNode, index);
502         if (errCode != E_OK) {
503             LOGE("[Query] Get count statement fail when bind field value, errCode = %d", errCode);
504             return errCode;
505         }
506     }
507     return errCode;
508 }
509 
GetSyncDataQuerySql(std::string & sql,bool hasSubQuery)510 int SqliteQueryHelper::GetSyncDataQuerySql(std::string &sql, bool hasSubQuery)
511 {
512     if (!isValid_) {
513         return -E_INVALID_QUERY_FORMAT;
514     }
515 
516     if (hasLimit_) {
517         hasSubQuery = true; // Need sub query.
518     } else {
519         isNeedOrderbyKey_ = false; // Need order by timestamp.
520     }
521 
522     sql = AssembleSqlForSuggestIndex(PRE_QUERY_ITEM_SQL + tableName_ + " ", FILTER_REMOTE_QUERY);
523     sql = !hasPrefixKey_ ? sql : (sql + " AND (key>=? AND key<=?) ");
524     sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size()));
525     sql = hasSubQuery ? sql : (sql + " AND (timestamp>=? AND timestamp<?) ");
526 
527     querySql_.clear(); // clear local query sql format
528     int errCode = ToQuerySyncSql(hasSubQuery);
529     if (errCode != E_OK) {
530         LOGE("To query sql fail! errCode[%d]", errCode);
531         return errCode;
532     }
533     sql += querySql_;
534     if (hasSubQuery) {
535         // The last timestamp in one query will be stored in continue token and used for next query.
536         // Therefore all query data must be ordered by timestamp.
537         // When there is limit in SQL, data should be ordered by key in sub query, and timestamp is ordered by outside.
538         sql = "SELECT * FROM ( " + sql + " ) WHERE (timestamp >= ? AND timestamp < ?) ORDER BY timestamp;";
539     }
540     return errCode;
541 }
542 
BindTimeRange(sqlite3_stmt * & statement,int & index,uint64_t beginTime,uint64_t endTime) const543 int SqliteQueryHelper::BindTimeRange(sqlite3_stmt *&statement, int &index, uint64_t beginTime, uint64_t endTime) const
544 {
545     int errCode = SQLiteUtils::BindInt64ToStatement(statement, index++, beginTime);
546     if (errCode != E_OK) {
547         SQLiteUtils::ResetStatement(statement, true, errCode);
548         return errCode;
549     }
550 
551     errCode = SQLiteUtils::BindInt64ToStatement(statement, index++, endTime);
552     if (errCode != E_OK) {
553         SQLiteUtils::ResetStatement(statement, true, errCode);
554     }
555     return errCode;
556 }
557 
BindObjNodes(sqlite3_stmt * & statement,int & index) const558 int SqliteQueryHelper::BindObjNodes(sqlite3_stmt *&statement, int &index) const
559 {
560     int errCode = E_OK;
561     for (const QueryObjNode &objNode : queryObjNodes_) {
562         errCode = BindFieldValue(statement, objNode, index);
563         if (errCode != E_OK) {
564             SQLiteUtils::ResetStatement(statement, true, errCode);
565             LOGE("[Query] Get statement fail when bind field value, errCode = %d", errCode);
566             break;
567         }
568     }
569     return errCode;
570 }
571 
GetQuerySyncStatement(sqlite3 * dbHandle,uint64_t beginTime,uint64_t endTime,sqlite3_stmt * & statement)572 int SqliteQueryHelper::GetQuerySyncStatement(sqlite3 *dbHandle, uint64_t beginTime, uint64_t endTime,
573     sqlite3_stmt *&statement)
574 {
575     bool hasSubQuery = false;
576     if (hasLimit_) {
577         hasSubQuery = true; // Need sub query.
578     } else {
579         isNeedOrderbyKey_ = false; // Need order by timestamp.
580     }
581     std::string sql;
582     int errCode = GetSyncDataQuerySql(sql, hasSubQuery);
583     if (errCode != E_OK) {
584         LOGE("[Query] Get SQL fail!");
585         return -E_INVALID_QUERY_FORMAT;
586     }
587 
588     errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
589     if (errCode != E_OK) {
590         LOGE("[Query] Get statement fail!");
591         return -E_INVALID_QUERY_FORMAT;
592     }
593 
594     int index = 1; // begin with 1.
595     if (hasPrefixKey_) {
596         // bind the prefix key for the first and second args.
597         errCode = SQLiteUtils::BindPrefixKey(statement, index, prefixKey_);
598         if (errCode != E_OK) {
599             SQLiteUtils::ResetStatement(statement, true, errCode);
600             LOGE("[Query] Get statement when bind prefix key, errCode = %d", errCode);
601             return errCode;
602         }
603         index = 3; // begin with 3 next if prefix key exists.
604     }
605 
606     errCode = BindKeysToStmt(keys_, statement, index);
607     if (errCode != E_OK) {
608         SQLiteUtils::ResetStatement(statement, true, errCode);
609         return errCode;
610     }
611 
612     if (hasSubQuery) {
613         // For sub query SQL, timestamp must be last : (prefix key), (objNodes), timestamp.
614         // SQL: SELECT * FROM ( SELECT * FROM sync_data WHERE (flag&0x03=0x02) LIMIT 10 OFFSET 0 ) WHERE (timestamp>=?
615         //      AND timestamp<?) ORDER BY timestamp;
616         errCode = BindObjNodes(statement, index);
617         if (errCode != E_OK) {
618             return errCode;
619         }
620         errCode = BindTimeRange(statement, index, beginTime, endTime);
621     } else {
622         // For normal SQL(no sub query), timestamp is just behind prefix key : (prefix key), timestamp, (ojbNodes).
623         // SQL: SELECT * FROM sync_data WHERE (timestamp>=? AND timestamp<?) AND (flag&0x03=0x02) ORDER BY timestamp;
624         errCode = BindTimeRange(statement, index, beginTime, endTime);
625         if (errCode != E_OK) {
626             return errCode;
627         }
628         errCode = BindObjNodes(statement, index);
629     }
630     return errCode;
631 }
632 
MapRelationalSymbolToSql(const QueryObjNode & queryNode,bool placeholder) const633 std::string SqliteQueryHelper::MapRelationalSymbolToSql(const QueryObjNode &queryNode, bool placeholder) const
634 {
635     if (RELATIONAL_SYMBOL_TO_SQL.find(queryNode.operFlag) == RELATIONAL_SYMBOL_TO_SQL.end()) {
636         return "";
637     };
638     std::string sql = RELATIONAL_SYMBOL_TO_SQL.at(queryNode.operFlag) + MapValueToSql(queryNode, placeholder);
639     if (GetSymbolType(queryNode.operFlag) == RANGE_SYMBOL) {
640         sql += ")";
641     }
642     return sql;
643 }
644 
MapLogicSymbolToSql(const QueryObjNode & queryNode) const645 std::string SqliteQueryHelper::MapLogicSymbolToSql(const QueryObjNode &queryNode) const
646 {
647     if (LOGIC_SYMBOL_TO_SQL.find(queryNode.operFlag) == LOGIC_SYMBOL_TO_SQL.end()) {
648         return "";
649     }
650     return LOGIC_SYMBOL_TO_SQL.at(queryNode.operFlag);
651 }
652 
MapKeywordSymbolToSql(const QueryObjNode & queryNode)653 std::string SqliteQueryHelper::MapKeywordSymbolToSql(const QueryObjNode &queryNode)
654 {
655     std::string sql;
656     switch (queryNode.operFlag) {
657         case QueryObjType::ORDERBY:
658             if (queryNode.fieldValue.size() == SINGLE_FIELD_VALUE_SIZE) {
659                 if (!isOrderByAppeared_) {
660                     sql += "ORDER BY ";
661                 }
662                 sql += GetFieldShape(queryNode);
663                 sql += queryNode.fieldValue[0].boolValue ? "ASC," : "DESC,";
664                 orderByCounts_--;
665                 if (orderByCounts_ == 0) {
666                     sql.pop_back();
667                 }
668                 isOrderByAppeared_ = true;
669             }
670             return sql;
671         case QueryObjType::LIMIT:
672             if (hasPrefixKey_ && !hasOrderBy_ && isNeedOrderbyKey_) {
673                 sql += "ORDER BY key ASC ";
674             }
675             sql += " LIMIT " + std::to_string(queryNode.fieldValue[0].integerValue);
676             sql += " OFFSET " + std::to_string(queryNode.fieldValue[1].integerValue);
677             return sql;
678         default:
679             return "";
680     }
681 }
682 
MapValueToSql(const QueryObjNode & queryNode,bool placeholder) const683 std::string SqliteQueryHelper::MapValueToSql(const QueryObjNode &queryNode, bool placeholder) const
684 {
685     std::string resultSql;
686     for (size_t i = 0; i < queryNode.fieldValue.size(); i++) {
687         if (i != 0) {
688             resultSql += ", ";
689         }
690         resultSql += placeholder ? "? " : FieldValue2String(queryNode.fieldValue[i], queryNode.type);
691     }
692     return resultSql;
693 }
694 
IsNeedCastWitEmptyValue(const QueryObjNode & queryNode)695 static bool IsNeedCastWitEmptyValue(const QueryObjNode &queryNode)
696 {
697     return (queryNode.operFlag == QueryObjType::IS_NULL || queryNode.operFlag == QueryObjType::IS_NOT_NULL ||
698         queryNode.operFlag == QueryObjType::IN || queryNode.operFlag == QueryObjType::NOT_IN);
699 }
700 
MapCastFuncSql(const QueryObjNode & queryNode,const std::string & accessStr)701 std::string SqliteQueryHelper::MapCastFuncSql(const QueryObjNode &queryNode, const std::string &accessStr)
702 {
703     std::string resultSql;
704     if (queryNode.fieldValue.empty() && !IsNeedCastWitEmptyValue(queryNode)) {
705         return resultSql;
706     }
707     // fieldPath and isQueryable had been checked ok in the previous code, So here parse path and get type won't fail.
708     FieldPath fieldPath;
709     SchemaUtils::ParseAndCheckFieldPath(queryNode.fieldName, fieldPath);
710     FieldType fieldType = FieldType::LEAF_FIELD_INTEGER;
711     schema_.CheckQueryableAndGetFieldType(fieldPath, fieldType);
712     resultSql += SchemaObject::GenerateExtractSQL(schema_.GetSchemaType(), fieldPath, fieldType,
713         schema_.GetSkipSize(), accessStr);
714     isNeedOrderbyKey_ = false; // When index by value, No need order by key!
715     return resultSql;
716 }
717 
BindFieldValue(sqlite3_stmt * statement,const QueryObjNode & queryNode,int & index) const718 int SqliteQueryHelper::BindFieldValue(sqlite3_stmt *statement, const QueryObjNode &queryNode, int &index) const
719 {
720     SymbolType symbolType = GetSymbolType(queryNode.operFlag);
721     if (symbolType != COMPARE_SYMBOL && symbolType != RELATIONAL_SYMBOL && symbolType != RANGE_SYMBOL) {
722         return E_OK;
723     }
724 
725     int errCode = SQLITE_OK;
726     for (size_t i = 0; i < queryNode.fieldValue.size(); i++) {
727         if (queryNode.type == QueryValueType::VALUE_TYPE_BOOL) {
728             errCode = sqlite3_bind_int(statement, index, queryNode.fieldValue[i].boolValue);
729         } else if (queryNode.type == QueryValueType::VALUE_TYPE_INTEGER) {
730             errCode = sqlite3_bind_int(statement, index, queryNode.fieldValue[i].integerValue);
731         } else if (queryNode.type == QueryValueType::VALUE_TYPE_LONG) {
732             errCode = sqlite3_bind_int64(statement, index, queryNode.fieldValue[i].longValue);
733         } else if (queryNode.type == QueryValueType::VALUE_TYPE_DOUBLE) {
734             errCode = sqlite3_bind_double(statement, index, queryNode.fieldValue[i].doubleValue);
735         } else {
736             if (queryNode.fieldValue[i].stringValue.size() > MAX_SQLITE_BIND_SIZE) {
737                 return -E_MAX_LIMITS;
738             }
739             errCode = sqlite3_bind_text(statement, index, queryNode.fieldValue[i].stringValue.c_str(),
740                 queryNode.fieldValue[i].stringValue.size(), SQLITE_TRANSIENT);
741         }
742         if (errCode != SQLITE_OK) {
743             break;
744         }
745         index++;
746     }
747     return SQLiteUtils::MapSQLiteErrno(errCode);
748 }
749 
GetFieldShape(const QueryObjNode & queryNode,const std::string & accessStr)750 std::string SqliteQueryHelper::GetFieldShape(const QueryObjNode &queryNode, const std::string &accessStr)
751 {
752     if (isRelationalQuery_) {
753         // For relational query, $. prefix is not permitted, so need not extract json. Return directly will be OK.
754         return "a.'" + queryNode.fieldName + "' ";
755     }
756     return MapCastFuncSql(queryNode, accessStr);
757 }
758 
ParseQueryExpression(const QueryObjNode & queryNode,std::string & querySql,const std::string & accessStr,bool placeholder)759 int SqliteQueryHelper::ParseQueryExpression(const QueryObjNode &queryNode, std::string &querySql,
760     const std::string &accessStr, bool placeholder)
761 {
762     SymbolType symbolType = GetSymbolType(queryNode.operFlag);
763     if (symbolType == RANGE_SYMBOL && queryNode.fieldValue.size() > MAX_CONDITIONS_SIZE) {
764         LOGE("[Query][Parse][Expression] conditions is too many!");
765         return -E_MAX_LIMITS;
766     }
767 
768     if (symbolType == COMPARE_SYMBOL || symbolType == RELATIONAL_SYMBOL || symbolType == RANGE_SYMBOL) {
769         querySql += GetFieldShape(queryNode, accessStr);
770         querySql += MapRelationalSymbolToSql(queryNode, placeholder);
771     } else if (symbolType == LOGIC_SYMBOL || symbolType == LINK_SYMBOL) {
772         querySql += MapLogicSymbolToSql(queryNode);
773     } else {
774         querySql += MapKeywordSymbolToSql(queryNode);
775     }
776 
777     if (querySql.size() > MAX_SQL_LEN) {
778         LOGE("[Query][Parse][Expression] Sql is too long!");
779         return -E_MAX_LIMITS;
780     }
781     return E_OK;
782 }
783 
AssembleSqlForSuggestIndex(const std::string & baseSql,const std::string & filter) const784 std::string SqliteQueryHelper::AssembleSqlForSuggestIndex(const std::string &baseSql, const std::string &filter) const
785 {
786     std::string formatIndex = CheckAndFormatSuggestIndex();
787     if (formatIndex.empty()) {
788         return baseSql + filter;
789     }
790 
791     return baseSql + USING_INDEX + "'" + formatIndex + "' " + filter;
792 }
793 
CheckAndFormatSuggestIndex() const794 std::string SqliteQueryHelper::CheckAndFormatSuggestIndex() const
795 {
796     if (suggestIndex_.empty()) {
797         return "";
798     }
799     IndexName indexName;
800     int errCode = SchemaUtils::ParseAndCheckFieldPath(suggestIndex_, indexName);
801     if (errCode != E_OK) {
802         LOGW("Check and format suggest index failed! %d", errCode);
803         return "";
804     }
805 
806     if (!schema_.IsIndexExist(indexName)) {
807         LOGW("The suggest index not exist!");
808         return "";
809     }
810     return SchemaUtils::FieldPathString(indexName);
811 }
812 
MapKeysInSubCondition(const std::string & accessStr) const813 std::string SqliteQueryHelper::MapKeysInSubCondition(const std::string &accessStr) const
814 {
815     std::string resultStr = "hex(" + accessStr + "key) IN (";
816     for (auto iter = keys_.begin(); iter != keys_.end(); iter++) {
817         if (iter != keys_.begin()) {
818             resultStr += ", ";
819         }
820         resultStr += "'" + DBCommon::VectorToHexString(*iter) + "' ";
821     }
822     resultStr += ")";
823     return resultStr;
824 }
825 
GetSubscribeCondition(const std::string & accessStr,std::string & conditionStr)826 int SqliteQueryHelper::GetSubscribeCondition(const std::string &accessStr, std::string &conditionStr)
827 {
828     if (queryObjNodes_.empty()) {
829         conditionStr += " (1 = 1) ";
830         return E_OK;
831     }
832 
833     bool hasQueryByValue = std::any_of(queryObjNodes_.begin(), queryObjNodes_.end(), [](const QueryObjNode &it) {
834         return GetSymbolType(it.operFlag) == SymbolType::COMPARE_SYMBOL ||
835             GetSymbolType(it.operFlag) == SymbolType::RELATIONAL_SYMBOL ||
836             GetSymbolType(it.operFlag) == SymbolType::RANGE_SYMBOL;
837     });
838     if (hasQueryByValue) {
839         // json_extract_by_path function will return error when value is empty, check it before when query by value
840         conditionStr += "((length(" + accessStr + "value) != 0 AND " + accessStr + "value IS NOT NULL) AND ";
841     } else {
842         conditionStr += "(";
843     }
844 
845     if (hasPrefixKey_) {
846         conditionStr += "(hex(" + accessStr + "key) LIKE '" + DBCommon::VectorToHexString(prefixKey_) + "%')";
847     }
848 
849     if (!keys_.empty()) {
850         if (hasPrefixKey_) {
851             conditionStr += " AND ";
852         }
853         conditionStr += "(" + MapKeysInSubCondition(accessStr) + ")";
854     }
855 
856     bool isNeedEndBracket = FilterSymbolToAddBracketLink(conditionStr, hasPrefixKey_ || !keys_.empty());
857     int errCode = E_OK;
858     for (const QueryObjNode &objNode : queryObjNodes_) {
859         SymbolType symbolType = GetSymbolType(objNode.operFlag);
860         if (symbolType == SPECIAL_SYMBOL && isNeedEndBracket) {
861             conditionStr += ") ";
862             isNeedEndBracket = false;
863         }
864         errCode = ParseQueryExpression(objNode, conditionStr, accessStr, false);
865         if (errCode != E_OK) {
866             conditionStr.clear();
867             return errCode;
868         }
869     }
870 
871     if (isNeedEndBracket) {
872         conditionStr += ") ";
873     }
874     conditionStr += ")";
875     return errCode;
876 }
877 
GetSubscribeSql(const std::string & subscribeId,TriggerModeEnum mode,std::string & subscribeCondition)878 int SqliteQueryHelper::GetSubscribeSql(const std::string &subscribeId, TriggerModeEnum mode,
879     std::string &subscribeCondition)
880 {
881     if (!isValid_) {
882         return -E_INVALID_QUERY_FORMAT;
883     }
884     int errCode = E_OK;
885     switch (mode) {
886         case TriggerModeEnum::INSERT:
887             errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_NEW, subscribeCondition);
888             break;
889         case TriggerModeEnum::UPDATE:
890             errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_OLD, subscribeCondition);
891             if (errCode != E_OK) {
892                 break;
893             }
894             subscribeCondition += " OR ";
895             errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_NEW, subscribeCondition);
896             break;
897         case TriggerModeEnum::DELETE:
898             errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_OLD, subscribeCondition);
899             break;
900         default:
901             errCode = -INVALID_ARGS;
902     }
903     if (errCode != E_OK) {
904         LOGD("Get subscribe query condition failed. %d", errCode);
905     }
906     return errCode;
907 }
908 
GetRelationalMissQuerySql(const std::vector<std::string> & fieldNames,std::string & sql)909 int SqliteQueryHelper::GetRelationalMissQuerySql(const std::vector<std::string> &fieldNames, std::string &sql)
910 {
911     if (!isValid_) {
912         return -E_INVALID_QUERY_FORMAT;
913     }
914 
915     if (hasPrefixKey_) {
916         LOGE("For relational DB query, prefix key is not supported.");
917         return -E_NOT_SUPPORT;
918     }
919 
920     sql = GetSelectAndFromClauseForRDB(tableName_, fieldNames);
921     sql += GetMissQueryFlagClauseForRDB();
922     sql += GetTimeRangeClauseForRDB();
923     sql += "ORDER BY " + DBConstant::TIMESTAMP_ALIAS + " ASC;";
924     return E_OK;
925 }
926 
GetRelationalSyncDataQuerySql(std::string & sql,bool hasSubQuery,const std::vector<std::string> & fieldNames)927 int SqliteQueryHelper::GetRelationalSyncDataQuerySql(std::string &sql, bool hasSubQuery,
928     const std::vector<std::string> &fieldNames)
929 {
930     if (!isValid_) {
931         return -E_INVALID_QUERY_FORMAT;
932     }
933 
934     if (hasPrefixKey_) {
935         LOGE("For relational DB query, prefix key is not supported.");
936         return -E_NOT_SUPPORT;
937     }
938 
939     sql = AssembleSqlForSuggestIndex(GetSelectAndFromClauseForRDB(tableName_, fieldNames), GetFlagClauseForRDB());
940     sql = hasSubQuery ? sql : (sql + GetTimeRangeClauseForRDB());
941 
942     querySql_.clear(); // clear local query sql format
943     int errCode = ToQuerySyncSql(hasSubQuery, true);
944     if (errCode != E_OK) {
945         LOGE("To query sql fail! errCode[%d]", errCode);
946         return errCode;
947     }
948     sql += querySql_;
949     if (hasSubQuery) {
950         // The last timestamp in one query will be stored in continue token and used for next query.
951         // Therefore all query data must be ordered by timestamp.
952         // When there is limit in SQL, data should be ordered by key in sub query, and timestamp is ordered by outside.
953         sql = GetOuterQueryClauseForRDB(sql);
954     }
955     return errCode;
956 }
957 
GetRelationalMissQueryStatement(sqlite3 * dbHandle,uint64_t beginTime,uint64_t endTime,const std::vector<std::string> & fieldNames,sqlite3_stmt * & statement)958 int SqliteQueryHelper::GetRelationalMissQueryStatement(sqlite3 *dbHandle, uint64_t beginTime, uint64_t endTime,
959     const std::vector<std::string> &fieldNames, sqlite3_stmt *&statement)
960 {
961     std::string sql;
962     int errCode = GetRelationalMissQuerySql(fieldNames, sql);
963     if (errCode != E_OK) {
964         LOGE("[Query] Get SQL fail!");
965         return -E_INVALID_QUERY_FORMAT;
966     }
967 
968     errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
969     if (errCode != E_OK) {
970         LOGE("[Query] Get statement fail!");
971         return -E_INVALID_QUERY_FORMAT;
972     }
973 
974     int index = 1; // begin with 1.
975     return BindTimeRange(statement, index, beginTime, endTime);
976 }
977 
978 namespace {
GetRelationalSyncDataQueryHeader(const std::vector<std::string> & fieldNames)979 std::string GetRelationalSyncDataQueryHeader(const std::vector<std::string> &fieldNames)
980 {
981     std::string sql = "SELECT b.data_key,"
982         "b.device,"
983         "b.ori_device,"
984         "b.timestamp as " + DBConstant::TIMESTAMP_ALIAS + ","
985         "b.wtimestamp,"
986         "b.flag,"
987         "b.hash_key,";
988     if (fieldNames.empty()) {  // For query check. If column count changed, can be discovered.
989         sql += "a.*";
990     } else {
991         for (const auto &fieldName : fieldNames) {  // For query data.
992             sql += "a." + fieldName + ",";
993         }
994         sql.pop_back();
995     }
996     return sql;
997 }
998 
GetRelationalCloudSyncDataQueryHeader(const std::vector<Field> & fields)999 std::string GetRelationalCloudSyncDataQueryHeader(const std::vector<Field> &fields)
1000 {
1001     std::string sql = "SELECT b.data_key,"
1002         "b.device,"
1003         "b.ori_device,"
1004         "b.timestamp as " + DBConstant::TIMESTAMP_ALIAS + ","
1005         "b.wtimestamp,"
1006         "b.flag,"
1007         "b.hash_key,"
1008         "b.cloud_gid,";
1009     if (fields.empty()) {  // For query check. If column count changed, can be discovered.
1010         sql += "a.*";
1011     } else {
1012         for (const auto &field : fields) {  // For query data.
1013             sql += "a." + field.colName + ",";
1014         }
1015         sql.pop_back();
1016     }
1017     return sql;
1018 }
1019 }
1020 
GetRelationalSyncDataQuerySqlWithLimit(const std::vector<std::string> & fieldNames,std::string & sql)1021 int SqliteQueryHelper::GetRelationalSyncDataQuerySqlWithLimit(const std::vector<std::string> &fieldNames,
1022     std::string &sql)
1023 {
1024     if (!isValid_) {
1025         return -E_INVALID_QUERY_FORMAT;
1026     }
1027 
1028     if (hasPrefixKey_) {
1029         LOGE("For relational DB query, prefix key is not supported.");
1030         return -E_NOT_SUPPORT;
1031     }
1032     sql = GetRelationalSyncDataQueryHeader(fieldNames);
1033     sql += " FROM '" + tableName_ + "' AS a INNER JOIN ";
1034     sql += DBConstant::RELATIONAL_PREFIX + tableName_ + "_log";
1035     sql += " AS b ON (a.rowid = b.data_key)";
1036     sql += " WHERE (b.flag&0x03=0x02)";
1037 
1038     querySql_.clear(); // clear local query sql format
1039     int errCode = ToQuerySyncSql(true, true);
1040     if (errCode != E_OK) {
1041         LOGE("To query sql fail! errCode[%d]", errCode);
1042         return errCode;
1043     }
1044     sql += querySql_;
1045     return E_OK;
1046 }
1047 
GetRelationalQueryStatement(sqlite3 * dbHandle,uint64_t beginTime,uint64_t endTime,const std::vector<std::string> & fieldNames,sqlite3_stmt * & statement)1048 int SqliteQueryHelper::GetRelationalQueryStatement(sqlite3 *dbHandle, uint64_t beginTime, uint64_t endTime,
1049     const std::vector<std::string> &fieldNames, sqlite3_stmt *&statement)
1050 {
1051     int errCode = E_OK;
1052     bool hasSubQuery = false;
1053     std::string sql;
1054     if (hasLimit_ && !hasOrderBy_) { // Query with limit and no order by
1055         hasSubQuery = true; // Need sub query.
1056         errCode = GetRelationalSyncDataQuerySqlWithLimit(fieldNames, sql);
1057     } else if (hasLimit_ || hasOrderBy_) {
1058         hasSubQuery = true; // Need sub query.
1059         errCode = GetRelationalSyncDataQuerySql(sql, hasSubQuery, fieldNames);
1060     } else {
1061         isNeedOrderbyKey_ = false; // Need order by timestamp.
1062         errCode = GetRelationalSyncDataQuerySql(sql, hasSubQuery, fieldNames);
1063     }
1064     if (errCode != E_OK) {
1065         LOGE("[Query] Get SQL fail!");
1066         return -E_INVALID_QUERY_FORMAT;
1067     }
1068 
1069     errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
1070     if (errCode != E_OK) {
1071         LOGE("[Query] Get statement fail!");
1072         return -E_INVALID_QUERY_FORMAT;
1073     }
1074 
1075     int index = 1; // begin with 1.
1076     if (hasSubQuery) {
1077         /**
1078          *   SELECT b.data_key,b.device,b.ori_device,b.timestamp as naturalbase_rdb_timestamp,
1079          *          b.wtimestamp,b.flag,b.hash_key,a.*
1080          *   FROM tableName AS a INNER JOIN naturalbase_rdb_log AS b
1081          *   ON a.rowid=b.data_key
1082          *   WHERE (b.flag&0x03=0x02)
1083          *   ORDER BY a.xxx
1084          *   LIMIT ? OFFSET ? )
1085          */
1086         errCode = BindObjNodes(statement, index);
1087         if (errCode != E_OK) {
1088             return errCode;
1089         }
1090         if (!hasLimit_ || hasOrderBy_) {
1091             errCode = BindTimeRange(statement, index, beginTime, endTime);
1092         }
1093     } else {
1094         /**
1095          * SELECT b.data_key,b.device,b.ori_device,b.timestamp as naturalbase_rdb_timestamp,
1096          *        b.wtimestamp,b.flag,b.hash_key,a.*
1097          * FROM tableName AS a INNER JOIN naturalbase_rdb_log AS b
1098          * ON a.rowid=b.data_key
1099          * WHERE (b.flag&0x03=0x02) AND (naturalbase_rdb_timestamp>=? AND naturalbase_rdb_timestamp<?)
1100          * ORDER BY naturalbase_rdb_timestamp ASC;
1101          */
1102         errCode = BindTimeRange(statement, index, beginTime, endTime);
1103         if (errCode != E_OK) {
1104             return errCode;
1105         }
1106         errCode = BindObjNodes(statement, index);
1107     }
1108     return errCode;
1109 }
1110 
MapKeysInToSql(size_t keysNum) const1111 std::string SqliteQueryHelper::MapKeysInToSql(size_t keysNum) const
1112 {
1113     std::string resultSql = "key IN (";
1114     for (size_t i = 0; i < keysNum; i++) {
1115         if (i != 0) {
1116             resultSql += ", ";
1117         }
1118         resultSql += "? ";
1119     }
1120     resultSql += ") ";
1121     return resultSql;
1122 }
1123 
BindKeysToStmt(const std::set<Key> & keys,sqlite3_stmt * & statement,int & index) const1124 int SqliteQueryHelper::BindKeysToStmt(const std::set<Key> &keys, sqlite3_stmt *&statement, int &index) const
1125 {
1126     if (!keys_.empty()) {
1127         int errCode = E_OK;
1128         for (const auto &key : keys) {
1129             errCode = SQLiteUtils::BindBlobToStatement(statement, index, key);
1130             if (errCode != E_OK) {
1131                 LOGE("[Query] Get statement when bind keys failed, errCode = %d", errCode);
1132                 return errCode;
1133             }
1134             index++;
1135         }
1136     }
1137     return E_OK;
1138 }
1139 
GetRelationalCloudQueryStatement(sqlite3 * dbHandle,uint64_t beginTime,const std::vector<Field> & fields,const bool & isCloudForcePush,sqlite3_stmt * & statement)1140 int SqliteQueryHelper::GetRelationalCloudQueryStatement(sqlite3 *dbHandle, uint64_t beginTime,
1141     const std::vector<Field> &fields, const bool &isCloudForcePush, sqlite3_stmt *&statement)
1142 {
1143     std::string sql = GetRelationalCloudSyncDataQueryHeader(fields);
1144     sql += " FROM '" + DBCommon::GetLogTableName(tableName_) + "' AS b LEFT JOIN '";
1145     sql += tableName_ + "' AS a ON (a.rowid = b.data_key)";
1146     sql += isCloudForcePush ? " WHERE b.timestamp > ? AND (b.flag & 0x04 != 0x04)":
1147         " WHERE b.timestamp > ? AND (b.flag & 0x02 = 0x02)";
1148     sql += " AND (b.cloud_gid != '' or"; // actually, b.cloud_gid will not be null.
1149     sql += " (b.cloud_gid == '' and (b.flag & 0x01 = 0))) ";
1150 
1151     querySql_.clear(); // clear local query sql format
1152     int errCode = ToQuerySyncSql(false, true);
1153     if (errCode != E_OK) {
1154         LOGE("To query sql fail! errCode[%d]", errCode);
1155         return errCode;
1156     }
1157     sql += querySql_;
1158     errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
1159     if (errCode != E_OK) {
1160         LOGE("[Query] Get statement fail!");
1161         return -E_INVALID_QUERY_FORMAT;
1162     }
1163     errCode = SQLiteUtils::BindInt64ToStatement(statement, 1, beginTime);
1164     if (errCode != E_OK) {
1165         SQLiteUtils::ResetStatement(statement, true, errCode);
1166     }
1167     return errCode;
1168 }
1169 }