From: Sebastian Harl Date: Tue, 1 Apr 2014 20:45:19 +0000 (+0200) Subject: frontend: Added simple 'LOOKUP WHERE ' query. X-Git-Tag: sysdb-0.1.0~157 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=a916bb6643c413ee1d104f2a2274b5a9ca22d721;p=sysdb.git frontend: Added simple 'LOOKUP WHERE ' query. This query command may be used to retrieve a list of detailed host information for each host matching the specified expression. For now, querying hosts is supported only. --- diff --git a/src/frontend/connection-private.h b/src/frontend/connection-private.h index 534d3cb..f2d85f2 100644 --- a/src/frontend/connection-private.h +++ b/src/frontend/connection-private.h @@ -87,6 +87,12 @@ typedef struct { } conn_node_matcher_t; #define CONN_MATCHER(obj) ((conn_node_matcher_t *)(obj)) +typedef struct { + sdb_conn_node_t super; + conn_node_matcher_t *matcher; +} conn_lookup_t; +#define CONN_LOOKUP(obj) ((conn_lookup_t *)(obj)) + /* * type helper functions */ @@ -97,6 +103,13 @@ conn_fetch_destroy(sdb_object_t *obj) free(CONN_FETCH(obj)->name); } /* conn_fetch_destroy */ +static void __attribute__((unused)) +conn_lookup_destroy(sdb_object_t *obj) +{ + if (CONN_LOOKUP(obj)->matcher) + sdb_object_deref(SDB_OBJ(CONN_LOOKUP(obj)->matcher)); +} /* conn_fetch_destroy */ + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index 3802c9c..50bb00e 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -75,13 +75,16 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); %token SCANNER_ERROR +%token WHERE + %token IDENTIFIER STRING -%token FETCH LIST +%token FETCH LIST LOOKUP %type statements %type statement fetch_statement list_statement + lookup_statement expression %% @@ -141,6 +144,8 @@ statement: | list_statement | + lookup_statement + | /* empty */ { $$ = NULL; @@ -178,6 +183,32 @@ list_statement: } ; +/* + * LOOKUP WHERE ; + * + * Returns detailed information about matching expression. + */ +lookup_statement: + LOOKUP IDENTIFIER WHERE expression + { + /* TODO: support other types as well */ + if (strcasecmp($2, "hosts")) { + char errmsg[strlen($2) + 32]; + snprintf(errmsg, sizeof(errmsg), + YY_("unknown table %s"), $2); + sdb_fe_yyerror(&yylloc, scanner, errmsg); + YYABORT; + } + + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_lookup_t, conn_lookup_destroy)); + CONN_LOOKUP($$)->matcher = CONN_MATCHER($4); + $$->cmd = CONNECTION_LOOKUP; + free($2); + $2 = NULL; + } + ; + expression: STRING { diff --git a/src/frontend/query.c b/src/frontend/query.c index 96c46d2..759b9c9 100644 --- a/src/frontend/query.c +++ b/src/frontend/query.c @@ -34,6 +34,19 @@ #include +/* + * private helper functions + */ + +static int +lookup_tojson(sdb_store_base_t *obj, void *user_data) +{ + sdb_strbuf_t *buf = user_data; + if (sdb_strbuf_len(buf) > 1) + sdb_strbuf_append(buf, ","); + return sdb_store_host_tojson(obj, buf, /* flags = */ 0); +} /* lookup_tojson */ + /* * public API */ @@ -49,6 +62,8 @@ sdb_fe_exec(sdb_conn_t *conn, sdb_conn_node_t *node) return sdb_fe_fetch(conn, CONN_FETCH(node)->name); case CONNECTION_LIST: return sdb_fe_list(conn); + case CONNECTION_LOOKUP: + return sdb_fe_lookup(conn, CONN_LOOKUP(node)->matcher->matcher); default: sdb_log(SDB_LOG_ERR, "frontend: Unknown command %i", node->cmd); @@ -132,5 +147,39 @@ sdb_fe_list(sdb_conn_t *conn) return 0; } /* sdb_fe_list */ +int +sdb_fe_lookup(sdb_conn_t *conn, sdb_store_matcher_t *m) +{ + sdb_strbuf_t *buf; + + buf = sdb_strbuf_create(1024); + if (! buf) { + char errbuf[1024]; + sdb_log(SDB_LOG_ERR, "frontend: Failed to create " + "buffer to handle LOOKUP command: %s", + sdb_strerror(errno, errbuf, sizeof(errbuf))); + + sdb_strbuf_sprintf(conn->errbuf, "Out of memory"); + sdb_strbuf_destroy(buf); + return -1; + } + + sdb_strbuf_append(buf, "["); + + if (sdb_store_lookup(m, lookup_tojson, buf)) { + sdb_log(SDB_LOG_ERR, "frontend: Failed to lookup hosts"); + sdb_strbuf_sprintf(conn->errbuf, "Failed to lookup hosts"); + sdb_strbuf_destroy(buf); + return -1; + } + + sdb_strbuf_append(buf, "]"); + + sdb_connection_send(conn, CONNECTION_OK, + (uint32_t)sdb_strbuf_len(buf), sdb_strbuf_string(buf)); + sdb_strbuf_destroy(buf); + return 0; +} /* sdb_fe_lookup */ + /* vim: set tw=78 sw=4 ts=4 noexpandtab : */ diff --git a/src/frontend/scanner.l b/src/frontend/scanner.l index c0d167c..61f1743 100644 --- a/src/frontend/scanner.l +++ b/src/frontend/scanner.l @@ -91,11 +91,15 @@ string ('[^']*') } {identifier} { - /* XXX */ - if (! strcasecmp(yytext, "LIST")) - return LIST; - else if (! strcasecmp(yytext, "FETCH")) + /* XXX: simplify handling of reserved words */ + if (! strcasecmp(yytext, "FETCH")) return FETCH; + else if (! strcasecmp(yytext, "LIST")) + return LIST; + else if (! strcasecmp(yytext, "LOOKUP")) + return LOOKUP; + else if (! strcasecmp(yytext, "WHERE")) + return WHERE; yylval->str = strdup(yytext); return IDENTIFIER; diff --git a/src/include/frontend/connection.h b/src/include/frontend/connection.h index bf902dd..4791a5e 100644 --- a/src/include/frontend/connection.h +++ b/src/include/frontend/connection.h @@ -29,6 +29,7 @@ #define SDB_FRONTEND_CONNECTION_H 1 #include "frontend/proto.h" +#include "core/store.h" #include "utils/llist.h" #include "utils/strbuf.h" @@ -186,6 +187,17 @@ sdb_fe_fetch(sdb_conn_t *conn, const char *name); int sdb_fe_list(sdb_conn_t *conn); +/* + * sdb_fe_lookup: + * Send a list of hosts matching 'm', serialized as JSON, to the client. + * + * Returns: + * - 0 on success + * - a negative value else + */ +int +sdb_fe_lookup(sdb_conn_t *conn, sdb_store_matcher_t *m); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/include/frontend/proto.h b/src/include/frontend/proto.h index 132e10c..0f55a7c 100644 --- a/src/include/frontend/proto.h +++ b/src/include/frontend/proto.h @@ -52,6 +52,7 @@ typedef enum { /* query commands */ CONNECTION_FETCH, CONNECTION_LIST, + CONNECTION_LOOKUP, /* command elements */ CONNECTION_EXPR,