Skip to content

Commit

Permalink
Add whitebox test for query plan reordering
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed Dec 13, 2023
1 parent c89c9ee commit 220852f
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 18 deletions.
34 changes: 26 additions & 8 deletions flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -60660,7 +60660,7 @@ char* ecs_rule_str_w_profile(

#ifdef FLECS_LOG
char *str = ecs_strbuf_get(&buf);
flecs_colorize_buf(str, true, &buf);
flecs_colorize_buf(str, ecs_os_api.flags_ & EcsOsApiLogWithColors, &buf);
ecs_os_free(str);
#endif
return ecs_strbuf_get(&buf);
Expand Down Expand Up @@ -62462,6 +62462,24 @@ int flecs_rule_compile_term(
return -1;
}

static
bool flecs_rule_var_is_unknown(
ecs_rule_t *rule,
ecs_var_id_t var_id,
ecs_rule_compile_ctx_t *ctx)
{
ecs_rule_var_t *vars = rule->vars;
if (ctx->written & (1ull << var_id)) {
return false;
} else {
ecs_var_id_t table_var = vars[var_id].table_id;
if (table_var != EcsVarNone) {
return flecs_rule_var_is_unknown(rule, table_var, ctx);
}
}
return true;
}

static
bool flecs_rule_term_is_unknown(
ecs_rule_t *rule,
Expand All @@ -62473,7 +62491,7 @@ bool flecs_rule_term_is_unknown(
&dummy.first, EcsRuleFirst, EcsVarEntity, ctx, false);
flecs_rule_compile_term_id(NULL, rule, &dummy, &term->second,
&dummy.second, EcsRuleSecond, EcsVarEntity, ctx, false);
flecs_rule_compile_term_id(NULL, rule, &dummy, &term->second,
flecs_rule_compile_term_id(NULL, rule, &dummy, &term->src,
&dummy.src, EcsRuleSrc, EcsVarAny, ctx, false);

bool has_vars = dummy.flags &
Expand All @@ -62487,17 +62505,17 @@ bool flecs_rule_term_is_unknown(
}

if (dummy.flags & (EcsRuleIsVar << EcsRuleFirst)) {
if (ctx->written & (1 << dummy.first.var)) {
if (!flecs_rule_var_is_unknown(rule, dummy.first.var, ctx)) {
return false;
}
}
if (dummy.flags & (EcsRuleIsVar << EcsRuleSecond)) {
if (ctx->written & (1 << dummy.second.var)) {
if (!flecs_rule_var_is_unknown(rule, dummy.second.var, ctx)) {
return false;
}
}
if (dummy.flags & (EcsRuleIsVar << EcsRuleSrc)) {
if (ctx->written & (1 << dummy.src.var)) {
if (!flecs_rule_var_is_unknown(rule, dummy.src.var, ctx)) {
return false;
}
}
Expand All @@ -62518,7 +62536,7 @@ int32_t flecs_rule_term_next_known(

for (i = offset; i < count; i ++) {
ecs_term_t *term = &terms[i];
if (compiled & (1 << i)) {
if (compiled & (1ull << i)) {
continue;
}

Expand Down Expand Up @@ -62593,7 +62611,7 @@ int flecs_rule_compile(
ecs_term_t *term = &terms[i];
int32_t compile = i;

if (compiled & (1 << i)) {
if (compiled & (1ull << i)) {
continue; /* Already compiled */
}

Expand Down Expand Up @@ -62623,7 +62641,7 @@ int flecs_rule_compile(
return -1;
}

compiled |= (1 << compile);
compiled |= (1ull << compile);
}

ecs_var_id_t this_id = flecs_rule_find_var_id(rule, "This", EcsVarEntity);
Expand Down
2 changes: 1 addition & 1 deletion src/addons/rules/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ char* ecs_rule_str_w_profile(

#ifdef FLECS_LOG
char *str = ecs_strbuf_get(&buf);
flecs_colorize_buf(str, true, &buf);
flecs_colorize_buf(str, ecs_os_api.flags_ & EcsOsApiLogWithColors, &buf);
ecs_os_free(str);
#endif
return ecs_strbuf_get(&buf);
Expand Down
32 changes: 25 additions & 7 deletions src/addons/rules/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1684,6 +1684,24 @@ int flecs_rule_compile_term(
return -1;
}

static
bool flecs_rule_var_is_unknown(
ecs_rule_t *rule,
ecs_var_id_t var_id,
ecs_rule_compile_ctx_t *ctx)
{
ecs_rule_var_t *vars = rule->vars;
if (ctx->written & (1ull << var_id)) {
return false;
} else {
ecs_var_id_t table_var = vars[var_id].table_id;
if (table_var != EcsVarNone) {
return flecs_rule_var_is_unknown(rule, table_var, ctx);
}
}
return true;
}

static
bool flecs_rule_term_is_unknown(
ecs_rule_t *rule,
Expand All @@ -1695,7 +1713,7 @@ bool flecs_rule_term_is_unknown(
&dummy.first, EcsRuleFirst, EcsVarEntity, ctx, false);
flecs_rule_compile_term_id(NULL, rule, &dummy, &term->second,
&dummy.second, EcsRuleSecond, EcsVarEntity, ctx, false);
flecs_rule_compile_term_id(NULL, rule, &dummy, &term->second,
flecs_rule_compile_term_id(NULL, rule, &dummy, &term->src,
&dummy.src, EcsRuleSrc, EcsVarAny, ctx, false);

bool has_vars = dummy.flags &
Expand All @@ -1709,17 +1727,17 @@ bool flecs_rule_term_is_unknown(
}

if (dummy.flags & (EcsRuleIsVar << EcsRuleFirst)) {
if (ctx->written & (1 << dummy.first.var)) {
if (!flecs_rule_var_is_unknown(rule, dummy.first.var, ctx)) {
return false;
}
}
if (dummy.flags & (EcsRuleIsVar << EcsRuleSecond)) {
if (ctx->written & (1 << dummy.second.var)) {
if (!flecs_rule_var_is_unknown(rule, dummy.second.var, ctx)) {
return false;
}
}
if (dummy.flags & (EcsRuleIsVar << EcsRuleSrc)) {
if (ctx->written & (1 << dummy.src.var)) {
if (!flecs_rule_var_is_unknown(rule, dummy.src.var, ctx)) {
return false;
}
}
Expand All @@ -1740,7 +1758,7 @@ int32_t flecs_rule_term_next_known(

for (i = offset; i < count; i ++) {
ecs_term_t *term = &terms[i];
if (compiled & (1 << i)) {
if (compiled & (1ull << i)) {
continue;
}

Expand Down Expand Up @@ -1815,7 +1833,7 @@ int flecs_rule_compile(
ecs_term_t *term = &terms[i];
int32_t compile = i;

if (compiled & (1 << i)) {
if (compiled & (1ull << i)) {
continue; /* Already compiled */
}

Expand Down Expand Up @@ -1845,7 +1863,7 @@ int flecs_rule_compile(
return -1;
}

compiled |= (1 << compile);
compiled |= (1ull << compile);
}

ecs_var_id_t this_id = flecs_rule_find_var_id(rule, "This", EcsVarEntity);
Expand Down
4 changes: 3 additions & 1 deletion test/addons/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,9 @@
"unknown_before_known_after_or",
"unknown_before_known_after_not",
"unknown_before_known_after_optional",
"unknown_before_known_after_scope"
"unknown_before_known_after_scope",
"reordered_plan_1",
"reordered_plan_2"
]
}, {
"id": "RulesVariables",
Expand Down
77 changes: 77 additions & 0 deletions test/addons/src/RulesBasic.c
Original file line number Diff line number Diff line change
Expand Up @@ -6022,6 +6022,8 @@ void RulesBasic_unknown_before_known(void) {
test_uint(c, ecs_iter_get_var(&it, c_var));
test_uint(gc, ecs_iter_get_var(&it, gc_var));
test_assert(!ecs_rule_next(&it));

ecs_rule_fini(r);

ecs_fini(world);
}
Expand Down Expand Up @@ -6072,6 +6074,8 @@ void RulesBasic_unknown_before_known_after_or(void) {
test_uint(gc2, ecs_iter_get_var(&it, gc_var));
test_assert(!ecs_rule_next(&it));

ecs_rule_fini(r);

ecs_fini(world);
}

Expand Down Expand Up @@ -6109,6 +6113,8 @@ void RulesBasic_unknown_before_known_after_not(void) {
test_uint(c, ecs_iter_get_var(&it, c_var));
test_uint(gc1, ecs_iter_get_var(&it, gc_var));
test_assert(!ecs_rule_next(&it));

ecs_rule_fini(r);

ecs_fini(world);
}
Expand Down Expand Up @@ -6159,6 +6165,8 @@ void RulesBasic_unknown_before_known_after_optional(void) {
test_uint(c, ecs_iter_get_var(&it, c_var));
test_uint(gc2, ecs_iter_get_var(&it, gc_var));
test_assert(!ecs_rule_next(&it));

ecs_rule_fini(r);

ecs_fini(world);
}
Expand Down Expand Up @@ -6197,6 +6205,75 @@ void RulesBasic_unknown_before_known_after_scope(void) {
test_uint(c, ecs_iter_get_var(&it, c_var));
test_uint(gc1, ecs_iter_get_var(&it, gc_var));
test_assert(!ecs_rule_next(&it));

ecs_rule_fini(r);

ecs_fini(world);
}

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

ECS_TAG(world, Foo);
ECS_TAG(world, Bar);

ecs_rule_t *r = ecs_rule(world, {
.expr = "Foo, ChildOf($this, $p, $gp, $ggp), Bar($ggp)"
});

ecs_log_enable_colors(false);

const char *expect =
HEAD " 0. [-1, 1] setids "
LINE " 1. [ 0, 2] selfup $[this] (Foo)"
LINE " 2. [ 1, 3] and $[this] (ChildOf, $p)"
LINE " 3. [ 2, 4] and $p (ChildOf, $gp)"
LINE " 4. [ 3, 5] and $gp (ChildOf, $ggp)"
LINE " 5. [ 4, 6] selfup $ggp (Bar)"
LINE " 6. [ 5, 7] setvars "
LINE " 7. [ 6, 8] yield "
LINE "";
char *plan = ecs_rule_str(r);

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

ecs_rule_fini(r);

ecs_fini(world);
}

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

ECS_TAG(world, Foo);
ECS_TAG(world, Bar);

ecs_rule_t *r = ecs_rule(world, {
.expr = "Foo($ggp), ChildOf($this, $p, $gp, $ggp), Bar($this)"
});

ecs_log_enable_colors(false);

const char *expect =
HEAD " 0. [-1, 1] setids "
LINE " 1. [ 0, 2] selfup $[ggp] (Foo)"
LINE " 2. [ 1, 3] each $ggp ($[ggp])"
LINE " 3. [ 2, 4] and $[gp] (ChildOf, $ggp)"
LINE " 4. [ 3, 5] each $gp ($[gp])"
LINE " 5. [ 4, 6] and $[p] (ChildOf, $gp)"
LINE " 6. [ 5, 7] each $p ($[p])"
LINE " 7. [ 6, 8] and $[this] (ChildOf, $p)"
LINE " 8. [ 7, 9] selfup $[this] (Bar)"
LINE " 9. [ 8, 10] setvars "
LINE "10. [ 9, 11] yield "
LINE "";
char *plan = ecs_rule_str(r);

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

ecs_rule_fini(r);

ecs_fini(world);
}
12 changes: 11 additions & 1 deletion test/addons/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,8 @@ void RulesBasic_unknown_before_known_after_or(void);
void RulesBasic_unknown_before_known_after_not(void);
void RulesBasic_unknown_before_known_after_optional(void);
void RulesBasic_unknown_before_known_after_scope(void);
void RulesBasic_reordered_plan_1(void);
void RulesBasic_reordered_plan_2(void);

// Testsuite 'RulesVariables'
void RulesVariables_1_ent_src_w_var(void);
Expand Down Expand Up @@ -4820,6 +4822,14 @@ bake_test_case RulesBasic_testcases[] = {
{
"unknown_before_known_after_scope",
RulesBasic_unknown_before_known_after_scope
},
{
"reordered_plan_1",
RulesBasic_reordered_plan_1
},
{
"reordered_plan_2",
RulesBasic_reordered_plan_2
}
};

Expand Down Expand Up @@ -8581,7 +8591,7 @@ static bake_test_suite suites[] = {
"RulesBasic",
NULL,
NULL,
130,
132,
RulesBasic_testcases
},
{
Expand Down

0 comments on commit 220852f

Please sign in to comment.