Skip to content

Commit 34dc148

Browse files
committed
Fix issue where up traversal could return duplicate result
1 parent 2fbe476 commit 34dc148

File tree

6 files changed

+193
-37
lines changed

6 files changed

+193
-37
lines changed

distr/flecs.c

+5-18
Original file line numberDiff line numberDiff line change
@@ -2338,24 +2338,6 @@ bool flecs_query_self_up_with(
23382338
const ecs_query_run_ctx_t *ctx,
23392339
bool id_only);
23402340

2341-
bool flecs_query_up_select(
2342-
const ecs_query_op_t *op,
2343-
bool redo,
2344-
const ecs_query_run_ctx_t *ctx,
2345-
ecs_query_up_select_trav_kind_t trav_kind,
2346-
ecs_query_up_select_kind_t kind);
2347-
2348-
bool flecs_query_up_with(
2349-
const ecs_query_op_t *op,
2350-
bool redo,
2351-
const ecs_query_run_ctx_t *ctx);
2352-
2353-
bool flecs_query_self_up_with(
2354-
const ecs_query_op_t *op,
2355-
bool redo,
2356-
const ecs_query_run_ctx_t *ctx,
2357-
bool id_only);
2358-
23592341

23602342
/* Transitive relationship traversal */
23612343

@@ -72323,6 +72305,11 @@ void flecs_trav_entity_down_isa(
7232372305
continue;
7232472306
}
7232572307

72308+
if (ecs_table_has_id(world, table, idr_with->id)) {
72309+
/* Table owns component */
72310+
continue;
72311+
}
72312+
7232672313
const ecs_entity_t *entities = ecs_table_entities(table);
7232772314
int32_t i, count = ecs_table_count(table);
7232872315
for (i = 0; i < count; i ++) {

src/query/engine/engine.h

-18
Original file line numberDiff line numberDiff line change
@@ -314,24 +314,6 @@ bool flecs_query_self_up_with(
314314
const ecs_query_run_ctx_t *ctx,
315315
bool id_only);
316316

317-
bool flecs_query_up_select(
318-
const ecs_query_op_t *op,
319-
bool redo,
320-
const ecs_query_run_ctx_t *ctx,
321-
ecs_query_up_select_trav_kind_t trav_kind,
322-
ecs_query_up_select_kind_t kind);
323-
324-
bool flecs_query_up_with(
325-
const ecs_query_op_t *op,
326-
bool redo,
327-
const ecs_query_run_ctx_t *ctx);
328-
329-
bool flecs_query_self_up_with(
330-
const ecs_query_op_t *op,
331-
bool redo,
332-
const ecs_query_run_ctx_t *ctx,
333-
bool id_only);
334-
335317

336318
/* Transitive relationship traversal */
337319

src/query/engine/trav_down_cache.c

+5
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ void flecs_trav_entity_down_isa(
122122
continue;
123123
}
124124

125+
if (ecs_table_has_id(world, table, idr_with->id)) {
126+
/* Table owns component */
127+
continue;
128+
}
129+
125130
const ecs_entity_t *entities = ecs_table_entities(table);
126131
int32_t i, count = ecs_table_count(table);
127132
for (i = 0; i < count; i ++) {

test/query/project.json

+4
Original file line numberDiff line numberDiff line change
@@ -1411,8 +1411,12 @@
14111411
"up_all_owned",
14121412
"this_self_up_childof_inherited",
14131413
"this_up_childof_inherited",
1414+
"this_self_up_childof_inherited_override",
1415+
"this_up_childof_inherited_override",
14141416
"this_written_self_up_childof_inherited",
14151417
"this_written_up_childof_inherited",
1418+
"this_written_self_up_childof_inherited_override",
1419+
"this_written_up_childof_inherited_override",
14161420
"var_self_up_childof_inherited",
14171421
"var_up_childof_inherited",
14181422
"var_written_self_up_childof_inherited",

test/query/src/Traversal.c

+158
Original file line numberDiff line numberDiff line change
@@ -2811,6 +2811,78 @@ void Traversal_this_up_childof_inherited(void) {
28112811
ecs_fini(world);
28122812
}
28132813

2814+
void Traversal_this_self_up_childof_inherited_override(void) {
2815+
ecs_world_t *world = ecs_mini();
2816+
2817+
ECS_ENTITY(world, Foo, (OnInstantiate, Inherit));
2818+
2819+
ecs_entity_t base = ecs_entity(world, { .add = ecs_ids(Foo) });
2820+
ecs_entity_t parent = ecs_entity(world, { .add = ecs_ids(ecs_isa(base), Foo) });
2821+
ecs_entity_t child = ecs_entity(world, { .parent = parent });
2822+
2823+
ecs_query_t *r = ecs_query(world, {
2824+
.expr = "Foo(self|up)",
2825+
.cache_kind = cache_kind
2826+
});
2827+
2828+
test_assert(r != NULL);
2829+
2830+
ecs_iter_t it = ecs_query_iter(world, r);
2831+
test_bool(true, ecs_query_next(&it));
2832+
test_int(1, it.count);
2833+
test_uint(base, it.entities[0]);
2834+
test_uint(0, ecs_field_src(&it, 0));
2835+
test_uint(Foo, ecs_field_id(&it, 0));
2836+
2837+
test_bool(true, ecs_query_next(&it));
2838+
test_int(1, it.count);
2839+
test_uint(parent, it.entities[0]);
2840+
test_uint(0, ecs_field_src(&it, 0));
2841+
test_uint(Foo, ecs_field_id(&it, 0));
2842+
2843+
test_bool(true, ecs_query_next(&it));
2844+
test_int(1, it.count);
2845+
test_uint(child, it.entities[0]);
2846+
test_uint(parent, ecs_field_src(&it, 0));
2847+
test_uint(Foo, ecs_field_id(&it, 0));
2848+
2849+
test_bool(false, ecs_query_next(&it));
2850+
2851+
ecs_query_fini(r);
2852+
2853+
ecs_fini(world);
2854+
}
2855+
2856+
void Traversal_this_up_childof_inherited_override(void) {
2857+
ecs_world_t *world = ecs_mini();
2858+
2859+
ECS_ENTITY(world, Foo, (OnInstantiate, Inherit));
2860+
2861+
ecs_entity_t base = ecs_entity(world, { .add = ecs_ids(Foo) });
2862+
ecs_entity_t parent = ecs_entity(world, { .add = ecs_ids(ecs_isa(base), Foo) });
2863+
ecs_entity_t child = ecs_entity(world, { .parent = parent });
2864+
2865+
ecs_query_t *r = ecs_query(world, {
2866+
.expr = "Foo(up)",
2867+
.cache_kind = cache_kind
2868+
});
2869+
2870+
test_assert(r != NULL);
2871+
2872+
ecs_iter_t it = ecs_query_iter(world, r);
2873+
test_bool(true, ecs_query_next(&it));
2874+
test_int(1, it.count);
2875+
test_uint(child, it.entities[0]);
2876+
test_uint(parent, ecs_field_src(&it, 0));
2877+
test_uint(Foo, ecs_field_id(&it, 0));
2878+
2879+
test_bool(false, ecs_query_next(&it));
2880+
2881+
ecs_query_fini(r);
2882+
2883+
ecs_fini(world);
2884+
}
2885+
28142886
void Traversal_this_written_self_up_childof_inherited(void) {
28152887
ecs_world_t *world = ecs_mini();
28162888

@@ -2889,6 +2961,92 @@ void Traversal_this_written_up_childof_inherited(void) {
28892961
ecs_fini(world);
28902962
}
28912963

2964+
void Traversal_this_written_self_up_childof_inherited_override(void) {
2965+
ecs_world_t *world = ecs_mini();
2966+
2967+
ECS_ENTITY(world, Foo, (OnInstantiate, Inherit));
2968+
ECS_ENTITY(world, Tag, (OnInstantiate, Inherit));
2969+
2970+
ecs_query_t *r = ecs_query(world, {
2971+
.expr = "Tag(self), Foo(self|up)",
2972+
.cache_kind = cache_kind
2973+
});
2974+
2975+
test_assert(r != NULL);
2976+
2977+
ecs_set_with(world, Tag);
2978+
ecs_entity_t base = ecs_entity(world, { .add = ecs_ids(Foo) });
2979+
ecs_entity_t parent = ecs_entity(world, { .add = ecs_ids(ecs_isa(base), Foo) });
2980+
ecs_entity_t child = ecs_entity(world, { .parent = parent });
2981+
ecs_set_with(world, 0);
2982+
2983+
ecs_iter_t it = ecs_query_iter(world, r);
2984+
test_bool(true, ecs_query_next(&it));
2985+
test_int(1, it.count);
2986+
test_uint(base, it.entities[0]);
2987+
test_uint(0, ecs_field_src(&it, 0));
2988+
test_uint(0, ecs_field_src(&it, 1));
2989+
test_uint(Tag, ecs_field_id(&it, 0));
2990+
test_uint(Foo, ecs_field_id(&it, 1));
2991+
2992+
test_bool(true, ecs_query_next(&it));
2993+
test_int(1, it.count);
2994+
test_uint(parent, it.entities[0]);
2995+
test_uint(0, ecs_field_src(&it, 0));
2996+
test_uint(0, ecs_field_src(&it, 1));
2997+
test_uint(Tag, ecs_field_id(&it, 0));
2998+
test_uint(Foo, ecs_field_id(&it, 1));
2999+
3000+
test_bool(true, ecs_query_next(&it));
3001+
test_int(1, it.count);
3002+
test_uint(child, it.entities[0]);
3003+
test_uint(0, ecs_field_src(&it, 0));
3004+
test_uint(parent, ecs_field_src(&it, 1));
3005+
test_uint(Tag, ecs_field_id(&it, 0));
3006+
test_uint(Foo, ecs_field_id(&it, 1));
3007+
3008+
test_bool(false, ecs_query_next(&it));
3009+
3010+
ecs_query_fini(r);
3011+
3012+
ecs_fini(world);
3013+
}
3014+
3015+
void Traversal_this_written_up_childof_inherited_override(void) {
3016+
ecs_world_t *world = ecs_mini();
3017+
3018+
ECS_ENTITY(world, Foo, (OnInstantiate, Inherit));
3019+
ECS_ENTITY(world, Tag, (OnInstantiate, Inherit));
3020+
3021+
ecs_query_t *r = ecs_query(world, {
3022+
.expr = "Tag(self), Foo(up)",
3023+
.cache_kind = cache_kind
3024+
});
3025+
3026+
test_assert(r != NULL);
3027+
3028+
ecs_set_with(world, Tag);
3029+
ecs_entity_t base = ecs_entity(world, { .add = ecs_ids(Foo) });
3030+
ecs_entity_t parent = ecs_entity(world, { .add = ecs_ids(ecs_isa(base), Foo) });
3031+
ecs_entity_t child = ecs_entity(world, { .parent = parent });
3032+
ecs_set_with(world, 0);
3033+
3034+
ecs_iter_t it = ecs_query_iter(world, r);
3035+
test_bool(true, ecs_query_next(&it));
3036+
test_int(1, it.count);
3037+
test_uint(child, it.entities[0]);
3038+
test_uint(0, ecs_field_src(&it, 0));
3039+
test_uint(parent, ecs_field_src(&it, 1));
3040+
test_uint(Tag, ecs_field_id(&it, 0));
3041+
test_uint(Foo, ecs_field_id(&it, 1));
3042+
3043+
test_bool(false, ecs_query_next(&it));
3044+
3045+
ecs_query_fini(r);
3046+
3047+
ecs_fini(world);
3048+
}
3049+
28923050
void Traversal_var_self_up_childof_inherited(void) {
28933051
ecs_world_t *world = ecs_mini();
28943052

test/query/src/main.c

+21-1
Original file line numberDiff line numberDiff line change
@@ -1356,8 +1356,12 @@ void Traversal_self_up_all_owned(void);
13561356
void Traversal_up_all_owned(void);
13571357
void Traversal_this_self_up_childof_inherited(void);
13581358
void Traversal_this_up_childof_inherited(void);
1359+
void Traversal_this_self_up_childof_inherited_override(void);
1360+
void Traversal_this_up_childof_inherited_override(void);
13591361
void Traversal_this_written_self_up_childof_inherited(void);
13601362
void Traversal_this_written_up_childof_inherited(void);
1363+
void Traversal_this_written_self_up_childof_inherited_override(void);
1364+
void Traversal_this_written_up_childof_inherited_override(void);
13611365
void Traversal_var_self_up_childof_inherited(void);
13621366
void Traversal_var_up_childof_inherited(void);
13631367
void Traversal_var_written_self_up_childof_inherited(void);
@@ -7353,6 +7357,14 @@ bake_test_case Traversal_testcases[] = {
73537357
"this_up_childof_inherited",
73547358
Traversal_this_up_childof_inherited
73557359
},
7360+
{
7361+
"this_self_up_childof_inherited_override",
7362+
Traversal_this_self_up_childof_inherited_override
7363+
},
7364+
{
7365+
"this_up_childof_inherited_override",
7366+
Traversal_this_up_childof_inherited_override
7367+
},
73567368
{
73577369
"this_written_self_up_childof_inherited",
73587370
Traversal_this_written_self_up_childof_inherited
@@ -7361,6 +7373,14 @@ bake_test_case Traversal_testcases[] = {
73617373
"this_written_up_childof_inherited",
73627374
Traversal_this_written_up_childof_inherited
73637375
},
7376+
{
7377+
"this_written_self_up_childof_inherited_override",
7378+
Traversal_this_written_self_up_childof_inherited_override
7379+
},
7380+
{
7381+
"this_written_up_childof_inherited_override",
7382+
Traversal_this_written_up_childof_inherited_override
7383+
},
73647384
{
73657385
"var_self_up_childof_inherited",
73667386
Traversal_var_self_up_childof_inherited
@@ -10236,7 +10256,7 @@ static bake_test_suite suites[] = {
1023610256
"Traversal",
1023710257
Traversal_setup,
1023810258
NULL,
10239-
123,
10259+
127,
1024010260
Traversal_testcases,
1024110261
1,
1024210262
Traversal_params

0 commit comments

Comments
 (0)