• 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 {}
150 
GetSymbolType(const QueryObjType & queryObjType)151 SymbolType SqliteQueryHelper::GetSymbolType(const QueryObjType &queryObjType)
152 {
153     return static_cast<SymbolType>(static_cast<uint32_t>(queryObjType) & SYMBOL_TYPE_MASK);
154 }
155 
FilterSymbolToAddBracketLink(std::string & querySql,bool isNeedLink) const156 bool SqliteQueryHelper::FilterSymbolToAddBracketLink(std::string &querySql, bool isNeedLink) const
157 {
158     bool isNeedEndBracket = false;
159     for (const auto &iter : queryObjNodes_) {
160         SymbolType symbolType = GetSymbolType(iter.operFlag);
161         if (symbolType == COMPARE_SYMBOL || symbolType == RELATIONAL_SYMBOL || symbolType == RANGE_SYMBOL) {
162             querySql += isNeedLink ? " AND (" : " (";
163             isNeedEndBracket = true;
164             break;
165         } else if (symbolType == LOGIC_SYMBOL || symbolType == PREFIXKEY_SYMBOL || symbolType == IN_KEYS_SYMBOL) {
166             continue;
167         } else {
168             break;
169         }
170     }
171     return isNeedEndBracket;
172 }
173 
174 
ParseQueryObjNodeToSQL(bool isQueryForSync)175 int SqliteQueryHelper::ParseQueryObjNodeToSQL(bool isQueryForSync)
176 {
177     if (queryObjNodes_.empty()) {
178         if (!isQueryForSync) {
179             querySql_ += ";";
180         }
181         return E_OK;
182     }
183 
184     bool isNeedEndBracket = FilterSymbolToAddBracketLink(querySql_);
185 
186     int errCode = E_OK;
187     for (const QueryObjNode &objNode : queryObjNodes_) {
188         SymbolType symbolType = GetSymbolType(objNode.operFlag);
189         if (symbolType == SPECIAL_SYMBOL && isNeedEndBracket) {
190             querySql_ += ") ";
191             isNeedEndBracket = false;
192         }
193         errCode = ParseQueryExpression(objNode, querySql_);
194         if (errCode != E_OK) {
195             querySql_.clear();
196             return errCode;
197         }
198     }
199 
200     if (isNeedEndBracket) {
201         querySql_ += ") ";
202     }
203 
204     return errCode;
205 }
206 
ToQuerySql()207 int SqliteQueryHelper::ToQuerySql()
208 {
209     int errCode = ParseQueryObjNodeToSQL(false);
210     if (errCode != E_OK) {
211         return errCode;
212     }
213 
214     // Limit needs to be placed after orderBy and processed separately in the limit branch
215     if (hasPrefixKey_ && !hasOrderBy_ && !hasLimit_ && isNeedOrderbyKey_) {
216         LOGD("Need add order by key at last when has prefixKey no need order by value and limit!");
217         querySql_ += "ORDER BY key ASC";
218     }
219     querySql_ += ";";
220     return errCode;
221 }
222 
ToQuerySyncSql(bool hasSubQuery,bool useTimeStampAlias)223 int SqliteQueryHelper::ToQuerySyncSql(bool hasSubQuery, bool useTimeStampAlias)
224 {
225     int errCode = ParseQueryObjNodeToSQL(true);
226     if (errCode != E_OK) {
227         return errCode;
228     }
229 
230     // Order by time when no order by and no limit and no need order by key.
231     if (!hasOrderBy_ && !hasLimit_ && !isNeedOrderbyKey_) {
232         querySql_ += (useTimeStampAlias ?
233             ("ORDER BY " + DBConstant::TIMESTAMP_ALIAS + " ASC") :
234             "ORDER BY timestamp ASC");
235     }
236 
237     if (!hasSubQuery) {
238         querySql_ += ";";
239     }
240     return errCode;
241 }
242 
ToGetCountSql()243 int SqliteQueryHelper::ToGetCountSql()
244 {
245     countSql_.clear();
246     if (queryObjNodes_.empty()) {
247         countSql_ += ";";
248         return E_OK;
249     }
250     bool isNeedEndBracket = FilterSymbolToAddBracketLink(countSql_);
251 
252     int errCode = E_OK;
253     for (const QueryObjNode &objNode : queryObjNodes_) {
254         SymbolType symbolType = GetSymbolType(objNode.operFlag);
255         if (symbolType == SPECIAL_SYMBOL && isNeedEndBracket) {
256             countSql_ += ") ";
257             isNeedEndBracket = false;
258         }
259 
260         if (objNode.operFlag == QueryObjType::LIMIT) {
261             hasLimit_ = true;
262             continue;
263         }
264         if (objNode.operFlag == QueryObjType::ORDERBY) {
265             hasOrderBy_ = true;
266             continue;
267         }
268         errCode = ParseQueryExpression(objNode, countSql_);
269         if (errCode != E_OK) {
270             countSql_.clear();
271             return errCode;
272         }
273     }
274 
275     if (isNeedEndBracket) {
276         countSql_ += ") ";
277     }
278 
279     // Limit needs to be placed after orderBy and processed separately in the limit branch
280     if (hasPrefixKey_ && !hasOrderBy_ && !hasLimit_ && isNeedOrderbyKey_) {
281         LOGD("Need add order by key at last when has prefixKey no need order by value and limit!");
282         countSql_ += "ORDER BY key ASC";
283     }
284     countSql_ += ";";
285     return errCode;
286 }
287 
GetQuerySql(std::string & sql,bool onlyRowid)288 int SqliteQueryHelper::GetQuerySql(std::string &sql, bool onlyRowid)
289 {
290     if (!isValid_) {
291         return -E_INVALID_QUERY_FORMAT;
292     }
293 
294     const std::string &querySqlForUse = (onlyRowid ? PRE_QUERY_ROWID_SQL : PRE_QUERY_KV_SQL);
295     sql = AssembleSqlForSuggestIndex(querySqlForUse, FILTER_NATIVE_DATA_SQL);
296     sql = !hasPrefixKey_ ? sql : (sql + " AND (key>=? AND key<=?) ");
297     sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size()));
298     if (transformed_) {
299         LOGD("This query object has been parsed.");
300         sql += querySql_;
301         return E_OK;
302     }
303     int errCode = ToQuerySql();
304     if (errCode != E_OK) {
305         LOGE("Transfer to query sql failed! errCode[%d]", errCode);
306         return errCode;
307     }
308     transformed_ = true;
309     sql += querySql_;
310     return errCode;
311 }
312 
GetSyncDataCheckSql(std::string & sql)313 int SqliteQueryHelper::GetSyncDataCheckSql(std::string &sql)
314 {
315     int errCode = E_OK;
316     if (!isValid_) {
317         return -E_INVALID_QUERY_FORMAT;
318     }
319     sql = PRE_QUERY_ITEM_SQL + tableName_ + " WHERE hash_key=? AND (flag&0x01=0) ";
320     sql += hasPrefixKey_ ? " AND (key>=? AND key<=?) " : "";
321     sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size()));
322     if (!transformed_) {
323         errCode = ToQuerySql();
324         if (errCode != E_OK) {
325             LOGE("Transfer query to sync data check sql failed! errCode[%d]", errCode);
326             return errCode;
327         }
328         transformed_ = true;
329     }
330     sql += querySql_;
331     return errCode;
332 }
333 
BindSyncDataCheckStmt(sqlite3_stmt * statement,const Key & hashKey) const334 int SqliteQueryHelper::BindSyncDataCheckStmt(sqlite3_stmt *statement, const Key &hashKey) const
335 {
336     if (statement == nullptr) {
337         return -E_INVALID_ARGS;
338     }
339     int index = 1; // bind statement start index 1
340     int errCode = SQLiteUtils::BindBlobToStatement(statement, index++, hashKey, false);
341     if (errCode != E_OK) {
342         LOGE("Get sync data check statement failed when bind hash key, errCode = %d", errCode);
343         return errCode;
344     }
345     if (hasPrefixKey_) {
346         // bind the prefix key for the first and second args.
347         errCode = SQLiteUtils::BindPrefixKey(statement, index, prefixKey_);
348         if (errCode != E_OK) {
349             LOGE("Get sync data check statement failed when bind prefix key, errCode = %d", errCode);
350             return errCode;
351         }
352         index += 2; // prefixKey takes 2 position
353     }
354 
355     errCode = BindKeysToStmt(keys_, statement, index);
356     if (errCode != E_OK) {
357         SQLiteUtils::ResetStatement(statement, true, errCode);
358         return errCode;
359     }
360 
361     for (const QueryObjNode &objNode : queryObjNodes_) {
362         errCode = BindFieldValue(statement, objNode, index);
363         if (errCode != E_OK) {
364             LOGE("Get sync data check statement failed when bind field value, errCode = %d", errCode);
365             return errCode;
366         }
367     }
368     return errCode;
369 }
370 
GetCountQuerySql(std::string & sql)371 int SqliteQueryHelper::GetCountQuerySql(std::string &sql)
372 {
373     if (!isValid_) {
374         return -E_INVALID_QUERY_FORMAT;
375     }
376 
377     int errCode = ToGetCountSql();
378     if (errCode != E_OK) {
379         return errCode;
380     }
381     sql = AssembleSqlForSuggestIndex(PRE_GET_COUNT_SQL, FILTER_NATIVE_DATA_SQL);
382     sql = !hasPrefixKey_ ? sql : (sql + " AND (key>=? AND key<=?) ");
383     sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size()));
384     sql += countSql_;
385     return E_OK;
386 }
387 
GetQuerySqlStatement(sqlite3 * dbHandle,const std::string & sql,sqlite3_stmt * & statement)388 int SqliteQueryHelper::GetQuerySqlStatement(sqlite3 *dbHandle, const std::string &sql, sqlite3_stmt *&statement)
389 {
390     int errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
391     if (errCode != E_OK) {
392         LOGE("[Query] Get statement fail!");
393         return -E_INVALID_QUERY_FORMAT;
394     }
395     int index = 1;
396     if (hasPrefixKey_) {
397         // bind the prefix key for the first and second args.
398         errCode = SQLiteUtils::BindPrefixKey(statement, 1, prefixKey_);
399         if (errCode != E_OK) {
400             SQLiteUtils::ResetStatement(statement, true, errCode);
401             LOGE("[Query] Get statement when bind prefix key, errCode = %d", errCode);
402             return errCode;
403         }
404         index = 3; // begin from 3rd args
405     }
406 
407     errCode = BindKeysToStmt(keys_, statement, index);
408     if (errCode != E_OK) {
409         SQLiteUtils::ResetStatement(statement, true, errCode);
410         return errCode;
411     }
412 
413     for (const QueryObjNode &objNode : queryObjNodes_) {
414         errCode = BindFieldValue(statement, objNode, index);
415         if (errCode != E_OK) {
416             SQLiteUtils::ResetStatement(statement, true, errCode);
417             LOGE("[Query] Get statement fail when bind field value, errCode = %d", errCode);
418             return errCode;
419         }
420     }
421     return errCode;
422 }
423 
GetQuerySqlStatement(sqlite3 * dbHandle,bool onlyRowid,sqlite3_stmt * & statement)424 int SqliteQueryHelper::GetQuerySqlStatement(sqlite3 *dbHandle, bool onlyRowid, sqlite3_stmt *&statement)
425 {
426     std::string sql;
427     int errCode = GetQuerySql(sql, onlyRowid);
428     if (errCode != E_OK) {
429         return errCode;
430     }
431 
432     errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
433     if (errCode != E_OK) {
434         LOGE("[Query] Get statement fail!");
435         return -E_INVALID_QUERY_FORMAT;
436     }
437     int index = 1;
438     if (hasPrefixKey_) {
439         // bind the prefix key for the first and second args.
440         errCode = SQLiteUtils::BindPrefixKey(statement, 1, prefixKey_);
441         if (errCode != E_OK) {
442             LOGE("[Query] Get statement when bind prefix key, errCode = %d", errCode);
443             return errCode;
444         }
445         index = 3; // begin from 3rd args
446     }
447 
448     errCode = BindKeysToStmt(keys_, statement, index);
449     if (errCode != E_OK) {
450         return errCode;
451     }
452 
453     for (const QueryObjNode &objNode : queryObjNodes_) {
454         errCode = BindFieldValue(statement, objNode, index);
455         if (errCode != E_OK) {
456             LOGE("[Query] Get statement fail when bind field value, errCode = %d", errCode);
457             return errCode;
458         }
459     }
460     return errCode;
461 }
462 
GetCountSqlStatement(sqlite3 * dbHandle,sqlite3_stmt * & countStmt)463 int SqliteQueryHelper::GetCountSqlStatement(sqlite3 *dbHandle, sqlite3_stmt *&countStmt)
464 {
465     std::string countSql;
466     int errCode = GetCountQuerySql(countSql);
467     if (errCode != E_OK) {
468         return errCode;
469     }
470 
471     // bind statement for count
472     errCode = SQLiteUtils::GetStatement(dbHandle, countSql, countStmt);
473     if (errCode != E_OK) {
474         LOGE("Get count statement error:%d", errCode);
475         return -E_INVALID_QUERY_FORMAT;
476     }
477     int index = 1;
478     if (hasPrefixKey_) {
479         // bind the prefix key for the first and second args.
480         errCode = SQLiteUtils::BindPrefixKey(countStmt, 1, prefixKey_);
481         if (errCode != E_OK) {
482             LOGE("[Query] Get count statement fail when bind prefix key, errCode = %d", errCode);
483             return errCode;
484         }
485         index = 3; // begin from 3rd args
486     }
487 
488     errCode = BindKeysToStmt(keys_, countStmt, index);
489     if (errCode != E_OK) {
490         return errCode;
491     }
492 
493     for (const QueryObjNode &objNode : queryObjNodes_) {
494         if (GetSymbolType(objNode.operFlag) == SPECIAL_SYMBOL) {
495             continue;
496         }
497         errCode = BindFieldValue(countStmt, objNode, index);
498         if (errCode != E_OK) {
499             LOGE("[Query] Get count statement fail when bind field value, errCode = %d", errCode);
500             return errCode;
501         }
502     }
503     return errCode;
504 }
505 
GetSyncDataQuerySql(std::string & sql,bool hasSubQuery)506 int SqliteQueryHelper::GetSyncDataQuerySql(std::string &sql, bool hasSubQuery)
507 {
508     if (!isValid_) {
509         return -E_INVALID_QUERY_FORMAT;
510     }
511 
512     if (hasLimit_) {
513         hasSubQuery = true; // Need sub query.
514     } else {
515         isNeedOrderbyKey_ = false; // Need order by timestamp.
516     }
517 
518     sql = AssembleSqlForSuggestIndex(PRE_QUERY_ITEM_SQL + tableName_ + " ", FILTER_REMOTE_QUERY);
519     sql = !hasPrefixKey_ ? sql : (sql + " AND (key>=? AND key<=?) ");
520     sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size()));
521     sql = hasSubQuery ? sql : (sql + " AND (timestamp>=? AND timestamp<?) ");
522 
523     querySql_.clear(); // clear local query sql format
524     int errCode = ToQuerySyncSql(hasSubQuery);
525     if (errCode != E_OK) {
526         LOGE("To query sql fail! errCode[%d]", errCode);
527         return errCode;
528     }
529     sql += querySql_;
530     if (hasSubQuery) {
531         // The last timestamp in one query will be stored in continue token and used for next query.
532         // Therefore all query data must be ordered by timestamp.
533         // When there is limit in SQL, data should be ordered by key in sub query, and timestamp is ordered by outside.
534         sql = "SELECT * FROM ( " + sql + " ) WHERE (timestamp >= ? AND timestamp < ?) ORDER BY timestamp;";
535     }
536     return errCode;
537 }
538 
BindTimeRange(sqlite3_stmt * & statement,int & index,uint64_t beginTime,uint64_t endTime) const539 int SqliteQueryHelper::BindTimeRange(sqlite3_stmt *&statement, int &index, uint64_t beginTime, uint64_t endTime) const
540 {
541     int errCode = SQLiteUtils::BindInt64ToStatement(statement, index++, beginTime);
542     if (errCode != E_OK) {
543         SQLiteUtils::ResetStatement(statement, true, errCode);
544         return errCode;
545     }
546 
547     errCode = SQLiteUtils::BindInt64ToStatement(statement, index++, endTime);
548     if (errCode != E_OK) {
549         SQLiteUtils::ResetStatement(statement, true, errCode);
550     }
551     return errCode;
552 }
553 
BindObjNodes(sqlite3_stmt * & statement,int & index) const554 int SqliteQueryHelper::BindObjNodes(sqlite3_stmt *&statement, int &index) const
555 {
556     int errCode = E_OK;
557     for (const QueryObjNode &objNode : queryObjNodes_) {
558         errCode = BindFieldValue(statement, objNode, index);
559         if (errCode != E_OK) {
560             SQLiteUtils::ResetStatement(statement, true, errCode);
561             LOGE("[Query] Get statement fail when bind field value, errCode = %d", errCode);
562             break;
563         }
564     }
565     return errCode;
566 }
567 
GetQuerySyncStatement(sqlite3 * dbHandle,uint64_t beginTime,uint64_t endTime,sqlite3_stmt * & statement)568 int SqliteQueryHelper::GetQuerySyncStatement(sqlite3 *dbHandle, uint64_t beginTime, uint64_t endTime,
569     sqlite3_stmt *&statement)
570 {
571     bool hasSubQuery = false;
572     if (hasLimit_) {
573         hasSubQuery = true; // Need sub query.
574     } else {
575         isNeedOrderbyKey_ = false; // Need order by timestamp.
576     }
577     std::string sql;
578     int errCode = GetSyncDataQuerySql(sql, hasSubQuery);
579     if (errCode != E_OK) {
580         LOGE("[Query] Get SQL fail!");
581         return -E_INVALID_QUERY_FORMAT;
582     }
583 
584     errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
585     if (errCode != E_OK) {
586         LOGE("[Query] Get statement fail!");
587         return -E_INVALID_QUERY_FORMAT;
588     }
589 
590     int index = 1; // begin with 1.
591     if (hasPrefixKey_) {
592         // bind the prefix key for the first and second args.
593         errCode = SQLiteUtils::BindPrefixKey(statement, index, prefixKey_);
594         if (errCode != E_OK) {
595             SQLiteUtils::ResetStatement(statement, true, errCode);
596             LOGE("[Query] Get statement when bind prefix key, errCode = %d", errCode);
597             return errCode;
598         }
599         index = 3; // begin with 3 next if prefix key exists.
600     }
601 
602     errCode = BindKeysToStmt(keys_, statement, index);
603     if (errCode != E_OK) {
604         SQLiteUtils::ResetStatement(statement, true, errCode);
605         return errCode;
606     }
607 
608     if (hasSubQuery) {
609         // For sub query SQL, timestamp must be last : (prefix key), (objNodes), timestamp.
610         // SQL: SELECT * FROM ( SELECT * FROM sync_data WHERE (flag&0x03=0x02) LIMIT 10 OFFSET 0 ) WHERE (timestamp>=?
611         //      AND timestamp<?) ORDER BY timestamp;
612         errCode = BindObjNodes(statement, index);
613         if (errCode != E_OK) {
614             return errCode;
615         }
616         errCode = BindTimeRange(statement, index, beginTime, endTime);
617     } else {
618         // For normal SQL(no sub query), timestamp is just behind prefix key : (prefix key), timestamp, (ojbNodes).
619         // SQL: SELECT * FROM sync_data WHERE (timestamp>=? AND timestamp<?) AND (flag&0x03=0x02) ORDER BY timestamp;
620         errCode = BindTimeRange(statement, index, beginTime, endTime);
621         if (errCode != E_OK) {
622             return errCode;
623         }
624         errCode = BindObjNodes(statement, index);
625     }
626     return errCode;
627 }
628 
MapRelationalSymbolToSql(const QueryObjNode & queryNode,bool placeholder) const629 std::string SqliteQueryHelper::MapRelationalSymbolToSql(const QueryObjNode &queryNode, bool placeholder) const
630 {
631     if (RELATIONAL_SYMBOL_TO_SQL.find(queryNode.operFlag) == RELATIONAL_SYMBOL_TO_SQL.end()) {
632         return "";
633     };
634     std::string sql = RELATIONAL_SYMBOL_TO_SQL.at(queryNode.operFlag) + MapValueToSql(queryNode, placeholder);
635     if (GetSymbolType(queryNode.operFlag) == RANGE_SYMBOL) {
636         sql += ")";
637     }
638     return sql;
639 }
640 
MapLogicSymbolToSql(const QueryObjNode & queryNode) const641 std::string SqliteQueryHelper::MapLogicSymbolToSql(const QueryObjNode &queryNode) const
642 {
643     if (LOGIC_SYMBOL_TO_SQL.find(queryNode.operFlag) == LOGIC_SYMBOL_TO_SQL.end()) {
644         return "";
645     }
646     return LOGIC_SYMBOL_TO_SQL.at(queryNode.operFlag);
647 }
648 
MapKeywordSymbolToSql(const QueryObjNode & queryNode)649 std::string SqliteQueryHelper::MapKeywordSymbolToSql(const QueryObjNode &queryNode)
650 {
651     std::string sql;
652     switch (queryNode.operFlag) {
653         case QueryObjType::ORDERBY:
654             if (queryNode.fieldValue.size() == SINGLE_FIELD_VALUE_SIZE) {
655                 if (!isOrderByAppeared_) {
656                     sql += "ORDER BY ";
657                 }
658                 sql += GetFieldShape(queryNode);
659                 sql += queryNode.fieldValue[0].boolValue ? "ASC," : "DESC,";
660                 orderByCounts_--;
661                 if (orderByCounts_ == 0) {
662                     sql.pop_back();
663                 }
664                 isOrderByAppeared_ = true;
665             }
666             return sql;
667         case QueryObjType::LIMIT:
668             if (hasPrefixKey_ && !hasOrderBy_ && isNeedOrderbyKey_) {
669                 sql += "ORDER BY key ASC ";
670             }
671             sql += " LIMIT " + std::to_string(queryNode.fieldValue[0].integerValue);
672             sql += " OFFSET " + std::to_string(queryNode.fieldValue[1].integerValue);
673             return sql;
674         default:
675             return "";
676     }
677     return sql;
678 }
679 
MapValueToSql(const QueryObjNode & queryNode,bool placeholder) const680 std::string SqliteQueryHelper::MapValueToSql(const QueryObjNode &queryNode, bool placeholder) const
681 {
682     std::string resultSql;
683     for (size_t i = 0; i < queryNode.fieldValue.size(); i++) {
684         if (i != 0) {
685             resultSql += ", ";
686         }
687         resultSql += placeholder ? "? " : FieldValue2String(queryNode.fieldValue[i], queryNode.type);
688     }
689     return resultSql;
690 }
691 
IsNeedCastWitEmptyValue(const QueryObjNode & queryNode)692 static bool IsNeedCastWitEmptyValue(const QueryObjNode &queryNode)
693 {
694     return (queryNode.operFlag == QueryObjType::IS_NULL || queryNode.operFlag == QueryObjType::IS_NOT_NULL ||
695         queryNode.operFlag == QueryObjType::IN || queryNode.operFlag == QueryObjType::NOT_IN);
696 }
697 
MapCastFuncSql(const QueryObjNode & queryNode,const std::string & accessStr)698 std::string SqliteQueryHelper::MapCastFuncSql(const QueryObjNode &queryNode, const std::string &accessStr)
699 {
700     std::string resultSql;
701     if (queryNode.fieldValue.empty() && !IsNeedCastWitEmptyValue(queryNode)) {
702         return resultSql;
703     }
704     // fieldPath and isQueryable had been checked ok in the previous code, So here parse path and get type won't fail.
705     FieldPath fieldPath;
706     SchemaUtils::ParseAndCheckFieldPath(queryNode.fieldName, fieldPath);
707     FieldType fieldType = FieldType::LEAF_FIELD_INTEGER;
708     schema_.CheckQueryableAndGetFieldType(fieldPath, fieldType);
709     resultSql += SchemaObject::GenerateExtractSQL(schema_.GetSchemaType(), fieldPath, fieldType,
710         schema_.GetSkipSize(), accessStr);
711     isNeedOrderbyKey_ = false; // When index by value, No need order by key!
712     return resultSql;
713 }
714 
BindFieldValue(sqlite3_stmt * statement,const QueryObjNode & queryNode,int & index) const715 int SqliteQueryHelper::BindFieldValue(sqlite3_stmt *statement, const QueryObjNode &queryNode, int &index) const
716 {
717     SymbolType symbolType = GetSymbolType(queryNode.operFlag);
718     if (symbolType != COMPARE_SYMBOL && symbolType != RELATIONAL_SYMBOL && symbolType != RANGE_SYMBOL) {
719         return E_OK;
720     }
721 
722     int errCode = SQLITE_OK;
723     for (size_t i = 0; i < queryNode.fieldValue.size(); i++) {
724         if (queryNode.type == QueryValueType::VALUE_TYPE_BOOL) {
725             errCode = sqlite3_bind_int(statement, index, queryNode.fieldValue[i].boolValue);
726         } else if (queryNode.type == QueryValueType::VALUE_TYPE_INTEGER) {
727             errCode = sqlite3_bind_int(statement, index, queryNode.fieldValue[i].integerValue);
728         } else if (queryNode.type == QueryValueType::VALUE_TYPE_LONG) {
729             errCode = sqlite3_bind_int64(statement, index, queryNode.fieldValue[i].longValue);
730         } else if (queryNode.type == QueryValueType::VALUE_TYPE_DOUBLE) {
731             errCode = sqlite3_bind_double(statement, index, queryNode.fieldValue[i].doubleValue);
732         } else {
733             if (queryNode.fieldValue[i].stringValue.size() > MAX_SQLITE_BIND_SIZE) {
734                 return -E_MAX_LIMITS;
735             }
736             errCode = sqlite3_bind_text(statement, index, queryNode.fieldValue[i].stringValue.c_str(),
737                 queryNode.fieldValue[i].stringValue.size(), SQLITE_TRANSIENT);
738         }
739         if (errCode != SQLITE_OK) {
740             break;
741         }
742         index++;
743     }
744     return SQLiteUtils::MapSQLiteErrno(errCode);
745 }
746 
MapCastTypeSql(const FieldType & type) const747 std::string SqliteQueryHelper::MapCastTypeSql(const FieldType &type) const
748 {
749     switch (type) {
750         case FieldType::LEAF_FIELD_BOOL:
751         case FieldType::LEAF_FIELD_INTEGER:
752         case FieldType::LEAF_FIELD_LONG:
753             return "INT";
754         case FieldType::LEAF_FIELD_DOUBLE:
755             return "REAL";
756         case FieldType::LEAF_FIELD_STRING:
757             return "TEXT";
758         case FieldType::LEAF_FIELD_NULL:
759             return "NULL";
760         default:
761             return "";
762     }
763 }
764 
GetFieldShape(const QueryObjNode & queryNode,const std::string & accessStr)765 std::string SqliteQueryHelper::GetFieldShape(const QueryObjNode &queryNode, const std::string &accessStr)
766 {
767     if (isRelationalQuery_) {
768         // For relational query, $. prefix is not permitted, so need not extract json. Return directly will be OK.
769         return "a." + queryNode.fieldName + " ";
770     }
771     return MapCastFuncSql(queryNode, accessStr);
772 }
773 
ParseQueryExpression(const QueryObjNode & queryNode,std::string & querySql,const std::string & accessStr,bool placeholder)774 int SqliteQueryHelper::ParseQueryExpression(const QueryObjNode &queryNode, std::string &querySql,
775     const std::string &accessStr, bool placeholder)
776 {
777     SymbolType symbolType = GetSymbolType(queryNode.operFlag);
778     if (symbolType == RANGE_SYMBOL && queryNode.fieldValue.size() > MAX_CONDITIONS_SIZE) {
779         LOGE("[Query][Parse][Expression] conditions is too many!");
780         return -E_MAX_LIMITS;
781     }
782 
783     if (symbolType == COMPARE_SYMBOL || symbolType == RELATIONAL_SYMBOL || symbolType == RANGE_SYMBOL) {
784         querySql += GetFieldShape(queryNode, accessStr);
785         querySql += MapRelationalSymbolToSql(queryNode, placeholder);
786     } else if (symbolType == LOGIC_SYMBOL || symbolType == LINK_SYMBOL) {
787         querySql += MapLogicSymbolToSql(queryNode);
788     } else {
789         querySql += MapKeywordSymbolToSql(queryNode);
790     }
791 
792     if (querySql.size() > MAX_SQL_LEN) {
793         LOGE("[Query][Parse][Expression] Sql is too long!");
794         return -E_MAX_LIMITS;
795     }
796     return E_OK;
797 }
798 
AssembleSqlForSuggestIndex(const std::string & baseSql,const std::string & filter) const799 std::string SqliteQueryHelper::AssembleSqlForSuggestIndex(const std::string &baseSql, const std::string &filter) const
800 {
801     std::string formatIndex = CheckAndFormatSuggestIndex();
802     if (formatIndex.empty()) {
803         return baseSql + filter;
804     }
805 
806     return baseSql + USING_INDEX + "'" + formatIndex + "' " + filter;
807 }
808 
CheckAndFormatSuggestIndex() const809 std::string SqliteQueryHelper::CheckAndFormatSuggestIndex() const
810 {
811     if (suggestIndex_.empty()) {
812         return "";
813     }
814     IndexName indexName;
815     int errCode = SchemaUtils::ParseAndCheckFieldPath(suggestIndex_, indexName);
816     if (errCode != E_OK) {
817         LOGW("Check and format suggest index failed! %d", errCode);
818         return "";
819     }
820 
821     if (!schema_.IsIndexExist(indexName)) {
822         LOGW("The suggest index not exist!");
823         return "";
824     }
825     return SchemaUtils::FieldPathString(indexName);
826 }
827 
MapKeysInSubCondition(const std::string & accessStr) const828 std::string SqliteQueryHelper::MapKeysInSubCondition(const std::string &accessStr) const
829 {
830     std::string resultStr = "hex(" + accessStr + "key) IN (";
831     for (auto iter = keys_.begin(); iter != keys_.end(); iter++) {
832         if (iter != keys_.begin()) {
833             resultStr += ", ";
834         }
835         resultStr += "'" + DBCommon::VectorToHexString(*iter) + "' ";
836     }
837     resultStr += ")";
838     return resultStr;
839 }
840 
GetSubscribeCondition(const std::string & accessStr,std::string & conditionStr)841 int SqliteQueryHelper::GetSubscribeCondition(const std::string &accessStr, std::string &conditionStr)
842 {
843     if (queryObjNodes_.empty()) {
844         conditionStr += " (1 = 1) ";
845         return E_OK;
846     }
847     conditionStr += "(";
848     if (hasPrefixKey_) {
849         conditionStr += "(hex(" + accessStr + "key) LIKE '" + DBCommon::VectorToHexString(prefixKey_) + "%')";
850     }
851 
852     if (!keys_.empty()) {
853         if (hasPrefixKey_) {
854             conditionStr += " AND ";
855         }
856         conditionStr += "(" + MapKeysInSubCondition(accessStr) + ")";
857     }
858 
859     bool isNeedEndBracket = FilterSymbolToAddBracketLink(conditionStr, hasPrefixKey_ || !keys_.empty());
860     int errCode = E_OK;
861     for (const QueryObjNode &objNode : queryObjNodes_) {
862         SymbolType symbolType = GetSymbolType(objNode.operFlag);
863         if (symbolType == SPECIAL_SYMBOL && isNeedEndBracket) {
864             conditionStr += ") ";
865             isNeedEndBracket = false;
866         }
867         errCode = ParseQueryExpression(objNode, conditionStr, accessStr, false);
868         if (errCode != E_OK) {
869             conditionStr.clear();
870             return errCode;
871         }
872     }
873 
874     if (isNeedEndBracket) {
875         conditionStr += ") ";
876     }
877     conditionStr += ")";
878     return errCode;
879 }
880 
GetSubscribeSql(const std::string & subscribeId,TriggerModeEnum mode,std::string & subscribeCondition)881 int SqliteQueryHelper::GetSubscribeSql(const std::string &subscribeId, TriggerModeEnum mode,
882     std::string &subscribeCondition)
883 {
884     if (!isValid_) {
885         return -E_INVALID_QUERY_FORMAT;
886     }
887     int errCode = E_OK;
888     switch (mode) {
889         case TriggerModeEnum::INSERT:
890             errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_NEW, subscribeCondition);
891             break;
892         case TriggerModeEnum::UPDATE:
893             errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_OLD, subscribeCondition);
894             if (errCode != E_OK) {
895                 break;
896             }
897             subscribeCondition += " OR ";
898             errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_NEW, subscribeCondition);
899             break;
900         case TriggerModeEnum::DELETE:
901             errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_OLD, subscribeCondition);
902             break;
903         default:
904             errCode = -INVALID_ARGS;
905     }
906     if (errCode != E_OK) {
907         LOGD("Get subscribe query condition failed. %d", errCode);
908     }
909     return errCode;
910 }
911 
GetRelationalMissQuerySql(const std::vector<std::string> & fieldNames,std::string & sql)912 int SqliteQueryHelper::GetRelationalMissQuerySql(const std::vector<std::string> &fieldNames, std::string &sql)
913 {
914     if (!isValid_) {
915         return -E_INVALID_QUERY_FORMAT;
916     }
917 
918     if (hasPrefixKey_) {
919         LOGE("For relational DB query, prefix key is not supported.");
920         return -E_NOT_SUPPORT;
921     }
922 
923     sql = GetSelectAndFromClauseForRDB(tableName_, fieldNames);
924     sql += GetMissQueryFlagClauseForRDB();
925     sql += GetTimeRangeClauseForRDB();
926     sql += "ORDER BY " + DBConstant::TIMESTAMP_ALIAS + " ASC;";
927     return E_OK;
928 }
929 
GetRelationalSyncDataQuerySql(std::string & sql,bool hasSubQuery,const std::vector<std::string> & fieldNames)930 int SqliteQueryHelper::GetRelationalSyncDataQuerySql(std::string &sql, bool hasSubQuery,
931     const std::vector<std::string> &fieldNames)
932 {
933     if (!isValid_) {
934         return -E_INVALID_QUERY_FORMAT;
935     }
936 
937     if (hasPrefixKey_) {
938         LOGE("For relational DB query, prefix key is not supported.");
939         return -E_NOT_SUPPORT;
940     }
941 
942     sql = AssembleSqlForSuggestIndex(GetSelectAndFromClauseForRDB(tableName_, fieldNames), GetFlagClauseForRDB());
943     sql = hasSubQuery ? sql : (sql + GetTimeRangeClauseForRDB());
944 
945     querySql_.clear(); // clear local query sql format
946     int errCode = ToQuerySyncSql(hasSubQuery, true);
947     if (errCode != E_OK) {
948         LOGE("To query sql fail! errCode[%d]", errCode);
949         return errCode;
950     }
951     sql += querySql_;
952     if (hasSubQuery) {
953         // The last timestamp in one query will be stored in continue token and used for next query.
954         // Therefore all query data must be ordered by timestamp.
955         // When there is limit in SQL, data should be ordered by key in sub query, and timestamp is ordered by outside.
956         sql = GetOuterQueryClauseForRDB(sql);
957     }
958     return errCode;
959 }
960 
GetRelationalMissQueryStatement(sqlite3 * dbHandle,uint64_t beginTime,uint64_t endTime,const std::vector<std::string> & fieldNames,sqlite3_stmt * & statement)961 int SqliteQueryHelper::GetRelationalMissQueryStatement(sqlite3 *dbHandle, uint64_t beginTime, uint64_t endTime,
962     const std::vector<std::string> &fieldNames, sqlite3_stmt *&statement)
963 {
964     std::string sql;
965     int errCode = GetRelationalMissQuerySql(fieldNames, sql);
966     if (errCode != E_OK) {
967         LOGE("[Query] Get SQL fail!");
968         return -E_INVALID_QUERY_FORMAT;
969     }
970 
971     errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
972     if (errCode != E_OK) {
973         LOGE("[Query] Get statement fail!");
974         return -E_INVALID_QUERY_FORMAT;
975     }
976 
977     int index = 1; // begin with 1.
978     return BindTimeRange(statement, index, beginTime, endTime);
979 }
980 
GetRelationalQueryStatement(sqlite3 * dbHandle,uint64_t beginTime,uint64_t endTime,const std::vector<std::string> & fieldNames,sqlite3_stmt * & statement)981 int SqliteQueryHelper::GetRelationalQueryStatement(sqlite3 *dbHandle, uint64_t beginTime, uint64_t endTime,
982     const std::vector<std::string> &fieldNames, sqlite3_stmt *&statement)
983 {
984     bool hasSubQuery = false;
985     if (hasLimit_ || hasOrderBy_) {
986         hasSubQuery = true; // Need sub query.
987     } else {
988         isNeedOrderbyKey_ = false; // Need order by timestamp.
989     }
990     std::string sql;
991     int errCode = GetRelationalSyncDataQuerySql(sql, hasSubQuery, fieldNames);
992     if (errCode != E_OK) {
993         LOGE("[Query] Get SQL fail!");
994         return -E_INVALID_QUERY_FORMAT;
995     }
996 
997     errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
998     if (errCode != E_OK) {
999         LOGE("[Query] Get statement fail!");
1000         return -E_INVALID_QUERY_FORMAT;
1001     }
1002 
1003     int index = 1; // begin with 1.
1004     if (hasSubQuery) {
1005         /**
1006          * SELECT * FROM (
1007          *   SELECT b.data_key,b.device,b.ori_device,b.timestamp as naturalbase_rdb_timestamp,
1008          *          b.wtimestamp,b.flag,b.hash_key,a.*
1009          *   FROM tableName AS a INNER JOIN naturalbase_rdb_log AS b
1010          *   ON a.rowid=b.data_key
1011          *   WHERE (b.flag&0x03=0x02)
1012          *   LIMIT ? OFFSET ? )
1013          * WHERE (naturalbase_rdb_timestamp>=? AND naturalbase_rdb_timestamp<?)
1014          * ORDER BY naturalbase_rdb_timestamp;
1015          */
1016         errCode = BindObjNodes(statement, index);
1017         if (errCode != E_OK) {
1018             return errCode;
1019         }
1020         errCode = BindTimeRange(statement, index, beginTime, endTime);
1021     } else {
1022         /**
1023          * SELECT b.data_key,b.device,b.ori_device,b.timestamp as naturalbase_rdb_timestamp,
1024          *        b.wtimestamp,b.flag,b.hash_key,a.*
1025          * FROM tableName AS a INNER JOIN naturalbase_rdb_log AS b
1026          * ON a.rowid=b.data_key
1027          * WHERE (b.flag&0x03=0x02) AND (naturalbase_rdb_timestamp>=? AND naturalbase_rdb_timestamp<?)
1028          * ORDER BY naturalbase_rdb_timestamp ASC;
1029          */
1030         errCode = BindTimeRange(statement, index, beginTime, endTime);
1031         if (errCode != E_OK) {
1032             return errCode;
1033         }
1034         errCode = BindObjNodes(statement, index);
1035     }
1036     return errCode;
1037 }
1038 
MapKeysInToSql(size_t keysNum) const1039 std::string SqliteQueryHelper::MapKeysInToSql(size_t keysNum) const
1040 {
1041     std::string resultSql = "key IN (";
1042     for (size_t i = 0; i < keysNum; i++) {
1043         if (i != 0) {
1044             resultSql += ", ";
1045         }
1046         resultSql += "? ";
1047     }
1048     resultSql += ") ";
1049     return resultSql;
1050 }
1051 
BindKeysToStmt(const std::set<Key> & keys,sqlite3_stmt * & statement,int & index) const1052 int SqliteQueryHelper::BindKeysToStmt(const std::set<Key> &keys, sqlite3_stmt *&statement, int &index) const
1053 {
1054     if (!keys_.empty()) {
1055         int errCode = E_OK;
1056         for (const auto &key : keys) {
1057             errCode = SQLiteUtils::BindBlobToStatement(statement, index, key);
1058             if (errCode != E_OK) {
1059                 LOGE("[Query] Get statement when bind keys failed, errCode = %d", errCode);
1060                 return errCode;
1061             }
1062             index++;
1063         }
1064     }
1065     return E_OK;
1066 }
1067 }