• 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     return sql;
682 }
683 
MapValueToSql(const QueryObjNode & queryNode,bool placeholder) const684 std::string SqliteQueryHelper::MapValueToSql(const QueryObjNode &queryNode, bool placeholder) const
685 {
686     std::string resultSql;
687     for (size_t i = 0; i < queryNode.fieldValue.size(); i++) {
688         if (i != 0) {
689             resultSql += ", ";
690         }
691         resultSql += placeholder ? "? " : FieldValue2String(queryNode.fieldValue[i], queryNode.type);
692     }
693     return resultSql;
694 }
695 
IsNeedCastWitEmptyValue(const QueryObjNode & queryNode)696 static bool IsNeedCastWitEmptyValue(const QueryObjNode &queryNode)
697 {
698     return (queryNode.operFlag == QueryObjType::IS_NULL || queryNode.operFlag == QueryObjType::IS_NOT_NULL ||
699         queryNode.operFlag == QueryObjType::IN || queryNode.operFlag == QueryObjType::NOT_IN);
700 }
701 
MapCastFuncSql(const QueryObjNode & queryNode,const std::string & accessStr)702 std::string SqliteQueryHelper::MapCastFuncSql(const QueryObjNode &queryNode, const std::string &accessStr)
703 {
704     std::string resultSql;
705     if (queryNode.fieldValue.empty() && !IsNeedCastWitEmptyValue(queryNode)) {
706         return resultSql;
707     }
708     // fieldPath and isQueryable had been checked ok in the previous code, So here parse path and get type won't fail.
709     FieldPath fieldPath;
710     SchemaUtils::ParseAndCheckFieldPath(queryNode.fieldName, fieldPath);
711     FieldType fieldType = FieldType::LEAF_FIELD_INTEGER;
712     schema_.CheckQueryableAndGetFieldType(fieldPath, fieldType);
713     resultSql += SchemaObject::GenerateExtractSQL(schema_.GetSchemaType(), fieldPath, fieldType,
714         schema_.GetSkipSize(), accessStr);
715     isNeedOrderbyKey_ = false; // When index by value, No need order by key!
716     return resultSql;
717 }
718 
BindFieldValue(sqlite3_stmt * statement,const QueryObjNode & queryNode,int & index) const719 int SqliteQueryHelper::BindFieldValue(sqlite3_stmt *statement, const QueryObjNode &queryNode, int &index) const
720 {
721     SymbolType symbolType = GetSymbolType(queryNode.operFlag);
722     if (symbolType != COMPARE_SYMBOL && symbolType != RELATIONAL_SYMBOL && symbolType != RANGE_SYMBOL) {
723         return E_OK;
724     }
725 
726     int errCode = SQLITE_OK;
727     for (size_t i = 0; i < queryNode.fieldValue.size(); i++) {
728         if (queryNode.type == QueryValueType::VALUE_TYPE_BOOL) {
729             errCode = sqlite3_bind_int(statement, index, queryNode.fieldValue[i].boolValue);
730         } else if (queryNode.type == QueryValueType::VALUE_TYPE_INTEGER) {
731             errCode = sqlite3_bind_int(statement, index, queryNode.fieldValue[i].integerValue);
732         } else if (queryNode.type == QueryValueType::VALUE_TYPE_LONG) {
733             errCode = sqlite3_bind_int64(statement, index, queryNode.fieldValue[i].longValue);
734         } else if (queryNode.type == QueryValueType::VALUE_TYPE_DOUBLE) {
735             errCode = sqlite3_bind_double(statement, index, queryNode.fieldValue[i].doubleValue);
736         } else {
737             if (queryNode.fieldValue[i].stringValue.size() > MAX_SQLITE_BIND_SIZE) {
738                 return -E_MAX_LIMITS;
739             }
740             errCode = sqlite3_bind_text(statement, index, queryNode.fieldValue[i].stringValue.c_str(),
741                 queryNode.fieldValue[i].stringValue.size(), SQLITE_TRANSIENT);
742         }
743         if (errCode != SQLITE_OK) {
744             break;
745         }
746         index++;
747     }
748     return SQLiteUtils::MapSQLiteErrno(errCode);
749 }
750 
MapCastTypeSql(const FieldType & type) const751 std::string SqliteQueryHelper::MapCastTypeSql(const FieldType &type) const
752 {
753     switch (type) {
754         case FieldType::LEAF_FIELD_BOOL:
755         case FieldType::LEAF_FIELD_INTEGER:
756         case FieldType::LEAF_FIELD_LONG:
757             return "INT";
758         case FieldType::LEAF_FIELD_DOUBLE:
759             return "REAL";
760         case FieldType::LEAF_FIELD_STRING:
761             return "TEXT";
762         case FieldType::LEAF_FIELD_NULL:
763             return "NULL";
764         default:
765             return "";
766     }
767 }
768 
GetFieldShape(const QueryObjNode & queryNode,const std::string & accessStr)769 std::string SqliteQueryHelper::GetFieldShape(const QueryObjNode &queryNode, const std::string &accessStr)
770 {
771     if (isRelationalQuery_) {
772         // For relational query, $. prefix is not permitted, so need not extract json. Return directly will be OK.
773         return "a." + queryNode.fieldName + " ";
774     }
775     return MapCastFuncSql(queryNode, accessStr);
776 }
777 
ParseQueryExpression(const QueryObjNode & queryNode,std::string & querySql,const std::string & accessStr,bool placeholder)778 int SqliteQueryHelper::ParseQueryExpression(const QueryObjNode &queryNode, std::string &querySql,
779     const std::string &accessStr, bool placeholder)
780 {
781     SymbolType symbolType = GetSymbolType(queryNode.operFlag);
782     if (symbolType == RANGE_SYMBOL && queryNode.fieldValue.size() > MAX_CONDITIONS_SIZE) {
783         LOGE("[Query][Parse][Expression] conditions is too many!");
784         return -E_MAX_LIMITS;
785     }
786 
787     if (symbolType == COMPARE_SYMBOL || symbolType == RELATIONAL_SYMBOL || symbolType == RANGE_SYMBOL) {
788         querySql += GetFieldShape(queryNode, accessStr);
789         querySql += MapRelationalSymbolToSql(queryNode, placeholder);
790     } else if (symbolType == LOGIC_SYMBOL || symbolType == LINK_SYMBOL) {
791         querySql += MapLogicSymbolToSql(queryNode);
792     } else {
793         querySql += MapKeywordSymbolToSql(queryNode);
794     }
795 
796     if (querySql.size() > MAX_SQL_LEN) {
797         LOGE("[Query][Parse][Expression] Sql is too long!");
798         return -E_MAX_LIMITS;
799     }
800     return E_OK;
801 }
802 
AssembleSqlForSuggestIndex(const std::string & baseSql,const std::string & filter) const803 std::string SqliteQueryHelper::AssembleSqlForSuggestIndex(const std::string &baseSql, const std::string &filter) const
804 {
805     std::string formatIndex = CheckAndFormatSuggestIndex();
806     if (formatIndex.empty()) {
807         return baseSql + filter;
808     }
809 
810     return baseSql + USING_INDEX + "'" + formatIndex + "' " + filter;
811 }
812 
CheckAndFormatSuggestIndex() const813 std::string SqliteQueryHelper::CheckAndFormatSuggestIndex() const
814 {
815     if (suggestIndex_.empty()) {
816         return "";
817     }
818     IndexName indexName;
819     int errCode = SchemaUtils::ParseAndCheckFieldPath(suggestIndex_, indexName);
820     if (errCode != E_OK) {
821         LOGW("Check and format suggest index failed! %d", errCode);
822         return "";
823     }
824 
825     if (!schema_.IsIndexExist(indexName)) {
826         LOGW("The suggest index not exist!");
827         return "";
828     }
829     return SchemaUtils::FieldPathString(indexName);
830 }
831 
MapKeysInSubCondition(const std::string & accessStr) const832 std::string SqliteQueryHelper::MapKeysInSubCondition(const std::string &accessStr) const
833 {
834     std::string resultStr = "hex(" + accessStr + "key) IN (";
835     for (auto iter = keys_.begin(); iter != keys_.end(); iter++) {
836         if (iter != keys_.begin()) {
837             resultStr += ", ";
838         }
839         resultStr += "'" + DBCommon::VectorToHexString(*iter) + "' ";
840     }
841     resultStr += ")";
842     return resultStr;
843 }
844 
GetSubscribeCondition(const std::string & accessStr,std::string & conditionStr)845 int SqliteQueryHelper::GetSubscribeCondition(const std::string &accessStr, std::string &conditionStr)
846 {
847     if (queryObjNodes_.empty()) {
848         conditionStr += " (1 = 1) ";
849         return E_OK;
850     }
851 
852     bool hasQueryByValue = std::any_of(queryObjNodes_.begin(), queryObjNodes_.end(), [](const QueryObjNode &it) {
853         return GetSymbolType(it.operFlag) == SymbolType::COMPARE_SYMBOL ||
854             GetSymbolType(it.operFlag) == SymbolType::RELATIONAL_SYMBOL ||
855             GetSymbolType(it.operFlag) == SymbolType::RANGE_SYMBOL;
856     });
857     if (hasQueryByValue) {
858         // json_extract_by_path function will return error when value is empty, check it before when query by value
859         conditionStr += "((length(" + accessStr + "value) != 0 AND " + accessStr + "value IS NOT NULL) AND ";
860     } else {
861         conditionStr += "(";
862     }
863 
864     if (hasPrefixKey_) {
865         conditionStr += "(hex(" + accessStr + "key) LIKE '" + DBCommon::VectorToHexString(prefixKey_) + "%')";
866     }
867 
868     if (!keys_.empty()) {
869         if (hasPrefixKey_) {
870             conditionStr += " AND ";
871         }
872         conditionStr += "(" + MapKeysInSubCondition(accessStr) + ")";
873     }
874 
875     bool isNeedEndBracket = FilterSymbolToAddBracketLink(conditionStr, hasPrefixKey_ || !keys_.empty());
876     int errCode = E_OK;
877     for (const QueryObjNode &objNode : queryObjNodes_) {
878         SymbolType symbolType = GetSymbolType(objNode.operFlag);
879         if (symbolType == SPECIAL_SYMBOL && isNeedEndBracket) {
880             conditionStr += ") ";
881             isNeedEndBracket = false;
882         }
883         errCode = ParseQueryExpression(objNode, conditionStr, accessStr, false);
884         if (errCode != E_OK) {
885             conditionStr.clear();
886             return errCode;
887         }
888     }
889 
890     if (isNeedEndBracket) {
891         conditionStr += ") ";
892     }
893     conditionStr += ")";
894     return errCode;
895 }
896 
GetSubscribeSql(const std::string & subscribeId,TriggerModeEnum mode,std::string & subscribeCondition)897 int SqliteQueryHelper::GetSubscribeSql(const std::string &subscribeId, TriggerModeEnum mode,
898     std::string &subscribeCondition)
899 {
900     if (!isValid_) {
901         return -E_INVALID_QUERY_FORMAT;
902     }
903     int errCode = E_OK;
904     switch (mode) {
905         case TriggerModeEnum::INSERT:
906             errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_NEW, subscribeCondition);
907             break;
908         case TriggerModeEnum::UPDATE:
909             errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_OLD, subscribeCondition);
910             if (errCode != E_OK) {
911                 break;
912             }
913             subscribeCondition += " OR ";
914             errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_NEW, subscribeCondition);
915             break;
916         case TriggerModeEnum::DELETE:
917             errCode = GetSubscribeCondition(DBConstant::TRIGGER_REFERENCES_OLD, subscribeCondition);
918             break;
919         default:
920             errCode = -INVALID_ARGS;
921     }
922     if (errCode != E_OK) {
923         LOGD("Get subscribe query condition failed. %d", errCode);
924     }
925     return errCode;
926 }
927 
GetRelationalMissQuerySql(const std::vector<std::string> & fieldNames,std::string & sql)928 int SqliteQueryHelper::GetRelationalMissQuerySql(const std::vector<std::string> &fieldNames, std::string &sql)
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 = GetSelectAndFromClauseForRDB(tableName_, fieldNames);
940     sql += GetMissQueryFlagClauseForRDB();
941     sql += GetTimeRangeClauseForRDB();
942     sql += "ORDER BY " + DBConstant::TIMESTAMP_ALIAS + " ASC;";
943     return E_OK;
944 }
945 
GetRelationalSyncDataQuerySql(std::string & sql,bool hasSubQuery,const std::vector<std::string> & fieldNames)946 int SqliteQueryHelper::GetRelationalSyncDataQuerySql(std::string &sql, bool hasSubQuery,
947     const std::vector<std::string> &fieldNames)
948 {
949     if (!isValid_) {
950         return -E_INVALID_QUERY_FORMAT;
951     }
952 
953     if (hasPrefixKey_) {
954         LOGE("For relational DB query, prefix key is not supported.");
955         return -E_NOT_SUPPORT;
956     }
957 
958     sql = AssembleSqlForSuggestIndex(GetSelectAndFromClauseForRDB(tableName_, fieldNames), GetFlagClauseForRDB());
959     sql = hasSubQuery ? sql : (sql + GetTimeRangeClauseForRDB());
960 
961     querySql_.clear(); // clear local query sql format
962     int errCode = ToQuerySyncSql(hasSubQuery, true);
963     if (errCode != E_OK) {
964         LOGE("To query sql fail! errCode[%d]", errCode);
965         return errCode;
966     }
967     sql += querySql_;
968     if (hasSubQuery) {
969         // The last timestamp in one query will be stored in continue token and used for next query.
970         // Therefore all query data must be ordered by timestamp.
971         // When there is limit in SQL, data should be ordered by key in sub query, and timestamp is ordered by outside.
972         sql = GetOuterQueryClauseForRDB(sql);
973     }
974     return errCode;
975 }
976 
GetRelationalMissQueryStatement(sqlite3 * dbHandle,uint64_t beginTime,uint64_t endTime,const std::vector<std::string> & fieldNames,sqlite3_stmt * & statement)977 int SqliteQueryHelper::GetRelationalMissQueryStatement(sqlite3 *dbHandle, uint64_t beginTime, uint64_t endTime,
978     const std::vector<std::string> &fieldNames, sqlite3_stmt *&statement)
979 {
980     std::string sql;
981     int errCode = GetRelationalMissQuerySql(fieldNames, sql);
982     if (errCode != E_OK) {
983         LOGE("[Query] Get SQL fail!");
984         return -E_INVALID_QUERY_FORMAT;
985     }
986 
987     errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
988     if (errCode != E_OK) {
989         LOGE("[Query] Get statement fail!");
990         return -E_INVALID_QUERY_FORMAT;
991     }
992 
993     int index = 1; // begin with 1.
994     return BindTimeRange(statement, index, beginTime, endTime);
995 }
996 
GetRelationalQueryStatement(sqlite3 * dbHandle,uint64_t beginTime,uint64_t endTime,const std::vector<std::string> & fieldNames,sqlite3_stmt * & statement)997 int SqliteQueryHelper::GetRelationalQueryStatement(sqlite3 *dbHandle, uint64_t beginTime, uint64_t endTime,
998     const std::vector<std::string> &fieldNames, sqlite3_stmt *&statement)
999 {
1000     bool hasSubQuery = false;
1001     if (hasLimit_ || hasOrderBy_) {
1002         hasSubQuery = true; // Need sub query.
1003     } else {
1004         isNeedOrderbyKey_ = false; // Need order by timestamp.
1005     }
1006     std::string sql;
1007     int errCode = GetRelationalSyncDataQuerySql(sql, hasSubQuery, fieldNames);
1008     if (errCode != E_OK) {
1009         LOGE("[Query] Get SQL fail!");
1010         return -E_INVALID_QUERY_FORMAT;
1011     }
1012 
1013     errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement);
1014     if (errCode != E_OK) {
1015         LOGE("[Query] Get statement fail!");
1016         return -E_INVALID_QUERY_FORMAT;
1017     }
1018 
1019     int index = 1; // begin with 1.
1020     if (hasSubQuery) {
1021         /**
1022          * SELECT * FROM (
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)
1028          *   LIMIT ? OFFSET ? )
1029          * WHERE (naturalbase_rdb_timestamp>=? AND naturalbase_rdb_timestamp<?)
1030          * ORDER BY naturalbase_rdb_timestamp;
1031          */
1032         errCode = BindObjNodes(statement, index);
1033         if (errCode != E_OK) {
1034             return errCode;
1035         }
1036         errCode = BindTimeRange(statement, index, beginTime, endTime);
1037     } else {
1038         /**
1039          * SELECT b.data_key,b.device,b.ori_device,b.timestamp as naturalbase_rdb_timestamp,
1040          *        b.wtimestamp,b.flag,b.hash_key,a.*
1041          * FROM tableName AS a INNER JOIN naturalbase_rdb_log AS b
1042          * ON a.rowid=b.data_key
1043          * WHERE (b.flag&0x03=0x02) AND (naturalbase_rdb_timestamp>=? AND naturalbase_rdb_timestamp<?)
1044          * ORDER BY naturalbase_rdb_timestamp ASC;
1045          */
1046         errCode = BindTimeRange(statement, index, beginTime, endTime);
1047         if (errCode != E_OK) {
1048             return errCode;
1049         }
1050         errCode = BindObjNodes(statement, index);
1051     }
1052     return errCode;
1053 }
1054 
MapKeysInToSql(size_t keysNum) const1055 std::string SqliteQueryHelper::MapKeysInToSql(size_t keysNum) const
1056 {
1057     std::string resultSql = "key IN (";
1058     for (size_t i = 0; i < keysNum; i++) {
1059         if (i != 0) {
1060             resultSql += ", ";
1061         }
1062         resultSql += "? ";
1063     }
1064     resultSql += ") ";
1065     return resultSql;
1066 }
1067 
BindKeysToStmt(const std::set<Key> & keys,sqlite3_stmt * & statement,int & index) const1068 int SqliteQueryHelper::BindKeysToStmt(const std::set<Key> &keys, sqlite3_stmt *&statement, int &index) const
1069 {
1070     if (!keys_.empty()) {
1071         int errCode = E_OK;
1072         for (const auto &key : keys) {
1073             errCode = SQLiteUtils::BindBlobToStatement(statement, index, key);
1074             if (errCode != E_OK) {
1075                 LOGE("[Query] Get statement when bind keys failed, errCode = %d", errCode);
1076                 return errCode;
1077             }
1078             index++;
1079         }
1080     }
1081     return E_OK;
1082 }
1083 }