summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: c2f7813)
raw | patch | inline | side by side (parent: c2f7813)
author | Sebastian Harl <sh@tokkee.org> | |
Sun, 17 May 2015 19:58:03 +0000 (21:58 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Sun, 17 May 2015 19:58:03 +0000 (21:58 +0200) |
This new function executes a generic QUERY matcher as returned by
sdb_store_query_prepare and writes the reply to a string buffer.
sdb_store_query_prepare and writes the reply to a string buffer.
src/Makefile.am | patch | blob | history | |
src/core/store_exec.c | [new file with mode: 0644] | patch | blob |
src/core/store_query.c | patch | blob | history | |
src/frontend/query.c | patch | blob | history | |
src/frontend/store.c | patch | blob | history | |
src/include/core/store.h | patch | blob | history | |
src/include/frontend/connection.h | patch | blob | history | |
t/unit/frontend/query_test.c | patch | blob | history |
diff --git a/src/Makefile.am b/src/Makefile.am
index 6b560df7b8b2bc6c56d6615c7b7e516dc8129fd2..52bd42b0682143e31e378be5d1db8251585832c2 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
core/plugin.c include/core/plugin.h \
core/store.c include/core/store.h \
core/store-private.h \
+ core/store_exec.c \
core/store_expr.c \
core/store_json.c \
core/store_lookup.c \
diff --git a/src/core/store_exec.c b/src/core/store_exec.c
--- /dev/null
+++ b/src/core/store_exec.c
@@ -0,0 +1,381 @@
+/*
+ * SysDB - src/core/store_exec.c
+ * Copyright (C) 2014-2015 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core/object.h"
+#include "core/store-private.h"
+#include "frontend/connection.h"
+#include "parser/ast.h"
+#include "utils/error.h"
+
+#include <errno.h>
+
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * private helper functions
+ */
+
+static int
+list_tojson(sdb_store_obj_t *obj,
+ sdb_store_matcher_t __attribute__((unused)) *filter,
+ void *user_data)
+{
+ sdb_store_json_formatter_t *f = user_data;
+ return sdb_store_json_emit(f, obj);
+} /* list_tojson */
+
+static int
+lookup_tojson(sdb_store_obj_t *obj, sdb_store_matcher_t *filter,
+ void *user_data)
+{
+ sdb_store_json_formatter_t *f = user_data;
+ return sdb_store_json_emit_full(f, obj, filter);
+} /* lookup_tojson */
+
+static size_t
+sstrlen(const char *s)
+{
+ return s ? strlen(s) : 0;
+} /* sstrlen */
+
+/*
+ * query implementations
+ */
+
+static int
+exec_fetch(sdb_strbuf_t *buf, sdb_strbuf_t *errbuf, int type,
+ const char *hostname, const char *name, sdb_store_matcher_t *filter)
+{
+ uint32_t res_type = htonl(SDB_CONNECTION_FETCH);
+
+ sdb_store_obj_t *host;
+ sdb_store_obj_t *obj;
+
+ sdb_store_json_formatter_t *f;
+
+ if ((! name) || ((type == SDB_HOST) && hostname)
+ || ((type != SDB_HOST) && (! hostname))) {
+ /* This is a programming error, not something the client did wrong */
+ sdb_strbuf_sprintf(errbuf, "INTERNAL ERROR: invalid "
+ "arguments to FETCH(%s, %s, %s)",
+ SDB_STORE_TYPE_TO_NAME(type), hostname, name);
+ return -1;
+ }
+ if (type == SDB_HOST)
+ hostname = name;
+
+ host = sdb_store_get_host(hostname);
+ if ((! host)
+ || (filter && (! sdb_store_matcher_matches(filter, host, NULL)))) {
+ sdb_strbuf_sprintf(errbuf, "Failed to fetch %s %s: "
+ "host %s not found", SDB_STORE_TYPE_TO_NAME(type),
+ name, hostname);
+ sdb_object_deref(SDB_OBJ(host));
+ return -1;
+ }
+ if (type == SDB_HOST) {
+ obj = host;
+ }
+ else {
+ obj = sdb_store_get_child(host, type, name);
+ if ((! obj)
+ || (filter && (! sdb_store_matcher_matches(filter, obj, NULL)))) {
+ sdb_strbuf_sprintf(errbuf, "Failed to fetch %s %s.%s: "
+ "%s not found", SDB_STORE_TYPE_TO_NAME(type),
+ hostname, name, name);
+ if (obj)
+ sdb_object_deref(SDB_OBJ(obj));
+ sdb_object_deref(SDB_OBJ(host));
+ return -1;
+ }
+ sdb_object_deref(SDB_OBJ(host));
+ }
+ host = NULL;
+
+ f = sdb_store_json_formatter(buf, type, /* flags = */ 0);
+ if (! f) {
+ char err[1024];
+ sdb_log(SDB_LOG_ERR, "frontend: Failed to create "
+ "JSON formatter to handle FETCH command: %s",
+ sdb_strerror(errno, err, sizeof(err)));
+
+ sdb_strbuf_sprintf(errbuf, "Out of memory");
+ sdb_object_deref(SDB_OBJ(obj));
+ return -1;
+ }
+
+ sdb_strbuf_memcpy(buf, &res_type, sizeof(uint32_t));
+ if (sdb_store_json_emit_full(f, obj, filter)) {
+ sdb_log(SDB_LOG_ERR, "frontend: Failed to serialize "
+ "%s %s.%s to JSON", SDB_STORE_TYPE_TO_NAME(type),
+ hostname, name);
+ sdb_strbuf_sprintf(errbuf, "Out of memory");
+ free(f);
+ sdb_object_deref(SDB_OBJ(obj));
+ return -1;
+ }
+
+ sdb_object_deref(SDB_OBJ(obj));
+ sdb_store_json_finish(f);
+ free(f);
+
+ return SDB_CONNECTION_DATA;
+} /* exec_fetch */
+
+static int
+exec_list(sdb_strbuf_t *buf, sdb_strbuf_t *errbuf, int type,
+ sdb_store_matcher_t *filter)
+{
+ uint32_t res_type = htonl(SDB_CONNECTION_LIST);
+ sdb_store_json_formatter_t *f;
+
+ f = sdb_store_json_formatter(buf, type, SDB_WANT_ARRAY);
+ if (! f) {
+ char err[1024];
+ sdb_log(SDB_LOG_ERR, "frontend: Failed to create "
+ "JSON formatter to handle LIST command: %s",
+ sdb_strerror(errno, err, sizeof(err)));
+
+ sdb_strbuf_sprintf(errbuf, "Out of memory");
+ return -1;
+ }
+
+ sdb_strbuf_memcpy(buf, &res_type, sizeof(uint32_t));
+ if (sdb_store_scan(type, /* m = */ NULL, filter, list_tojson, f)) {
+ sdb_log(SDB_LOG_ERR, "frontend: Failed to serialize "
+ "store to JSON");
+ sdb_strbuf_sprintf(errbuf, "Out of memory");
+ free(f);
+ return -1;
+ }
+
+ sdb_store_json_finish(f);
+ free(f);
+
+ return SDB_CONNECTION_DATA;
+} /* exec_list */
+
+static int
+exec_lookup(sdb_strbuf_t *buf, sdb_strbuf_t *errbuf, int type,
+ sdb_store_matcher_t *m, sdb_store_matcher_t *filter)
+{
+ uint32_t res_type = htonl(SDB_CONNECTION_LOOKUP);
+ sdb_store_json_formatter_t *f;
+
+ f = sdb_store_json_formatter(buf, type, SDB_WANT_ARRAY);
+ if (! f) {
+ char err[1024];
+ sdb_log(SDB_LOG_ERR, "frontend: Failed to create "
+ "JSON formatter to handle LOOKUP command: %s",
+ sdb_strerror(errno, err, sizeof(err)));
+
+ sdb_strbuf_sprintf(errbuf, "Out of memory");
+ return -1;
+ }
+
+ sdb_strbuf_memcpy(buf, &res_type, sizeof(uint32_t));
+
+ if (sdb_store_scan(type, m, filter, lookup_tojson, f)) {
+ sdb_log(SDB_LOG_ERR, "frontend: Failed to lookup %ss",
+ SDB_STORE_TYPE_TO_NAME(type));
+ sdb_strbuf_sprintf(errbuf, "Failed to lookup %ss",
+ SDB_STORE_TYPE_TO_NAME(type));
+ free(f);
+ return -1;
+ }
+
+ sdb_store_json_finish(f);
+ free(f);
+
+ return SDB_CONNECTION_DATA;
+} /* exec_lookup */
+
+static int
+exec_store(sdb_strbuf_t *buf, sdb_strbuf_t *errbuf, sdb_ast_store_t *st)
+{
+ char name[sstrlen(st->hostname) + sstrlen(st->parent) + sstrlen(st->name) + 3];
+ sdb_metric_store_t metric_store;
+ int type = st->obj_type, status = -1;
+
+ switch (st->obj_type) {
+ case SDB_HOST:
+ strncpy(name, st->name, sizeof(name));
+ status = sdb_store_host(st->name, st->last_update);
+ break;
+
+ case SDB_SERVICE:
+ snprintf(name, sizeof(name), "%s.%s", st->hostname, st->name);
+ status = sdb_store_service(st->hostname, st->name, st->last_update);
+ break;
+
+ case SDB_METRIC:
+ snprintf(name, sizeof(name), "%s.%s", st->hostname, st->name);
+ metric_store.type = st->store_type;
+ metric_store.id = st->store_id;
+ status = sdb_store_metric(st->hostname, st->name,
+ &metric_store, st->last_update);
+ break;
+
+ case SDB_ATTRIBUTE:
+ type |= st->parent_type;
+
+ if (st->parent)
+ snprintf(name, sizeof(name), "%s.%s.%s",
+ st->hostname, st->parent, st->name);
+ else
+ snprintf(name, sizeof(name), "%s.%s", st->hostname, st->name);
+
+ switch (st->parent_type) {
+ case 0:
+ type |= SDB_HOST;
+ status = sdb_store_attribute(st->hostname,
+ st->name, &st->value, st->last_update);
+ break;
+
+ case SDB_SERVICE:
+ status = sdb_store_service_attr(st->hostname, st->parent,
+ st->name, &st->value, st->last_update);
+ break;
+
+ case SDB_METRIC:
+ status = sdb_store_metric_attr(st->hostname, st->parent,
+ st->name, &st->value, st->last_update);
+ break;
+
+ default:
+ sdb_log(SDB_LOG_ERR, "store: Invalid parent type in STORE: %s",
+ SDB_STORE_TYPE_TO_NAME(st->parent_type));
+ return -1;
+ }
+ break;
+
+ default:
+ sdb_log(SDB_LOG_ERR, "store: Invalid object type in STORE: %s",
+ SDB_STORE_TYPE_TO_NAME(st->obj_type));
+ return -1;
+ }
+
+ if (status < 0) {
+ sdb_strbuf_sprintf(errbuf, "STORE: Failed to store %s object",
+ SDB_STORE_TYPE_TO_NAME(type));
+ return -1;
+ }
+
+ if (! status) {
+ sdb_strbuf_sprintf(buf, "Successfully stored %s %s",
+ SDB_STORE_TYPE_TO_NAME(type), name);
+ }
+ else {
+ char type_str[32];
+ strncpy(type_str, SDB_STORE_TYPE_TO_NAME(type), sizeof(type_str));
+ type_str[0] = (char)toupper((int)type_str[0]);
+ sdb_strbuf_sprintf(buf, "%s %s already up to date", type_str, name);
+ }
+
+ return SDB_CONNECTION_OK;
+} /* exec_store */
+
+static int
+exec_timeseries(sdb_strbuf_t *buf, sdb_strbuf_t *errbuf,
+ const char *hostname, const char *metric,
+ sdb_timeseries_opts_t *opts)
+{
+ uint32_t res_type = htonl(SDB_CONNECTION_TIMESERIES);
+
+ sdb_strbuf_memcpy(buf, &res_type, sizeof(uint32_t));
+ if (sdb_store_fetch_timeseries(hostname, metric, opts, buf)) {
+ sdb_log(SDB_LOG_ERR, "frontend: Failed to fetch time-series");
+ sdb_strbuf_sprintf(errbuf, "Failed to fetch time-series");
+ return -1;
+ }
+
+ return SDB_CONNECTION_DATA;
+} /* exec_timeseries */
+
+/*
+ * public API
+ */
+
+int
+sdb_store_query_execute(sdb_store_matcher_t *m,
+ sdb_strbuf_t *buf, sdb_strbuf_t *errbuf)
+{
+ sdb_timeseries_opts_t ts_opts;
+ sdb_ast_node_t *ast;
+
+ if ((! m) || (m->type != MATCHER_QUERY)) {
+ int t = m ? m-> type : -1;
+ sdb_log(SDB_LOG_ERR, "store: Invalid query of type %s", MATCHER_SYM(t));
+ return -1;
+ }
+ if (! QUERY_M(m)->ast) {
+ sdb_log(SDB_LOG_ERR, "store: Invalid empty query");
+ return -1;
+ }
+
+ ast = QUERY_M(m)->ast;
+ switch (ast->type) {
+ case SDB_AST_TYPE_FETCH:
+ return exec_fetch(buf, errbuf, SDB_AST_FETCH(ast)->obj_type,
+ SDB_AST_FETCH(ast)->hostname, SDB_AST_FETCH(ast)->name,
+ QUERY_M(m)->filter);
+
+ case SDB_AST_TYPE_LIST:
+ return exec_list(buf, errbuf, SDB_AST_LIST(ast)->obj_type,
+ QUERY_M(m)->filter);
+
+ case SDB_AST_TYPE_LOOKUP:
+ return exec_lookup(buf, errbuf, SDB_AST_LOOKUP(ast)->obj_type,
+ QUERY_M(m)->matcher, QUERY_M(m)->filter);
+
+ case SDB_AST_TYPE_STORE:
+ if (ast->type != SDB_AST_TYPE_STORE) {
+ sdb_log(SDB_LOG_ERR, "store: Invalid AST node for STORE command: %s",
+ SDB_AST_TYPE_TO_STRING(ast));
+ return -1;
+ }
+ return exec_store(buf, errbuf, SDB_AST_STORE(ast));
+
+ case SDB_AST_TYPE_TIMESERIES:
+ ts_opts.start = SDB_AST_TIMESERIES(ast)->start;
+ ts_opts.end = SDB_AST_TIMESERIES(ast)->end;
+ return exec_timeseries(buf, errbuf, SDB_AST_TIMESERIES(ast)->hostname,
+ SDB_AST_TIMESERIES(ast)->metric, &ts_opts);
+
+ default:
+ sdb_log(SDB_LOG_ERR, "store: Invalid query of type %s",
+ SDB_AST_TYPE_TO_STRING(ast));
+ return -1;
+ }
+
+ return 0;
+} /* sdb_store_query_execute */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
diff --git a/src/core/store_query.c b/src/core/store_query.c
index 90d45bf521c9d093b2dc34a153f465ef4e24712e..88b076a81a8cd0d19a38ac053fa98eeef23cd043 100644 (file)
--- a/src/core/store_query.c
+++ b/src/core/store_query.c
/*
- * SysDB - src/core/store_lookup.c
+ * SysDB - src/core/store_query.c
* Copyright (C) 2014-2015 Sebastian 'tokkee' Harl <sh@tokkee.org>
* All rights reserved.
*
diff --git a/src/frontend/query.c b/src/frontend/query.c
index 2c80be76f84f5ee8ca98560cebf293219c238e31..149750b05782dc80311278f495fc994ad1b9cf1f 100644 (file)
--- a/src/frontend/query.c
+++ b/src/frontend/query.c
#include "core/store.h"
#include "frontend/connection-private.h"
-#include "frontend/parser.h"
+#include "parser/ast.h"
+#include "parser/parser.h"
#include "utils/error.h"
#include "utils/proto.h"
#include "utils/strbuf.h"
sdb_fe_query(sdb_conn_t *conn)
{
sdb_llist_t *parsetree;
- sdb_conn_node_t *node = NULL;
+ sdb_ast_node_t *ast = NULL;
+
+ sdb_store_matcher_t *q;
+ sdb_strbuf_t *buf = NULL;
int status = 0;
if ((! conn) || (conn->cmd != SDB_CONNECTION_QUERY))
return -1;
- parsetree = sdb_fe_parse(sdb_strbuf_string(conn->buf),
+ parsetree = sdb_parser_parse(sdb_strbuf_string(conn->buf),
(int)conn->cmd_len, conn->errbuf);
if (! parsetree) {
char query[conn->cmd_len + 1];
sdb_connection_send(conn, SDB_CONNECTION_DATA, 0, NULL);
break;
case 1:
- node = SDB_CONN_NODE(sdb_llist_get(parsetree, 0));
+ ast = SDB_AST_NODE(sdb_llist_get(parsetree, 0));
break;
default:
sdb_llist_len(parsetree) - 1,
sdb_llist_len(parsetree) == 2 ? "" : "s",
query);
- node = SDB_CONN_NODE(sdb_llist_get(parsetree, 0));
+ ast = SDB_AST_NODE(sdb_llist_get(parsetree, 0));
}
}
- if (node) {
- status = sdb_fe_exec(conn, node);
- sdb_object_deref(SDB_OBJ(node));
+ q = sdb_store_query_prepare(ast);
+ if (! q) {
+ /* this shouldn't happen */
+ sdb_strbuf_sprintf(conn->errbuf, "failed to compile AST");
+ sdb_log(SDB_LOG_ERR, "frontend: failed to compile AST");
+ status = -1;
+ } else {
+ buf = sdb_strbuf_create(1024);
+ if (! buf) {
+ sdb_strbuf_sprintf(conn->errbuf, "Out of memory");
+ sdb_object_deref(SDB_OBJ(q));
+ return -1;
+ }
+ status = sdb_store_query_execute(q, buf, conn->errbuf);
+ if (status < 0) {
+ char query[conn->cmd_len + 1];
+ strncpy(query, sdb_strbuf_string(conn->buf), conn->cmd_len);
+ query[sizeof(query) - 1] = '\0';
+ sdb_log(SDB_LOG_ERR, "frontend: failed to execute query '%s'", query);
+ }
}
-
+ sdb_object_deref(SDB_OBJ(ast));
sdb_llist_destroy(parsetree);
- return status;
+
+ if (status < 0) {
+ sdb_object_deref(SDB_OBJ(q));
+ sdb_strbuf_destroy(buf);
+ return status;
+ }
+
+ assert(buf);
+ sdb_connection_send(conn, status,
+ (uint32_t)sdb_strbuf_len(buf), sdb_strbuf_string(buf));
+
+ sdb_strbuf_destroy(buf);
+ sdb_object_deref(SDB_OBJ(q));
+ return 0;
} /* sdb_fe_query */
int
return status;
} /* sdb_fe_lookup */
-int
-sdb_fe_exec(sdb_conn_t *conn, sdb_conn_node_t *node)
-{
- sdb_store_matcher_t *m = NULL, *filter = NULL;
-
- if (! node)
- return -1;
-
- switch (node->cmd) {
- case SDB_CONNECTION_FETCH:
- if (CONN_FETCH(node)->filter)
- filter = CONN_FETCH(node)->filter->matcher;
- return sdb_fe_exec_fetch(conn, CONN_FETCH(node)->type,
- CONN_FETCH(node)->host, CONN_FETCH(node)->name, filter);
- case SDB_CONNECTION_LIST:
- if (CONN_LIST(node)->filter)
- filter = CONN_LIST(node)->filter->matcher;
- return sdb_fe_exec_list(conn, CONN_LIST(node)->type, filter);
- case SDB_CONNECTION_LOOKUP:
- if (CONN_LOOKUP(node)->matcher)
- m = CONN_LOOKUP(node)->matcher->matcher;
- if (CONN_LOOKUP(node)->filter)
- filter = CONN_LOOKUP(node)->filter->matcher;
- return sdb_fe_exec_lookup(conn,
- CONN_LOOKUP(node)->type, m, filter);
- case SDB_CONNECTION_STORE_HOST:
- {
- conn_store_host_t *n = CONN_STORE_HOST(node);
- sdb_proto_host_t host = { n->last_update, n->name };
- return sdb_fe_store_host(conn, &host);
- }
- case SDB_CONNECTION_STORE_SERVICE:
- {
- conn_store_svc_t *n = CONN_STORE_SVC(node);
- sdb_proto_service_t svc = { n->last_update, n->hostname, n->name };
- return sdb_fe_store_service(conn, &svc);
- }
- case SDB_CONNECTION_STORE_METRIC:
- {
- conn_store_metric_t *n = CONN_STORE_METRIC(node);
- sdb_proto_metric_t metric = {
- n->last_update, n->hostname, n->name,
- n->store_type, n->store_id
- };
- return sdb_fe_store_metric(conn, &metric);
- }
- case SDB_CONNECTION_STORE_ATTRIBUTE:
- {
- conn_store_attr_t *n = CONN_STORE_ATTR(node);
- sdb_proto_attribute_t attr = {
- n->last_update, n->parent_type, n->hostname, n->parent,
- n->key, n->value
- };
- return sdb_fe_store_attribute(conn, &attr);
- }
- case SDB_CONNECTION_TIMESERIES:
- return sdb_fe_exec_timeseries(conn,
- CONN_TS(node)->hostname, CONN_TS(node)->metric,
- &CONN_TS(node)->opts);
-
- default:
- sdb_log(SDB_LOG_ERR, "frontend: Unknown command %i", node->cmd);
- return -1;
- }
- return -1;
-} /* sdb_fe_exec */
+/*
+ * TODO: let the functions above build an AST; then drop sdb_fe_exec_*.
+ */
int
sdb_fe_exec_fetch(sdb_conn_t *conn, int type,
diff --git a/src/frontend/store.c b/src/frontend/store.c
index 6cad8cd312637036af82ef0a763eba7fbfd46c20..3d1a847b00b61f236c2d9d8ae914d7fa847ff3b1 100644 (file)
--- a/src/frontend/store.c
+++ b/src/frontend/store.c
* public API
*/
+/*
+ * TODO: move sdb_fe_store to frontend/query.c and let it build an AST
+ */
+
int
sdb_fe_store(sdb_conn_t *conn)
{
index 0abf0cb467d3d0a66fb3f99008537bce2f8848de..179b5d05a470a9f59e13b73c9826edfed9fa184e 100644 (file)
--- a/src/include/core/store.h
+++ b/src/include/core/store.h
sdb_store_matcher_t *
sdb_store_query_prepare(sdb_ast_node_t *ast);
+/*
+ * sdb_store_query_execute:
+ * Execute a previously prepared query. The query result will be written to
+ * 'buf' and any errors to 'errbuf'.
+ *
+ * Returns:
+ * - the result type (to be used by the server reply)
+ * - a negative value on error
+ */
+int
+sdb_store_query_execute(sdb_store_matcher_t *m,
+ sdb_strbuf_t *buf, sdb_strbuf_t *errbuf);
+
/*
* sdb_store_expr_create:
* Creates an arithmetic expression implementing the specified operator on the
index 0397e508d2eeab6f5d0fc58a9d5dbadc4496ec27..98c41360a990ba11175f2a24150a922185769458 100644 (file)
/*
* sdb_fe_parse:
* Parse the query text specified in 'query' of length 'len' and return a list
- * of parse trees (for each command) to be executed by sdb_fe_exec. The list
- * has to be freed by the caller. If 'len' is less than zero, parse the whole
- * (nul-terminated) string. If specified, errbuf will be used to record parse
- * errors.
+ * of parse trees (for each command). The list has to be freed by the caller.
+ * If 'len' is less than zero, parse the whole (nul-terminated) string. If
+ * specified, errbuf will be used to record parse errors.
*
* Returns:
* - an sdb_llist_t object of sdb_conn_node_t on success
sdb_llist_t *
sdb_fe_parse(const char *query, int len, sdb_strbuf_t *errbuf);
-/*
- * sdb_fe_exec:
- * Execute the command identified by 'node' on the specified connection.
- *
- * Returns:
- * - 0 on success
- * - a negative value else
- */
-int
-sdb_fe_exec(sdb_conn_t *conn, sdb_conn_node_t *node);
-
/*
* session handling
*/
index 7e15502096a04ed83358c1fb41f5aab8e14c098a..2160255d39f4ed0285e60a7fc0f0a502e3d107b9 100644 (file)
},
{
"STORE service attribute 'h2'.'s1'.'aA' 'vA'",
- 0, SDB_CONNECTION_OK, 43, 0, "Successfully stored service attribute s1.aA",
+ 0, SDB_CONNECTION_OK, 46, 0, "Successfully stored service attribute h2.s1.aA",
},
{
"STORE service attribute 'h2'.'x1'.'aA' 'vA'",
},
{
"STORE metric attribute 'h1'.'m1'.'aA' 'vA'",
- 0, SDB_CONNECTION_OK, 42, 0, "Successfully stored metric attribute m1.aA",
+ 0, SDB_CONNECTION_OK, 45, 0, "Successfully stored metric attribute h1.m1.aA",
},
{
"STORE metric attribute 'h1'.'x1'.'aA' 'vA'",
check = sdb_fe_query(conn);
fail_unless(check == query_data[_i].expected,
- "sdb_fe_query(%s) = %d; expected: %d",
- query_data[_i].query, check, query_data[_i].expected);
+ "sdb_fe_query(%s) = %d; expected: %d (err: %s)",
+ query_data[_i].query, check, query_data[_i].expected,
+ sdb_strbuf_string(conn->errbuf));
data = sdb_strbuf_string(MOCK_CONN(conn)->write_buf);
len = sdb_strbuf_len(MOCK_CONN(conn)->write_buf);