static int database_cursor_open(libretrodb_t *db, libretrodb_cursor_t *cur, const char *path, const char *query) { const char *error = NULL; libretrodb_query_t *q = NULL; if ((libretrodb_open(path, db)) != 0) return -1; if (query) q = (libretrodb_query_t*)libretrodb_query_compile(db, query, strlen(query), &error); if (error) goto error; if ((libretrodb_cursor_open(db, cur, q)) != 0) goto error; if (q) libretrodb_query_free(q); return 0; error: if (q) libretrodb_query_free(q); libretrodb_close(db); return -1; }
static int db_query(lua_State *L) { int rv; libretrodb_cursor_t *cursor = NULL; libretrodb_t *db = checkdb(L); const char *query = luaL_checkstring(L, -1); const char *error = NULL; libretrodb_query_t *q = libretrodb_query_compile( db, query, strlen(query), &error); if (error) { lua_pushnil(L); lua_pushstring(L, error); } else { cursor = lua_newuserdata(L, sizeof(libretrodb_t)); if ((rv = libretrodb_cursor_open(db, cursor, q)) == 0) { luaL_getmetatable(L, "RarchDB.Cursor"); lua_setmetatable(L, -2); lua_pushnil(L); } else { lua_pop(L, 1); lua_pushnil(L); lua_pushstring(L, strerror(-rv)); } libretrodb_query_free(q); } return 2; }
static int db_cursor_open(lua_State *L) { int rv; libretrodb_cursor_t *cursor = NULL; libretrodb_t *db = checkdb(L); cursor = lua_newuserdata(L, sizeof(libretrodb_t)); if ((rv = libretrodb_cursor_open(db, cursor, NULL)) == 0) { luaL_getmetatable(L, "RarchDB.Cursor"); lua_setmetatable(L, -2); lua_pushnil(L); } else { lua_pop(L, 1); lua_pushnil(L); lua_pushstring(L, strerror(-rv)); } return 2; }
int main(int argc, char ** argv) { int rv; libretrodb_t db; libretrodb_cursor_t cur; libretrodb_query_t *q; struct rmsgpack_dom_value item; const char *command, *path, *query_exp, *error; if (argc < 3) { printf("Usage: %s <db file> <command> [extra args...]\n", argv[0]); printf("Available Commands:\n"); printf("\tlist\n"); printf("\tcreate-index <index name> <field name>\n"); printf("\tfind <query expression>\n"); return 1; } command = argv[2]; path = argv[1]; if ((rv = libretrodb_open(path, &db)) != 0) { printf("Could not open db file '%s': %s\n", path, strerror(-rv)); return 1; } else if (strcmp(command, "list") == 0) { if ((rv = libretrodb_cursor_open(&db, &cur, NULL)) != 0) { printf("Could not open cursor: %s\n", strerror(-rv)); return 1; } if (argc != 3) { printf("Usage: %s <db file> list\n", argv[0]); return 1; } while (libretrodb_cursor_read_item(&cur, &item) == 0) { rmsgpack_dom_value_print(&item); printf("\n"); rmsgpack_dom_value_free(&item); } } else if (strcmp(command, "find") == 0) { if (argc != 4) { printf("Usage: %s <db file> find <query expression>\n", argv[0]); return 1; } query_exp = argv[3]; error = NULL; q = libretrodb_query_compile(&db, query_exp, strlen(query_exp), &error); if (error) { printf("%s\n", error); return 1; } if ((rv = libretrodb_cursor_open(&db, &cur, q)) != 0) { printf("Could not open cursor: %s\n", strerror(-rv)); return 1; } while (libretrodb_cursor_read_item(&cur, &item) == 0) { rmsgpack_dom_value_print(&item); printf("\n"); rmsgpack_dom_value_free(&item); } } else if (strcmp(command, "create-index") == 0) { const char * index_name, * field_name; if (argc != 5) { printf("Usage: %s <db file> create-index <index name> <field name>\n", argv[0]); return 1; } index_name = argv[3]; field_name = argv[4]; libretrodb_create_index(&db, index_name, field_name); } else { printf("Unknown command %s\n", argv[2]); return 1; } libretrodb_close(&db); return 1; }
int libretrodb_create_index(libretrodb_t *db, const char *name, const char *field_name) { int rv; struct node_iter_ctx nictx; struct rmsgpack_dom_value key; libretrodb_index_t idx; struct rmsgpack_dom_value item; struct rmsgpack_dom_value * field; struct bintree tree; libretrodb_cursor_t cur; uint64_t idx_header_offset; void * buff = NULL; uint64_t * buff_u64 = NULL; uint8_t field_size = 0; uint64_t item_loc = libretrodb_tell(db); bintree_new(&tree, node_compare, &field_size); if (libretrodb_cursor_open(db, &cur, NULL) != 0) { rv = -1; goto clean; } key.type = RDT_STRING; key.string.len = strlen(field_name); /* We know we aren't going to change it */ key.string.buff = (char *) field_name; while (libretrodb_cursor_read_item(&cur, &item) == 0) { if (item.type != RDT_MAP) { rv = -EINVAL; printf("Only map keys are supported\n"); goto clean; } field = rmsgpack_dom_value_map_value(&item, &key); if (!field) { rv = -EINVAL; printf("field not found in item\n"); goto clean; } if (field->type != RDT_BINARY) { rv = -EINVAL; printf("field is not binary\n"); goto clean; } if (field->binary.len == 0) { rv = -EINVAL; printf("field is empty\n"); goto clean; } if (field_size == 0) field_size = field->binary.len; else if (field->binary.len != field_size) { rv = -EINVAL; printf("field is not of correct size\n"); goto clean; } buff = malloc(field_size + sizeof(uint64_t)); if (!buff) { rv = -ENOMEM; goto clean; } memcpy(buff, field->binary.buff, field_size); buff_u64 = (uint64_t *)buff + field_size; memcpy(buff_u64, &item_loc, sizeof(uint64_t)); if (bintree_insert(&tree, buff) != 0) { printf("Value is not unique: "); rmsgpack_dom_value_print(field); printf("\n"); rv = -EINVAL; goto clean; } buff = NULL; rmsgpack_dom_value_free(&item); item_loc = libretrodb_tell(db); } (void)rv; (void)idx_header_offset; idx_header_offset = lseek(db->fd, 0, SEEK_END); strncpy(idx.name, name, 50); idx.name[49] = '\0'; idx.key_size = field_size; idx.next = db->count * (field_size + sizeof(uint64_t)); libretrodb_write_index_header(db->fd, &idx); nictx.db = db; nictx.idx = &idx; bintree_iterate(&tree, node_iter, &nictx); bintree_free(&tree); clean: rmsgpack_dom_value_free(&item); if (buff) free(buff); if (cur.is_valid) libretrodb_cursor_close(&cur); return 0; }