Book authors

This commit is contained in:
Meutel 2016-12-30 15:40:21 +01:00
parent efbe2be19c
commit 609c2ed8ac
3 changed files with 86 additions and 13 deletions

64
db.c
View File

@ -31,14 +31,26 @@
enum stmt { enum stmt {
STMT_BOOK, STMT_BOOK,
STMT_BOOKS, STMT_BOOKS,
STMT_BOOKS_AUTHORS,
STMT__MAX STMT__MAX
}; };
static const char *const stmts[STMT__MAX] = { static const char *const stmts[STMT__MAX] = {
/* STMT_BOOK */ /* 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 = ?", "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 */ /* 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 LIMIT ?", "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 static void
@ -101,18 +113,56 @@ db_books_load(struct kreq *r, BookAdv **books, int limit)
return 0; return 0;
} }
struct ksqlstmt *stmt; struct ksqlstmt *stmt;
int i = 0; struct bookauth *p = NULL;
int i, count = 0;
ksql_stmt_alloc(r->arg, &stmt, ksql_stmt_alloc(r->arg, &stmt,
stmts[STMT_BOOKS], stmts[STMT_BOOKS],
STMT_BOOKS); STMT_BOOKS);
ksql_bind_int(stmt, 0, limit); ksql_bind_int(stmt, 0, limit);
while (KSQL_ROW == ksql_stmt_step(stmt)) { while (KSQL_ROW == ksql_stmt_step(stmt)) {
books[i] = kcalloc(1, sizeof(BookAdv)); books[count] = kcalloc(1, sizeof(BookAdv));
db_book_fill(&books[i]->b,stmt); db_book_fill(&books[count]->b,stmt);
i++; books[count]->asize = 0;
count++;
} }
ksql_stmt_free(stmt); 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 * Book *

View File

@ -52,7 +52,7 @@ typedef struct
typedef struct typedef struct
{ {
Book b; Book b;
Author *a; Author **a;
size_t asize; size_t asize;
// TODO tags // TODO tags
} BookAdv; } BookAdv;

33
main.c
View File

@ -86,7 +86,7 @@ http_open(struct kreq *r, enum khttp code)
khttp_body(r); khttp_body(r);
} }
void static void
puterror(struct kjsonreq *req, char *message) puterror(struct kjsonreq *req, char *message)
{ {
kjson_obj_open(req); kjson_obj_open(req);
@ -94,7 +94,21 @@ puterror(struct kjsonreq *req, char *message)
kjson_obj_close(req); 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) putbook(struct kjsonreq *req, Book *b)
{ {
kjson_obj_open(req); kjson_obj_open(req);
@ -107,7 +121,6 @@ putbook(struct kjsonreq *req, Book *b)
kjson_putdoublep(req, "idx", b->s_idx); kjson_putdoublep(req, "idx", b->s_idx);
kjson_obj_close(req); kjson_obj_close(req);
} }
kjson_obj_close(req);
} }
static void static void
@ -132,14 +145,24 @@ sendbooks(struct kreq *r)
puterror(&req, "Unknown book"); puterror(&req, "Unknown book");
} else if (NULL != b) { } else if (NULL != b) {
putbook(&req, b); putbook(&req, b);
kjson_obj_close(&req);
db_book_free(b); db_book_free(b);
} else { } else {
kjson_array_open(&req); kjson_array_open(&req);
BookAdv **books = kcalloc(10, sizeof(BookAdv)); BookAdv **books = kcalloc(200, sizeof(BookAdv));
res = db_books_load(r, books, 10); res = db_books_load(r, books, 200);
while (i < res) { while (i < res) {
Book b = books[i]->b; Book b = books[i]->b;
putbook(&req, &b); putbook(&req, &b);
if (books[i]->asize > 0) {
kjson_arrayp_open(&req, "authors");
for (size_t j=0; j<books[i]->asize; 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]); db_book_adv_free(books[i]);
i++; i++;
} }