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 }