From d23aa7f0ecd05055fdaebe27cd601d87e450d8fa Mon Sep 17 00:00:00 2001 From: Meutel Date: Fri, 13 Jan 2017 20:40:51 +0100 Subject: [PATCH] Sort and order books, authors, series --- db.c | 2 + db_author.c | 49 +++++++++++------- db_book.c | 144 ++++++++++++++++++++++++++++++++-------------------- db_series.c | 93 ++++++++++++++++++++------------- extern.h | 8 +-- main.c | 19 +++++-- 6 files changed, 203 insertions(+), 112 deletions(-) diff --git a/db.c b/db.c index 470b5f9..ffff4c9 100644 --- a/db.c +++ b/db.c @@ -28,6 +28,8 @@ #include "extern.h" +#define STMT_PAGE " LIMIT ? OFFSET ?" + char * strornull(struct ksqlstmt *stmt, int col) { diff --git a/db_author.c b/db_author.c index fab5b2c..c8eaf24 100644 --- a/db_author.c +++ b/db_author.c @@ -28,9 +28,15 @@ #include "extern.h" +#define STMT_PAGE " LIMIT ? OFFSET ?" +#define STMT_AUTHORS0 "SELECT authors.id, authors.name, count(book) as count FROM authors, books_authors_link "\ + "WHERE authors.id = books_authors_link.author GROUP BY author " + enum stmt { - STMT_AUTHORS_ID, - STMT_AUTHORS_NAME, + STMT_AUTHORS_ID_ASC, + STMT_AUTHORS_ID_DESC, + STMT_AUTHORS_NAME_ASC, + STMT_AUTHORS_NAME_DESC, STMT_AUTHOR_BOOKS, STMT_AUTHORS_AUTHORS, STMT_AUTHOR, @@ -38,14 +44,14 @@ enum stmt { }; static const char *const stmts[STMT__MAX] = { - /* 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_AUTHORS_ID_ASC */ + STMT_AUTHORS0 "ORDER BY authors.id " STMT_PAGE, + /* STMT_AUTHORS_ID_DESC */ + STMT_AUTHORS0 "ORDER BY authors.id DESC " STMT_PAGE, + /* STMT_AUTHORS_NAME_ASC */ + STMT_AUTHORS0 "ORDER BY authors.sort " STMT_PAGE, + /* STMT_AUTHORS_NAME_DESC */ + STMT_AUTHORS0 "ORDER BY authors.sort DESC " STMT_PAGE, /* 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 \ @@ -81,6 +87,18 @@ db_author_free(Author *p) { db_author_unfill(p); free(p); } + +static int +query_authors(const char* sort, const char *order) +{ + int query = STMT_AUTHORS_ID_ASC; + if (NULL != sort && 0 == strcmp(sort, "name")) + query = STMT_AUTHORS_NAME_ASC; + if (NULL != order && 0 == strcmp(order, "desc")) + query++; + return query; +} + AuthorFull * db_author_load(struct kreq *r, int64_t id) { @@ -150,20 +168,15 @@ db_author_load(struct kreq *r, int64_t id) } int -db_authors_load(struct kreq *r, AuthorAdv **authors, const char *sort, int limit, int offset) +db_authors_load(struct kreq *r, AuthorAdv **authors, const char *sort, const char *order, int limit, int offset) { if (limit < 0 || offset < 0) { return 0; } struct ksqlstmt *stmt; - int query, count = 0; + int count = 0; - if (sort == NULL) - query = STMT_AUTHORS_ID; - else if (0 == strcmp(sort, "name")) - query = STMT_AUTHORS_NAME; - else - query = STMT_AUTHORS_ID; + int query = query_authors(sort, order); ksql_stmt_alloc(r->arg, &stmt, stmts[query], query); diff --git a/db_book.c b/db_book.c index 71b8a84..a7c2c2f 100644 --- a/db_book.c +++ b/db_book.c @@ -28,22 +28,40 @@ #include "extern.h" +#define STMT_PAGE " LIMIT ? OFFSET ?" +#define STMT_BOOKS0 "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 " +#define STMT_BOOKS_TAGS0 "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 " +#define STMT_BOOKS_AUTHORS0 "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 " + enum stmt { + STMT_BOOKS_COUNT, STMT_BOOK, STMT_BOOK_TAGS, STMT_BOOK_AUTHORS, STMT_BOOK_DATA, - STMT_BOOKS_ID, - STMT_BOOKS_TITLE, - STMT_BOOKS_COUNT, - STMT_BOOKS_TAGS_ID, - STMT_BOOKS_TAGS_TITLE, - STMT_BOOKS_AUTHORS_ID, - STMT_BOOKS_AUTHORS_TITLE, + STMT_BOOKS_ID_ASC, + STMT_BOOKS_ID_DESC, + STMT_BOOKS_TITLE_ASC, + STMT_BOOKS_TITLE_DESC, + STMT_BOOKS_TAGS_ID_ASC, + STMT_BOOKS_TAGS_ID_DESC, + STMT_BOOKS_TAGS_TITLE_ASC, + STMT_BOOKS_TAGS_TITLE_DESC, + STMT_BOOKS_AUTHORS_ID_ASC, + STMT_BOOKS_AUTHORS_ID_DESC, + STMT_BOOKS_AUTHORS_TITLE_ASC, + STMT_BOOKS_AUTHORS_TITLE_DESC, STMT__MAX }; static const char *const stmts[STMT__MAX] = { + /* STMT_BOOKS_COUNT */ + "SELECT count(id) FROM books", /* STMT_BOOK */ "SELECT books.id AS id,title, series_index, series.name AS series_name, series.id AS series_id, \ strftime('%s', timestamp), strftime('%Y', pubdate), isbn,lccn,path,uuid,has_cover, \ @@ -65,32 +83,30 @@ 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_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_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_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 ?)", + /* STMT_BOOKS_ID_ASC */ + STMT_BOOKS0 " ORDER BY id" STMT_PAGE, + /* STMT_BOOKS_ID_DESC */ + STMT_BOOKS0 "ORDER BY id DESC" STMT_PAGE, + /* STMT_BOOKS_TITLE_ASC */ + STMT_BOOKS0 "ORDER BY books.sort" STMT_PAGE, + /* STMT_BOOKS_TITLE_DESC */ + STMT_BOOKS0 "ORDER BY books.sort DESC" STMT_PAGE, + /* STMT_BOOKS_TAGS_ID_ASC */ + STMT_BOOKS_TAGS0 "ORDER BY id" STMT_PAGE ")", + /* STMT_BOOKS_TAGS_ID_DESC */ + STMT_BOOKS_TAGS0 "ORDER BY id DESC" STMT_PAGE ")", + /* STMT_BOOKS_TAGS_TITLE_ASC */ + STMT_BOOKS_TAGS0 "ORDER BY books.sort" STMT_PAGE ")", + /* STMT_BOOKS_TAGS_TITLE_DESC */ + STMT_BOOKS_TAGS0 "ORDER BY books.sort DESC" STMT_PAGE ")", + /* STMT_BOOKS_AUTHORS_ID_ASC */ + STMT_BOOKS_AUTHORS0 "ORDER BY id" STMT_PAGE ")", + /* STMT_BOOKS_AUTHORS_ID_DESC */ + STMT_BOOKS_AUTHORS0 "ORDER BY id DESC" STMT_PAGE ")", + /* STMT_BOOKS_AUTHORS_TITLE_ASC */ + STMT_BOOKS_AUTHORS0 "ORDER BY books.sort" STMT_PAGE ")", + /* STMT_BOOKS_AUTHORS_TITLE_DESC */ + STMT_BOOKS_AUTHORS0 "ORDER BY books.sort DESC" STMT_PAGE ")", }; static void @@ -235,21 +251,49 @@ db_assign_book_authors(struct bookauth *list) } } +static int +query_books(const char* sort, const char *order) +{ + int query = STMT_BOOKS_ID_ASC; + if (NULL != sort && 0 == strcmp(sort, "title")) + query = STMT_BOOKS_TITLE_ASC; + if (NULL != order && 0 == strcmp(order, "desc")) + query++; + return query; +} + +static int +query_books_authors(const char* sort, const char *order) +{ + int query = STMT_BOOKS_AUTHORS_ID_ASC; + if (NULL != sort && 0 == strcmp(sort, "title")) + query = STMT_BOOKS_AUTHORS_TITLE_ASC; + if (NULL != order && 0 == strcmp(order, "desc")) + query++; + return query; +} + +static int +query_books_tags(const char* sort, const char *order) +{ + int query = STMT_BOOKS_TAGS_ID_ASC; + if (NULL != sort && 0 == strcmp(sort, "title")) + query = STMT_BOOKS_TAGS_TITLE_ASC; + if (NULL != order && 0 == strcmp(order, "desc")) + query++; + return query; +} + static struct booktag * -db_load_books_tags(struct kreq *r, BookAdv **books, int count, const char *sort, int limit, int offset) +db_load_books_tags(struct kreq *r, BookAdv **books, int count, const char *sort, const char *order, int limit, int offset) { struct ksqlstmt *stmt; struct booktag *p = NULL; struct booktag *item = NULL; - int i, query; + int i; 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; + int query = query_books_tags(sort, order); ksql_stmt_alloc(r->arg, &stmt, stmts[query], query); @@ -300,7 +344,7 @@ db_load_books_authors(BookAdv **books, int count, struct ksqlstmt *stmt) } int -db_books_load(struct kreq *r, BookAdv **books, const char *sort, int limit, int offset) +db_books_load(struct kreq *r, BookAdv **books, const char *sort, const char *order, int limit, int offset) { if (limit < 0 || offset < 0) { return 0; @@ -308,18 +352,9 @@ db_books_load(struct kreq *r, BookAdv **books, const char *sort, int limit, int struct ksqlstmt *stmt; struct bookauth *p_a; struct booktag *p_t; - int query, querya, count = 0; + int 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; - } + int query = query_books(sort, order); ksql_stmt_alloc(r->arg, &stmt, stmts[query], query); @@ -334,6 +369,7 @@ db_books_load(struct kreq *r, BookAdv **books, const char *sort, int limit, int } ksql_stmt_free(stmt); + int querya = query_books_authors(sort, order); ksql_stmt_alloc(r->arg, &stmt, stmts[querya], querya); @@ -343,7 +379,7 @@ db_books_load(struct kreq *r, BookAdv **books, const char *sort, int limit, int ksql_stmt_free(stmt); db_assign_book_authors(p_a); - p_t = db_load_books_tags(r, books, count, sort, limit, offset); + p_t = db_load_books_tags(r, books, count, sort, order, limit, offset); db_assign_book_tags(p_t); return count; diff --git a/db_series.c b/db_series.c index db62f5a..f5853f7 100644 --- a/db_series.c +++ b/db_series.c @@ -28,11 +28,24 @@ #include "extern.h" +#define STMT_PAGE " LIMIT ? OFFSET ?" +#define STMT_SERIES0 "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 " +#define STMT_SERIES_AUTHORS0 "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 " + enum stmt { - STMT_SERIES_ID, - STMT_SERIES_NAME, - STMT_SERIES_AUTHORS_ID, - STMT_SERIES_AUTHORS_NAME, + STMT_SERIES_ID_ASC, + STMT_SERIES_ID_DESC, + STMT_SERIES_NAME_ASC, + STMT_SERIES_NAME_DESC, + STMT_SERIES_AUTHORS_ID_ASC, + STMT_SERIES_AUTHORS_ID_DESC, + STMT_SERIES_AUTHORS_NAME_ASC, + STMT_SERIES_AUTHORS_NAME_DESC, STMT_SERIE, STMT_SERIE_BOOKS, STMT_SERIE_AUTHORS, @@ -40,24 +53,22 @@ enum stmt { }; static const char *const stmts[STMT__MAX] = { - /* 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_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_SERIES_ID_ASC */ + STMT_SERIES0 " ORDER BY series.id" STMT_PAGE, + /* STMT_SERIES_ID_DESC */ + STMT_SERIES0 " ORDER BY series.id DESC" STMT_PAGE, + /* STMT_SERIES_NAME_ASC */ + STMT_SERIES0 " ORDER BY series.sort" STMT_PAGE, + /* STMT_SERIES_NAME_DESC */ + STMT_SERIES0 " ORDER BY series.sort DESC" STMT_PAGE, + /* STMT_SERIES_AUTHORS_ID_ASC */ + STMT_SERIES_AUTHORS0 " ORDER BY series.id" STMT_PAGE ")", + /* STMT_SERIES_AUTHORS_ID_DESC */ + STMT_SERIES_AUTHORS0 " ORDER BY series.id DESC" STMT_PAGE ")", + /* STMT_SERIES_AUTHORS_NAME_ASC */ + STMT_SERIES_AUTHORS0 " ORDER BY series.sort" STMT_PAGE ")", + /* STMT_SERIES_AUTHORS_NAME_DESC */ + STMT_SERIES_AUTHORS0 " ORDER BY series.sort DESC" STMT_PAGE ")", /* STMT_SERIE */ "SELECT series.id, series.name FROM series WHERE series.id = ?", /* STMT_SERIE_BOOKS */ @@ -109,6 +120,28 @@ db_series_adv_free(SeriesAdv *p) free(p); } +static int +query_series(const char* sort, const char *order) +{ + int query = STMT_SERIES_ID_ASC; + if (NULL != sort && 0 == strcmp(sort, "name")) + query = STMT_SERIES_NAME_ASC; + if (NULL != order && 0 == strcmp(order, "desc")) + query++; + return query; +} + +static int +query_seriesauth(const char* sort, const char *order) +{ + int query = STMT_SERIES_AUTHORS_ID_ASC; + if (NULL != sort && 0 == strcmp(sort, "name")) + query = STMT_SERIES_AUTHORS_NAME_ASC; + if (NULL != order && 0 == strcmp(order, "desc")) + query++; + return query; +} + static void db_assign_series_authors(struct seriesauth *list) { @@ -255,24 +288,15 @@ db_serie_load(struct kreq *r, int64_t id) } int -db_series_load(struct kreq *r, SeriesAdv **series, const char *sort, int limit, int offset) +db_series_load(struct kreq *r, SeriesAdv **series, const char *sort, const char *order, int limit, int offset) { if (limit < 0 || offset < 0) return 0; struct ksqlstmt *stmt; - int query, queryauth, count = 0; + int 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; - } + int query = query_series(sort, order); ksql_stmt_alloc(r->arg, &stmt, stmts[query], @@ -289,6 +313,7 @@ db_series_load(struct kreq *r, SeriesAdv **series, const char *sort, int limit, } ksql_stmt_free(stmt); + int queryauth = query_seriesauth(sort, order); ksql_stmt_alloc(r->arg, &stmt, stmts[queryauth], queryauth); diff --git a/extern.h b/extern.h index 72bf59c..584fbc9 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, const char *sort, int limit, int offset); +int db_books_load(struct kreq *r, BookAdv **books, const char *sort, const char *order, 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,14 @@ 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, const char *sort, int limit, int offset); +int db_authors_load(struct kreq *r, AuthorAdv **authors, const char *sort, const char *order, + 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, const char *sort, int limit, int offset); +int db_series_load(struct kreq *r, SeriesAdv **series, const char *sort, const char *order, + 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 d8dbc45..45c5c40 100644 --- a/main.c +++ b/main.c @@ -45,6 +45,7 @@ enum key { KEY_PAGE, KEY_PERPAGE, KEY_SORT, + KEY_ORDER, KEY__MAX }; @@ -59,6 +60,7 @@ static const struct kvalid keys[KEY__MAX] = { { kvalid_int, "page" }, /* KEY_PAGE */ { kvalid_int, "perpage" }, /* KEY_PERPAGE */ { kvalid_string, "sort" }, /* KEY_SORT */ + { kvalid_string, "order" }, /* KEY_ORDER */ }; /* @@ -205,6 +207,14 @@ initsort(struct kreq *r) return NULL; } +static const char* +initorder(struct kreq *r) +{ + if (NULL != r->fieldmap[KEY_ORDER]) + return r->fieldmap[KEY_ORDER]->parsed.s; + return NULL; +} + static int initpage(struct kreq *r) { @@ -240,6 +250,7 @@ sendbooks(struct kreq *r) int page = initpage(r); int per = initperpage(r); const char* sort = initsort(r); + const char* order = initorder(r); int64_t id = idfrompath(r); if (id >= 0) { @@ -259,7 +270,7 @@ sendbooks(struct kreq *r) } else { kjson_array_open(&req); BookAdv **books = kcalloc(per, sizeof(BookAdv)); - res = db_books_load(r, books, sort, per, per * (page-1)); + res = db_books_load(r, books, sort, order, per, per * (page-1)); while (i < res) { putbookadv(&req, books[i]); i++; @@ -280,6 +291,7 @@ sendauthors(struct kreq *r) int page = initpage(r); int per = initperpage(r); const char* sort = initsort(r); + const char* order = initorder(r); int64_t id = idfrompath(r); http_open(r, KHTTP_200); @@ -304,7 +316,7 @@ sendauthors(struct kreq *r) } else { kjson_array_open(&req); AuthorAdv **authors = kcalloc(per, sizeof(AuthorAdv)); - res = db_authors_load(r, authors, sort, per, per * (page-1)); + res = db_authors_load(r, authors, sort, order, per, per * (page-1)); while (i < res) { kjson_obj_open(&req); kjson_putintp(&req, "id", authors[i]->a.id); @@ -331,6 +343,7 @@ sendseries(struct kreq *r) int page = initpage(r); int per = initperpage(r); const char* sort = initsort(r); + const char* order = initorder(r); int64_t id = idfrompath(r); http_open(r, KHTTP_200); @@ -364,7 +377,7 @@ sendseries(struct kreq *r) } else { kjson_array_open(&req); SeriesAdv **series = kcalloc(per, sizeof(SeriesAdv)); - res = db_series_load(r, series, sort, per, per * (page-1)); + res = db_series_load(r, series, sort, order, per, per * (page-1)); while (i < res) { kjson_obj_open(&req); kjson_putintp(&req, "id", series[i]->s.id);