1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3 * Copyright (C) 2021 VMware Inc, Steven Rostedt <rostedt@goodmis.org>
4 *
5 * Updates:
6 * Copyright (C) 2021, VMware, Tzvetomir Stoyanov <tz.stoyanov@gmail.com>
7 *
8 */
9 #include <trace-seq.h>
10 #include <stdlib.h>
11 #include <stdarg.h>
12 #include <ctype.h>
13 #include <errno.h>
14
15 #include "tracefs.h"
16 #include "tracefs-local.h"
17 #include "sqlhist-parse.h"
18
19 extern int yylex_init(void* ptr_yy_globals);
20 extern int yylex_init_extra(struct sqlhist_bison *sb, void* ptr_yy_globals);
21 extern int yylex_destroy (void * yyscanner );
22
23 struct str_hash {
24 struct str_hash *next;
25 char *str;
26 };
27
28 enum alias_type {
29 ALIAS_EVENT,
30 ALIAS_FIELD,
31 };
32
33 enum field_type {
34 FIELD_NONE,
35 FIELD_FROM,
36 FIELD_TO,
37 };
38
39 #define for_each_field(expr, field, table) \
40 for (expr = (table)->fields; expr; expr = (field)->next)
41
42 #define TIMESTAMP_COMPARE "TIMESTAMP_DELTA"
43 #define TIMESTAMP_USECS_COMPARE "TIMESTAMP_DELTA_USECS"
44 #define EVENT_START "__START_EVENT__"
45 #define EVENT_END "__END_EVENT__"
46 #define TIMESTAMP_NSECS "TIMESTAMP"
47 #define TIMESTAMP_USECS "TIMESTAMP_USECS"
48
49 struct field {
50 struct expr *next; /* private link list */
51 const char *system;
52 const char *event_name;
53 struct tep_event *event;
54 const char *raw;
55 const char *label;
56 const char *field;
57 const char *type;
58 enum field_type ftype;
59 };
60
61 struct filter {
62 enum filter_type type;
63 struct expr *lval;
64 struct expr *rval;
65 };
66
67 struct match {
68 struct match *next;
69 struct expr *lval;
70 struct expr *rval;
71 };
72
73 struct compare {
74 enum compare_type type;
75 struct expr *lval;
76 struct expr *rval;
77 const char *name;
78 };
79
80 enum expr_type
81 {
82 EXPR_NUMBER,
83 EXPR_STRING,
84 EXPR_FIELD,
85 EXPR_FILTER,
86 EXPR_COMPARE,
87 };
88
89 struct expr {
90 struct expr *free_list;
91 struct expr *next;
92 enum expr_type type;
93 int line;
94 int idx;
95 union {
96 struct field field;
97 struct filter filter;
98 struct compare compare;
99 const char *string;
100 long number;
101 };
102 };
103
104 struct sql_table {
105 struct sqlhist_bison *sb;
106 const char *name;
107 struct expr *exprs;
108 struct expr *fields;
109 struct expr *from;
110 struct expr *to;
111 struct expr *where;
112 struct expr **next_where;
113 struct match *matches;
114 struct match **next_match;
115 struct expr *selections;
116 struct expr **next_selection;
117 };
118
my_yyinput(void * extra,char * buf,int max)119 __hidden int my_yyinput(void *extra, char *buf, int max)
120 {
121 struct sqlhist_bison *sb = extra;
122
123 if (!sb || !sb->buffer)
124 return 0;
125
126 if (sb->buffer_idx + max > sb->buffer_size)
127 max = sb->buffer_size - sb->buffer_idx;
128
129 if (max)
130 memcpy(buf, sb->buffer + sb->buffer_idx, max);
131
132 sb->buffer_idx += max;
133
134 return max;
135 }
136
sql_parse_error(struct sqlhist_bison * sb,const char * text,const char * fmt,va_list ap)137 __hidden void sql_parse_error(struct sqlhist_bison *sb, const char *text,
138 const char *fmt, va_list ap)
139 {
140 const char *buffer = sb->buffer;
141 struct trace_seq s;
142 int line = sb->line_no;
143 int idx = sb->line_idx - strlen(text);
144 int i;
145
146 if (!buffer)
147 return;
148
149 trace_seq_init(&s);
150 if (!s.buffer) {
151 tracefs_warning("Error allocating internal buffer\n");
152 return;
153 }
154
155 for (i = 0; line && buffer[i]; i++) {
156 if (buffer[i] == '\n')
157 line--;
158 }
159 for (; buffer[i] && buffer[i] != '\n'; i++)
160 trace_seq_putc(&s, buffer[i]);
161 trace_seq_putc(&s, '\n');
162 for (i = idx; i > 0; i--)
163 trace_seq_putc(&s, ' ');
164 trace_seq_puts(&s, "^\n");
165 trace_seq_printf(&s, "ERROR: '%s'\n", text);
166 trace_seq_vprintf(&s, fmt, ap);
167
168 trace_seq_terminate(&s);
169
170 sb->parse_error_str = strdup(s.buffer);
171 trace_seq_destroy(&s);
172 }
173
parse_error(struct sqlhist_bison * sb,const char * text,const char * fmt,...)174 static void parse_error(struct sqlhist_bison *sb, const char *text,
175 const char *fmt, ...)
176 {
177 va_list ap;
178
179 va_start(ap, fmt);
180 sql_parse_error(sb, text, fmt, ap);
181 va_end(ap);
182 }
183
quick_hash(const char * str)184 __hidden unsigned int quick_hash(const char *str)
185 {
186 unsigned int val = 0;
187 int len = strlen(str);
188
189 for (; len >= 4; str += 4, len -= 4) {
190 val += str[0];
191 val += str[1] << 8;
192 val += str[2] << 16;
193 val += str[3] << 24;
194 }
195 for (; len > 0; str++, len--)
196 val += str[0] << (len * 8);
197
198 val *= 2654435761;
199
200 return val & ((1 << HASH_BITS) - 1);
201 }
202
203
find_string(struct sqlhist_bison * sb,const char * str)204 static struct str_hash *find_string(struct sqlhist_bison *sb, const char *str)
205 {
206 unsigned int key = quick_hash(str);
207 struct str_hash *hash = sb->str_hash[key];
208
209 for (; hash; hash = hash->next) {
210 if (!strcmp(hash->str, str))
211 return hash;
212 }
213 return NULL;
214 }
215
216 /*
217 * If @str is found, then return the hash string.
218 * This lets store_str() know to free str.
219 */
add_hash(struct sqlhist_bison * sb,const char * str)220 static char **add_hash(struct sqlhist_bison *sb, const char *str)
221 {
222 struct str_hash *hash;
223 unsigned int key;
224
225 if ((hash = find_string(sb, str))) {
226 return &hash->str;
227 }
228
229 hash = malloc(sizeof(*hash));
230 if (!hash)
231 return NULL;
232 key = quick_hash(str);
233 hash->next = sb->str_hash[key];
234 sb->str_hash[key] = hash;
235 hash->str = NULL;
236 return &hash->str;
237 }
238
store_str(struct sqlhist_bison * sb,const char * str)239 __hidden char *store_str(struct sqlhist_bison *sb, const char *str)
240 {
241 char **pstr = add_hash(sb, str);
242
243 if (!pstr)
244 return NULL;
245
246 if (!(*pstr))
247 *pstr = strdup(str);
248
249 return *pstr;
250 }
251
add_cast(struct sqlhist_bison * sb,void * data,const char * type)252 __hidden void *add_cast(struct sqlhist_bison *sb,
253 void *data, const char *type)
254 {
255 struct expr *expr = data;
256 struct field *field = &expr->field;
257
258 field->type = type;
259 return expr;
260 }
261
add_selection(struct sqlhist_bison * sb,void * select,const char * name)262 __hidden int add_selection(struct sqlhist_bison *sb, void *select,
263 const char *name)
264 {
265 struct sql_table *table = sb->table;
266 struct expr *expr = select;
267
268 switch (expr->type) {
269 case EXPR_FIELD:
270 expr->field.label = name;
271 break;
272 case EXPR_COMPARE:
273 expr->compare.name = name;
274 break;
275 case EXPR_NUMBER:
276 case EXPR_STRING:
277 case EXPR_FILTER:
278 default:
279 return -1;
280 }
281
282 if (expr->next)
283 return -1;
284
285 *table->next_selection = expr;
286 table->next_selection = &expr->next;
287
288 return 0;
289 }
290
find_field(struct sqlhist_bison * sb,const char * raw,const char * label)291 static struct expr *find_field(struct sqlhist_bison *sb,
292 const char *raw, const char *label)
293 {
294 struct field *field;
295 struct expr *expr;
296
297 for_each_field(expr, field, sb->table) {
298 field = &expr->field;
299
300 if (!strcmp(field->raw, raw)) {
301 if (label && !field->label)
302 field->label = label;
303 if (label && strcmp(label, field->label) != 0)
304 continue;
305 return expr;
306 }
307
308 if (label && !strcmp(field->raw, label)) {
309 if (!field->label) {
310 field->label = label;
311 field->raw = raw;
312 }
313 return expr;
314 }
315
316 if (!field->label)
317 continue;
318
319 if (!strcmp(field->label, raw))
320 return expr;
321
322 if (label && !strcmp(field->label, label))
323 return expr;
324 }
325 return NULL;
326 }
327
create_expr(struct sqlhist_bison * sb,enum expr_type type,struct expr ** expr_p)328 static void *create_expr(struct sqlhist_bison *sb,
329 enum expr_type type, struct expr **expr_p)
330 {
331 struct expr *expr;
332
333 expr = calloc(1, sizeof(*expr));
334 if (!expr)
335 return NULL;
336
337 if (expr_p)
338 *expr_p = expr;
339
340 expr->free_list = sb->table->exprs;
341 sb->table->exprs = expr;
342
343 expr->type = type;
344 expr->line = sb->line_no;
345 expr->idx = sb->line_idx;
346
347 switch (type) {
348 case EXPR_FIELD: return &expr->field;
349 case EXPR_COMPARE: return &expr->compare;
350 case EXPR_NUMBER: return &expr->number;
351 case EXPR_STRING: return &expr->string;
352 case EXPR_FILTER: return &expr->filter;
353 }
354
355 return NULL;
356 }
357
358 #define __create_expr(var, type, ENUM, expr) \
359 do { \
360 var = (type *)create_expr(sb, EXPR_##ENUM, expr); \
361 } while(0)
362
363 #define create_field(var, expr) \
364 __create_expr(var, struct field, FIELD, expr)
365
366 #define create_filter(var, expr) \
367 __create_expr(var, struct filter, FILTER, expr)
368
369 #define create_compare(var, expr) \
370 __create_expr(var, struct compare, COMPARE, expr)
371
372 #define create_string(var, expr) \
373 __create_expr(var, const char *, STRING, expr)
374
375 #define create_number(var, expr) \
376 __create_expr(var, long, NUMBER, expr)
377
add_field(struct sqlhist_bison * sb,const char * field_name,const char * label)378 __hidden void *add_field(struct sqlhist_bison *sb,
379 const char *field_name, const char *label)
380 {
381 struct sql_table *table = sb->table;
382 struct expr *expr;
383 struct field *field;
384 bool nsecs;
385
386 /* Check if this is a TIMESTAMP compare */
387 if ((nsecs = (strcmp(field_name, TIMESTAMP_COMPARE) == 0)) ||
388 strcmp(field_name, TIMESTAMP_USECS_COMPARE) == 0) {
389 const char *field_nameA;
390 const char *field_nameB;
391 struct expr *exprA;
392 struct expr *exprB;
393 struct field *fieldA;
394 struct field *fieldB;
395
396 if (nsecs) {
397 field_nameA = EVENT_END "." TIMESTAMP_NSECS;
398 field_nameB = EVENT_START "." TIMESTAMP_NSECS;
399 } else {
400 field_nameA = EVENT_END "." TIMESTAMP_USECS;
401 field_nameB = EVENT_START "." TIMESTAMP_USECS;
402 }
403
404 exprA = find_field(sb, field_nameA, NULL);
405 if (!exprA) {
406 create_field(fieldA, &exprA);
407 fieldA->next = table->fields;
408 table->fields = exprA;
409 fieldA->raw = field_nameA;
410 }
411
412 exprB = find_field(sb, field_nameB, NULL);
413 if (!exprB) {
414 create_field(fieldB, &exprB);
415 fieldB->next = table->fields;
416 table->fields = exprB;
417 fieldB->raw = field_nameB;
418 }
419
420 return add_compare(sb, exprA, exprB, COMPARE_SUB);
421 }
422
423 expr = find_field(sb, field_name, label);
424 if (expr)
425 return expr;
426
427 create_field(field, &expr);
428
429 field->next = table->fields;
430 table->fields = expr;
431
432 field->raw = field_name;
433 field->label = label;
434
435 return expr;
436 }
437
add_filter(struct sqlhist_bison * sb,void * A,void * B,enum filter_type op)438 __hidden void *add_filter(struct sqlhist_bison *sb,
439 void *A, void *B, enum filter_type op)
440 {
441 struct filter *filter;
442 struct expr *expr;
443
444 create_filter(filter, &expr);
445
446 filter->lval = A;
447 filter->rval = B;
448
449 filter->type = op;
450
451 return expr;
452 }
453
add_match(struct sqlhist_bison * sb,void * A,void * B)454 __hidden int add_match(struct sqlhist_bison *sb, void *A, void *B)
455 {
456 struct sql_table *table = sb->table;
457 struct match *match;
458
459 match = calloc(1, sizeof(*match));
460 if (!match)
461 return -1;
462
463 match->lval = A;
464 match->rval = B;
465
466 *table->next_match = match;
467 table->next_match = &match->next;
468
469 return 0;
470 }
add_compare(struct sqlhist_bison * sb,void * A,void * B,enum compare_type type)471 __hidden void *add_compare(struct sqlhist_bison *sb,
472 void *A, void *B, enum compare_type type)
473 {
474 struct compare *compare;
475 struct expr *expr;
476
477 create_compare(compare, &expr);
478
479 compare = &expr->compare;
480 compare->lval = A;
481 compare->rval = B;
482 compare->type = type;
483
484 return expr;
485 }
486
add_where(struct sqlhist_bison * sb,void * item)487 __hidden int add_where(struct sqlhist_bison *sb, void *item)
488 {
489 struct expr *expr = item;
490 struct sql_table *table = sb->table;
491
492 if (expr->type != EXPR_FILTER)
493 return -1;
494
495 *table->next_where = expr;
496 table->next_where = &expr->next;
497
498 if (expr->next)
499 return -1;
500
501 return 0;
502 }
503
add_from(struct sqlhist_bison * sb,void * item)504 __hidden int add_from(struct sqlhist_bison *sb, void *item)
505 {
506 struct expr *expr = item;
507
508 if (expr->type != EXPR_FIELD)
509 return -1;
510
511 sb->table->from = expr;
512
513 return 0;
514 }
515
add_to(struct sqlhist_bison * sb,void * item)516 __hidden int add_to(struct sqlhist_bison *sb, void *item)
517 {
518 struct expr *expr = item;
519
520 if (expr->type != EXPR_FIELD)
521 return -1;
522
523 sb->table->to = expr;
524
525 return 0;
526 }
527
add_string(struct sqlhist_bison * sb,const char * str)528 __hidden void *add_string(struct sqlhist_bison *sb, const char *str)
529 {
530 struct expr *expr;
531 const char **str_p;
532
533 create_string(str_p, &expr);
534 *str_p = str;
535 return expr;
536 }
537
add_number(struct sqlhist_bison * sb,long val)538 __hidden void *add_number(struct sqlhist_bison *sb, long val)
539 {
540 struct expr *expr;
541 long *num;
542
543 create_number(num, &expr);
544 *num = val;
545 return expr;
546 }
547
table_start(struct sqlhist_bison * sb)548 __hidden int table_start(struct sqlhist_bison *sb)
549 {
550 struct sql_table *table;
551
552 table = calloc(1, sizeof(*table));
553 if (!table)
554 return -ENOMEM;
555
556 table->sb = sb;
557 sb->table = table;
558
559 table->next_where = &table->where;
560 table->next_match = &table->matches;
561 table->next_selection = &table->selections;
562
563 return 0;
564 }
565
test_event_exists(struct tep_handle * tep,struct sqlhist_bison * sb,struct expr * expr,struct tep_event ** pevent)566 static int test_event_exists(struct tep_handle *tep,
567 struct sqlhist_bison *sb,
568 struct expr *expr, struct tep_event **pevent)
569 {
570 struct field *field = &expr->field;
571 const char *system = field->system;
572 const char *event = field->event_name;
573
574 if (!field->event)
575 field->event = tep_find_event_by_name(tep, system, event);
576 if (pevent)
577 *pevent = field->event;
578
579 if (field->event)
580 return 0;
581
582 sb->line_no = expr->line;
583 sb->line_idx = expr->idx;
584
585 parse_error(sb, field->raw, "event not found\n");
586 return -1;
587 }
588
test_field_exists(struct tep_handle * tep,struct sqlhist_bison * sb,struct expr * expr)589 static int test_field_exists(struct tep_handle *tep,
590 struct sqlhist_bison *sb,
591 struct expr *expr)
592 {
593 struct field *field = &expr->field;
594 struct tep_format_field *tfield;
595 char *field_name;
596 const char *p;
597
598 if (!field->event) {
599 if (test_event_exists(tep, sb, expr, NULL))
600 return -1;
601 }
602
603 /* The field could have a conversion */
604 p = strchr(field->field, '.');
605 if (p)
606 field_name = strndup(field->field, p - field->field);
607 else
608 field_name = strdup(field->field);
609
610 if (!field_name)
611 return -1;
612
613 if (!strcmp(field_name, TRACEFS_TIMESTAMP) ||
614 !strcmp(field->field, TRACEFS_TIMESTAMP_USECS) ||
615 !strcmp(field->field, TRACEFS_STACKTRACE))
616 tfield = (void *)1L;
617 else
618 tfield = tep_find_any_field(field->event, field_name);
619 free(field_name);
620
621 if (!tfield && (!strcmp(field->field, "COMM") || !strcmp(field->field, "comm")))
622 tfield = (void *)1L;
623
624 if (tfield)
625 return 0;
626
627 sb->line_no = expr->line;
628 sb->line_idx = expr->idx;
629
630 parse_error(sb, field->raw,
631 "Field '%s' not part of event %s\n",
632 field->field, field->event_name);
633 return -1;
634 }
635
update_vars(struct tep_handle * tep,struct sql_table * table,struct expr * expr)636 static int update_vars(struct tep_handle *tep,
637 struct sql_table *table,
638 struct expr *expr)
639 {
640 struct sqlhist_bison *sb = table->sb;
641 struct field *event_field = &expr->field;
642 enum field_type ftype = FIELD_NONE;
643 struct tep_event *event;
644 struct field *field;
645 const char *extra_label = NULL;
646 const char *label;
647 const char *raw = event_field->raw;
648 const char *event_name;
649 const char *system;
650 const char *p;
651 int label_len = 0, event_len, system_len;
652 int extra_label_len = 0;
653
654 if (expr == table->to) {
655 ftype = FIELD_TO;
656 extra_label = EVENT_END;
657 } else if (expr == table->from) {
658 ftype = FIELD_FROM;
659 extra_label = EVENT_START;
660 }
661
662 if (extra_label)
663 extra_label_len = strlen(extra_label);
664
665 p = strchr(raw, '.');
666 if (p) {
667 char *str;
668
669 str = strndup(raw, p - raw);
670 if (!str)
671 return -1;
672 event_field->system = store_str(sb, str);
673 free(str);
674 if (!event_field->system)
675 return -1;
676 p++;
677 } else {
678 p = raw;
679 }
680
681 event_field->event_name = store_str(sb, p);
682 if (!event_field->event_name)
683 return -1;
684
685 if (test_event_exists(tep, sb, expr, &event))
686 return -1;
687
688 if (!event_field->system)
689 event_field->system = store_str(sb, event->system);
690
691 if (!event_field->system)
692 return -1;
693
694 label = event_field->label;
695 if (label)
696 label_len = strlen(label);
697
698 system = event_field->system;
699 system_len = strlen(system);
700
701 event_name = event_field->event_name;
702 event_len = strlen(event_name);
703
704 for_each_field(expr, field, table) {
705 int len;
706
707 field = &expr->field;
708
709 if (field->event)
710 continue;
711
712 raw = field->raw;
713
714 /*
715 * The field could be:
716 * system.event.field...
717 * event.field...
718 * label.field...
719 * We check label first.
720 */
721
722 len = label_len;
723 if (label && !strncmp(raw, label, len) &&
724 raw[len] == '.') {
725 /* Label matches and takes precedence */
726 goto found;
727 }
728
729 len = extra_label_len;
730 if (extra_label && !strncmp(raw, extra_label, len) &&
731 raw[len] == '.') {
732 /* Label matches and takes precedence */
733 goto found;
734 }
735
736 if (!strncmp(raw, system, system_len) &&
737 raw[system_len] == '.') {
738 raw += system_len + 1;
739 /* Check the event portion next */
740 }
741
742 len = event_len;
743 if (strncmp(raw, event_name, len) ||
744 raw[len] != '.') {
745 /* Does not match */
746 continue;
747 }
748 found:
749 field->system = system;
750 field->event_name = event_name;
751 field->event = event;
752 field->field = raw + len + 1;
753 field->ftype = ftype;
754
755 if (!strcmp(field->field, "TIMESTAMP"))
756 field->field = store_str(sb, TRACEFS_TIMESTAMP);
757 if (!strcmp(field->field, "TIMESTAMP_USECS"))
758 field->field = store_str(sb, TRACEFS_TIMESTAMP_USECS);
759 if (!strcmp(field->field, "STACKTRACE"))
760 field->field = store_str(sb, TRACEFS_STACKTRACE);
761 if (test_field_exists(tep, sb, expr))
762 return -1;
763 }
764
765 return 0;
766 }
767
768 /*
769 * Called when there's a FROM but no JOIN(to), which means that the
770 * selections can be fields and not mention the event itself.
771 */
update_fields(struct tep_handle * tep,struct sql_table * table,struct expr * expr)772 static int update_fields(struct tep_handle *tep,
773 struct sql_table *table,
774 struct expr *expr)
775 {
776 struct field *event_field = &expr->field;
777 struct sqlhist_bison *sb = table->sb;
778 struct tep_format_field *tfield;
779 struct tep_event *event;
780 struct field *field;
781 const char *p;
782 int len;
783
784 /* First update fields with aliases an such and add event */
785 update_vars(tep, table, expr);
786
787 /*
788 * If event is not found, the creation of the synth will
789 * add a proper error, so return "success".
790 */
791 if (!event_field->event)
792 return 0;
793
794 event = event_field->event;
795
796 for_each_field(expr, field, table) {
797 const char *field_name;
798
799 field = &expr->field;
800
801 if (field->event)
802 continue;
803
804 field_name = field->raw;
805
806 p = strchr(field_name, '.');
807 if (p) {
808 len = p - field_name;
809 p = strndup(field_name, len);
810 if (!p)
811 return -1;
812 field_name = store_str(sb, p);
813 free((char *)p);
814 if (!field_name)
815 return -1;
816 }
817
818 tfield = tep_find_any_field(event, field_name);
819 /* Let it error properly later */
820 if (!tfield)
821 continue;
822
823 field->system = event_field->system;
824 field->event_name = event_field->event_name;
825 field->event = event;
826 field->field = field_name;
827 }
828
829 return 0;
830 }
831
match_error(struct sqlhist_bison * sb,struct match * match,struct field * lmatch,struct field * rmatch)832 static int match_error(struct sqlhist_bison *sb, struct match *match,
833 struct field *lmatch, struct field *rmatch)
834 {
835 struct field *lval = &match->lval->field;
836 struct field *rval = &match->rval->field;
837 struct field *field;
838 struct expr *expr;
839
840 if (lval->system != lmatch->system ||
841 lval->event != lmatch->event) {
842 expr = match->lval;
843 field = lval;
844 } else {
845 expr = match->rval;
846 field = rval;
847 }
848
849 sb->line_no = expr->line;
850 sb->line_idx = expr->idx;
851
852 parse_error(sb, field->raw,
853 "'%s' and '%s' must be a field for each event: '%s' and '%s'\n",
854 lval->raw, rval->raw, sb->table->to->field.raw,
855 sb->table->from->field.raw);
856
857 return -1;
858 }
859
test_match(struct sql_table * table,struct match * match)860 static int test_match(struct sql_table *table, struct match *match)
861 {
862 struct field *lval, *rval;
863 struct field *to, *from;
864
865 if (!match->lval || !match->rval)
866 return -1;
867
868 if (match->lval->type != EXPR_FIELD || match->rval->type != EXPR_FIELD)
869 return -1;
870
871 to = &table->to->field;
872 from = &table->from->field;
873
874 lval = &match->lval->field;
875 rval = &match->rval->field;
876
877 /*
878 * Note, strings are stored in the string store, so all
879 * duplicate strings are the same value, and we can use
880 * normal "==" and "!=" instead of strcmp().
881 *
882 * Either lval == to and rval == from
883 * or lval == from and rval == to.
884 */
885 if ((lval->system != to->system) ||
886 (lval->event != to->event)) {
887 if ((rval->system != to->system) ||
888 (rval->event != to->event) ||
889 (lval->system != from->system) ||
890 (lval->event != from->event))
891 return match_error(table->sb, match, from, to);
892 } else {
893 if ((rval->system != from->system) ||
894 (rval->event != from->event) ||
895 (lval->system != to->system) ||
896 (lval->event != to->event))
897 return match_error(table->sb, match, to, from);
898 }
899 return 0;
900 }
901
assign_match(const char * system,const char * event,struct match * match,const char ** start_match,const char ** end_match)902 static void assign_match(const char *system, const char *event,
903 struct match *match,
904 const char **start_match, const char **end_match)
905 {
906 struct field *lval, *rval;
907
908 lval = &match->lval->field;
909 rval = &match->rval->field;
910
911 if (lval->system == system &&
912 lval->event_name == event) {
913 *start_match = lval->field;
914 *end_match = rval->field;
915 } else {
916 *start_match = rval->field;
917 *end_match = lval->field;
918 }
919 }
920
build_compare(struct tracefs_synth * synth,const char * system,const char * event,struct compare * compare)921 static int build_compare(struct tracefs_synth *synth,
922 const char *system, const char *event,
923 struct compare *compare)
924 {
925 const char *start_field;
926 const char *end_field;
927 struct field *lval, *rval;
928 enum tracefs_synth_calc calc;
929 int ret;
930
931 if (!compare->name)
932 return -1;
933
934 lval = &compare->lval->field;
935 rval = &compare->rval->field;
936
937 if (lval->system == system &&
938 lval->event_name == event) {
939 start_field = lval->field;
940 end_field = rval->field;
941 calc = TRACEFS_SYNTH_DELTA_START;
942 } else {
943 start_field = rval->field;
944 end_field = lval->field;
945 calc = TRACEFS_SYNTH_DELTA_END;
946 }
947
948 if (compare->type == COMPARE_ADD)
949 calc = TRACEFS_SYNTH_ADD;
950
951 ret = tracefs_synth_add_compare_field(synth, start_field,
952 end_field, calc,
953 compare->name);
954 return ret;
955 }
956
verify_filter_error(struct sqlhist_bison * sb,struct expr * expr,const char * event)957 static int verify_filter_error(struct sqlhist_bison *sb, struct expr *expr,
958 const char *event)
959 {
960 struct field *field = &expr->field;
961
962 sb->line_no = expr->line;
963 sb->line_idx = expr->idx;
964
965 parse_error(sb, field->raw,
966 "event '%s' can not be grouped or '||' together with '%s'\n"
967 "All filters between '&&' must be for the same event\n",
968 field->event, event);
969 return -1;
970 }
971
do_verify_filter(struct sqlhist_bison * sb,struct filter * filter,const char ** system,const char ** event,enum field_type * ftype)972 static int do_verify_filter(struct sqlhist_bison *sb, struct filter *filter,
973 const char **system, const char **event,
974 enum field_type *ftype)
975 {
976 int ret;
977
978 if (filter->type == FILTER_OR ||
979 filter->type == FILTER_AND) {
980 ret = do_verify_filter(sb, &filter->lval->filter, system, event, ftype);
981 if (ret)
982 return ret;
983 return do_verify_filter(sb, &filter->rval->filter, system, event, ftype);
984 }
985 if (filter->type == FILTER_GROUP ||
986 filter->type == FILTER_NOT_GROUP) {
987 return do_verify_filter(sb, &filter->lval->filter, system, event, ftype);
988 }
989
990 /*
991 * system and event will be NULL until we find the left most
992 * node. Then assign it, and compare on the way back up.
993 */
994 if (!*system && !*event) {
995 *system = filter->lval->field.system;
996 *event = filter->lval->field.event_name;
997 *ftype = filter->lval->field.ftype;
998 return 0;
999 }
1000
1001 if (filter->lval->field.system != *system ||
1002 filter->lval->field.event_name != *event)
1003 return verify_filter_error(sb, filter->lval, *event);
1004
1005 return 0;
1006 }
1007
verify_filter(struct sqlhist_bison * sb,struct filter * filter,const char ** system,const char ** event,enum field_type * ftype)1008 static int verify_filter(struct sqlhist_bison *sb, struct filter *filter,
1009 const char **system, const char **event,
1010 enum field_type *ftype)
1011 {
1012 int ret;
1013
1014 switch (filter->type) {
1015 case FILTER_OR:
1016 case FILTER_AND:
1017 case FILTER_GROUP:
1018 case FILTER_NOT_GROUP:
1019 break;
1020 default:
1021 return do_verify_filter(sb, filter, system, event, ftype);
1022 }
1023
1024 ret = do_verify_filter(sb, &filter->lval->filter, system, event, ftype);
1025 if (ret)
1026 return ret;
1027
1028 switch (filter->type) {
1029 case FILTER_OR:
1030 case FILTER_AND:
1031 return do_verify_filter(sb, &filter->rval->filter, system, event, ftype);
1032 default:
1033 return 0;
1034 }
1035 }
1036
1037 static int test_field_exists(struct tep_handle *tep, struct sqlhist_bison *sb,
1038 struct expr *expr);
1039
filter_compare_error(struct tep_handle * tep,struct sqlhist_bison * sb,struct expr * expr)1040 static void filter_compare_error(struct tep_handle *tep,
1041 struct sqlhist_bison *sb,
1042 struct expr *expr)
1043 {
1044 struct field *field = &expr->field;
1045
1046 switch (errno) {
1047 case ENODEV:
1048 case EBADE:
1049 break;
1050 case EINVAL:
1051 parse_error(sb, field->raw, "Invalid compare\n");
1052 break;
1053 default:
1054 parse_error(sb, field->raw, "System error?\n");
1055 return;
1056 }
1057
1058 /* ENODEV means that an event or field does not exist */
1059 if (errno == ENODEV) {
1060 if (test_field_exists(tep, sb, expr))
1061 return;
1062 if (test_field_exists(tep, sb, expr))
1063 return;
1064 return;
1065 }
1066
1067 /* fields exist, but values are not compatible */
1068 sb->line_no = expr->line;
1069 sb->line_idx = expr->idx;
1070
1071 parse_error(sb, field->raw,
1072 "Field '%s' is not compatible to be compared with the given value\n",
1073 field->field);
1074 }
1075
filter_error(struct tep_handle * tep,struct sqlhist_bison * sb,struct expr * expr)1076 static void filter_error(struct tep_handle *tep,
1077 struct sqlhist_bison *sb, struct expr *expr)
1078 {
1079 struct filter *filter = &expr->filter;
1080
1081 sb->line_no = expr->line;
1082 sb->line_idx = expr->idx;
1083
1084 switch (filter->type) {
1085 case FILTER_NOT_GROUP:
1086 case FILTER_GROUP:
1087 case FILTER_OR:
1088 case FILTER_AND:
1089 break;
1090 default:
1091 filter_compare_error(tep, sb, filter->lval);
1092 return;
1093 }
1094
1095 sb->line_no = expr->line;
1096 sb->line_idx = expr->idx;
1097
1098 parse_error(sb, "", "Problem with filter entry?\n");
1099 }
1100
build_filter(struct tep_handle * tep,struct sqlhist_bison * sb,struct tracefs_synth * synth,bool start,struct expr * expr,bool * started)1101 static int build_filter(struct tep_handle *tep, struct sqlhist_bison *sb,
1102 struct tracefs_synth *synth,
1103 bool start, struct expr *expr, bool *started)
1104 {
1105 int (*append_filter)(struct tracefs_synth *synth,
1106 enum tracefs_filter type,
1107 const char *field,
1108 enum tracefs_compare compare,
1109 const char *val);
1110 struct filter *filter = &expr->filter;
1111 enum tracefs_compare cmp;
1112 const char *val = NULL;
1113 int and_or = TRACEFS_FILTER_AND;
1114 char num[64];
1115 int ret;
1116
1117 if (start)
1118 append_filter = tracefs_synth_append_start_filter;
1119 else
1120 append_filter = tracefs_synth_append_end_filter;
1121
1122 if (started && *started) {
1123 ret = append_filter(synth, and_or, NULL, 0, NULL);
1124 ret = append_filter(synth, TRACEFS_FILTER_OPEN_PAREN,
1125 NULL, 0, NULL);
1126 }
1127
1128 switch (filter->type) {
1129 case FILTER_NOT_GROUP:
1130 ret = append_filter(synth, TRACEFS_FILTER_NOT,
1131 NULL, 0, NULL);
1132 if (ret < 0)
1133 goto out;
1134 /* Fall through */
1135 case FILTER_GROUP:
1136 ret = append_filter(synth, TRACEFS_FILTER_OPEN_PAREN,
1137 NULL, 0, NULL);
1138 if (ret < 0)
1139 goto out;
1140 ret = build_filter(tep, sb, synth, start, filter->lval, NULL);
1141 if (ret < 0)
1142 goto out;
1143 ret = append_filter(synth, TRACEFS_FILTER_CLOSE_PAREN,
1144 NULL, 0, NULL);
1145 goto out;
1146
1147 case FILTER_OR:
1148 and_or = TRACEFS_FILTER_OR;
1149 /* Fall through */
1150 case FILTER_AND:
1151 ret = build_filter(tep, sb, synth, start, filter->lval, NULL);
1152 if (ret < 0)
1153 goto out;
1154 ret = append_filter(synth, and_or, NULL, 0, NULL);
1155
1156 if (ret)
1157 goto out;
1158 ret = build_filter(tep, sb, synth, start, filter->rval, NULL);
1159 goto out;
1160 default:
1161 break;
1162 }
1163
1164 switch (filter->rval->type) {
1165 case EXPR_NUMBER:
1166 sprintf(num, "%ld", filter->rval->number);
1167 val = num;
1168 break;
1169 case EXPR_STRING:
1170 val = filter->rval->string;
1171 break;
1172 default:
1173 break;
1174 }
1175
1176 switch (filter->type) {
1177 case FILTER_EQ: cmp = TRACEFS_COMPARE_EQ; break;
1178 case FILTER_NE: cmp = TRACEFS_COMPARE_NE; break;
1179 case FILTER_LE: cmp = TRACEFS_COMPARE_LE; break;
1180 case FILTER_LT: cmp = TRACEFS_COMPARE_LT; break;
1181 case FILTER_GE: cmp = TRACEFS_COMPARE_GE; break;
1182 case FILTER_GT: cmp = TRACEFS_COMPARE_GT; break;
1183 case FILTER_BIN_AND: cmp = TRACEFS_COMPARE_AND; break;
1184 case FILTER_STR_CMP: cmp = TRACEFS_COMPARE_RE; break;
1185 default:
1186 tracefs_warning("Error invalid filter type '%d'", filter->type);
1187 return ERANGE;
1188 }
1189
1190 ret = append_filter(synth, TRACEFS_FILTER_COMPARE,
1191 filter->lval->field.field, cmp, val);
1192
1193 if (ret)
1194 filter_error(tep, sb, expr);
1195 out:
1196 if (!ret && started) {
1197 if (*started)
1198 ret = append_filter(synth, TRACEFS_FILTER_CLOSE_PAREN,
1199 NULL, 0, NULL);
1200 *started = true;
1201 }
1202 return ret;
1203 }
1204
field_match_error(struct tep_handle * tep,struct sqlhist_bison * sb,struct match * match)1205 static void *field_match_error(struct tep_handle *tep, struct sqlhist_bison *sb,
1206 struct match *match)
1207 {
1208 switch (errno) {
1209 case ENODEV:
1210 case EBADE:
1211 break;
1212 default:
1213 /* System error */
1214 return NULL;
1215 }
1216
1217 /* ENODEV means that an event or field does not exist */
1218 if (errno == ENODEV) {
1219 if (test_field_exists(tep, sb, match->lval))
1220 return NULL;
1221 if (test_field_exists(tep, sb, match->rval))
1222 return NULL;
1223 return NULL;
1224 }
1225
1226 /* fields exist, but values are not compatible */
1227 sb->line_no = match->lval->line;
1228 sb->line_idx = match->lval->idx;
1229
1230 parse_error(sb, match->lval->field.raw,
1231 "Field '%s' is not compatible to match field '%s'\n",
1232 match->lval->field.raw, match->rval->field.raw);
1233 return NULL;
1234 }
1235
synth_init_error(struct tep_handle * tep,struct sql_table * table)1236 static void *synth_init_error(struct tep_handle *tep, struct sql_table *table)
1237 {
1238 struct sqlhist_bison *sb = table->sb;
1239 struct match *match = table->matches;
1240
1241 switch (errno) {
1242 case ENODEV:
1243 case EBADE:
1244 break;
1245 default:
1246 /* System error */
1247 return NULL;
1248 }
1249
1250 /* ENODEV could mean that start or end events do not exist */
1251 if (errno == ENODEV) {
1252 if (test_event_exists(tep, sb, table->from, NULL))
1253 return NULL;
1254 if (test_event_exists(tep, sb, table->to, NULL))
1255 return NULL;
1256 }
1257
1258 return field_match_error(tep, sb, match);
1259 }
1260
selection_error(struct tep_handle * tep,struct sqlhist_bison * sb,struct expr * expr)1261 static void selection_error(struct tep_handle *tep,
1262 struct sqlhist_bison *sb, struct expr *expr)
1263 {
1264 /* We just care about event not existing */
1265 if (errno != ENODEV)
1266 return;
1267
1268 test_field_exists(tep, sb, expr);
1269 }
1270
compare_error(struct tep_handle * tep,struct sqlhist_bison * sb,struct expr * expr)1271 static void compare_error(struct tep_handle *tep,
1272 struct sqlhist_bison *sb, struct expr *expr)
1273 {
1274 struct compare *compare = &expr->compare;
1275
1276 if (!compare->name) {
1277 sb->line_no = expr->line;
1278 sb->line_idx = expr->idx + strlen("no name");
1279
1280 parse_error(sb, "no name",
1281 "Field calculations must be labeled 'AS name'\n");
1282 }
1283
1284 switch (errno) {
1285 case ENODEV:
1286 case EBADE:
1287 break;
1288 default:
1289 /* System error */
1290 return;
1291 }
1292
1293 /* ENODEV means that an event or field does not exist */
1294 if (errno == ENODEV) {
1295 if (test_field_exists(tep, sb, compare->lval))
1296 return;
1297 if (test_field_exists(tep, sb, compare->rval))
1298 return;
1299 return;
1300 }
1301
1302 /* fields exist, but values are not compatible */
1303 sb->line_no = compare->lval->line;
1304 sb->line_idx = compare->lval->idx;
1305
1306 parse_error(sb, compare->lval->field.raw,
1307 "'%s' is not compatible to compare with '%s'\n",
1308 compare->lval->field.raw, compare->rval->field.raw);
1309 }
1310
compare_no_to_error(struct sqlhist_bison * sb,struct expr * expr)1311 static void compare_no_to_error(struct sqlhist_bison *sb, struct expr *expr)
1312 {
1313 struct compare *compare = &expr->compare;
1314
1315 sb->line_no = compare->lval->line;
1316 sb->line_idx = compare->lval->idx;
1317
1318 parse_error(sb, compare->lval->field.raw,
1319 "Simple SQL (without JOIN/ON) do not allow comparisons\n",
1320 compare->lval->field.raw, compare->rval->field.raw);
1321 }
1322
where_no_to_error(struct sqlhist_bison * sb,struct expr * expr,const char * from_event,const char * event)1323 static void where_no_to_error(struct sqlhist_bison *sb, struct expr *expr,
1324 const char *from_event, const char *event)
1325 {
1326 while (expr) {
1327 switch (expr->filter.type) {
1328 case FILTER_OR:
1329 case FILTER_AND:
1330 case FILTER_GROUP:
1331 case FILTER_NOT_GROUP:
1332 expr = expr->filter.lval;
1333 continue;
1334 default:
1335 break;
1336 }
1337 break;
1338 }
1339 sb->line_no = expr->filter.lval->line;
1340 sb->line_idx = expr->filter.lval->idx;
1341
1342 parse_error(sb, expr->filter.lval->field.raw,
1343 "Event '%s' does not match FROM event '%s'\n",
1344 event, from_event);
1345 }
1346
verify_field_type(struct tep_handle * tep,struct sqlhist_bison * sb,struct expr * expr,int * cnt)1347 static int verify_field_type(struct tep_handle *tep,
1348 struct sqlhist_bison *sb,
1349 struct expr *expr, int *cnt)
1350 {
1351 struct field *field = &expr->field;
1352 struct tep_event *event;
1353 struct tep_format_field *tfield;
1354 char *type;
1355 int ret;
1356 int i;
1357
1358 if (!field->type)
1359 return 0;
1360
1361 sb->line_no = expr->line;
1362 sb->line_idx = expr->idx;
1363
1364 event = tep_find_event_by_name(tep, field->system, field->event_name);
1365 if (!event) {
1366 parse_error(sb, field->raw,
1367 "Event '%s' not found\n",
1368 field->event_name ? : "(null)");
1369 return -1;
1370 }
1371
1372 tfield = tep_find_any_field(event, field->field);
1373 if (!tfield) {
1374 parse_error(sb, field->raw,
1375 "Field '%s' not part of event '%s'\n",
1376 field->field ? : "(null)", field->event);
1377 return -1;
1378 }
1379
1380 type = strdup(field->type);
1381 if (!type)
1382 return -1;
1383
1384 if (!strcmp(type, TRACEFS_HIST_COUNTER) ||
1385 !strcmp(type, "_COUNTER_")) {
1386 ret = HIST_COUNTER_TYPE;
1387 if (tfield->flags & (TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY)) {
1388 parse_error(sb, field->raw,
1389 "'%s' is a string, and counters may only be used with numbers\n");
1390 ret = -1;
1391 }
1392 goto out;
1393 }
1394
1395 for (i = 0; type[i]; i++)
1396 type[i] = tolower(type[i]);
1397
1398 if (!strcmp(type, "hex")) {
1399 if (tfield->flags & (TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY))
1400 goto fail_type;
1401 ret = TRACEFS_HIST_KEY_HEX;
1402 } else if (!strcmp(type, "sym")) {
1403 if (tfield->flags & (TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY))
1404 goto fail_type;
1405 ret = TRACEFS_HIST_KEY_SYM;
1406 } else if (!strcmp(type, "sym-offset")) {
1407 if (tfield->flags & (TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY))
1408 goto fail_type;
1409 ret = TRACEFS_HIST_KEY_SYM_OFFSET;
1410 } else if (!strcmp(type, "syscall")) {
1411 if (tfield->flags & (TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY))
1412 goto fail_type;
1413 ret = TRACEFS_HIST_KEY_SYSCALL;
1414 } else if (!strcmp(type, "execname") ||
1415 !strcmp(type, "comm")) {
1416 ret = TRACEFS_HIST_KEY_EXECNAME;
1417 if (strcmp(field->field, "common_pid")) {
1418 parse_error(sb, field->raw,
1419 "'%s' is only allowed for common_pid\n",
1420 type);
1421 ret = -1;
1422 }
1423 } else if (!strcmp(type, "log") ||
1424 !strcmp(type, "log2")) {
1425 if (tfield->flags & (TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY))
1426 goto fail_type;
1427 ret = TRACEFS_HIST_KEY_LOG;
1428 } else if (!strncmp(type, "buckets", 7)) {
1429 if (type[7] != '=' || !isdigit(type[8])) {
1430 parse_error(sb, field->raw,
1431 "buckets type must have '=[number]' after it\n");
1432 ret = -1;
1433 goto out;
1434 }
1435 *cnt = atoi(&type[8]);
1436 if (tfield->flags & (TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY))
1437 goto fail_type;
1438 ret = TRACEFS_HIST_KEY_BUCKETS;
1439 } else {
1440 parse_error(sb, field->raw,
1441 "Cast of '%s' to unknown type '%s'\n",
1442 field->raw, type);
1443 ret = -1;
1444 }
1445 out:
1446 free(type);
1447 return ret;
1448 fail_type:
1449 parse_error(sb, field->raw,
1450 "Field '%s' cast to '%s' but is of type %s\n",
1451 field->field, type, tfield->flags & TEP_FIELD_IS_STRING ?
1452 "string" : "array");
1453 free(type);
1454 return -1;
1455 }
1456
build_synth(struct tep_handle * tep,const char * name,struct sql_table * table)1457 static struct tracefs_synth *build_synth(struct tep_handle *tep,
1458 const char *name,
1459 struct sql_table *table)
1460 {
1461 struct tracefs_synth *synth;
1462 struct field *field;
1463 struct match *match;
1464 struct expr *expr;
1465 const char *start_system;
1466 const char *start_event;
1467 const char *end_system;
1468 const char *end_event;
1469 const char *start_match;
1470 const char *end_match;
1471 bool started_start = false;
1472 bool started_end = false;
1473 bool non_val = false;
1474 int ret;
1475
1476 if (!table->from)
1477 return NULL;
1478
1479 /* This could be a simple SQL statement to only build a histogram */
1480 if (!table->to) {
1481 ret = update_fields(tep, table, table->from);
1482 if (ret < 0)
1483 return NULL;
1484
1485 start_system = table->from->field.system;
1486 start_event = table->from->field.event_name;
1487
1488 synth = synth_init_from(tep, start_system, start_event);
1489 if (!synth)
1490 return synth_init_error(tep, table);
1491 goto hist_only;
1492 }
1493
1494 ret = update_vars(tep, table, table->from);
1495 if (ret < 0)
1496 return NULL;
1497
1498 ret = update_vars(tep, table, table->to);
1499 if (ret < 0)
1500 return NULL;
1501
1502 start_system = table->from->field.system;
1503 start_event = table->from->field.event_name;
1504
1505 match = table->matches;
1506 if (!match)
1507 return NULL;
1508
1509 ret = test_match(table, match);
1510 if (ret < 0)
1511 return NULL;
1512
1513 end_system = table->to->field.system;
1514 end_event = table->to->field.event_name;
1515
1516 assign_match(start_system, start_event, match,
1517 &start_match, &end_match);
1518
1519 synth = tracefs_synth_alloc(tep, name, start_system,
1520 start_event, end_system, end_event,
1521 start_match, end_match, NULL);
1522 if (!synth)
1523 return synth_init_error(tep, table);
1524
1525 for (match = match->next; match; match = match->next) {
1526 ret = test_match(table, match);
1527 if (ret < 0)
1528 goto free;
1529
1530 assign_match(start_system, start_event, match,
1531 &start_match, &end_match);
1532
1533 ret = tracefs_synth_add_match_field(synth,
1534 start_match,
1535 end_match, NULL);
1536 if (ret < 0) {
1537 field_match_error(tep, table->sb, match);
1538 goto free;
1539 }
1540 }
1541
1542 hist_only:
1543 /* table->to may be NULL here */
1544
1545 for (expr = table->selections; expr; expr = expr->next) {
1546 if (expr->type == EXPR_FIELD) {
1547 ret = -1;
1548 field = &expr->field;
1549 if (field->ftype != FIELD_TO &&
1550 field->system == start_system &&
1551 field->event_name == start_event) {
1552 int type;
1553 int cnt = 0;
1554 type = verify_field_type(tep, table->sb, expr, &cnt);
1555 if (type < 0)
1556 goto free;
1557 if (type != HIST_COUNTER_TYPE)
1558 non_val = true;
1559 ret = synth_add_start_field(synth,
1560 field->field, field->label,
1561 type, cnt);
1562 } else if (table->to) {
1563 ret = tracefs_synth_add_end_field(synth,
1564 field->field, field->label);
1565 }
1566 if (ret < 0) {
1567 selection_error(tep, table->sb, expr);
1568 goto free;
1569 }
1570 continue;
1571 }
1572
1573 if (!table->to) {
1574 compare_no_to_error(table->sb, expr);
1575 goto free;
1576 }
1577
1578 if (expr->type != EXPR_COMPARE)
1579 goto free;
1580
1581 ret = build_compare(synth, start_system, end_system,
1582 &expr->compare);
1583 if (ret < 0) {
1584 compare_error(tep, table->sb, expr);
1585 goto free;
1586 }
1587 }
1588
1589 if (!non_val && !table->to) {
1590 table->sb->line_no = 0;
1591 table->sb->line_idx = 10;
1592 parse_error(table->sb, "CAST",
1593 "Not all SELECT items can be of type _COUNTER_\n");
1594 goto free;
1595 }
1596
1597 for (expr = table->where; expr; expr = expr->next) {
1598 const char *filter_system = NULL;
1599 const char *filter_event = NULL;
1600 enum field_type ftype = FIELD_NONE;
1601 bool *started;
1602 bool start;
1603
1604 ret = verify_filter(table->sb, &expr->filter, &filter_system,
1605 &filter_event, &ftype);
1606 if (ret < 0)
1607 goto free;
1608
1609 start = filter_system == start_system &&
1610 filter_event == start_event &&
1611 ftype != FIELD_TO;
1612
1613 if (start)
1614 started = &started_start;
1615 else if (!table->to) {
1616 where_no_to_error(table->sb, expr, start_event,
1617 filter_event);
1618 goto free;
1619 } else
1620 started = &started_end;
1621
1622 ret = build_filter(tep, table->sb, synth, start, expr, started);
1623 if (ret < 0)
1624 goto free;
1625 }
1626
1627 return synth;
1628 free:
1629 tracefs_synth_free(synth);
1630 return NULL;
1631 }
1632
free_sql_table(struct sql_table * table)1633 static void free_sql_table(struct sql_table *table)
1634 {
1635 struct match *match;
1636 struct expr *expr;
1637
1638 if (!table)
1639 return;
1640
1641 while ((expr = table->exprs)) {
1642 table->exprs = expr->free_list;
1643 free(expr);
1644 }
1645
1646 while ((match = table->matches)) {
1647 table->matches = match->next;
1648 free(match);
1649 }
1650
1651 free(table);
1652 }
1653
free_str_hash(struct str_hash ** hash)1654 static void free_str_hash(struct str_hash **hash)
1655 {
1656 struct str_hash *item;
1657 int i;
1658
1659 for (i = 0; i < 1 << HASH_BITS; i++) {
1660 while ((item = hash[i])) {
1661 hash[i] = item->next;
1662 free(item->str);
1663 free(item);
1664 }
1665 }
1666 }
1667
free_sb(struct sqlhist_bison * sb)1668 static void free_sb(struct sqlhist_bison *sb)
1669 {
1670 free_sql_table(sb->table);
1671 free_str_hash(sb->str_hash);
1672 free(sb->parse_error_str);
1673 }
1674
tracefs_sql(struct tep_handle * tep,const char * name,const char * sql_buffer,char ** err)1675 struct tracefs_synth *tracefs_sql(struct tep_handle *tep, const char *name,
1676 const char *sql_buffer, char **err)
1677 {
1678 struct tracefs_synth *synth = NULL;
1679 struct sqlhist_bison sb;
1680 int ret;
1681
1682 if (!tep || !sql_buffer) {
1683 errno = EINVAL;
1684 return NULL;
1685 }
1686
1687 memset(&sb, 0, sizeof(sb));
1688
1689 sb.buffer = sql_buffer;
1690 sb.buffer_size = strlen(sql_buffer);
1691 sb.buffer_idx = 0;
1692
1693 ret = yylex_init_extra(&sb, &sb.scanner);
1694 if (ret < 0) {
1695 yylex_destroy(sb.scanner);
1696 return NULL;
1697 }
1698
1699 ret = tracefs_parse(&sb);
1700 yylex_destroy(sb.scanner);
1701
1702 if (ret)
1703 goto free;
1704
1705 synth = build_synth(tep, name, sb.table);
1706
1707 free:
1708 if (!synth) {
1709 if (sb.parse_error_str && err) {
1710 *err = sb.parse_error_str;
1711 sb.parse_error_str = NULL;
1712 }
1713 }
1714 free_sb(&sb);
1715 return synth;
1716 }
1717