• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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