• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/window_operator_table.h"
18 
19 #include "src/trace_processor/sqlite/sqlite_utils.h"
20 
21 namespace perfetto {
22 namespace trace_processor {
23 
24 namespace {
25 using namespace sqlite_utils;
26 }  // namespace
27 
WindowOperatorTable(sqlite3 *,const TraceStorage *)28 WindowOperatorTable::WindowOperatorTable(sqlite3*, const TraceStorage*) {}
29 
RegisterTable(sqlite3 * db,const TraceStorage * storage)30 void WindowOperatorTable::RegisterTable(sqlite3* db,
31                                         const TraceStorage* storage) {
32   SqliteTable::Register<WindowOperatorTable>(db, storage, "window", true);
33 }
34 
Init(int,const char * const *,Schema * schema)35 util::Status WindowOperatorTable::Init(int,
36                                        const char* const*,
37                                        Schema* schema) {
38   const bool kHidden = true;
39   *schema = Schema(
40       {
41           // These are the operator columns:
42           SqliteTable::Column(Column::kRowId, "rowid", SqlValue::Type::kLong,
43                               kHidden),
44           SqliteTable::Column(Column::kQuantum, "quantum",
45                               SqlValue::Type::kLong, kHidden),
46           SqliteTable::Column(Column::kWindowStart, "window_start",
47                               SqlValue::Type::kLong, kHidden),
48           SqliteTable::Column(Column::kWindowDur, "window_dur",
49                               SqlValue::Type::kLong, kHidden),
50           // These are the ouput columns:
51           SqliteTable::Column(Column::kTs, "ts", SqlValue::Type::kLong),
52           SqliteTable::Column(Column::kDuration, "dur", SqlValue::Type::kLong),
53           SqliteTable::Column(Column::kQuantumTs, "quantum_ts",
54                               SqlValue::Type::kLong),
55       },
56       {Column::kRowId});
57   return util::OkStatus();
58 }
59 
CreateCursor()60 std::unique_ptr<SqliteTable::Cursor> WindowOperatorTable::CreateCursor() {
61   return std::unique_ptr<SqliteTable::Cursor>(new Cursor(this));
62 }
63 
BestIndex(const QueryConstraints &,BestIndexInfo *)64 int WindowOperatorTable::BestIndex(const QueryConstraints&, BestIndexInfo*) {
65   return SQLITE_OK;
66 }
67 
ModifyConstraints(QueryConstraints * qc)68 int WindowOperatorTable::ModifyConstraints(QueryConstraints* qc) {
69   // Remove ordering on timestamp if it is the only ordering as we are already
70   // sorted on TS. This makes span joining significantly faster.
71   const auto& ob = qc->order_by();
72   if (ob.size() == 1 && ob[0].iColumn == Column::kTs && !ob[0].desc) {
73     qc->mutable_order_by()->clear();
74   }
75   return SQLITE_OK;
76 }
77 
Update(int argc,sqlite3_value ** argv,sqlite3_int64 *)78 int WindowOperatorTable::Update(int argc,
79                                 sqlite3_value** argv,
80                                 sqlite3_int64*) {
81   // We only support updates to ts and dur. Disallow deletes (argc == 1) and
82   // inserts (argv[0] == null).
83   if (argc < 2 || sqlite3_value_type(argv[0]) == SQLITE_NULL)
84     return SQLITE_READONLY;
85 
86   int64_t new_quantum = sqlite3_value_int64(argv[3]);
87   int64_t new_start = sqlite3_value_int64(argv[4]);
88   int64_t new_dur = sqlite3_value_int64(argv[5]);
89   if (new_dur == 0) {
90     auto* err = sqlite3_mprintf("Cannot set duration of window table to zero.");
91     SetErrorMessage(err);
92     return SQLITE_ERROR;
93   }
94 
95   quantum_ = new_quantum;
96   window_start_ = new_start;
97   window_dur_ = new_dur;
98 
99   return SQLITE_OK;
100 }
101 
Cursor(WindowOperatorTable * table)102 WindowOperatorTable::Cursor::Cursor(WindowOperatorTable* table)
103     : SqliteTable::Cursor(table), table_(table) {}
104 
Filter(const QueryConstraints & qc,sqlite3_value ** argv,FilterHistory)105 int WindowOperatorTable::Cursor::Filter(const QueryConstraints& qc,
106                                         sqlite3_value** argv,
107                                         FilterHistory) {
108   *this = Cursor(table_);
109   window_start_ = table_->window_start_;
110   window_end_ = table_->window_start_ + table_->window_dur_;
111   step_size_ = table_->quantum_ == 0 ? table_->window_dur_ : table_->quantum_;
112 
113   current_ts_ = window_start_;
114 
115   // Set return first if there is a equals constraint on the row id asking to
116   // return the first row.
117   bool return_first = qc.constraints().size() == 1 &&
118                       qc.constraints()[0].column == Column::kRowId &&
119                       IsOpEq(qc.constraints()[0].op) &&
120                       sqlite3_value_int(argv[0]) == 0;
121   if (return_first) {
122     filter_type_ = FilterType::kReturnFirst;
123   } else {
124     filter_type_ = FilterType::kReturnAll;
125   }
126   return SQLITE_OK;
127 }
128 
Column(sqlite3_context * context,int N)129 int WindowOperatorTable::Cursor::Column(sqlite3_context* context, int N) {
130   switch (N) {
131     case Column::kQuantum: {
132       sqlite3_result_int64(context,
133                            static_cast<sqlite_int64>(table_->quantum_));
134       break;
135     }
136     case Column::kWindowStart: {
137       sqlite3_result_int64(context,
138                            static_cast<sqlite_int64>(table_->window_start_));
139       break;
140     }
141     case Column::kWindowDur: {
142       sqlite3_result_int(context, static_cast<int>(table_->window_dur_));
143       break;
144     }
145     case Column::kTs: {
146       sqlite3_result_int64(context, static_cast<sqlite_int64>(current_ts_));
147       break;
148     }
149     case Column::kDuration: {
150       sqlite3_result_int64(context, static_cast<sqlite_int64>(step_size_));
151       break;
152     }
153     case Column::kQuantumTs: {
154       sqlite3_result_int64(context, static_cast<sqlite_int64>(quantum_ts_));
155       break;
156     }
157     case Column::kRowId: {
158       sqlite3_result_int64(context, static_cast<sqlite_int64>(row_id_));
159       break;
160     }
161     default: {
162       PERFETTO_FATAL("Unknown column %d", N);
163       break;
164     }
165   }
166   return SQLITE_OK;
167 }
168 
Next()169 int WindowOperatorTable::Cursor::Next() {
170   switch (filter_type_) {
171     case FilterType::kReturnFirst:
172       current_ts_ = window_end_;
173       break;
174     case FilterType::kReturnAll:
175       current_ts_ += step_size_;
176       quantum_ts_++;
177       break;
178   }
179   row_id_++;
180   return SQLITE_OK;
181 }
182 
Eof()183 int WindowOperatorTable::Cursor::Eof() {
184   return current_ts_ >= window_end_;
185 }
186 
187 }  // namespace trace_processor
188 }  // namespace perfetto
189