diff --git a/db.c b/db.c index 89290c3..10978fb 100644 --- a/db.c +++ b/db.c @@ -31,14 +31,26 @@ enum stmt { STMT_BOOK, STMT_BOOKS, + STMT_BOOKS_AUTHORS, STMT__MAX }; static const char *const stmts[STMT__MAX] = { /* STMT_BOOK */ "SELECT books.id AS id,title,series_index,name as series_name,series.id AS series_id FROM books LEFT OUTER JOIN books_series_link ON books.id = books_series_link.book LEFT OUTER JOIN series ON series.id = books_series_link.series WHERE books.id = ?", - /* STMT_BOOKS */ - "SELECT books.id AS id,title,series_index,name as series_name,series.id AS series_id FROM books LEFT OUTER JOIN books_series_link ON books.id = books_series_link.book LEFT OUTER JOIN series ON series.id = books_series_link.series LIMIT ?", + /* STMT_BOOKS */ //TODO offset + "SELECT books.id AS id,title,series_index,name as series_name,series.id AS series_id FROM books LEFT OUTER JOIN books_series_link ON books.id = books_series_link.book LEFT OUTER JOIN series ON series.id = books_series_link.series ORDER BY id LIMIT ?", + /* STMT_BOOKS_AUTHORS */ + "SELECT authors.id, authors.name, books_authors_link.book as book FROM authors, books_authors_link WHERE books_authors_link.author = authors.id AND books_authors_link.book IN ( SELECT id FROM books ORDER BY id LIMIT ? )", +}; + +/* + * Linked list authors of book. + */ +struct bookauth { + Author *a; + BookAdv *b; + struct bookauth *p; }; static void @@ -101,18 +113,56 @@ db_books_load(struct kreq *r, BookAdv **books, int limit) return 0; } struct ksqlstmt *stmt; - int i = 0; + struct bookauth *p = NULL; + int i, count = 0; + ksql_stmt_alloc(r->arg, &stmt, stmts[STMT_BOOKS], STMT_BOOKS); ksql_bind_int(stmt, 0, limit); while (KSQL_ROW == ksql_stmt_step(stmt)) { - books[i] = kcalloc(1, sizeof(BookAdv)); - db_book_fill(&books[i]->b,stmt); - i++; + books[count] = kcalloc(1, sizeof(BookAdv)); + db_book_fill(&books[count]->b,stmt); + books[count]->asize = 0; + count++; } ksql_stmt_free(stmt); - return i; + + ksql_stmt_alloc(r->arg, &stmt, + stmts[STMT_BOOKS_AUTHORS], + STMT_BOOKS_AUTHORS); + ksql_bind_int(stmt, 0, limit); + while (KSQL_ROW == ksql_stmt_step(stmt)) { + // add author to list, link related book and increment asize + struct bookauth *item = kcalloc(1, sizeof(struct bookauth)); + item->a = kcalloc(1, sizeof(Author)); + item->a->id = ksql_stmt_int(stmt, 0); + item->a->name = kstrdup(ksql_stmt_str(stmt, 1)); + int64_t bid = ksql_stmt_int(stmt, 2); + for (i = 0; i < count && NULL == item->b; i++) { + if (books[i]->b.id == bid) { + item->b = books[i]; + item->b->asize++; + } + } + item->p = p; + p = item; + } + + // assign authors to books + while (NULL != p) { + if (NULL != p->b && NULL == p->b->a && p->b->asize > 0) { + p->b->a = kcalloc(p->b->asize, sizeof(Author)); + p->b->asize = 0; // use as counter for insert + } + p->b->a[p->b->asize] = p->a;// add author + p->b->asize++; + p = p->p; + } + // TODO free linked list (not authors) + ksql_stmt_free(stmt); + + return count; } Book * diff --git a/extern.h b/extern.h index d028ed0..b5a4d55 100644 --- a/extern.h +++ b/extern.h @@ -52,7 +52,7 @@ typedef struct typedef struct { Book b; - Author *a; + Author **a; size_t asize; // TODO tags } BookAdv; diff --git a/main.c b/main.c index a59bd04..34ec26c 100644 --- a/main.c +++ b/main.c @@ -86,7 +86,7 @@ http_open(struct kreq *r, enum khttp code) khttp_body(r); } -void +static void puterror(struct kjsonreq *req, char *message) { kjson_obj_open(req); @@ -94,7 +94,21 @@ puterror(struct kjsonreq *req, char *message) kjson_obj_close(req); } -void +/* + * Append author object to json (NOT CLOSED). + */ +static void +putauthor(struct kjsonreq *req, Author *a) +{ + kjson_obj_open(req); + kjson_putintp(req, "id", a->id); + kjson_putstringp(req, "name", a->name); +} + +/* + * Append book object to json (NOT CLOSED). + */ +static void putbook(struct kjsonreq *req, Book *b) { kjson_obj_open(req); @@ -107,7 +121,6 @@ putbook(struct kjsonreq *req, Book *b) kjson_putdoublep(req, "idx", b->s_idx); kjson_obj_close(req); } - kjson_obj_close(req); } static void @@ -132,14 +145,24 @@ sendbooks(struct kreq *r) puterror(&req, "Unknown book"); } else if (NULL != b) { putbook(&req, b); + kjson_obj_close(&req); db_book_free(b); } else { kjson_array_open(&req); - BookAdv **books = kcalloc(10, sizeof(BookAdv)); - res = db_books_load(r, books, 10); + BookAdv **books = kcalloc(200, sizeof(BookAdv)); + res = db_books_load(r, books, 200); while (i < res) { Book b = books[i]->b; putbook(&req, &b); + if (books[i]->asize > 0) { + kjson_arrayp_open(&req, "authors"); + for (size_t j=0; jasize; j++) { + putauthor(&req, books[i]->a[j]); + kjson_obj_close(&req); + } + kjson_array_close(&req); + } + kjson_obj_close(&req); db_book_adv_free(books[i]); i++; }