@@ -507,6 +507,7 @@ __hidden int table_start(struct sqlhist_bison *sb)
}
static int test_event_exists(struct tep_handle *tep,
+ struct sqlhist_bison *sb,
struct expr *expr, struct tep_event **pevent)
{
struct field *field = &expr->field;
@@ -517,18 +518,30 @@ static int test_event_exists(struct tep_handle *tep,
field->event = tep_find_event_by_name(tep, system, event);
if (pevent)
*pevent = field->event;
- return field->event != NULL ? 0 : -1;
+
+ if (field->event)
+ return 0;
+
+ sb->line_no = expr->line;
+ sb->line_idx = expr->idx;
+
+ parse_error(sb, field->raw, "event not found\n");
+ return -1;
}
-static int test_field_exists(struct expr *expr)
+static int test_field_exists(struct tep_handle *tep,
+ struct sqlhist_bison *sb,
+ struct expr *expr)
{
struct field *field = &expr->field;
struct tep_format_field *tfield;
char *field_name;
const char *p;
- if (!field->event)
- return -1;
+ if (!field->event) {
+ if (test_event_exists(tep, sb, expr, NULL))
+ return -1;
+ }
/* The field could have a conversion */
p = strchr(field->field, '.');
@@ -547,7 +560,16 @@ static int test_field_exists(struct expr *expr)
tfield = tep_find_any_field(field->event, field_name);
free(field_name);
- return tfield != NULL ? 0 : -1;
+ if (tfield)
+ return 0;
+
+ sb->line_no = expr->line;
+ sb->line_idx = expr->idx;
+
+ parse_error(sb, field->raw,
+ "Field '%s' not part of event %s\n",
+ field->field, field->event_name);
+ return -1;
}
static int update_vars(struct tep_handle *tep,
@@ -585,7 +607,7 @@ static int update_vars(struct tep_handle *tep,
if (!event_field->event_name)
return -1;
- if (test_event_exists(tep, expr, &event))
+ if (test_event_exists(tep, sb, expr, &event))
return -1;
if (!event_field->system)
@@ -651,7 +673,7 @@ static int update_vars(struct tep_handle *tep,
field->field = store_str(sb, TRACEFS_TIMESTAMP);
if (!strcmp(field->field, "TIMESTAMP_USECS"))
field->field = store_str(sb, TRACEFS_TIMESTAMP_USECS);
- if (test_field_exists(expr))
+ if (test_field_exists(tep, sb, expr))
return -1;
}
@@ -941,6 +963,62 @@ static int build_filter(struct tracefs_synth *synth,
return ret;
}
+static void *field_match_error(struct tep_handle *tep, struct sqlhist_bison *sb,
+ struct match *match)
+{
+ switch (errno) {
+ case ENODEV:
+ case EBADE:
+ break;
+ default:
+ /* System error */
+ return NULL;
+ }
+
+ /* ENODEV means that an event or field does not exist */
+ if (errno == ENODEV) {
+ if (test_field_exists(tep, sb, match->lval))
+ return NULL;
+ if (test_field_exists(tep, sb, match->rval))
+ return NULL;
+ return NULL;
+ }
+
+ /* fields exist, but values are not compatible */
+ sb->line_no = match->lval->line;
+ sb->line_idx = match->lval->idx;
+
+ parse_error(sb, match->lval->field.raw,
+ "Field '%s' is not compatible to match field '%s'\n",
+ match->lval->field.raw, match->rval->field.raw);
+ return NULL;
+}
+
+static void *synth_init_error(struct tep_handle *tep, struct sql_table *table)
+{
+ struct sqlhist_bison *sb = table->sb;
+ struct match *match = table->matches;
+
+ switch (errno) {
+ case ENODEV:
+ case EBADE:
+ break;
+ default:
+ /* System error */
+ return NULL;
+ }
+
+ /* ENODEV could mean that start or end events do not exist */
+ if (errno == ENODEV) {
+ if (test_event_exists(tep, sb, table->from, NULL))
+ return NULL;
+ if (test_event_exists(tep, sb, table->to, NULL))
+ return NULL;
+ }
+
+ return field_match_error(tep, sb, match);
+}
+
static struct tracefs_synth *build_synth(struct tep_handle *tep,
const char *name,
struct sql_table *table)
@@ -991,7 +1069,7 @@ static struct tracefs_synth *build_synth(struct tep_handle *tep,
start_event, end_system, end_event,
start_match, end_match, NULL);
if (!synth)
- return NULL;
+ return synth_init_error(tep, table);
for (match = match->next; match; match = match->next) {
ret = test_match(table, match);
@@ -1004,8 +1082,10 @@ static struct tracefs_synth *build_synth(struct tep_handle *tep,
ret = tracefs_synth_add_match_field(synth,
start_match,
end_match, NULL);
- if (ret < 0)
+ if (ret < 0) {
+ field_match_error(tep, table->sb, match);
goto free;
+ }
}
for (expr = table->selections; expr; expr = expr->next) {