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 }