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