Skip to content

Commit

Permalink
#1473 Fix issue where queries would return inconsistent component id …
Browse files Browse the repository at this point in the history
…for AndFrom/NotFrom/OrFrom fields
  • Loading branch information
SanderMertens committed Dec 18, 2024
1 parent d911c70 commit 8a15828
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 19 deletions.
18 changes: 12 additions & 6 deletions distr/flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1532,6 +1532,7 @@ typedef struct {
/* *From operator iterator context */
typedef struct {
ecs_query_and_ctx_t and;
ecs_entity_t type_id;
ecs_type_t *type;
int32_t first_id_index;
int32_t cur_id_index;
Expand Down Expand Up @@ -70614,13 +70615,15 @@ bool flecs_query_x_from(
ecs_query_xfrom_ctx_t *op_ctx = flecs_op_ctx(ctx, xfrom);
ecs_world_t *world = ctx->world;
ecs_type_t *type;
ecs_entity_t type_id;
int32_t i;

if (!redo) {
/* Find entity that acts as the template from which we match the ids */
ecs_id_t id = flecs_query_op_get_id(op, ctx);
ecs_assert(ecs_is_alive(world, id), ECS_INTERNAL_ERROR, NULL);
ecs_record_t *r = flecs_entities_get(world, id);
type_id = flecs_query_op_get_id(op, ctx);
op_ctx->type_id = type_id;
ecs_assert(ecs_is_alive(world, type_id), ECS_INTERNAL_ERROR, NULL);
ecs_record_t *r = flecs_entities_get(world, type_id);
ecs_table_t *table;
if (!r || !(table = r->table)) {
/* Nothing to match */
Expand All @@ -70637,6 +70640,7 @@ bool flecs_query_x_from(
return false; /* No ids to filter on */
}
} else {
type_id = op_ctx->type_id;
type = op_ctx->type;
}

Expand Down Expand Up @@ -70682,7 +70686,7 @@ bool flecs_query_x_from(
if (!src_table) {
continue;
}

redo = true;

if (!src_written && oper == EcsOrFrom) {
Expand All @@ -70708,7 +70712,7 @@ bool flecs_query_x_from(
continue;
}
}
return true;
goto match;
}

if (oper == EcsAndFrom || oper == EcsNotFrom || src_written) {
Expand All @@ -70734,7 +70738,7 @@ bool flecs_query_x_from(
if (oper == EcsNotFrom) {
break; /* Must have none of the ids */
} else if (oper == EcsOrFrom) {
return true; /* Single match is enough */
goto match; /* Single match is enough */
}
}
}
Expand All @@ -70747,6 +70751,8 @@ bool flecs_query_x_from(
}
} while (true);

match:
ctx->it->ids[op->field_index] = type_id;
return true;
}

Expand Down
17 changes: 11 additions & 6 deletions src/query/engine/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,13 +398,15 @@ bool flecs_query_x_from(
ecs_query_xfrom_ctx_t *op_ctx = flecs_op_ctx(ctx, xfrom);
ecs_world_t *world = ctx->world;
ecs_type_t *type;
ecs_entity_t type_id;
int32_t i;

if (!redo) {
/* Find entity that acts as the template from which we match the ids */
ecs_id_t id = flecs_query_op_get_id(op, ctx);
ecs_assert(ecs_is_alive(world, id), ECS_INTERNAL_ERROR, NULL);
ecs_record_t *r = flecs_entities_get(world, id);
type_id = flecs_query_op_get_id(op, ctx);
op_ctx->type_id = type_id;
ecs_assert(ecs_is_alive(world, type_id), ECS_INTERNAL_ERROR, NULL);
ecs_record_t *r = flecs_entities_get(world, type_id);
ecs_table_t *table;
if (!r || !(table = r->table)) {
/* Nothing to match */
Expand All @@ -421,6 +423,7 @@ bool flecs_query_x_from(
return false; /* No ids to filter on */
}
} else {
type_id = op_ctx->type_id;
type = op_ctx->type;
}

Expand Down Expand Up @@ -466,7 +469,7 @@ bool flecs_query_x_from(
if (!src_table) {
continue;
}

redo = true;

if (!src_written && oper == EcsOrFrom) {
Expand All @@ -492,7 +495,7 @@ bool flecs_query_x_from(
continue;
}
}
return true;
goto match;
}

if (oper == EcsAndFrom || oper == EcsNotFrom || src_written) {
Expand All @@ -518,7 +521,7 @@ bool flecs_query_x_from(
if (oper == EcsNotFrom) {
break; /* Must have none of the ids */
} else if (oper == EcsOrFrom) {
return true; /* Single match is enough */
goto match; /* Single match is enough */
}
}
}
Expand All @@ -531,6 +534,8 @@ bool flecs_query_x_from(
}
} while (true);

match:
ctx->it->ids[op->field_index] = type_id;
return true;
}

Expand Down
1 change: 1 addition & 0 deletions src/query/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ typedef struct {
/* *From operator iterator context */
typedef struct {
ecs_query_and_ctx_t and;
ecs_entity_t type_id;
ecs_type_t *type;
int32_t first_id_index;
int32_t cur_id_index;
Expand Down
3 changes: 3 additions & 0 deletions test/query/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,9 @@
"and_from_empty_w_tag",
"not_from_empty_w_tag",
"or_from_empty_w_tag",
"and_from_existing_and_new_table",
"not_from_existing_and_new_table",
"or_from_existing_and_new_table",
"or_w_wildcard",
"or_w_component_and_tag",
"or_w_tag_and_component"
Expand Down
Loading

0 comments on commit 8a15828

Please sign in to comment.