Skip to content

Commit 45b242e

Browse files
Fix crash when sorted query with MatchEmptyTables flag only matches empty tables
Differential Revision: D66028916 Pull Request resolved: #1441
1 parent 544cccc commit 45b242e

File tree

5 files changed

+89
-2
lines changed

5 files changed

+89
-2
lines changed

distr/flecs.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68023,6 +68023,12 @@ ecs_query_cache_t* flecs_query_cache_init(
6802368023
ecs_flags32_t query_flags = const_desc->flags | world->default_query_flags;
6802468024
desc.flags |= EcsQueryMatchEmptyTables | EcsQueryTableOnly | EcsQueryNested;
6802568025

68026+
/* order_by is not compatible with matching empty tables, as it causes
68027+
* a query to return table slices, not entire tables. */
68028+
if (const_desc->order_by_callback) {
68029+
query_flags &= ~EcsQueryMatchEmptyTables;
68030+
}
68031+
6802668032
ecs_query_t *q = result->query = ecs_query_init(world, &desc);
6802768033
if (!q) {
6802868034
goto error;

src/query/engine/cache.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,12 @@ ecs_query_cache_t* flecs_query_cache_init(
12381238
ecs_flags32_t query_flags = const_desc->flags | world->default_query_flags;
12391239
desc.flags |= EcsQueryMatchEmptyTables | EcsQueryTableOnly | EcsQueryNested;
12401240

1241+
/* order_by is not compatible with matching empty tables, as it causes
1242+
* a query to return table slices, not entire tables. */
1243+
if (const_desc->order_by_callback) {
1244+
query_flags &= ~EcsQueryMatchEmptyTables;
1245+
}
1246+
12411247
ecs_query_t *q = result->query = ecs_query_init(world, &desc);
12421248
if (!q) {
12431249
goto error;

test/query/project.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2120,7 +2120,9 @@
21202120
"sort_by_wildcard",
21212121
"sort_not_term",
21222122
"sort_or_term",
2123-
"sort_optional_term"
2123+
"sort_optional_term",
2124+
"order_empty_table",
2125+
"order_empty_table_only"
21242126
]
21252127
}, {
21262128
"id": "OrderByEntireTable",

test/query/src/OrderBy.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,3 +2172,66 @@ void OrderBy_sort_w_nontrivial_component(void) {
21722172

21732173
ecs_fini(world);
21742174
}
2175+
2176+
void OrderBy_order_empty_table(void) {
2177+
ecs_world_t *world = ecs_mini();
2178+
2179+
ECS_COMPONENT(world, Position);
2180+
ECS_TAG(world, Foo);
2181+
2182+
ecs_entity_t e1 = ecs_insert(world, ecs_value(Position, {3, 0}));
2183+
ecs_entity_t e2 = ecs_insert(world, ecs_value(Position, {1, 0}));
2184+
ecs_entity_t e3 = ecs_insert(world, ecs_value(Position, {5, 0}));
2185+
ecs_entity_t e4 = ecs_insert(world, ecs_value(Position, {2, 0}));
2186+
ecs_entity_t e5 = ecs_insert(world, ecs_value(Position, {4, 0}));
2187+
2188+
// Create empty table
2189+
ecs_add(world, e5, Foo);
2190+
ecs_delete(world, e5);
2191+
2192+
ecs_query_t *q = ecs_query(world, {
2193+
.expr = "Position",
2194+
.order_by = ecs_id(Position),
2195+
.order_by_callback = compare_position,
2196+
.flags = EcsQueryMatchEmptyTables
2197+
});
2198+
2199+
ecs_iter_t it = ecs_query_iter(world, q);
2200+
2201+
test_assert(ecs_query_next(&it));
2202+
test_int(it.count, 4);
2203+
2204+
test_assert(it.entities[0] == e2);
2205+
test_assert(it.entities[1] == e4);
2206+
test_assert(it.entities[2] == e1);
2207+
test_assert(it.entities[3] == e3);
2208+
test_assert(!ecs_query_next(&it));
2209+
2210+
ecs_query_fini(q);
2211+
2212+
ecs_fini(world);
2213+
}
2214+
2215+
void OrderBy_order_empty_table_only(void) {
2216+
ecs_world_t *world = ecs_mini();
2217+
2218+
ECS_COMPONENT(world, Position);
2219+
2220+
// Create empty table
2221+
ecs_entity_t e = ecs_new_w(world, Position);
2222+
ecs_delete(world, e);
2223+
2224+
ecs_query_t *q = ecs_query(world, {
2225+
.expr = "Position",
2226+
.order_by = ecs_id(Position),
2227+
.order_by_callback = compare_position,
2228+
.flags = EcsQueryMatchEmptyTables
2229+
});
2230+
2231+
ecs_iter_t it = ecs_query_iter(world, q);
2232+
test_assert(!ecs_query_next(&it));
2233+
2234+
ecs_query_fini(q);
2235+
2236+
ecs_fini(world);
2237+
}

test/query/src/main.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2036,6 +2036,8 @@ void OrderBy_sort_by_wildcard(void);
20362036
void OrderBy_sort_not_term(void);
20372037
void OrderBy_sort_or_term(void);
20382038
void OrderBy_sort_optional_term(void);
2039+
void OrderBy_order_empty_table(void);
2040+
void OrderBy_order_empty_table_only(void);
20392041

20402042
// Testsuite 'OrderByEntireTable'
20412043
void OrderByEntireTable_sort_by_component(void);
@@ -10066,6 +10068,14 @@ bake_test_case OrderBy_testcases[] = {
1006610068
{
1006710069
"sort_optional_term",
1006810070
OrderBy_sort_optional_term
10071+
},
10072+
{
10073+
"order_empty_table",
10074+
OrderBy_order_empty_table
10075+
},
10076+
{
10077+
"order_empty_table_only",
10078+
OrderBy_order_empty_table_only
1006910079
}
1007010080
};
1007110081

@@ -10584,7 +10594,7 @@ static bake_test_suite suites[] = {
1058410594
"OrderBy",
1058510595
NULL,
1058610596
NULL,
10587-
42,
10597+
44,
1058810598
OrderBy_testcases
1058910599
},
1059010600
{

0 commit comments

Comments
 (0)