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/sql_stats_table.h"
18
19 #include <sqlite3.h>
20 #include <memory>
21
22 #include "perfetto/base/logging.h"
23 #include "src/trace_processor/sqlite/bindings/sqlite_result.h"
24 #include "src/trace_processor/storage/trace_storage.h"
25
26 namespace perfetto::trace_processor {
27
Connect(sqlite3 * db,void * aux,int,const char * const *,sqlite3_vtab ** vtab,char **)28 int SqlStatsModule::Connect(sqlite3* db,
29 void* aux,
30 int,
31 const char* const*,
32 sqlite3_vtab** vtab,
33 char**) {
34 static constexpr char kSchema[] = R"(
35 CREATE TABLE x(
36 query TEXT,
37 started BIGINT,
38 first_next BIGINT,
39 ended BIGINT,
40 PRIMARY KEY(started)
41 ) WITHOUT ROWID
42 )";
43 if (int ret = sqlite3_declare_vtab(db, kSchema); ret != SQLITE_OK) {
44 return ret;
45 }
46 std::unique_ptr<Vtab> res = std::make_unique<Vtab>();
47 res->storage = GetContext(aux);
48 *vtab = res.release();
49 return SQLITE_OK;
50 }
51
Disconnect(sqlite3_vtab * vtab)52 int SqlStatsModule::Disconnect(sqlite3_vtab* vtab) {
53 delete GetVtab(vtab);
54 return SQLITE_OK;
55 }
56
BestIndex(sqlite3_vtab *,sqlite3_index_info *)57 int SqlStatsModule::BestIndex(sqlite3_vtab*, sqlite3_index_info*) {
58 return SQLITE_OK;
59 }
60
Open(sqlite3_vtab * raw_vtab,sqlite3_vtab_cursor ** cursor)61 int SqlStatsModule::Open(sqlite3_vtab* raw_vtab, sqlite3_vtab_cursor** cursor) {
62 std::unique_ptr<Cursor> c = std::make_unique<Cursor>();
63 c->storage = GetVtab(raw_vtab)->storage;
64 *cursor = c.release();
65 return SQLITE_OK;
66 }
67
Close(sqlite3_vtab_cursor * cursor)68 int SqlStatsModule::Close(sqlite3_vtab_cursor* cursor) {
69 delete GetCursor(cursor);
70 return SQLITE_OK;
71 }
72
Filter(sqlite3_vtab_cursor * cursor,int,const char *,int,sqlite3_value **)73 int SqlStatsModule::Filter(sqlite3_vtab_cursor* cursor,
74 int,
75 const char*,
76 int,
77 sqlite3_value**) {
78 auto* c = GetCursor(cursor);
79 c->row = 0;
80 c->num_rows = c->storage->sql_stats().size();
81 return SQLITE_OK;
82 }
83
Next(sqlite3_vtab_cursor * cursor)84 int SqlStatsModule::Next(sqlite3_vtab_cursor* cursor) {
85 GetCursor(cursor)->row++;
86 return SQLITE_OK;
87 }
88
Eof(sqlite3_vtab_cursor * cursor)89 int SqlStatsModule::Eof(sqlite3_vtab_cursor* cursor) {
90 auto* c = GetCursor(cursor);
91 return c->row >= c->num_rows;
92 }
93
Column(sqlite3_vtab_cursor * cursor,sqlite3_context * ctx,int N)94 int SqlStatsModule::Column(sqlite3_vtab_cursor* cursor,
95 sqlite3_context* ctx,
96 int N) {
97 auto* c = GetCursor(cursor);
98 const TraceStorage::SqlStats& stats = c->storage->sql_stats();
99 switch (N) {
100 case Column::kQuery:
101 sqlite::result::StaticString(ctx, stats.queries()[c->row].c_str());
102 break;
103 case Column::kTimeStarted:
104 sqlite::result::Long(ctx, stats.times_started()[c->row]);
105 break;
106 case Column::kTimeFirstNext:
107 sqlite::result::Long(ctx, stats.times_first_next()[c->row]);
108 break;
109 case Column::kTimeEnded:
110 sqlite::result::Long(ctx, stats.times_ended()[c->row]);
111 break;
112 default:
113 PERFETTO_FATAL("Unknown column %d", N);
114 break;
115 }
116 return SQLITE_OK;
117 }
118
Rowid(sqlite3_vtab_cursor *,sqlite_int64 *)119 int SqlStatsModule::Rowid(sqlite3_vtab_cursor*, sqlite_int64*) {
120 return SQLITE_ERROR;
121 }
122
123 } // namespace perfetto::trace_processor
124