• 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/prelude/operators/span_join_operator.h"
18 
19 #include "src/trace_processor/sqlite/sqlite_engine.h"
20 #include "test/gtest_and_gmock.h"
21 
22 namespace perfetto {
23 namespace trace_processor {
24 namespace {
25 
26 class SpanJoinOperatorTableTest : public ::testing::Test {
27  public:
SpanJoinOperatorTableTest()28   SpanJoinOperatorTableTest() {
29     engine_.RegisterVirtualTableModule<SpanJoinOperatorTable>(
30         "span_join", nullptr, SqliteTable::TableType::kExplicitCreate, false);
31     engine_.RegisterVirtualTableModule<SpanJoinOperatorTable>(
32         "span_left_join", nullptr, SqliteTable::TableType::kExplicitCreate,
33         false);
34   }
35 
PrepareValidStatement(const std::string & sql)36   void PrepareValidStatement(const std::string& sql) {
37     int size = static_cast<int>(sql.size());
38     sqlite3_stmt* stmt;
39     ASSERT_EQ(
40         sqlite3_prepare_v2(engine_.db(), sql.c_str(), size, &stmt, nullptr),
41         SQLITE_OK);
42     stmt_.reset(stmt);
43   }
44 
RunStatement(const std::string & sql)45   void RunStatement(const std::string& sql) {
46     PrepareValidStatement(sql);
47     ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_DONE);
48   }
49 
AssertNextRow(const std::vector<int64_t> elements)50   void AssertNextRow(const std::vector<int64_t> elements) {
51     ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
52     for (size_t i = 0; i < elements.size(); ++i) {
53       ASSERT_EQ(sqlite3_column_int64(stmt_.get(), static_cast<int>(i)),
54                 elements[i]);
55     }
56   }
57 
58  protected:
59   SqliteEngine engine_;
60   ScopedStmt stmt_;
61 };
62 
TEST_F(SpanJoinOperatorTableTest,JoinTwoSpanTables)63 TEST_F(SpanJoinOperatorTableTest, JoinTwoSpanTables) {
64   RunStatement(
65       "CREATE TEMP TABLE f("
66       "ts BIGINT PRIMARY KEY, "
67       "dur BIGINT, "
68       "cpu UNSIGNED INT"
69       ");");
70   RunStatement(
71       "CREATE TEMP TABLE s("
72       "ts BIGINT PRIMARY KEY, "
73       "dur BIGINT, "
74       "cpu UNSIGNED INT"
75       ");");
76   RunStatement(
77       "CREATE VIRTUAL TABLE sp USING span_join(f PARTITIONED cpu, "
78       "s PARTITIONED cpu);");
79 
80   RunStatement("INSERT INTO f VALUES(100, 10, 5);");
81   RunStatement("INSERT INTO f VALUES(110, 50, 5);");
82   RunStatement("INSERT INTO f VALUES(120, 100, 2);");
83   RunStatement("INSERT INTO f VALUES(160, 10, 5);");
84 
85   RunStatement("INSERT INTO s VALUES(100, 5, 5);");
86   RunStatement("INSERT INTO s VALUES(105, 100, 5);");
87   RunStatement("INSERT INTO s VALUES(110, 50, 2);");
88   RunStatement("INSERT INTO s VALUES(160, 100, 2);");
89 
90   PrepareValidStatement("SELECT * FROM sp");
91 
92   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
93   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 120);
94   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 40);
95   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 2);
96 
97   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
98   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 160);
99   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 60);
100   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 2);
101 
102   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
103   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 100);
104   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 5);
105   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 5);
106 
107   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
108   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 105);
109   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 5);
110   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 5);
111 
112   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
113   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 110);
114   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 50);
115   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 5);
116 
117   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
118   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 160);
119   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 10);
120   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 5);
121 
122   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_DONE);
123 }
124 
TEST_F(SpanJoinOperatorTableTest,NullPartitionKey)125 TEST_F(SpanJoinOperatorTableTest, NullPartitionKey) {
126   RunStatement(
127       "CREATE TEMP TABLE f("
128       "ts BIGINT PRIMARY KEY, "
129       "dur BIGINT, "
130       "cpu UNSIGNED INT"
131       ");");
132   RunStatement(
133       "CREATE TEMP TABLE s("
134       "ts BIGINT PRIMARY KEY, "
135       "dur BIGINT, "
136       "cpu UNSIGNED INT"
137       ");");
138   RunStatement(
139       "CREATE VIRTUAL TABLE sp USING span_join(f PARTITIONED cpu, "
140       "s PARTITIONED cpu);");
141 
142   RunStatement("INSERT INTO f VALUES(30, 20, NULL);");
143   RunStatement("INSERT INTO f VALUES(100, 10, 5);");
144   RunStatement("INSERT INTO f VALUES(110, 50, 5);");
145   RunStatement("INSERT INTO f VALUES(120, 100, 2);");
146   RunStatement("INSERT INTO f VALUES(160, 10, 5);");
147 
148   RunStatement("INSERT INTO s VALUES(40, 10, NULL);");
149   RunStatement("INSERT INTO s VALUES(100, 5, 5);");
150   RunStatement("INSERT INTO s VALUES(105, 100, 5);");
151   RunStatement("INSERT INTO s VALUES(110, 50, 2);");
152   RunStatement("INSERT INTO s VALUES(160, 100, 2);");
153 
154   PrepareValidStatement("SELECT * FROM sp");
155 
156   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
157   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 120);
158   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 40);
159   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 2);
160 
161   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
162   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 160);
163   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 60);
164   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 2);
165 
166   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
167   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 100);
168   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 5);
169   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 5);
170 
171   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
172   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 105);
173   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 5);
174   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 5);
175 
176   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
177   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 110);
178   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 50);
179   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 5);
180 
181   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
182   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 160);
183   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 10);
184   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 5);
185 
186   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_DONE);
187 }
188 
TEST_F(SpanJoinOperatorTableTest,MixedPartitioning)189 TEST_F(SpanJoinOperatorTableTest, MixedPartitioning) {
190   RunStatement(
191       "CREATE TEMP TABLE f("
192       "ts BIGINT PRIMARY KEY, "
193       "dur BIGINT, "
194       "upid UNSIGNED INT"
195       ");");
196   RunStatement(
197       "CREATE TEMP TABLE s("
198       "ts BIGINT PRIMARY KEY, "
199       "dur BIGINT, "
200       "s_val BIGINT"
201       ");");
202   RunStatement(
203       "CREATE VIRTUAL TABLE sp USING span_join(f PARTITIONED upid, s);");
204 
205   RunStatement("INSERT INTO f VALUES(30, 20, NULL);");
206   RunStatement("INSERT INTO f VALUES(100, 10, 5);");
207   RunStatement("INSERT INTO f VALUES(110, 50, 5);");
208   RunStatement("INSERT INTO f VALUES(120, 100, 2);");
209   RunStatement("INSERT INTO f VALUES(160, 10, 5);");
210   RunStatement("INSERT INTO f VALUES(300, 100, 2);");
211 
212   RunStatement("INSERT INTO s VALUES(100, 5, 11111);");
213   RunStatement("INSERT INTO s VALUES(105, 5, 22222);");
214   RunStatement("INSERT INTO s VALUES(110, 60, 33333);");
215   RunStatement("INSERT INTO s VALUES(320, 10, 44444);");
216 
217   PrepareValidStatement("SELECT * FROM sp");
218   AssertNextRow({120, 50, 2, 33333});
219   AssertNextRow({320, 10, 2, 44444});
220   AssertNextRow({100, 5, 5, 11111});
221   AssertNextRow({105, 5, 5, 22222});
222   AssertNextRow({110, 50, 5, 33333});
223   AssertNextRow({160, 10, 5, 33333});
224   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_DONE);
225 }
226 
TEST_F(SpanJoinOperatorTableTest,NoPartitioning)227 TEST_F(SpanJoinOperatorTableTest, NoPartitioning) {
228   RunStatement(
229       "CREATE TEMP TABLE f("
230       "ts BIGINT PRIMARY KEY, "
231       "dur BIGINT, "
232       "f_val BIGINT"
233       ");");
234   RunStatement(
235       "CREATE TEMP TABLE s("
236       "ts BIGINT PRIMARY KEY, "
237       "dur BIGINT, "
238       "s_val BIGINT"
239       ");");
240   RunStatement("CREATE VIRTUAL TABLE sp USING span_join(f, s);");
241 
242   RunStatement("INSERT INTO f VALUES(100, 10, 44444);");
243   RunStatement("INSERT INTO f VALUES(110, 50, 55555);");
244   RunStatement("INSERT INTO f VALUES(160, 10, 44444);");
245 
246   RunStatement("INSERT INTO s VALUES(100, 5, 11111);");
247   RunStatement("INSERT INTO s VALUES(105, 5, 22222);");
248   RunStatement("INSERT INTO s VALUES(110, 60, 33333);");
249 
250   PrepareValidStatement("SELECT * FROM sp");
251   AssertNextRow({100, 5, 44444, 11111});
252   AssertNextRow({105, 5, 44444, 22222});
253   AssertNextRow({110, 50, 55555, 33333});
254   AssertNextRow({160, 10, 44444, 33333});
255   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_DONE);
256 }
257 
TEST_F(SpanJoinOperatorTableTest,LeftJoinTwoSpanTables)258 TEST_F(SpanJoinOperatorTableTest, LeftJoinTwoSpanTables) {
259   RunStatement(
260       "CREATE TEMP TABLE f("
261       "ts BIGINT PRIMARY KEY, "
262       "dur BIGINT, "
263       "cpu UNSIGNED INT"
264       ");");
265   RunStatement(
266       "CREATE TEMP TABLE s("
267       "ts BIGINT PRIMARY KEY, "
268       "dur BIGINT, "
269       "tid UNSIGNED INT"
270       ");");
271   RunStatement("CREATE VIRTUAL TABLE sp USING span_left_join(f, s);");
272 
273   RunStatement("INSERT INTO f VALUES(100, 10, 0);");
274   RunStatement("INSERT INTO f VALUES(110, 50, 1);");
275 
276   RunStatement("INSERT INTO s VALUES(100, 5, 1);");
277   RunStatement("INSERT INTO s VALUES(110, 40, 2);");
278   RunStatement("INSERT INTO s VALUES(150, 50, 3);");
279 
280   PrepareValidStatement("SELECT * FROM sp");
281 
282   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
283   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 100);
284   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 5);
285   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 0);
286   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 3), 1);
287 
288   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
289   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 105);
290   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 5);
291   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 0);
292   ASSERT_EQ(sqlite3_column_type(stmt_.get(), 3), SQLITE_NULL);
293 
294   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
295   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 110);
296   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 40);
297   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 1);
298   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 3), 2);
299 
300   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
301   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 150);
302   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 10);
303   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 1);
304   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 3), 3);
305 
306   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_DONE);
307 }
308 
TEST_F(SpanJoinOperatorTableTest,LeftJoinTwoSpanTables_EmptyRight)309 TEST_F(SpanJoinOperatorTableTest, LeftJoinTwoSpanTables_EmptyRight) {
310   RunStatement(
311       "CREATE TEMP TABLE f("
312       "ts BIGINT PRIMARY KEY, "
313       "dur BIGINT, "
314       "cpu UNSIGNED INT"
315       ");");
316   RunStatement(
317       "CREATE TEMP TABLE s("
318       "ts BIGINT PRIMARY KEY, "
319       "dur BIGINT, "
320       "tid UNSIGNED INT"
321       ");");
322   RunStatement("CREATE VIRTUAL TABLE sp USING span_left_join(f, s);");
323 
324   RunStatement("INSERT INTO f VALUES(100, 10, 0);");
325   RunStatement("INSERT INTO f VALUES(110, 50, 1);");
326 
327   PrepareValidStatement("SELECT * FROM sp");
328 
329   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
330   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 100);
331   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 10);
332   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 0);
333   ASSERT_EQ(sqlite3_column_type(stmt_.get(), 3), SQLITE_NULL);
334 
335   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
336   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 110);
337   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 50);
338   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 1);
339   ASSERT_EQ(sqlite3_column_type(stmt_.get(), 3), SQLITE_NULL);
340 
341   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_DONE);
342 }
343 
TEST_F(SpanJoinOperatorTableTest,CapitalizedLeftJoin)344 TEST_F(SpanJoinOperatorTableTest, CapitalizedLeftJoin) {
345   RunStatement(
346       "CREATE TEMP TABLE f("
347       "ts BIGINT PRIMARY KEY, "
348       "dur BIGINT, "
349       "cpu UNSIGNED INT"
350       ");");
351   RunStatement(
352       "CREATE TEMP TABLE s("
353       "ts BIGINT PRIMARY KEY, "
354       "dur BIGINT, "
355       "tid UNSIGNED INT"
356       ");");
357   RunStatement("CREATE VIRTUAL TABLE sp USING SPAN_LEFT_JOIN(f, s);");
358 
359   RunStatement("INSERT INTO f VALUES(100, 10, 0);");
360   RunStatement("INSERT INTO f VALUES(110, 50, 1);");
361 
362   PrepareValidStatement("SELECT * FROM sp");
363 
364   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
365   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 100);
366   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 10);
367   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 0);
368   ASSERT_EQ(sqlite3_column_type(stmt_.get(), 3), SQLITE_NULL);
369 
370   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_ROW);
371   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 0), 110);
372   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 1), 50);
373   ASSERT_EQ(sqlite3_column_int64(stmt_.get(), 2), 1);
374   ASSERT_EQ(sqlite3_column_type(stmt_.get(), 3), SQLITE_NULL);
375 
376   ASSERT_EQ(sqlite3_step(stmt_.get()), SQLITE_DONE);
377 }
378 
379 }  // namespace
380 }  // namespace trace_processor
381 }  // namespace perfetto
382