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