Skip to content

Commit

Permalink
Move query plan serialization to JSON option
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed Feb 20, 2024
1 parent 44feea4 commit ac6cdca
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 154 deletions.
115 changes: 56 additions & 59 deletions flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -34765,6 +34765,7 @@ void flecs_rest_parse_json_ser_iter_params(
flecs_rest_bool_param(req, "type_info", &desc->serialize_type_info);
flecs_rest_bool_param(req, "field_info", &desc->serialize_field_info);
flecs_rest_bool_param(req, "query_info", &desc->serialize_query_info);
flecs_rest_bool_param(req, "query_plan", &desc->serialize_query_plan);
flecs_rest_bool_param(req, "table", &desc->serialize_table);
flecs_rest_bool_param(req, "rows", &desc->serialize_rows);
bool results = true;
Expand Down Expand Up @@ -34992,13 +34993,19 @@ bool flecs_rest_reply_existing_query(
}

const EcsPoly *poly = ecs_get_pair(world, q, EcsPoly, EcsQuery);
if (!poly || !poly->poly) {
if (!poly) {
flecs_reply_error(reply,
"resolved identifier '%s' is not a query", name);
reply->code = 400;
return true;
}

if (!poly->poly) {
flecs_reply_error(reply, "query '%s' is not initialized", name);
reply->code = 400;
return true;
}

ecs_iter_t it;
ecs_iter_poly(world, poly->poly, &it, NULL);

Expand Down Expand Up @@ -35076,60 +35083,6 @@ bool flecs_rest_reply_query(
return true;
}

static
bool flecs_rest_reply_query_plan(
ecs_world_t *world,
const ecs_http_request_t* req,
ecs_http_reply_t *reply)
{
const char *q_name = ecs_http_get_param(req, "name");
if (q_name) {
reply->code = 400;
ecs_strbuf_appendlit(&reply->body,
"query plan endpoint unsupported for named queries");
return true;
}

const char *q = ecs_http_get_param(req, "q");
if (!q) {
ecs_strbuf_appendlit(&reply->body, "Missing parameter 'q'");
reply->code = 400; /* bad request */
return true;
}

bool try = false;
flecs_rest_bool_param(req, "try", &try);

ecs_dbg_2("rest: request query plan for '%s'", q);
bool prev_color = ecs_log_enable_colors(false);
rest_prev_log = ecs_os_api.log_;
ecs_os_api.log_ = flecs_rest_capture_log;

ecs_rule_t *r = ecs_rule_init(world, &(ecs_filter_desc_t){
.expr = q
});
if (!r) {
flecs_rest_reply_set_captured_log(reply);
if (try) {
/* If client is trying queries, don't spam console with errors */
reply->code = 200;
}
} else {
ecs_log_enable_colors(true);
char *plan = ecs_rule_str(r);
ecs_strbuf_appendlit(&reply->body, "{\"content\":");
flecs_json_string_escape(&reply->body, plan);
ecs_strbuf_appendlit(&reply->body, "}");
ecs_os_free(plan);
ecs_rule_fini(r);
}

ecs_os_api.log_ = rest_prev_log;
ecs_log_enable_colors(prev_color);

return true;
}

#ifdef FLECS_MONITOR

static
Expand Down Expand Up @@ -35514,10 +35467,6 @@ bool flecs_rest_reply(
} else if (!ecs_os_strcmp(req->path, "query")) {
return flecs_rest_reply_query(world, req, reply);

/* Query plan endpoint */
} else if (!ecs_os_strcmp(req->path, "query_plan")) {
return flecs_rest_reply_query_plan(world, req, reply);

/* World endpoint */
} else if (!ecs_os_strcmp(req->path, "world")) {
return flecs_rest_reply_world(world, req, reply);
Expand Down Expand Up @@ -53285,6 +53234,49 @@ void flecs_json_serialize_query_info(
flecs_json_serialize_query(world, q, buf);
}

static
void flecs_json_serialize_query_plan(
const ecs_world_t *world,
const ecs_iter_t *it,
ecs_strbuf_t *buf)
{
(void)world;
(void)it;
(void)buf;

#ifdef FLECS_RULES
if (!it->query) {
return;
}

/* Temporary hack to get rule object. Will no longer be necessary in v4 */
ecs_iter_next_action_t next = it->next;
if (next == ecs_page_next) {
if (!it->chain_it) {
return;
}

next = it->chain_it->next;
}

if (next != ecs_rule_next) {
return;
}

const ecs_filter_t *f = it->query;
const ecs_rule_t *q = ECS_OFFSET(f, -ECS_SIZEOF(ecs_header_t));
ecs_poly_assert(q, ecs_rule_t);

flecs_json_memberl(buf, "query_plan");

bool prev_color = ecs_log_enable_colors(true);
char *plan = ecs_rule_str(q);
flecs_json_string_escape(buf, plan);
ecs_os_free(plan);
ecs_log_enable_colors(prev_color);
#endif
}

static
void flecs_json_serialize_iter_variables(ecs_iter_t *it, ecs_strbuf_t *buf) {
char **variable_names = it->variable_names;
Expand Down Expand Up @@ -54030,6 +54022,11 @@ int ecs_iter_to_json_buf(
flecs_json_serialize_query_info(world, it, buf);
}

/* Serialize query plan if enabled */
if (desc && desc->serialize_query_plan) {
flecs_json_serialize_query_plan(world, it, buf);
}

/* Serialize results */
if (!desc || !desc->dont_serialize_results) {
flecs_json_memberl(buf, "results");
Expand Down
2 changes: 2 additions & 0 deletions flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -12997,6 +12997,7 @@ typedef struct ecs_iter_to_json_desc_t {
bool serialize_rows; /**< Use row-based serialization, with entities in separate elements */
bool serialize_field_info; /**< Serialize metadata for fields returned by query */
bool serialize_query_info; /**< Serialize query terms */
bool serialize_query_plan; /**< Serialize query plan */
bool dont_serialize_results; /**< If true, query won't be evaluated */
} ecs_iter_to_json_desc_t;

Expand All @@ -13022,6 +13023,7 @@ typedef struct ecs_iter_to_json_desc_t {
.serialize_rows = false, \
.serialize_field_info = false, \
.serialize_query_info = false, \
.serialize_query_plan = false, \
.dont_serialize_results = false, \
}

Expand Down
2 changes: 2 additions & 0 deletions include/flecs/addons/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ typedef struct ecs_iter_to_json_desc_t {
bool serialize_rows; /**< Use row-based serialization, with entities in separate elements */
bool serialize_field_info; /**< Serialize metadata for fields returned by query */
bool serialize_query_info; /**< Serialize query terms */
bool serialize_query_plan; /**< Serialize query plan */
bool dont_serialize_results; /**< If true, query won't be evaluated */
} ecs_iter_to_json_desc_t;

Expand All @@ -311,6 +312,7 @@ typedef struct ecs_iter_to_json_desc_t {
.serialize_rows = false, \
.serialize_field_info = false, \
.serialize_query_info = false, \
.serialize_query_plan = false, \
.dont_serialize_results = false, \
}

Expand Down
48 changes: 48 additions & 0 deletions src/addons/json/serialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -1511,6 +1511,49 @@ void flecs_json_serialize_query_info(
flecs_json_serialize_query(world, q, buf);
}

static
void flecs_json_serialize_query_plan(
const ecs_world_t *world,
const ecs_iter_t *it,
ecs_strbuf_t *buf)
{
(void)world;
(void)it;
(void)buf;

#ifdef FLECS_RULES
if (!it->query) {
return;
}

/* Temporary hack to get rule object. Will no longer be necessary in v4 */
ecs_iter_next_action_t next = it->next;
if (next == ecs_page_next) {
if (!it->chain_it) {
return;
}

next = it->chain_it->next;
}

if (next != ecs_rule_next) {
return;
}

const ecs_filter_t *f = it->query;
const ecs_rule_t *q = ECS_OFFSET(f, -ECS_SIZEOF(ecs_header_t));
ecs_poly_assert(q, ecs_rule_t);

flecs_json_memberl(buf, "query_plan");

bool prev_color = ecs_log_enable_colors(true);
char *plan = ecs_rule_str(q);
flecs_json_string_escape(buf, plan);
ecs_os_free(plan);
ecs_log_enable_colors(prev_color);
#endif
}

static
void flecs_json_serialize_iter_variables(ecs_iter_t *it, ecs_strbuf_t *buf) {
char **variable_names = it->variable_names;
Expand Down Expand Up @@ -2256,6 +2299,11 @@ int ecs_iter_to_json_buf(
flecs_json_serialize_query_info(world, it, buf);
}

/* Serialize query plan if enabled */
if (desc && desc->serialize_query_plan) {
flecs_json_serialize_query_plan(world, it, buf);
}

/* Serialize results */
if (!desc || !desc->dont_serialize_results) {
flecs_json_memberl(buf, "results");
Expand Down
67 changes: 8 additions & 59 deletions src/addons/rest.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ void flecs_rest_parse_json_ser_iter_params(
flecs_rest_bool_param(req, "type_info", &desc->serialize_type_info);
flecs_rest_bool_param(req, "field_info", &desc->serialize_field_info);
flecs_rest_bool_param(req, "query_info", &desc->serialize_query_info);
flecs_rest_bool_param(req, "query_plan", &desc->serialize_query_plan);
flecs_rest_bool_param(req, "table", &desc->serialize_table);
flecs_rest_bool_param(req, "rows", &desc->serialize_rows);
bool results = true;
Expand Down Expand Up @@ -420,13 +421,19 @@ bool flecs_rest_reply_existing_query(
}

const EcsPoly *poly = ecs_get_pair(world, q, EcsPoly, EcsQuery);
if (!poly || !poly->poly) {
if (!poly) {
flecs_reply_error(reply,
"resolved identifier '%s' is not a query", name);
reply->code = 400;
return true;
}

if (!poly->poly) {
flecs_reply_error(reply, "query '%s' is not initialized", name);
reply->code = 400;
return true;
}

ecs_iter_t it;
ecs_iter_poly(world, poly->poly, &it, NULL);

Expand Down Expand Up @@ -504,60 +511,6 @@ bool flecs_rest_reply_query(
return true;
}

static
bool flecs_rest_reply_query_plan(
ecs_world_t *world,
const ecs_http_request_t* req,
ecs_http_reply_t *reply)
{
const char *q_name = ecs_http_get_param(req, "name");
if (q_name) {
reply->code = 400;
ecs_strbuf_appendlit(&reply->body,
"query plan endpoint unsupported for named queries");
return true;
}

const char *q = ecs_http_get_param(req, "q");
if (!q) {
ecs_strbuf_appendlit(&reply->body, "Missing parameter 'q'");
reply->code = 400; /* bad request */
return true;
}

bool try = false;
flecs_rest_bool_param(req, "try", &try);

ecs_dbg_2("rest: request query plan for '%s'", q);
bool prev_color = ecs_log_enable_colors(false);
rest_prev_log = ecs_os_api.log_;
ecs_os_api.log_ = flecs_rest_capture_log;

ecs_rule_t *r = ecs_rule_init(world, &(ecs_filter_desc_t){
.expr = q
});
if (!r) {
flecs_rest_reply_set_captured_log(reply);
if (try) {
/* If client is trying queries, don't spam console with errors */
reply->code = 200;
}
} else {
ecs_log_enable_colors(true);
char *plan = ecs_rule_str(r);
ecs_strbuf_appendlit(&reply->body, "{\"content\":");
flecs_json_string_escape(&reply->body, plan);
ecs_strbuf_appendlit(&reply->body, "}");
ecs_os_free(plan);
ecs_rule_fini(r);
}

ecs_os_api.log_ = rest_prev_log;
ecs_log_enable_colors(prev_color);

return true;
}

#ifdef FLECS_MONITOR

static
Expand Down Expand Up @@ -942,10 +895,6 @@ bool flecs_rest_reply(
} else if (!ecs_os_strcmp(req->path, "query")) {
return flecs_rest_reply_query(world, req, reply);

/* Query plan endpoint */
} else if (!ecs_os_strcmp(req->path, "query_plan")) {
return flecs_rest_reply_query_plan(world, req, reply);

/* World endpoint */
} else if (!ecs_os_strcmp(req->path, "world")) {
return flecs_rest_reply_world(world, req, reply);
Expand Down
1 change: 0 additions & 1 deletion test/addons/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -1854,7 +1854,6 @@
"get_cached",
"get_cached_invalid",
"try_query",
"try_query_plan",
"query",
"named_query"
]
Expand Down
Loading

0 comments on commit ac6cdca

Please sign in to comment.