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