1 /*
2  * Copyright (c) 2021-2024 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 "sys_event_query.h"
16 
17 #include <memory>
18 #include <string>
19 #include <utility>
20 
21 #include "doc_query.h"
22 #include "sys_event_database.h"
23 
24 namespace OHOS {
25 namespace HiviewDFX {
26 namespace EventStore {
27 namespace {
28 constexpr double ESP = 0.0000001;
CompareSeqFuncLess(const Entry & entryA,const Entry & entryB)29 bool CompareSeqFuncLess(const Entry& entryA, const Entry& entryB)
30 {
31     return entryA.id < entryB.id;
32 }
33 
CompareSeqFuncGreater(const Entry & entryA,const Entry & entryB)34 bool CompareSeqFuncGreater(const Entry& entryA, const Entry& entryB)
35 {
36     return entryA.id > entryB.id;
37 }
38 
CompareTimestampFuncLess(const Entry & entryA,const Entry & entryB)39 bool CompareTimestampFuncLess(const Entry& entryA, const Entry& entryB)
40 {
41     return entryA.ts < entryB.ts;
42 }
43 
CompareTimestampFuncGreater(const Entry & entryA,const Entry & entryB)44 bool CompareTimestampFuncGreater(const Entry& entryA, const Entry& entryB)
45 {
46     return entryA.ts > entryB.ts;
47 }
48 }
49 
IsNumber() const50 bool FieldValue::IsNumber() const
51 {
52     return (Index() == NUMBER);
53 }
54 
IsString() const55 bool FieldValue::IsString() const
56 {
57     return (Index() == STRING);
58 }
59 
GetString() const60 std::string FieldValue::GetString() const
61 {
62     if (Index() == NUMBER) {
63         return "";
64     }
65     return std::get<STRING>(val_);
66 }
67 
GetFieldNumber() const68 FieldNumber FieldValue::GetFieldNumber() const
69 {
70     if (Index() == STRING) {
71         FieldNumber number(0);
72         return number; // default
73     }
74     return std::get<NUMBER>(val_);
75 }
76 
FormatAsString() const77 std::string FieldValue::FormatAsString() const
78 {
79     if (Index() == STRING) {
80         return std::get<STRING>(val_);
81     }
82     return std::get<NUMBER>(val_).FormatAsString();
83 }
84 
Index() const85 FieldValue::ValueType FieldValue::Index() const
86 {
87     return FieldValue::ValueType(val_.index());
88 }
89 
operator ==(const FieldValue & fieldValue) const90 bool FieldValue::operator==(const FieldValue& fieldValue) const
91 {
92     if (Index() != fieldValue.Index()) {
93         return false;
94     }
95     if (IsNumber()) {
96         return GetFieldNumber() == fieldValue.GetFieldNumber();
97     }
98     if (IsString()) {
99         return GetString() == fieldValue.GetString();
100     }
101     return false;
102 }
103 
operator !=(const FieldValue & fieldValue) const104 bool FieldValue::operator!=(const FieldValue& fieldValue) const
105 {
106     if (Index() != fieldValue.Index()) {
107         return false;
108     }
109     if (IsNumber()) {
110         return GetFieldNumber() != fieldValue.GetFieldNumber();
111     }
112     if (IsString()) {
113         return GetString() != fieldValue.GetString();
114     }
115     return false;
116 }
117 
operator <(const FieldValue & fieldValue) const118 bool FieldValue::operator<(const FieldValue& fieldValue) const
119 {
120     if (Index() != fieldValue.Index()) {
121         return false;
122     }
123     if (IsNumber()) {
124         return GetFieldNumber() < fieldValue.GetFieldNumber();
125     }
126     if (IsString()) {
127         return GetString() < fieldValue.GetString();
128     }
129     return false;
130 }
131 
operator <=(const FieldValue & fieldValue) const132 bool FieldValue::operator<=(const FieldValue& fieldValue) const
133 {
134     if (Index() != fieldValue.Index()) {
135         return false;
136     }
137     if (IsNumber()) {
138         return GetFieldNumber() <= fieldValue.GetFieldNumber();
139     }
140     if (IsString()) {
141         return GetString() <= fieldValue.GetString();
142     }
143     return false;
144 }
145 
operator >(const FieldValue & fieldValue) const146 bool FieldValue::operator>(const FieldValue& fieldValue) const
147 {
148     if (Index() != fieldValue.Index()) {
149         return false;
150     }
151     if (IsNumber()) {
152         return GetFieldNumber() > fieldValue.GetFieldNumber();
153     }
154     if (IsString()) {
155         return GetString() > fieldValue.GetString();
156     }
157     return false;
158 }
159 
operator >=(const FieldValue & fieldValue) const160 bool FieldValue::operator>=(const FieldValue& fieldValue) const
161 {
162     if (Index() != fieldValue.Index()) {
163         return false;
164     }
165     if (IsNumber()) {
166         return GetFieldNumber() >= fieldValue.GetFieldNumber();
167     }
168     if (IsString()) {
169         return GetString() >= fieldValue.GetString();
170     }
171     return false;
172 }
173 
IsStartWith(const FieldValue & fieldValue) const174 bool FieldValue::IsStartWith(const FieldValue& fieldValue) const
175 {
176     if (Index() != fieldValue.Index()) {
177         return false;
178     }
179     if (IsString()) {
180         return GetString().find(fieldValue.GetString()) == 0;
181     }
182     return false;
183 }
184 
IsNotStartWith(const FieldValue & fieldValue) const185 bool FieldValue::IsNotStartWith(const FieldValue& fieldValue) const
186 {
187     if (Index() != fieldValue.Index()) {
188         return false;
189     }
190     if (IsString()) {
191         return !(GetString().find(fieldValue.GetString()) == 0);
192     }
193     return false;
194 }
195 
operator ==(const FieldNumber & fieldNum) const196 bool FieldNumber::operator==(const FieldNumber& fieldNum) const
197 {
198     if ((Index() == DOUBLE) || (fieldNum.Index() == DOUBLE)) {
199         return abs(GetNumber<double>() - fieldNum.GetNumber<double>()) <= ESP;
200     }
201     if (Index() == fieldNum.Index()) {
202         return (Index() == INT) ? (GetNumber<int64_t>() == fieldNum.GetNumber<int64_t>()) :
203             (GetNumber<uint64_t>() == fieldNum.GetNumber<uint64_t>());
204     }
205     if (Index() == INT) {
206         return (GetNumber<int64_t>() >= 0) && (GetNumber<uint64_t>() == fieldNum.GetNumber<uint64_t>());
207     }
208     return (fieldNum.GetNumber<int64_t>() >= 0) && (fieldNum.GetNumber<uint64_t>() == GetNumber<uint64_t>());
209 }
210 
operator !=(const FieldNumber & fieldNum) const211 bool FieldNumber::operator!=(const FieldNumber& fieldNum) const
212 {
213     if ((Index() == DOUBLE) || (fieldNum.Index() == DOUBLE)) {
214         return abs(GetNumber<double>() - fieldNum.GetNumber<double>()) > ESP;
215     }
216     if (Index() == fieldNum.Index()) {
217         return (Index() == INT) ? (GetNumber<int64_t>() != fieldNum.GetNumber<int64_t>()) :
218             (GetNumber<uint64_t>() != fieldNum.GetNumber<uint64_t>());
219     }
220     if (Index() == INT) {
221         return (GetNumber<int64_t>() < 0) || (GetNumber<uint64_t>() != fieldNum.GetNumber<uint64_t>());
222     }
223     return (fieldNum.GetNumber<int64_t>() < 0) || (fieldNum.GetNumber<uint64_t>() != GetNumber<uint64_t>());
224 }
225 
operator <(const FieldNumber & fieldNum) const226 bool FieldNumber::operator<(const FieldNumber& fieldNum) const
227 {
228     if ((Index() == DOUBLE) || (fieldNum.Index() == DOUBLE)) {
229         return (abs(GetNumber<double>() - fieldNum.GetNumber<double>()) > ESP) &&
230             (GetNumber<double>() < fieldNum.GetNumber<double>());
231     }
232     if (Index() == fieldNum.Index()) {
233         return (Index() == INT) ? (GetNumber<int64_t>() < fieldNum.GetNumber<int64_t>()) :
234             (GetNumber<uint64_t>() < fieldNum.GetNumber<uint64_t>());
235     }
236     if (Index() == INT) {
237         return (GetNumber<int64_t>() < 0) || (GetNumber<uint64_t>() < fieldNum.GetNumber<uint64_t>());
238     }
239     return (fieldNum.GetNumber<int64_t>() >= 0) && (GetNumber<uint64_t>() < fieldNum.GetNumber<uint64_t>());
240 }
241 
operator <=(const FieldNumber & fieldNum) const242 bool FieldNumber::operator<=(const FieldNumber& fieldNum) const
243 {
244     if ((Index() == DOUBLE) || (fieldNum.Index() == DOUBLE)) {
245         return (abs(GetNumber<double>() - fieldNum.GetNumber<double>()) <= ESP) ||
246             (GetNumber<double>() < fieldNum.GetNumber<double>());
247     }
248     if (Index() == fieldNum.Index()) {
249         return (Index() == INT) ? (GetNumber<int64_t>() <= fieldNum.GetNumber<int64_t>()) :
250             (GetNumber<uint64_t>() <= fieldNum.GetNumber<uint64_t>());
251     }
252     if (Index() == INT) {
253         return (GetNumber<int64_t>() < 0) || (GetNumber<uint64_t>() <= fieldNum.GetNumber<uint64_t>());
254     }
255     return (fieldNum.GetNumber<int64_t>() >= 0) && (GetNumber<uint64_t>() <= fieldNum.GetNumber<uint64_t>());
256 }
257 
operator >(const FieldNumber & fieldNum) const258 bool FieldNumber::operator>(const FieldNumber& fieldNum) const
259 {
260     if ((Index() == DOUBLE) || (fieldNum.Index() == DOUBLE)) {
261         return (abs(GetNumber<double>() - fieldNum.GetNumber<double>()) > ESP) &&
262             (GetNumber<double>() > fieldNum.GetNumber<double>());
263     }
264     if (Index() == fieldNum.Index()) {
265         return (Index() == INT) ? (GetNumber<int64_t>() > fieldNum.GetNumber<int64_t>()) :
266             (GetNumber<uint64_t>() > fieldNum.GetNumber<uint64_t>());
267     }
268     if (Index() == INT) {
269         return (GetNumber<int64_t>() >= 0) && (GetNumber<uint64_t>() > fieldNum.GetNumber<uint64_t>());
270     }
271     return (fieldNum.GetNumber<int64_t>() < 0) || (GetNumber<uint64_t>() > fieldNum.GetNumber<uint64_t>());
272 }
273 
operator >=(const FieldNumber & fieldNum) const274 bool FieldNumber::operator>=(const FieldNumber& fieldNum) const
275 {
276     if ((Index() == DOUBLE) || (fieldNum.Index() == DOUBLE)) {
277         return (abs(GetNumber<double>() - fieldNum.GetNumber<double>()) <= ESP) ||
278             (GetNumber<double>() > fieldNum.GetNumber<double>());
279     }
280     if (Index() == fieldNum.Index()) {
281         return (Index() == INT) ? (GetNumber<int64_t>() >= fieldNum.GetNumber<int64_t>()) :
282             (GetNumber<uint64_t>() >= fieldNum.GetNumber<uint64_t>());
283     }
284     if (Index() == INT) {
285         return (GetNumber<int64_t>() >= 0) && (GetNumber<uint64_t>() >= fieldNum.GetNumber<uint64_t>());
286     }
287     return (fieldNum.GetNumber<int64_t>() < 0) || (GetNumber<uint64_t>() >= fieldNum.GetNumber<uint64_t>());
288 }
289 
FormatAsString() const290 std::string FieldNumber::FormatAsString() const
291 {
292     if (Index() == DOUBLE) {
293         return std::to_string(std::get<DOUBLE>(val_));
294     }
295     if (Index() == UINT) {
296         return std::to_string(std::get<UINT>(val_));
297     }
298     return std::to_string(std::get<INT>(val_));
299 }
300 
Index() const301 FieldNumber::ValueType FieldNumber::Index() const
302 {
303     return FieldNumber::ValueType(val_.index());
304 }
305 
And(const Cond & cond)306 Cond &Cond::And(const Cond &cond)
307 {
308     andConds_.emplace_back(cond);
309     return *this;
310 }
311 
IsSimpleCond(const Cond & cond)312 bool Cond::IsSimpleCond(const Cond &cond)
313 {
314     return !cond.col_.empty() && cond.andConds_.empty();
315 }
316 
Traval(DocQuery & docQuery,const Cond & cond)317 void Cond::Traval(DocQuery &docQuery, const Cond &cond)
318 {
319     if (!cond.col_.empty()) {
320         docQuery.And(cond);
321     }
322     if (!cond.andConds_.empty()) {
323         for (auto& andCond : cond.andConds_) {
324             if (IsSimpleCond(andCond)) {
325                 docQuery.And(andCond);
326             } else {
327                 Traval(docQuery, andCond);
328             }
329         }
330     }
331 }
332 
ToString() const333 std::string Cond::ToString() const
334 {
335     std::string output;
336     output.append(col_);
337 
338     switch (op_) {
339         case EQ:
340             output.append(" == ");
341             break;
342         case NE:
343             output.append(" != ");
344             break;
345         case GT:
346             output.append(" > ");
347             break;
348         case GE:
349             output.append(" >= ");
350             break;
351         case LT:
352             output.append(" < ");
353             break;
354         case LE:
355             output.append(" <= ");
356             break;
357         case SW:
358             output.append(" SW ");
359             break;
360         case NSW:
361             output.append(" NSW ");
362             break;
363         default:
364             return "INVALID COND";
365     }
366 
367     output.append(fieldValue_.FormatAsString());
368 
369     return output;
370 }
371 
ResultSet()372 ResultSet::ResultSet(): iter_(eventRecords_.begin()), code_(0), has_(false)
373 {
374 }
375 
~ResultSet()376 ResultSet::~ResultSet()
377 {
378 }
379 
ResultSet(ResultSet && result)380 ResultSet::ResultSet(ResultSet &&result)
381 {
382     eventRecords_ = move(result.eventRecords_);
383     code_ = result.code_;
384     has_ = result.has_;
385     iter_ = result.iter_;
386 }
387 
operator =(ResultSet && result)388 ResultSet& ResultSet::operator = (ResultSet &&result)
389 {
390     eventRecords_ = move(result.eventRecords_);
391     code_ = result.code_;
392     has_ = result.has_;
393     iter_ = result.iter_;
394     return *this;
395 }
396 
GetErrCode() const397 int ResultSet::GetErrCode() const
398 {
399     return code_;
400 }
401 
HasNext() const402 bool ResultSet::HasNext() const
403 {
404     return has_;
405 }
406 
Next()407 ResultSet::RecordIter ResultSet::Next()
408 {
409     if (!has_) {
410         return eventRecords_.end();
411     }
412 
413     auto tempIter = iter_;
414     iter_++;
415     if (iter_ == eventRecords_.end()) {
416         has_ = false;
417     }
418 
419     return tempIter;
420 }
421 
Set(int code,bool has)422 void ResultSet::Set(int code, bool has)
423 {
424     code_ = code;
425     has_ = has;
426     if (eventRecords_.size() > 0) {
427         iter_ = eventRecords_.begin();
428     }
429 }
430 
SysEventQuery(const std::string & domain,const std::vector<std::string> & names)431 SysEventQuery::SysEventQuery(const std::string& domain, const std::vector<std::string>& names)
432     : SysEventQuery(domain, names, 0, INVALID_VALUE_INT, INVALID_VALUE_INT)
433 {}
434 
SysEventQuery(const std::string & domain,const std::vector<std::string> & names,uint32_t type,int64_t toSeq,int64_t fromSeq)435 SysEventQuery::SysEventQuery(const std::string& domain, const std::vector<std::string>& names,
436     uint32_t type, int64_t toSeq, int64_t fromSeq) : queryArg_(domain, names, type, toSeq, fromSeq)
437 {}
438 
Select(const std::vector<std::string> & eventCols)439 SysEventQuery &SysEventQuery::Select(const std::vector<std::string> &eventCols)
440 {
441     return *this;
442 }
443 
Where(const Cond & cond)444 SysEventQuery &SysEventQuery::Where(const Cond &cond)
445 {
446     cond_.And(cond);
447     return *this;
448 }
449 
And(const Cond & cond)450 SysEventQuery &SysEventQuery::And(const Cond &cond)
451 {
452     cond_.And(cond);
453     return *this;
454 }
455 
Order(const std::string & col,bool isAsc)456 SysEventQuery &SysEventQuery::Order(const std::string &col, bool isAsc)
457 {
458     orderCol_ = std::make_pair<>(col, isAsc);
459     return *this;
460 }
461 
BuildDocQuery(DocQuery & docQuery) const462 void SysEventQuery::BuildDocQuery(DocQuery &docQuery) const
463 {
464     Cond::Traval(docQuery, cond_);
465 }
466 
CreateCompareFunc() const467 CompareFunc SysEventQuery::CreateCompareFunc() const
468 {
469     if (orderCol_.first == EventCol::TS) {
470         if (orderCol_.second) {
471             return &CompareTimestampFuncGreater;
472         } else {
473             return &CompareTimestampFuncLess;
474         }
475     } else {
476         if (orderCol_.second) {
477             return &CompareSeqFuncGreater;
478         } else {
479             return &CompareSeqFuncLess;
480         }
481     }
482 }
483 
Execute(int limit,DbQueryTag tag,QueryProcessInfo callerInfo,DbQueryCallback queryCallback)484 ResultSet SysEventQuery::Execute(int limit, DbQueryTag tag, QueryProcessInfo callerInfo,
485     DbQueryCallback queryCallback)
486 {
487     limit_ = limit;
488 
489     // sort query return events
490     EntryQueue entries(CreateCompareFunc());
491     int retCode = SysEventDatabase::GetInstance().Query(*this, entries);
492     ResultSet resultSet;
493     if (retCode != DOC_STORE_SUCCESS) {
494         resultSet.Set(retCode, false);
495         return resultSet;
496     }
497     if (entries.empty()) {
498         resultSet.Set(DOC_STORE_SUCCESS, false);
499         return resultSet;
500     }
501 
502     // for an internal query, the number of returned query results need to be limit
503     int resultNum = static_cast<int>(entries.size());
504     if (resultNum > limit && tag.isInnerQuery) {
505         resultNum = limit;
506     }
507     while (!entries.empty() && resultNum >= 0) {
508         auto& entry = entries.top();
509         resultSet.eventRecords_.emplace_back("", nullptr, entry.data, entry.id, entry.sysVersion, entry.patchVersion);
510         entries.pop();
511         resultNum--;
512     }
513     resultSet.Set(DOC_STORE_SUCCESS, true);
514     return resultSet;
515 }
516 
ToString() const517 std::string SysEventQuery::ToString() const
518 {
519     std::string output;
520     output.append("domain=[").append(queryArg_.domain).append("], names=[");
521     for (auto& name : queryArg_.names) {
522         output.append(name);
523         if (&name != &queryArg_.names.back()) {
524             output.append(",");
525         }
526     }
527     output.append("], type=[").append(std::to_string(queryArg_.type)).append("], condition=[");
528     DocQuery docQuery;
529     BuildDocQuery(docQuery);
530     output.append(docQuery.ToString()).append("]");
531     return output;
532 }
533 } // EventStore
534 } // namespace HiviewDFX
535 } // namespace OHOS
536