Skip to content

Commit

Permalink
Allow (IsA, tgt|self) queries to be cached
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed Sep 22, 2024
1 parent e844213 commit b2cf189
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 46 deletions.
46 changes: 24 additions & 22 deletions distr/flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -33995,29 +33995,29 @@ int flecs_term_finalize(
ecs_record_t *first_record = flecs_entities_get(world, first_entity);
ecs_table_t *first_table = first_record ? first_record->table : NULL;
if (first_table) {
/* Add traversal flags for transitive relationships */
if (ecs_term_ref_is_set(second) && !((second_flags & EcsTraverseFlags) == EcsSelf)) {
if (!((src->id & EcsIsVariable) && (src_id == EcsAny))) {
if (!((second->id & EcsIsVariable) && (second_id == EcsAny))) {
if (ecs_table_has_id(world, first_table, EcsTransitive)) {
term->flags_ |= EcsTermTransitive;
if (ecs_term_ref_is_set(second)) {
/* Add traversal flags for transitive relationships */
if (!((second_flags & EcsTraverseFlags) == EcsSelf)) {
if (!((src->id & EcsIsVariable) && (src_id == EcsAny))) {
if (!((second->id & EcsIsVariable) && (second_id == EcsAny))) {
if (ecs_table_has_id(world, first_table, EcsTransitive)) {
term->flags_ |= EcsTermTransitive;
}

if (ecs_table_has_id(world, first_table, EcsReflexive)) {
term->flags_ |= EcsTermReflexive;
}
}
}
}
}

if (ECS_IS_PAIR(term->id)) {
if (ecs_table_has_id(world, first_table, EcsReflexive)) {
term->flags_ |= EcsTermReflexive;
}
}

/* Check if term is union */
if (ecs_table_has_id(world, first_table, EcsUnion)) {
/* Any wildcards don't need special handling as they just return
* (Rel, *). */
if (ECS_IS_PAIR(term->id) && ECS_PAIR_SECOND(term->id) != EcsAny) {
term->flags_ |= EcsTermIsUnion;
/* Check if term is union */
if (ecs_table_has_id(world, first_table, EcsUnion)) {
/* Any wildcards don't need special handling as they just return
* (Rel, *). */
if (ECS_IS_PAIR(term->id) && ECS_PAIR_SECOND(term->id) != EcsAny) {
term->flags_ |= EcsTermIsUnion;
}
}
}
}
Expand Down Expand Up @@ -34089,7 +34089,7 @@ int flecs_term_finalize(

if (term->flags_ & EcsTermTransitive) {
trivial_term = false;
cacheable_term = false;
cacheable_term = false;
}

if (term->flags_ & EcsTermIdInherited) {
Expand Down Expand Up @@ -34810,11 +34810,13 @@ bool flecs_query_finalize_simple(
if (ECS_IS_PAIR(id)) {
if (ecs_has_id(world, first, EcsTransitive)) {
term->flags_ |= EcsTermTransitive;
cacheable = false; trivial = false;
trivial = false;
cacheable = false;
}
if (ecs_has_id(world, first, EcsReflexive)) {
term->flags_ |= EcsTermReflexive;
cacheable = false; trivial = false;
trivial = false;
cacheable = false;
}
}

Expand Down
46 changes: 24 additions & 22 deletions src/query/validator.c
Original file line number Diff line number Diff line change
Expand Up @@ -825,29 +825,29 @@ int flecs_term_finalize(
ecs_record_t *first_record = flecs_entities_get(world, first_entity);
ecs_table_t *first_table = first_record ? first_record->table : NULL;
if (first_table) {
/* Add traversal flags for transitive relationships */
if (ecs_term_ref_is_set(second) && !((second_flags & EcsTraverseFlags) == EcsSelf)) {
if (!((src->id & EcsIsVariable) && (src_id == EcsAny))) {
if (!((second->id & EcsIsVariable) && (second_id == EcsAny))) {
if (ecs_table_has_id(world, first_table, EcsTransitive)) {
term->flags_ |= EcsTermTransitive;
if (ecs_term_ref_is_set(second)) {
/* Add traversal flags for transitive relationships */
if (!((second_flags & EcsTraverseFlags) == EcsSelf)) {
if (!((src->id & EcsIsVariable) && (src_id == EcsAny))) {
if (!((second->id & EcsIsVariable) && (second_id == EcsAny))) {
if (ecs_table_has_id(world, first_table, EcsTransitive)) {
term->flags_ |= EcsTermTransitive;
}

if (ecs_table_has_id(world, first_table, EcsReflexive)) {
term->flags_ |= EcsTermReflexive;
}
}
}
}
}

if (ECS_IS_PAIR(term->id)) {
if (ecs_table_has_id(world, first_table, EcsReflexive)) {
term->flags_ |= EcsTermReflexive;
}
}

/* Check if term is union */
if (ecs_table_has_id(world, first_table, EcsUnion)) {
/* Any wildcards don't need special handling as they just return
* (Rel, *). */
if (ECS_IS_PAIR(term->id) && ECS_PAIR_SECOND(term->id) != EcsAny) {
term->flags_ |= EcsTermIsUnion;
/* Check if term is union */
if (ecs_table_has_id(world, first_table, EcsUnion)) {
/* Any wildcards don't need special handling as they just return
* (Rel, *). */
if (ECS_IS_PAIR(term->id) && ECS_PAIR_SECOND(term->id) != EcsAny) {
term->flags_ |= EcsTermIsUnion;
}
}
}
}
Expand Down Expand Up @@ -919,7 +919,7 @@ int flecs_term_finalize(

if (term->flags_ & EcsTermTransitive) {
trivial_term = false;
cacheable_term = false;
cacheable_term = false;
}

if (term->flags_ & EcsTermIdInherited) {
Expand Down Expand Up @@ -1640,11 +1640,13 @@ bool flecs_query_finalize_simple(
if (ECS_IS_PAIR(id)) {
if (ecs_has_id(world, first, EcsTransitive)) {
term->flags_ |= EcsTermTransitive;
cacheable = false; trivial = false;
trivial = false;
cacheable = false;
}
if (ecs_has_id(world, first, EcsReflexive)) {
term->flags_ |= EcsTermReflexive;
cacheable = false; trivial = false;
trivial = false;
cacheable = false;
}
}

Expand Down
6 changes: 5 additions & 1 deletion test/query/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,11 @@
"0_src_w_union",
"0_src_w_sparse_and_component",
"0_src_w_toggle_and_component",
"0_src_w_union_and_component"
"0_src_w_union_and_component",
"cached_isa_tgt",
"cached_isa_tgt_w_self_second",
"cached_isa_tgt_no_expr",
"cached_isa_tgt_w_self_second_no_expr"
]
}, {
"id": "Variables",
Expand Down
112 changes: 112 additions & 0 deletions test/query/src/Plan.c
Original file line number Diff line number Diff line change
Expand Up @@ -2474,3 +2474,115 @@ void Plan_0_src_w_union_and_component(void) {

ecs_fini(world);
}

void Plan_cached_isa_tgt(void) {
ecs_world_t *world = ecs_mini();

ECS_TAG(world, Tgt);

ecs_query_t *q = ecs_query(world, {
.expr = "(IsA, Tgt)",
.cache_kind = EcsQueryCacheAuto
});

test_assert(q != NULL);

ecs_log_enable_colors(false);

const char *expect =
HEAD " 0. [-1, 1] trav $[this] (IsA, Tgt)"
LINE " 1. [ 0, 2] yield "
LINE "";
char *plan = ecs_query_plan(q);

test_str(expect, plan);
ecs_os_free(plan);

ecs_query_fini(q);

ecs_fini(world);
}

void Plan_cached_isa_tgt_w_self_second(void) {
ecs_world_t *world = ecs_mini();

ECS_TAG(world, Tgt);

ecs_query_t *q = ecs_query(world, {
.expr = "(IsA, Tgt|self)",
.cache_kind = EcsQueryCacheAuto
});

test_assert(q != NULL);

ecs_log_enable_colors(false);

const char *expect =
HEAD " 0. [-1, 1] xcache "
LINE " 1. [ 0, 2] yield "
LINE "";
char *plan = ecs_query_plan(q);

test_str(expect, plan);
ecs_os_free(plan);

ecs_query_fini(q);

ecs_fini(world);
}

void Plan_cached_isa_tgt_no_expr(void) {
ecs_world_t *world = ecs_mini();

ECS_TAG(world, Tgt);

ecs_query_t *q = ecs_query(world, {
.terms = {{ ecs_pair(EcsIsA, Tgt) }},
.cache_kind = EcsQueryCacheAuto
});

test_assert(q != NULL);

ecs_log_enable_colors(false);

const char *expect =
HEAD " 0. [-1, 1] trav $[this] (IsA, Tgt)"
LINE " 1. [ 0, 2] yield "
LINE "";
char *plan = ecs_query_plan(q);

test_str(expect, plan);
ecs_os_free(plan);

ecs_query_fini(q);

ecs_fini(world);
}

void Plan_cached_isa_tgt_w_self_second_no_expr(void) {
ecs_world_t *world = ecs_mini();

ECS_TAG(world, Tgt);

ecs_query_t *q = ecs_query(world, {
.terms = {{ ecs_pair(EcsIsA, Tgt), .second.id = EcsSelf }},
.cache_kind = EcsQueryCacheAuto
});

test_assert(q != NULL);

ecs_log_enable_colors(false);

const char *expect =
HEAD " 0. [-1, 1] xcache "
LINE " 1. [ 0, 2] yield "
LINE "";
char *plan = ecs_query_plan(q);

test_str(expect, plan);
ecs_os_free(plan);

ecs_query_fini(q);

ecs_fini(world);
}
22 changes: 21 additions & 1 deletion test/query/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,10 @@ void Plan_0_src_w_union(void);
void Plan_0_src_w_sparse_and_component(void);
void Plan_0_src_w_toggle_and_component(void);
void Plan_0_src_w_union_and_component(void);
void Plan_cached_isa_tgt(void);
void Plan_cached_isa_tgt_w_self_second(void);
void Plan_cached_isa_tgt_no_expr(void);
void Plan_cached_isa_tgt_w_self_second_no_expr(void);

// Testsuite 'Variables'
void Variables_setup(void);
Expand Down Expand Up @@ -5050,6 +5054,22 @@ bake_test_case Plan_testcases[] = {
{
"0_src_w_union_and_component",
Plan_0_src_w_union_and_component
},
{
"cached_isa_tgt",
Plan_cached_isa_tgt
},
{
"cached_isa_tgt_w_self_second",
Plan_cached_isa_tgt_w_self_second
},
{
"cached_isa_tgt_no_expr",
Plan_cached_isa_tgt_no_expr
},
{
"cached_isa_tgt_w_self_second_no_expr",
Plan_cached_isa_tgt_w_self_second_no_expr
}
};

Expand Down Expand Up @@ -10340,7 +10360,7 @@ static bake_test_suite suites[] = {
"Plan",
NULL,
NULL,
72,
76,
Plan_testcases
},
{
Expand Down

0 comments on commit b2cf189

Please sign in to comment.