diff --git a/libretrodb/query.c b/libretrodb/query.c index 3954fc4171..833778b2e2 100644 --- a/libretrodb/query.c +++ b/libretrodb/query.c @@ -412,6 +412,12 @@ static struct buffer expect_eof( return buff; } +static struct buffer parse_table( + struct buffer buff, + struct invocation * invocation, + const char ** error +); + static int peek( struct buffer buff, const char * data @@ -531,7 +537,6 @@ static struct buffer parse_value( buff.offset += strlen("false"); value->type = RDT_BOOL; value->bool_ = 0; - //} else if (peek(buff, "{")) { //} else if (peek(buff, "[")) { //} else if (peek(buff, "b\"") || peek(buff, "b'")) { } else if (peek(buff, "\"") || peek(buff, "'")) { @@ -622,7 +627,7 @@ static struct buffer parse_method_call( } buff = chomp(buff); - while (1) { + while (!peek(buff, ")")) { if (argi >= MAX_ARGS) { raise_too_many_arguments(error); goto clean; @@ -678,6 +683,9 @@ static struct buffer parse_argument( ) { arg->type = AT_FUNCTION; buff = parse_method_call(buff, &arg->invocation, error); + } else if (peek(buff, "{")){ + arg->type = AT_FUNCTION; + buff = parse_table(buff, &arg->invocation, error); } else { arg->type = AT_VALUE; buff = parse_value(buff, &arg->value, error); @@ -694,6 +702,9 @@ static struct buffer parse_table( unsigned argi = 0; unsigned i; + const char * ident_name; + size_t ident_len; + memset(args, 0, sizeof(struct argument) * MAX_ARGS); buff = chomp(buff); buff = expect_char(buff, '{', error); @@ -702,12 +713,32 @@ static struct buffer parse_table( } buff = chomp(buff); - while (1) { + while (!peek(buff, "}")) { if (argi >= MAX_ARGS) { raise_too_many_arguments(error); goto clean; } - buff = parse_string(buff, &args[argi].value, error); + if (isalpha(buff.data[buff.offset])) { + buff = get_ident(buff, &ident_name, &ident_len, error); + if (!*error) { + args[argi].value.type = RDT_STRING; + args[argi].value.string.len = ident_len; + args[argi].value.string.buff = calloc( + ident_len + 1, + sizeof(char) + ); + if (!args[argi].value.string.buff) { + goto clean; + } + strncpy( + args[argi].value.string.buff, + ident_name, + ident_len + ); + } + } else { + buff = parse_string(buff, &args[argi].value, error); + } if (*error) { goto clean; } @@ -800,11 +831,19 @@ rarchdb_query * rarchdb_query_compile( if (*error) { goto clean; } + } else if (isalpha(buff.data[buff.offset])) { + buff = parse_method_call(buff, &q->root, error); } + buff = expect_eof(buff, error); if (*error) { goto clean; } + + if (q->root.func == NULL) { + raise_unexpected_eof(buff.offset, error); + return NULL; + } goto success; clean: if (q) { diff --git a/libretrodb/rarchdb_tool.c b/libretrodb/rarchdb_tool.c index c6b2dd032f..23adf56a24 100644 --- a/libretrodb/rarchdb_tool.c +++ b/libretrodb/rarchdb_tool.c @@ -27,8 +27,7 @@ int main( if ((rv = rarchdb_open(path, &db)) != 0) { printf("Could not open db file '%s': %s\n", path, strerror(-rv)); return 1; - } - else if (strcmp(command, "list") == 0) { + } else if (strcmp(command, "list") == 0) { if ((rv = rarchdb_cursor_open(&db, &cur, NULL)) != 0) { printf("Could not open cursor: %s\n", strerror(-rv)); return 1; @@ -43,8 +42,7 @@ int main( printf("\n"); rmsgpack_dom_value_free(&item); } - } - else if (strcmp(command, "find") == 0) { + } else if (strcmp(command, "find") == 0) { if (argc != 4) { printf("Usage: %s find \n", argv[0]); return 1; @@ -80,7 +78,7 @@ int main( rarchdb_create_index(&db, index_name, field_name); } else { - printf("Unkown command %s\n", argv[1]); + printf("Unkonwn command %s\n", argv[1]); return 1; } rarchdb_close(&db); diff --git a/libretrodb/tests.lua b/libretrodb/tests.lua index eb525e3f45..95d4e48f01 100644 --- a/libretrodb/tests.lua +++ b/libretrodb/tests.lua @@ -65,11 +65,13 @@ tests = { i = i + 1 end end, - test_boolean_field = query_test({{a=true},{a=false}}, {{a=true}}, "{'a':true}"), + test_boolean_field = query_test({{a=true},{a=false}}, {{a=true}}, "{a:true}"), test_number_field = query_test({{a=3}, {a=4}}, {{a=3}}, "{'a':3}"), + test_empty_query = query_test({{a=3}, {a=4}}, {{a=3}, {a=4}}, " {} "), test_string_field = query_test({{a="test"}, {a=4}}, {{a="test"}}, "{'a':'test'}"), test_or_operator = query_test({{a="test"}, {a=4}, {a=5}}, {{a="test"}, {a=4}}, "{'a':or('test', 4)}"), test_or_between = query_test({{a="test"}, {a=4}, {a=5}, {}}, {{a="test"}, {a=4}, {a=5}}, "{'a':or('test', between(2, 7))}"), + test_root_function = query_test({{a=1}, {b=4}, {a=5}, {}}, {{a=1}, {b=4}}, "or({a:1},{b:4})"), } for name, cb in pairs(tests) do local ok, err = pcall(cb)