From f1cd51b551551dd2540cf06f1dad5d8212ca5470 Mon Sep 17 00:00:00 2001 From: Meutel Date: Thu, 12 Jan 2017 20:52:20 +0100 Subject: [PATCH] Sort authors, books, series --- db_author.c | 23 ++++++++++++++----- db_book.c | 65 +++++++++++++++++++++++++++++++++++++++-------------- db_series.c | 45 +++++++++++++++++++++++++++---------- extern.h | 6 ++--- main.c | 19 +++++++++++++--- 5 files changed, 117 insertions(+), 41 deletions(-) diff --git a/db_author.c b/db_author.c index 3ae58d2..fab5b2c 100644 --- a/db_author.c +++ b/db_author.c @@ -29,7 +29,8 @@ #include "extern.h" enum stmt { - STMT_AUTHORS, + STMT_AUTHORS_ID, + STMT_AUTHORS_NAME, STMT_AUTHOR_BOOKS, STMT_AUTHORS_AUTHORS, STMT_AUTHOR, @@ -37,10 +38,14 @@ enum stmt { }; static const char *const stmts[STMT__MAX] = { - /* STMT_AUTHORS */ + /* STMT_AUTHORS_ID */ "SELECT authors.id, authors.name, count(book) as count FROM authors, books_authors_link \ WHERE authors.id = books_authors_link.author GROUP BY author \ ORDER BY authors.id LIMIT ? OFFSET ?", + /* STMT_AUTHORS_NAME */ + "SELECT authors.id, authors.name, count(book) as count FROM authors, books_authors_link \ + WHERE authors.id = books_authors_link.author GROUP BY author \ + ORDER BY authors.sort LIMIT ? OFFSET ?", /* STMT_AUTHOR_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 \ @@ -145,17 +150,23 @@ db_author_load(struct kreq *r, int64_t id) } int -db_authors_load(struct kreq *r, AuthorAdv **authors, int limit, int offset) +db_authors_load(struct kreq *r, AuthorAdv **authors, const char *sort, int limit, int offset) { if (limit < 0 || offset < 0) { return 0; } struct ksqlstmt *stmt; - int count = 0; + int query, count = 0; + if (sort == NULL) + query = STMT_AUTHORS_ID; + else if (0 == strcmp(sort, "name")) + query = STMT_AUTHORS_NAME; + else + query = STMT_AUTHORS_ID; ksql_stmt_alloc(r->arg, &stmt, - stmts[STMT_AUTHORS], - STMT_AUTHORS); + stmts[query], + query); ksql_bind_int(stmt, 0, limit); ksql_bind_int(stmt, 1, offset); while (KSQL_ROW == ksql_stmt_step(stmt)) { diff --git a/db_book.c b/db_book.c index 1b2150e..71b8a84 100644 --- a/db_book.c +++ b/db_book.c @@ -33,10 +33,13 @@ enum stmt { STMT_BOOK_TAGS, STMT_BOOK_AUTHORS, STMT_BOOK_DATA, - STMT_BOOKS, + STMT_BOOKS_ID, + STMT_BOOKS_TITLE, STMT_BOOKS_COUNT, - STMT_BOOKS_TAGS, - STMT_BOOKS_AUTHORS, + STMT_BOOKS_TAGS_ID, + STMT_BOOKS_TAGS_TITLE, + STMT_BOOKS_AUTHORS_ID, + STMT_BOOKS_AUTHORS_TITLE, STMT__MAX }; @@ -62,20 +65,32 @@ static const char *const stmts[STMT__MAX] = { /* STMT_BOOK_DATA */ "SELECT data.name, data.format, data.uncompressed_size \ FROM data WHERE data.book = ?", - /* STMT_BOOKS */ + /* STMT_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 ORDER BY id LIMIT ? OFFSET ?", + /* STMT_BOOKS_TITLE */ + "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 books.sort LIMIT ? OFFSET ?", /* STMT_BOOKS_COUNT */ "SELECT count(id) FROM books", - /* STMT_BOOKS_TAGS */ + /* STMT_BOOKS_TAGS_ID */ "SELECT name, books_tags_link.book as book FROM tags, books_tags_link \ WHERE tags.id = books_tags_link.tag AND books_tags_link.book \ IN ( SELECT id FROM books ORDER BY id LIMIT ? OFFSET ?)", - /* STMT_BOOKS_AUTHORS */ + /* STMT_BOOKS_TAGS_TITLE */ + "SELECT name, books_tags_link.book as book FROM tags, books_tags_link \ + WHERE tags.id = books_tags_link.tag AND books_tags_link.book \ + IN ( SELECT id FROM books ORDER BY books.sort LIMIT ? OFFSET ?)", + /* STMT_BOOKS_AUTHORS_ID */ "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 ? OFFSET ?)", + /* STMT_BOOKS_AUTHORS_TITLE */ + "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 books.sort LIMIT ? OFFSET ?)", }; static void @@ -221,17 +236,23 @@ db_assign_book_authors(struct bookauth *list) } static struct booktag * -db_load_books_tags(struct kreq *r, BookAdv **books, int count, int limit, int offset) +db_load_books_tags(struct kreq *r, BookAdv **books, int count, const char *sort, int limit, int offset) { struct ksqlstmt *stmt; struct booktag *p = NULL; struct booktag *item = NULL; - int i; + int i, query; int64_t bid; + if (sort == NULL) + query = STMT_BOOKS_TAGS_ID; + else if (0 == strcmp(sort, "title")) + query = STMT_BOOKS_TAGS_TITLE; + else + query = STMT_BOOKS_TAGS_ID; ksql_stmt_alloc(r->arg, &stmt, - stmts[STMT_BOOKS_TAGS], - STMT_BOOKS_TAGS); + stmts[query], + query); ksql_bind_int(stmt, 0, limit); ksql_bind_int(stmt, 1, offset); while (KSQL_ROW == ksql_stmt_step(stmt)) { @@ -279,7 +300,7 @@ db_load_books_authors(BookAdv **books, int count, struct ksqlstmt *stmt) } int -db_books_load(struct kreq *r, BookAdv **books, int limit, int offset) +db_books_load(struct kreq *r, BookAdv **books, const char *sort, int limit, int offset) { if (limit < 0 || offset < 0) { return 0; @@ -287,11 +308,21 @@ db_books_load(struct kreq *r, BookAdv **books, int limit, int offset) struct ksqlstmt *stmt; struct bookauth *p_a; struct booktag *p_t; - int count = 0; + int query, querya, count = 0; + if (sort == NULL) { + query = STMT_BOOKS_ID; + querya = STMT_BOOKS_AUTHORS_ID; + } else if (0 == strcmp(sort, "title")) { + query = STMT_BOOKS_TITLE; + querya = STMT_BOOKS_AUTHORS_TITLE; + } else { + query = STMT_BOOKS_ID; + querya = STMT_BOOKS_AUTHORS_ID; + } ksql_stmt_alloc(r->arg, &stmt, - stmts[STMT_BOOKS], - STMT_BOOKS); + stmts[query], + query); ksql_bind_int(stmt, 0, limit); ksql_bind_int(stmt, 1, offset); while (KSQL_ROW == ksql_stmt_step(stmt)) { @@ -304,15 +335,15 @@ db_books_load(struct kreq *r, BookAdv **books, int limit, int offset) ksql_stmt_free(stmt); ksql_stmt_alloc(r->arg, &stmt, - stmts[STMT_BOOKS_AUTHORS], - STMT_BOOKS_AUTHORS); + stmts[querya], + querya); ksql_bind_int(stmt, 0, limit); ksql_bind_int(stmt, 1, offset); p_a = db_load_books_authors(books, count, stmt); ksql_stmt_free(stmt); db_assign_book_authors(p_a); - p_t = db_load_books_tags(r, books, count, limit, offset); + p_t = db_load_books_tags(r, books, count, sort, limit, offset); db_assign_book_tags(p_t); return count; diff --git a/db_series.c b/db_series.c index 8391336..db62f5a 100644 --- a/db_series.c +++ b/db_series.c @@ -29,8 +29,10 @@ #include "extern.h" enum stmt { - STMT_SERIES, - STMT_SERIES_AUTHORS, + STMT_SERIES_ID, + STMT_SERIES_NAME, + STMT_SERIES_AUTHORS_ID, + STMT_SERIES_AUTHORS_NAME, STMT_SERIE, STMT_SERIE_BOOKS, STMT_SERIE_AUTHORS, @@ -38,15 +40,24 @@ enum stmt { }; static const char *const stmts[STMT__MAX] = { - /* STMT_SERIES */ + /* STMT_SERIES_ID */ "SELECT series.id, series.name, count(book) FROM series \ LEFT OUTER JOIN books_series_link ON books_series_link.series = series.id \ GROUP BY series.id ORDER BY series.id LIMIT ? OFFSET ?", - /* STMT_SERIES_AUTHORS */ + /* STMT_SERIES_NAME */ + "SELECT series.id, series.name, count(book) FROM series \ + LEFT OUTER JOIN books_series_link ON books_series_link.series = series.id \ + GROUP BY series.id ORDER BY sort LIMIT ? OFFSET ?", + /* STMT_SERIES_AUTHORS_ID */ "SELECT DISTINCT authors.id, authors.name, books_series_link.series \ FROM authors, books_authors_link, books_series_link \ WHERE books_authors_link.book = books_series_link.book AND books_authors_link.author = authors.id \ AND books_series_link.series IN ( SELECT id FROM series ORDER BY series.id LIMIT ? OFFSET ?)", + /* STMT_SERIES_AUTHORS */ + "SELECT DISTINCT authors.id, authors.name, books_series_link.series \ + FROM authors, books_authors_link, books_series_link \ + WHERE books_authors_link.book = books_series_link.book AND books_authors_link.author = authors.id \ + AND books_series_link.series IN ( SELECT id FROM series ORDER BY sort LIMIT ? OFFSET ?)", /* STMT_SERIE */ "SELECT series.id, series.name FROM series WHERE series.id = ?", /* STMT_SERIE_BOOKS */ @@ -244,18 +255,28 @@ db_serie_load(struct kreq *r, int64_t id) } int -db_series_load(struct kreq *r, SeriesAdv **series, int limit, int offset) +db_series_load(struct kreq *r, SeriesAdv **series, const char *sort, int limit, int offset) { - if (limit < 0 || offset < 0) { + if (limit < 0 || offset < 0) return 0; - } struct ksqlstmt *stmt; - int count = 0; + int query, queryauth, count = 0; struct seriesauth *p = NULL; + if (sort == NULL) { + query = STMT_SERIES_ID; + queryauth = STMT_SERIES_AUTHORS_ID; + } else if (0 == strcmp(sort, "name")) { + query = STMT_SERIES_NAME; + queryauth = STMT_SERIES_AUTHORS_NAME; + } else { + query = STMT_SERIES_ID; + queryauth = STMT_SERIES_AUTHORS_ID; + } + ksql_stmt_alloc(r->arg, &stmt, - stmts[STMT_SERIES], - STMT_SERIES); + stmts[query], + query); ksql_bind_int(stmt, 0, limit); ksql_bind_int(stmt, 1, offset); while (KSQL_ROW == ksql_stmt_step(stmt)) { @@ -269,8 +290,8 @@ db_series_load(struct kreq *r, SeriesAdv **series, int limit, int offset) ksql_stmt_free(stmt); ksql_stmt_alloc(r->arg, &stmt, - stmts[STMT_SERIES_AUTHORS], - STMT_SERIES_AUTHORS); + stmts[queryauth], + queryauth); ksql_bind_int(stmt, 0, limit); ksql_bind_int(stmt, 1, offset); p = db_load_series_authors(series, count, stmt); diff --git a/extern.h b/extern.h index ddc63a2..72bf59c 100644 --- a/extern.h +++ b/extern.h @@ -146,7 +146,7 @@ struct bookdata { __BEGIN_DECLS BookFull *db_book_load(struct kreq *r, int64_t id); -int db_books_load(struct kreq *r, BookAdv **books, int limit, int offset); +int db_books_load(struct kreq *r, BookAdv **books, const char *sort, int limit, int offset); int db_books_count(struct kreq *r); void db_book_free(Book *p); void db_book_adv_free(BookAdv *p); @@ -157,12 +157,12 @@ void db_assign_book_authors(struct bookauth *list); void db_author_unfill(Author *p); AuthorFull *db_author_load(struct kreq *r, int64_t id); -int db_authors_load(struct kreq *r, AuthorAdv **authors, int limit, int offset); +int db_authors_load(struct kreq *r, AuthorAdv **authors, const char *sort, int limit, int offset); void db_author_free(Author *p); void db_author_adv_free(AuthorAdv *p); void db_series_unfill(Series *p); -int db_series_load(struct kreq *r, SeriesAdv **series, int limit, int offset); +int db_series_load(struct kreq *r, SeriesAdv **series, const char *sort, int limit, int offset); SeriesFull *db_serie_load(struct kreq *r, int64_t id); void db_series_free(Series *p); void db_series_adv_free(SeriesAdv *p); diff --git a/main.c b/main.c index 38ea655..d8dbc45 100644 --- a/main.c +++ b/main.c @@ -44,6 +44,7 @@ enum page { enum key { KEY_PAGE, KEY_PERPAGE, + KEY_SORT, KEY__MAX }; @@ -57,6 +58,7 @@ static const char *const pages[PAGE__MAX] = { static const struct kvalid keys[KEY__MAX] = { { kvalid_int, "page" }, /* KEY_PAGE */ { kvalid_int, "perpage" }, /* KEY_PERPAGE */ + { kvalid_string, "sort" }, /* KEY_SORT */ }; /* @@ -195,6 +197,14 @@ putbookfull(struct kjsonreq *req, BookFull *b) kjson_putstringp(req, "publisher", b->publisher); } +static const char* +initsort(struct kreq *r) +{ + if (NULL != r->fieldmap[KEY_SORT]) + return r->fieldmap[KEY_SORT]->parsed.s; + return NULL; +} + static int initpage(struct kreq *r) { @@ -229,6 +239,7 @@ sendbooks(struct kreq *r) int page = initpage(r); int per = initperpage(r); + const char* sort = initsort(r); int64_t id = idfrompath(r); if (id >= 0) { @@ -248,7 +259,7 @@ sendbooks(struct kreq *r) } else { kjson_array_open(&req); BookAdv **books = kcalloc(per, sizeof(BookAdv)); - res = db_books_load(r, books, per, per * (page-1)); + res = db_books_load(r, books, sort, per, per * (page-1)); while (i < res) { putbookadv(&req, books[i]); i++; @@ -268,6 +279,7 @@ sendauthors(struct kreq *r) int page = initpage(r); int per = initperpage(r); + const char* sort = initsort(r); int64_t id = idfrompath(r); http_open(r, KHTTP_200); @@ -292,7 +304,7 @@ sendauthors(struct kreq *r) } else { kjson_array_open(&req); AuthorAdv **authors = kcalloc(per, sizeof(AuthorAdv)); - res = db_authors_load(r, authors, per, per * (page-1)); + res = db_authors_load(r, authors, sort, per, per * (page-1)); while (i < res) { kjson_obj_open(&req); kjson_putintp(&req, "id", authors[i]->a.id); @@ -318,6 +330,7 @@ sendseries(struct kreq *r) int page = initpage(r); int per = initperpage(r); + const char* sort = initsort(r); int64_t id = idfrompath(r); http_open(r, KHTTP_200); @@ -351,7 +364,7 @@ sendseries(struct kreq *r) } else { kjson_array_open(&req); SeriesAdv **series = kcalloc(per, sizeof(SeriesAdv)); - res = db_series_load(r, series, per, per * (page-1)); + res = db_series_load(r, series, sort, per, per * (page-1)); while (i < res) { kjson_obj_open(&req); kjson_putintp(&req, "id", series[i]->s.id);