1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/trace_processor/sqlite/query_constraints.h"
18
19 #include <sqlite3.h>
20
21 #include <string>
22
23 #include "perfetto/ext/base/string_splitter.h"
24
25 namespace perfetto {
26 namespace trace_processor {
27
28 QueryConstraints::QueryConstraints() = default;
29 QueryConstraints::~QueryConstraints() = default;
30 QueryConstraints::QueryConstraints(QueryConstraints&&) noexcept = default;
31 QueryConstraints& QueryConstraints::operator=(QueryConstraints&&) = default;
32
FreeSqliteString(char * resource)33 int QueryConstraints::FreeSqliteString(char* resource) {
34 sqlite3_free(resource);
35 return 0;
36 }
37
operator ==(const QueryConstraints & other) const38 bool QueryConstraints::operator==(const QueryConstraints& other) const {
39 if ((other.constraints().size() != constraints().size()) ||
40 (other.order_by().size() != order_by().size())) {
41 return false;
42 }
43
44 for (size_t i = 0; i < constraints().size(); ++i) {
45 if ((constraints()[i].column != other.constraints()[i].column) ||
46 (constraints()[i].op != other.constraints()[i].op)) {
47 return false;
48 }
49 }
50
51 for (size_t i = 0; i < order_by().size(); ++i) {
52 if ((order_by()[i].iColumn != other.order_by()[i].iColumn) ||
53 (order_by()[i].desc != other.order_by()[i].desc)) {
54 return false;
55 }
56 }
57
58 return true;
59 }
60
AddConstraint(int column,unsigned char op,int aconstraint_idx)61 void QueryConstraints::AddConstraint(int column,
62 unsigned char op,
63 int aconstraint_idx) {
64 Constraint c{};
65 c.column = column;
66 c.op = op;
67 c.a_constraint_idx = aconstraint_idx;
68 constraints_.emplace_back(c);
69 }
70
AddOrderBy(int column,unsigned char desc)71 void QueryConstraints::AddOrderBy(int column, unsigned char desc) {
72 OrderBy ob{};
73 ob.iColumn = column;
74 ob.desc = desc;
75 order_by_.emplace_back(ob);
76 }
77
ToNewSqlite3String() const78 QueryConstraints::SqliteString QueryConstraints::ToNewSqlite3String() const {
79 std::string str_result;
80 str_result.reserve(512);
81 str_result.append("C");
82 str_result.append(std::to_string(constraints_.size()));
83 str_result.append(",");
84 for (const auto& cs : constraints_) {
85 str_result.append(std::to_string(cs.column));
86 str_result.append(",");
87 str_result.append(std::to_string(cs.op));
88 str_result.append(",");
89 }
90 str_result.append("O");
91 str_result.append(std::to_string(order_by_.size()));
92 str_result.append(",");
93 for (const auto& ob : order_by_) {
94 str_result.append(std::to_string(ob.iColumn));
95 str_result.append(",");
96 str_result.append(std::to_string(ob.desc));
97 str_result.append(",");
98 }
99
100 // The last char is a "," so overwriting with the null terminator on purpose.
101 SqliteString result(
102 static_cast<char*>(sqlite3_malloc(static_cast<int>(str_result.size()))));
103 strncpy(result.get(), str_result.c_str(), str_result.size());
104 (*result)[str_result.size() - 1] = '\0';
105
106 return result;
107 }
108
FromString(const char * idxStr)109 QueryConstraints QueryConstraints::FromString(const char* idxStr) {
110 QueryConstraints qc;
111
112 base::StringSplitter splitter(std::string(idxStr), ',');
113
114 PERFETTO_CHECK(splitter.Next() && splitter.cur_token_size() > 1);
115 // The '+ 1' skips the letter 'C' in the first token.
116 long num_constraints = strtol(splitter.cur_token() + 1, nullptr, 10);
117 for (int i = 0; i < num_constraints; ++i) {
118 PERFETTO_CHECK(splitter.Next());
119 int col = static_cast<int>(strtol(splitter.cur_token(), nullptr, 10));
120 PERFETTO_CHECK(splitter.Next());
121 unsigned char op =
122 static_cast<unsigned char>(strtol(splitter.cur_token(), nullptr, 10));
123 qc.AddConstraint(col, op, 0);
124 }
125
126 PERFETTO_CHECK(splitter.Next() && splitter.cur_token_size() > 1);
127 // The '+ 1' skips the letter 'O' in the current token.
128 long num_order_by = strtol(splitter.cur_token() + 1, nullptr, 10);
129 for (int i = 0; i < num_order_by; ++i) {
130 PERFETTO_CHECK(splitter.Next());
131 int col = static_cast<int>(strtol(splitter.cur_token(), nullptr, 10));
132 PERFETTO_CHECK(splitter.Next());
133 unsigned char desc =
134 static_cast<unsigned char>(strtol(splitter.cur_token(), nullptr, 10));
135 qc.AddOrderBy(col, desc);
136 }
137
138 PERFETTO_DCHECK(!splitter.Next());
139 return qc;
140 }
141
142 } // namespace trace_processor
143 } // namespace perfetto
144