Sort authors, books, series

This commit is contained in:
Meutel 2017-01-12 20:52:20 +01:00
parent a2855f394a
commit f1cd51b551
5 changed files with 117 additions and 41 deletions

View File

@ -29,7 +29,8 @@
#include "extern.h" #include "extern.h"
enum stmt { enum stmt {
STMT_AUTHORS, STMT_AUTHORS_ID,
STMT_AUTHORS_NAME,
STMT_AUTHOR_BOOKS, STMT_AUTHOR_BOOKS,
STMT_AUTHORS_AUTHORS, STMT_AUTHORS_AUTHORS,
STMT_AUTHOR, STMT_AUTHOR,
@ -37,10 +38,14 @@ enum stmt {
}; };
static const char *const stmts[STMT__MAX] = { 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 \ "SELECT authors.id, authors.name, count(book) as count FROM authors, books_authors_link \
WHERE authors.id = books_authors_link.author GROUP BY author \ WHERE authors.id = books_authors_link.author GROUP BY author \
ORDER BY authors.id LIMIT ? OFFSET ?", 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 */ /* STMT_AUTHOR_BOOKS */
"SELECT books.id AS id,title,series_index,name as series_name,series.id AS series_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 \ 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 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) { if (limit < 0 || offset < 0) {
return 0; return 0;
} }
struct ksqlstmt *stmt; 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, ksql_stmt_alloc(r->arg, &stmt,
stmts[STMT_AUTHORS], stmts[query],
STMT_AUTHORS); query);
ksql_bind_int(stmt, 0, limit); ksql_bind_int(stmt, 0, limit);
ksql_bind_int(stmt, 1, offset); ksql_bind_int(stmt, 1, offset);
while (KSQL_ROW == ksql_stmt_step(stmt)) { while (KSQL_ROW == ksql_stmt_step(stmt)) {

View File

@ -33,10 +33,13 @@ enum stmt {
STMT_BOOK_TAGS, STMT_BOOK_TAGS,
STMT_BOOK_AUTHORS, STMT_BOOK_AUTHORS,
STMT_BOOK_DATA, STMT_BOOK_DATA,
STMT_BOOKS, STMT_BOOKS_ID,
STMT_BOOKS_TITLE,
STMT_BOOKS_COUNT, STMT_BOOKS_COUNT,
STMT_BOOKS_TAGS, STMT_BOOKS_TAGS_ID,
STMT_BOOKS_AUTHORS, STMT_BOOKS_TAGS_TITLE,
STMT_BOOKS_AUTHORS_ID,
STMT_BOOKS_AUTHORS_TITLE,
STMT__MAX STMT__MAX
}; };
@ -62,20 +65,32 @@ static const char *const stmts[STMT__MAX] = {
/* STMT_BOOK_DATA */ /* STMT_BOOK_DATA */
"SELECT data.name, data.format, data.uncompressed_size \ "SELECT data.name, data.format, data.uncompressed_size \
FROM data WHERE data.book = ?", 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 \ "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 \ 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 ?", 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 */ /* STMT_BOOKS_COUNT */
"SELECT count(id) FROM books", "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 \ "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 \ WHERE tags.id = books_tags_link.tag AND books_tags_link.book \
IN ( SELECT id FROM books ORDER BY id LIMIT ? OFFSET ?)", 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 \ "SELECT authors.id, authors.name, books_authors_link.book as book \
FROM authors, books_authors_link WHERE books_authors_link.author = authors.id \ 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 ?)", 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 static void
@ -221,17 +236,23 @@ db_assign_book_authors(struct bookauth *list)
} }
static struct booktag * 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 ksqlstmt *stmt;
struct booktag *p = NULL; struct booktag *p = NULL;
struct booktag *item = NULL; struct booktag *item = NULL;
int i; int i, query;
int64_t bid; 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, ksql_stmt_alloc(r->arg, &stmt,
stmts[STMT_BOOKS_TAGS], stmts[query],
STMT_BOOKS_TAGS); query);
ksql_bind_int(stmt, 0, limit); ksql_bind_int(stmt, 0, limit);
ksql_bind_int(stmt, 1, offset); ksql_bind_int(stmt, 1, offset);
while (KSQL_ROW == ksql_stmt_step(stmt)) { while (KSQL_ROW == ksql_stmt_step(stmt)) {
@ -279,7 +300,7 @@ db_load_books_authors(BookAdv **books, int count, struct ksqlstmt *stmt)
} }
int 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) { if (limit < 0 || offset < 0) {
return 0; return 0;
@ -287,11 +308,21 @@ db_books_load(struct kreq *r, BookAdv **books, int limit, int offset)
struct ksqlstmt *stmt; struct ksqlstmt *stmt;
struct bookauth *p_a; struct bookauth *p_a;
struct booktag *p_t; 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, ksql_stmt_alloc(r->arg, &stmt,
stmts[STMT_BOOKS], stmts[query],
STMT_BOOKS); query);
ksql_bind_int(stmt, 0, limit); ksql_bind_int(stmt, 0, limit);
ksql_bind_int(stmt, 1, offset); ksql_bind_int(stmt, 1, offset);
while (KSQL_ROW == ksql_stmt_step(stmt)) { 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_free(stmt);
ksql_stmt_alloc(r->arg, &stmt, ksql_stmt_alloc(r->arg, &stmt,
stmts[STMT_BOOKS_AUTHORS], stmts[querya],
STMT_BOOKS_AUTHORS); querya);
ksql_bind_int(stmt, 0, limit); ksql_bind_int(stmt, 0, limit);
ksql_bind_int(stmt, 1, offset); ksql_bind_int(stmt, 1, offset);
p_a = db_load_books_authors(books, count, stmt); p_a = db_load_books_authors(books, count, stmt);
ksql_stmt_free(stmt); ksql_stmt_free(stmt);
db_assign_book_authors(p_a); 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); db_assign_book_tags(p_t);
return count; return count;

View File

@ -29,8 +29,10 @@
#include "extern.h" #include "extern.h"
enum stmt { enum stmt {
STMT_SERIES, STMT_SERIES_ID,
STMT_SERIES_AUTHORS, STMT_SERIES_NAME,
STMT_SERIES_AUTHORS_ID,
STMT_SERIES_AUTHORS_NAME,
STMT_SERIE, STMT_SERIE,
STMT_SERIE_BOOKS, STMT_SERIE_BOOKS,
STMT_SERIE_AUTHORS, STMT_SERIE_AUTHORS,
@ -38,15 +40,24 @@ enum stmt {
}; };
static const char *const stmts[STMT__MAX] = { static const char *const stmts[STMT__MAX] = {
/* STMT_SERIES */ /* STMT_SERIES_ID */
"SELECT series.id, series.name, count(book) FROM series \ "SELECT series.id, series.name, count(book) FROM series \
LEFT OUTER JOIN books_series_link ON books_series_link.series = series.id \ LEFT OUTER JOIN books_series_link ON books_series_link.series = series.id \
GROUP BY series.id ORDER BY series.id LIMIT ? OFFSET ?", 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 \ "SELECT DISTINCT authors.id, authors.name, books_series_link.series \
FROM authors, books_authors_link, books_series_link \ FROM authors, books_authors_link, books_series_link \
WHERE books_authors_link.book = books_series_link.book AND books_authors_link.author = authors.id \ 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 ?)", 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 */ /* STMT_SERIE */
"SELECT series.id, series.name FROM series WHERE series.id = ?", "SELECT series.id, series.name FROM series WHERE series.id = ?",
/* STMT_SERIE_BOOKS */ /* STMT_SERIE_BOOKS */
@ -244,18 +255,28 @@ db_serie_load(struct kreq *r, int64_t id)
} }
int 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; return 0;
}
struct ksqlstmt *stmt; struct ksqlstmt *stmt;
int count = 0; int query, queryauth, count = 0;
struct seriesauth *p = NULL; 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, ksql_stmt_alloc(r->arg, &stmt,
stmts[STMT_SERIES], stmts[query],
STMT_SERIES); query);
ksql_bind_int(stmt, 0, limit); ksql_bind_int(stmt, 0, limit);
ksql_bind_int(stmt, 1, offset); ksql_bind_int(stmt, 1, offset);
while (KSQL_ROW == ksql_stmt_step(stmt)) { 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_free(stmt);
ksql_stmt_alloc(r->arg, &stmt, ksql_stmt_alloc(r->arg, &stmt,
stmts[STMT_SERIES_AUTHORS], stmts[queryauth],
STMT_SERIES_AUTHORS); queryauth);
ksql_bind_int(stmt, 0, limit); ksql_bind_int(stmt, 0, limit);
ksql_bind_int(stmt, 1, offset); ksql_bind_int(stmt, 1, offset);
p = db_load_series_authors(series, count, stmt); p = db_load_series_authors(series, count, stmt);

View File

@ -146,7 +146,7 @@ struct bookdata {
__BEGIN_DECLS __BEGIN_DECLS
BookFull *db_book_load(struct kreq *r, int64_t id); 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); int db_books_count(struct kreq *r);
void db_book_free(Book *p); void db_book_free(Book *p);
void db_book_adv_free(BookAdv *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); void db_author_unfill(Author *p);
AuthorFull *db_author_load(struct kreq *r, int64_t id); 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_free(Author *p);
void db_author_adv_free(AuthorAdv *p); void db_author_adv_free(AuthorAdv *p);
void db_series_unfill(Series *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); SeriesFull *db_serie_load(struct kreq *r, int64_t id);
void db_series_free(Series *p); void db_series_free(Series *p);
void db_series_adv_free(SeriesAdv *p); void db_series_adv_free(SeriesAdv *p);

19
main.c
View File

@ -44,6 +44,7 @@ enum page {
enum key { enum key {
KEY_PAGE, KEY_PAGE,
KEY_PERPAGE, KEY_PERPAGE,
KEY_SORT,
KEY__MAX KEY__MAX
}; };
@ -57,6 +58,7 @@ static const char *const pages[PAGE__MAX] = {
static const struct kvalid keys[KEY__MAX] = { static const struct kvalid keys[KEY__MAX] = {
{ kvalid_int, "page" }, /* KEY_PAGE */ { kvalid_int, "page" }, /* KEY_PAGE */
{ kvalid_int, "perpage" }, /* KEY_PERPAGE */ { 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); 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 static int
initpage(struct kreq *r) initpage(struct kreq *r)
{ {
@ -229,6 +239,7 @@ sendbooks(struct kreq *r)
int page = initpage(r); int page = initpage(r);
int per = initperpage(r); int per = initperpage(r);
const char* sort = initsort(r);
int64_t id = idfrompath(r); int64_t id = idfrompath(r);
if (id >= 0) { if (id >= 0) {
@ -248,7 +259,7 @@ sendbooks(struct kreq *r)
} else { } else {
kjson_array_open(&req); kjson_array_open(&req);
BookAdv **books = kcalloc(per, sizeof(BookAdv)); 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) { while (i < res) {
putbookadv(&req, books[i]); putbookadv(&req, books[i]);
i++; i++;
@ -268,6 +279,7 @@ sendauthors(struct kreq *r)
int page = initpage(r); int page = initpage(r);
int per = initperpage(r); int per = initperpage(r);
const char* sort = initsort(r);
int64_t id = idfrompath(r); int64_t id = idfrompath(r);
http_open(r, KHTTP_200); http_open(r, KHTTP_200);
@ -292,7 +304,7 @@ sendauthors(struct kreq *r)
} else { } else {
kjson_array_open(&req); kjson_array_open(&req);
AuthorAdv **authors = kcalloc(per, sizeof(AuthorAdv)); 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) { while (i < res) {
kjson_obj_open(&req); kjson_obj_open(&req);
kjson_putintp(&req, "id", authors[i]->a.id); kjson_putintp(&req, "id", authors[i]->a.id);
@ -318,6 +330,7 @@ sendseries(struct kreq *r)
int page = initpage(r); int page = initpage(r);
int per = initperpage(r); int per = initperpage(r);
const char* sort = initsort(r);
int64_t id = idfrompath(r); int64_t id = idfrompath(r);
http_open(r, KHTTP_200); http_open(r, KHTTP_200);
@ -351,7 +364,7 @@ sendseries(struct kreq *r)
} else { } else {
kjson_array_open(&req); kjson_array_open(&req);
SeriesAdv **series = kcalloc(per, sizeof(SeriesAdv)); 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) { while (i < res) {
kjson_obj_open(&req); kjson_obj_open(&req);
kjson_putintp(&req, "id", series[i]->s.id); kjson_putintp(&req, "id", series[i]->s.id);