1 /*
2 * Copyright (C) 2023 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_source.h"
18
19 #include "test/gtest_and_gmock.h"
20
21 namespace perfetto {
22 namespace trace_processor {
23 namespace {
24
TEST(SqlSourceTest,Factory)25 TEST(SqlSourceTest, Factory) {
26 SqlSource source = SqlSource::FromExecuteQuery("SELECT * FROM slice");
27 ASSERT_EQ(source.AsTraceback(0),
28 "Traceback (most recent call last):\n"
29 " File \"stdin\" line 1 col 1\n"
30 " SELECT * FROM slice\n"
31 " ^\n");
32 ASSERT_EQ(source.AsTraceback(7),
33 "Traceback (most recent call last):\n"
34 " File \"stdin\" line 1 col 8\n"
35 " SELECT * FROM slice\n"
36 " ^\n");
37 }
38
TEST(SqlSourceTest,Substr)39 TEST(SqlSourceTest, Substr) {
40 SqlSource source =
41 SqlSource::FromExecuteQuery("SELECT * FROM slice").Substr(9, 10);
42 ASSERT_EQ(source.sql(), "FROM slice");
43
44 ASSERT_EQ(source.AsTraceback(0),
45 "Traceback (most recent call last):\n"
46 " File \"stdin\" line 1 col 10\n"
47 " FROM slice\n"
48 " ^\n");
49 ASSERT_EQ(source.AsTraceback(6),
50 "Traceback (most recent call last):\n"
51 " File \"stdin\" line 1 col 16\n"
52 " FROM slice\n"
53 " ^\n");
54 }
55
TEST(SqlSourceTest,RewriteAllIgnoreExisting)56 TEST(SqlSourceTest, RewriteAllIgnoreExisting) {
57 SqlSource source =
58 SqlSource::FromExecuteQuery("macro!()")
59 .RewriteAllIgnoreExisting(SqlSource::FromTraceProcessorImplementation(
60 "SELECT * FROM slice"));
61 ASSERT_EQ(source.sql(), "SELECT * FROM slice");
62
63 ASSERT_EQ(source.AsTraceback(0),
64 "Fully expanded statement\n"
65 " SELECT * FROM slice\n"
66 " ^\n"
67 "Traceback (most recent call last):\n"
68 " File \"stdin\" line 1 col 1\n"
69 " macro!()\n"
70 " ^\n"
71 " Trace Processor Internal line 1 col 1\n"
72 " SELECT * FROM slice\n"
73 " ^\n");
74 ASSERT_EQ(source.AsTraceback(7),
75 "Fully expanded statement\n"
76 " SELECT * FROM slice\n"
77 " ^\n"
78 "Traceback (most recent call last):\n"
79 " File \"stdin\" line 1 col 1\n"
80 " macro!()\n"
81 " ^\n"
82 " Trace Processor Internal line 1 col 8\n"
83 " SELECT * FROM slice\n"
84 " ^\n");
85 }
86
TEST(SqlSourceTest,NestedFullRewrite)87 TEST(SqlSourceTest, NestedFullRewrite) {
88 SqlSource nested =
89 SqlSource::FromTraceProcessorImplementation("nested!()")
90 .RewriteAllIgnoreExisting(SqlSource::FromTraceProcessorImplementation(
91 "SELECT * FROM slice"));
92 ASSERT_EQ(nested.sql(), "SELECT * FROM slice");
93
94 SqlSource source = SqlSource::FromExecuteQuery("macro!()")
95 .RewriteAllIgnoreExisting(std::move(nested));
96 ASSERT_EQ(source.sql(), "SELECT * FROM slice");
97
98 ASSERT_EQ(source.AsTraceback(0),
99 "Fully expanded statement\n"
100 " SELECT * FROM slice\n"
101 " ^\n"
102 "Traceback (most recent call last):\n"
103 " File \"stdin\" line 1 col 1\n"
104 " macro!()\n"
105 " ^\n"
106 " Trace Processor Internal line 1 col 1\n"
107 " nested!()\n"
108 " ^\n"
109 " Trace Processor Internal line 1 col 1\n"
110 " SELECT * FROM slice\n"
111 " ^\n");
112 ASSERT_EQ(source.AsTraceback(7),
113 "Fully expanded statement\n"
114 " SELECT * FROM slice\n"
115 " ^\n"
116 "Traceback (most recent call last):\n"
117 " File \"stdin\" line 1 col 1\n"
118 " macro!()\n"
119 " ^\n"
120 " Trace Processor Internal line 1 col 1\n"
121 " nested!()\n"
122 " ^\n"
123 " Trace Processor Internal line 1 col 8\n"
124 " SELECT * FROM slice\n"
125 " ^\n");
126 }
127
TEST(SqlSourceTest,RewriteAllIgnoresExistingCorrectly)128 TEST(SqlSourceTest, RewriteAllIgnoresExistingCorrectly) {
129 SqlSource foo =
130 SqlSource::FromExecuteQuery("foo!()").RewriteAllIgnoreExisting(
131 SqlSource::FromTraceProcessorImplementation("SELECT * FROM slice"));
132 SqlSource source = foo.RewriteAllIgnoreExisting(
133 SqlSource::FromTraceProcessorImplementation("SELECT 0 WHERE 0"));
134 ASSERT_EQ(source.sql(), "SELECT 0 WHERE 0");
135
136 ASSERT_EQ(source.AsTraceback(0),
137 "Fully expanded statement\n"
138 " SELECT 0 WHERE 0\n"
139 " ^\n"
140 "Traceback (most recent call last):\n"
141 " File \"stdin\" line 1 col 1\n"
142 " foo!()\n"
143 " ^\n"
144 " Trace Processor Internal line 1 col 1\n"
145 " SELECT 0 WHERE 0\n"
146 " ^\n");
147 ASSERT_EQ(source.AsTraceback(4),
148 "Fully expanded statement\n"
149 " SELECT 0 WHERE 0\n"
150 " ^\n"
151 "Traceback (most recent call last):\n"
152 " File \"stdin\" line 1 col 1\n"
153 " foo!()\n"
154 " ^\n"
155 " Trace Processor Internal line 1 col 5\n"
156 " SELECT 0 WHERE 0\n"
157 " ^\n");
158 }
159
TEST(SqlSourceTest,Rewriter)160 TEST(SqlSourceTest, Rewriter) {
161 SqlSource::Rewriter rewriter(
162 SqlSource::FromExecuteQuery("SELECT cols!() FROM slice"));
163 rewriter.Rewrite(7, 14,
164 SqlSource::FromTraceProcessorImplementation(
165 "ts, dur, ts + dur AS ts_end"));
166
167 SqlSource rewritten = std::move(rewriter).Build();
168 ASSERT_EQ(rewritten.sql(), "SELECT ts, dur, ts + dur AS ts_end FROM slice");
169
170 // Offset points at the top level source.
171 ASSERT_EQ(rewritten.AsTraceback(0),
172 "Fully expanded statement\n"
173 " SELECT ts, dur, ts + dur AS ts_end FROM slice\n"
174 " ^\n"
175 "Traceback (most recent call last):\n"
176 " File \"stdin\" line 1 col 1\n"
177 " SELECT cols!() FROM slice\n"
178 " ^\n");
179 ASSERT_EQ(rewritten.AsTraceback(40),
180 "Fully expanded statement\n"
181 " SELECT ts, dur, ts + dur AS ts_end FROM slice\n"
182 " ^\n"
183 "Traceback (most recent call last):\n"
184 " File \"stdin\" line 1 col 21\n"
185 " SELECT cols!() FROM slice\n"
186 " ^\n");
187
188 // Offset points at the nested source.
189 ASSERT_EQ(rewritten.AsTraceback(16),
190 "Fully expanded statement\n"
191 " SELECT ts, dur, ts + dur AS ts_end FROM slice\n"
192 " ^\n"
193 "Traceback (most recent call last):\n"
194 " File \"stdin\" line 1 col 8\n"
195 " SELECT cols!() FROM slice\n"
196 " ^\n"
197 " Trace Processor Internal line 1 col 10\n"
198 " ts, dur, ts + dur AS ts_end\n"
199 " ^\n");
200 }
201
TEST(SqlSourceTest,NestedRewriter)202 TEST(SqlSourceTest, NestedRewriter) {
203 SqlSource::Rewriter nested_rewrite(
204 SqlSource::FromTraceProcessorImplementation(
205 "id, common_cols!(), other_cols!(), name"));
206 nested_rewrite.Rewrite(
207 4, 18, SqlSource::FromTraceProcessorImplementation("ts, dur"));
208 nested_rewrite.Rewrite(20, 33,
209 SqlSource::FromTraceProcessorImplementation("depth"));
210
211 SqlSource::Rewriter rewriter(
212 SqlSource::FromExecuteQuery("SELECT cols!() FROM slice"));
213 rewriter.Rewrite(7, 14, std::move(nested_rewrite).Build());
214
215 SqlSource rewritten = std::move(rewriter).Build();
216 ASSERT_EQ(rewritten.sql(), "SELECT id, ts, dur, depth, name FROM slice");
217
218 // Offset points at the top level source.
219 ASSERT_EQ(rewritten.AsTraceback(0),
220 "Fully expanded statement\n"
221 " SELECT id, ts, dur, depth, name FROM slice\n"
222 " ^\n"
223 "Traceback (most recent call last):\n"
224 " File \"stdin\" line 1 col 1\n"
225 " SELECT cols!() FROM slice\n"
226 " ^\n");
227 ASSERT_EQ(rewritten.AsTraceback(37),
228 "Fully expanded statement\n"
229 " SELECT id, ts, dur, depth, name FROM slice\n"
230 " ^\n"
231 "Traceback (most recent call last):\n"
232 " File \"stdin\" line 1 col 21\n"
233 " SELECT cols!() FROM slice\n"
234 " ^\n");
235
236 // Offset points at the first nested source.
237 ASSERT_EQ(rewritten.AsTraceback(15),
238 "Fully expanded statement\n"
239 " SELECT id, ts, dur, depth, name FROM slice\n"
240 " ^\n"
241 "Traceback (most recent call last):\n"
242 " File \"stdin\" line 1 col 8\n"
243 " SELECT cols!() FROM slice\n"
244 " ^\n"
245 " Trace Processor Internal line 1 col 5\n"
246 " id, common_cols!(), other_cols!(), name\n"
247 " ^\n"
248 " Trace Processor Internal line 1 col 5\n"
249 " ts, dur\n"
250 " ^\n");
251
252 // Offset points at the second nested source.
253 ASSERT_EQ(rewritten.AsTraceback(20),
254 "Fully expanded statement\n"
255 " SELECT id, ts, dur, depth, name FROM slice\n"
256 " ^\n"
257 "Traceback (most recent call last):\n"
258 " File \"stdin\" line 1 col 8\n"
259 " SELECT cols!() FROM slice\n"
260 " ^\n"
261 " Trace Processor Internal line 1 col 21\n"
262 " id, common_cols!(), other_cols!(), name\n"
263 " ^\n"
264 " Trace Processor Internal line 1 col 1\n"
265 " depth\n"
266 " ^\n");
267 ASSERT_EQ(rewritten.AsTraceback(22),
268 "Fully expanded statement\n"
269 " SELECT id, ts, dur, depth, name FROM slice\n"
270 " ^\n"
271 "Traceback (most recent call last):\n"
272 " File \"stdin\" line 1 col 8\n"
273 " SELECT cols!() FROM slice\n"
274 " ^\n"
275 " Trace Processor Internal line 1 col 21\n"
276 " id, common_cols!(), other_cols!(), name\n"
277 " ^\n"
278 " Trace Processor Internal line 1 col 3\n"
279 " depth\n"
280 " ^\n");
281 }
282
TEST(SqlSourceTest,NestedRewriteSubstr)283 TEST(SqlSourceTest, NestedRewriteSubstr) {
284 SqlSource::Rewriter nested_rewrite(
285 SqlSource::FromTraceProcessorImplementation(
286 "id, common_cols!(), other_cols!(), name"));
287 nested_rewrite.Rewrite(
288 4, 18, SqlSource::FromTraceProcessorImplementation("ts, dur"));
289 nested_rewrite.Rewrite(20, 33,
290 SqlSource::FromTraceProcessorImplementation("depth"));
291
292 SqlSource::Rewriter rewriter(
293 SqlSource::FromExecuteQuery("SELECT cols!() FROM slice"));
294 rewriter.Rewrite(7, 14, std::move(nested_rewrite).Build());
295
296 SqlSource rewritten = std::move(rewriter).Build();
297 ASSERT_EQ(rewritten.sql(), "SELECT id, ts, dur, depth, name FROM slice");
298
299 // Full macro cover.
300 SqlSource cols = rewritten.Substr(7, 24);
301 ASSERT_EQ(cols.sql(), "id, ts, dur, depth, name");
302 ASSERT_EQ(cols.AsTraceback(0),
303 "Fully expanded statement\n"
304 " id, ts, dur, depth, name\n"
305 " ^\n"
306 "Traceback (most recent call last):\n"
307 " File \"stdin\" line 1 col 8\n"
308 " cols!()\n"
309 " ^\n"
310 " Trace Processor Internal line 1 col 1\n"
311 " id, common_cols!(), other_cols!(), name\n"
312 " ^\n");
313 ASSERT_EQ(cols.AsTraceback(5),
314 "Fully expanded statement\n"
315 " id, ts, dur, depth, name\n"
316 " ^\n"
317 "Traceback (most recent call last):\n"
318 " File \"stdin\" line 1 col 8\n"
319 " cols!()\n"
320 " ^\n"
321 " Trace Processor Internal line 1 col 5\n"
322 " id, common_cols!(), other_cols!(), name\n"
323 " ^\n"
324 " Trace Processor Internal line 1 col 2\n"
325 " ts, dur\n"
326 " ^\n");
327 ASSERT_EQ(cols.AsTraceback(14),
328 "Fully expanded statement\n"
329 " id, ts, dur, depth, name\n"
330 " ^\n"
331 "Traceback (most recent call last):\n"
332 " File \"stdin\" line 1 col 8\n"
333 " cols!()\n"
334 " ^\n"
335 " Trace Processor Internal line 1 col 21\n"
336 " id, common_cols!(), other_cols!(), name\n"
337 " ^\n"
338 " Trace Processor Internal line 1 col 2\n"
339 " depth\n"
340 " ^\n");
341
342 // Intersect with nested.
343 SqlSource intersect = rewritten.Substr(8, 13);
344 ASSERT_EQ(intersect.sql(), "d, ts, dur, d");
345 ASSERT_EQ(intersect.AsTraceback(0),
346 "Fully expanded statement\n"
347 " d, ts, dur, d\n"
348 " ^\n"
349 "Traceback (most recent call last):\n"
350 " File \"stdin\" line 1 col 8\n"
351 " cols!()\n"
352 " ^\n"
353 " Trace Processor Internal line 1 col 2\n"
354 " d, common_cols!(), other_cols!()\n"
355 " ^\n");
356 ASSERT_EQ(intersect.AsTraceback(4),
357 "Fully expanded statement\n"
358 " d, ts, dur, d\n"
359 " ^\n"
360 "Traceback (most recent call last):\n"
361 " File \"stdin\" line 1 col 8\n"
362 " cols!()\n"
363 " ^\n"
364 " Trace Processor Internal line 1 col 5\n"
365 " d, common_cols!(), other_cols!()\n"
366 " ^\n"
367 " Trace Processor Internal line 1 col 2\n"
368 " ts, dur\n"
369 " ^\n");
370 ASSERT_EQ(intersect.AsTraceback(12),
371 "Fully expanded statement\n"
372 " d, ts, dur, d\n"
373 " ^\n"
374 "Traceback (most recent call last):\n"
375 " File \"stdin\" line 1 col 8\n"
376 " cols!()\n"
377 " ^\n"
378 " Trace Processor Internal line 1 col 21\n"
379 " d, common_cols!(), other_cols!()\n"
380 " ^\n"
381 " Trace Processor Internal line 1 col 1\n"
382 " d\n"
383 " ^\n");
384 }
385
TEST(SqlSourceTest,Rerewrites)386 TEST(SqlSourceTest, Rerewrites) {
387 SqlSource::Rewriter rewriter(
388 SqlSource::FromExecuteQuery("SELECT foo!(a) FROM bar!(slice) a"));
389 rewriter.Rewrite(7, 14,
390 SqlSource::FromTraceProcessorImplementation("a.x, a.y"));
391 rewriter.Rewrite(20, 31,
392 SqlSource::FromTraceProcessorImplementation(
393 "(SELECT slice.x, slice.y, slice.z FROM slice)"));
394
395 SqlSource rewritten = std::move(rewriter).Build();
396 ASSERT_EQ(
397 rewritten.sql(),
398 "SELECT a.x, a.y FROM (SELECT slice.x, slice.y, slice.z FROM slice) a");
399
400 SqlSource::Rewriter rerewriter(std::move(rewritten));
401 rerewriter.Rewrite(0, 7,
402 SqlSource::FromTraceProcessorImplementation("INSERT "));
403 rerewriter.Rewrite(7, 14,
404 SqlSource::FromTraceProcessorImplementation("a.z, "));
405
406 SqlSource rerewritten = std::move(rerewriter).Build();
407 ASSERT_EQ(
408 rerewritten.sql(),
409 "INSERT a.z, y FROM (SELECT slice.x, slice.y, slice.z FROM slice) a");
410 ASSERT_EQ(
411 rerewritten.AsTraceback(0),
412 "Fully expanded statement\n"
413 " INSERT a.z, y FROM (SELECT slice.x, slice.y, slice.z FROM slice) a\n"
414 " ^\n"
415 "Traceback (most recent call last):\n"
416 " File \"stdin\" line 1 col 1\n"
417 " SELECT foo!(a) FROM bar!(slice) a\n"
418 " ^\n"
419 " Trace Processor Internal line 1 col 1\n"
420 " INSERT \n"
421 " ^\n");
422 ASSERT_EQ(
423 rerewritten.AsTraceback(8),
424 "Fully expanded statement\n"
425 " INSERT a.z, y FROM (SELECT slice.x, slice.y, slice.z FROM slice) a\n"
426 " ^\n"
427 "Traceback (most recent call last):\n"
428 " File \"stdin\" line 1 col 8\n"
429 " SELECT foo!(a) FROM bar!(slice) a\n"
430 " ^\n"
431 " Trace Processor Internal line 1 col 1\n"
432 " a.x, a.y\n"
433 " ^\n"
434 " Trace Processor Internal line 1 col 2\n"
435 " a.z, \n"
436 " ^\n");
437 }
438
439 } // namespace
440 } // namespace trace_processor
441 } // namespace perfetto
442