From 91df265d40ac56bef1d5d388dfeb6a622168582a Mon Sep 17 00:00:00 2001 From: Ozzie Isaacs Date: Wed, 8 Jun 2022 17:17:07 +0200 Subject: [PATCH] Fix for #2437 (advanced search for read status crashes calibre-web) --- cps/db.py | 8 +++--- cps/helper.py | 4 +-- cps/render_template.py | 13 ---------- cps/search.py | 59 ++++++++++++------------------------------ cps/web.py | 4 +-- 5 files changed, 25 insertions(+), 63 deletions(-) diff --git a/cps/db.py b/cps/db.py index 0b98f683..d1c5ec71 100644 --- a/cps/db.py +++ b/cps/db.py @@ -627,7 +627,7 @@ class CalibreDB: .join(read_column, read_column.book == book_id, isouter=True)) except (KeyError, AttributeError, IndexError): - log.error("Custom Column No.{} is not existing in calibre database".format(read_column)) + log.error("Custom Column No.{} does not exist in calibre database".format(read_column)) # Skip linking read column and return None instead of read status bd = self.session.query(Books, None, ub.ArchivedBook.is_archived) return (bd.filter(Books.id == book_id) @@ -674,9 +674,9 @@ class CalibreDB: except (KeyError, AttributeError, IndexError): pos_content_cc_filter = false() neg_content_cc_filter = true() - log.error("Custom Column No.{} is not existing in calibre database".format( + log.error("Custom Column No.{} does not exist in calibre database".format( self.config.config_restricted_column)) - flash(_("Custom Column No.%(column)d is not existing in calibre database", + flash(_("Custom Column No.%(column)d does not exist in calibre database", column=self.config.config_restricted_column), category="error") @@ -699,7 +699,7 @@ class CalibreDB: .select_from(Books) .outerjoin(read_column, read_column.book == Books.id)) except (KeyError, AttributeError, IndexError): - log.error("Custom Column No.{} is not existing in calibre database".format(config_read_column)) + log.error("Custom Column No.{} does not exist in calibre database".format(config_read_column)) # Skip linking read column and return None instead of read status query = self.session.query(database, None, ub.ArchivedBook.is_archived) return query.outerjoin(ub.ArchivedBook, and_(Books.id == ub.ArchivedBook.book_id, diff --git a/cps/helper.py b/cps/helper.py index 6db991b0..f936ed39 100755 --- a/cps/helper.py +++ b/cps/helper.py @@ -336,8 +336,8 @@ def edit_book_read_status(book_id, read_status=None): calibre_db.session.commit() except (KeyError, AttributeError, IndexError): log.error( - "Custom Column No.{} is not existing in calibre database".format(config.config_read_column)) - return "Custom Column No.{} is not existing in calibre database".format(config.config_read_column) + "Custom Column No.{} does not exist in calibre database".format(config.config_read_column)) + return "Custom Column No.{} does not exist in calibre database".format(config.config_read_column) except (OperationalError, InvalidRequestError) as ex: calibre_db.session.rollback() log.error(u"Read status could not set: {}".format(ex)) diff --git a/cps/render_template.py b/cps/render_template.py index 0750a9c4..04a50bbb 100644 --- a/cps/render_template.py +++ b/cps/render_template.py @@ -101,19 +101,6 @@ def get_sidebar_config(kwargs=None): "show_text": _('Show Books List'), "config_show": content}) return sidebar, simple -'''def get_readbooks_ids(): - if not config.config_read_column: - readBooks = ub.session.query(ub.ReadBook).filter(ub.ReadBook.user_id == int(current_user.id))\ - .filter(ub.ReadBook.read_status == ub.ReadBook.STATUS_FINISHED).all() - return frozenset([x.book_id for x in readBooks]) - else: - try: - readBooks = calibre_db.session.query(db.cc_classes[config.config_read_column])\ - .filter(db.cc_classes[config.config_read_column].value == True).all() - return frozenset([x.book for x in readBooks]) - except (KeyError, AttributeError, IndexError): - log.error("Custom Column No.{} is not existing in calibre database".format(config.config_read_column)) - return []''' # Returns the template for rendering and includes the instance name def render_title_template(*args, **kwargs): diff --git a/cps/search.py b/cps/search.py index 602881bf..88d790fc 100644 --- a/cps/search.py +++ b/cps/search.py @@ -22,7 +22,7 @@ from flask import session as flask_session from flask_login import current_user from flask_babel import format_date from flask_babel import gettext as _ -from sqlalchemy.sql.expression import func, not_, and_, or_, text +from sqlalchemy.sql.expression import func, not_, and_, or_, text, true from sqlalchemy.sql.functions import coalesce from . import logger, db, calibre_db, config, ub @@ -119,32 +119,23 @@ def adv_search_ratings(q, rating_high, rating_low): return q -def adv_search_read_status(q, read_status): - if read_status: - if config.config_read_column: - try: - if read_status == "True": - q = q.join(db.cc_classes[config.config_read_column], isouter=True) \ - .filter(db.cc_classes[config.config_read_column].value == True) - else: - q = q.join(db.cc_classes[config.config_read_column], isouter=True) \ - .filter(coalesce(db.cc_classes[config.config_read_column].value, False) != True) - except (KeyError, AttributeError): - log.error(u"Custom Column No.%d is not existing in calibre database", config.config_read_column) - flash(_("Custom Column No.%(column)d is not existing in calibre database", - column=config.config_read_column), - category="error") - return q +def adv_search_read_status(read_status): + if not config.config_read_column: + if read_status == "True": + db_filter = and_(ub.ReadBook.user_id == int(current_user.id), + ub.ReadBook.read_status == ub.ReadBook.STATUS_FINISHED) else: + db_filter = coalesce(ub.ReadBook.read_status, 0) != ub.ReadBook.STATUS_FINISHED + else: + try: if read_status == "True": - q = q.join(ub.ReadBook, db.Books.id == ub.ReadBook.book_id, isouter=True) \ - .filter(ub.ReadBook.user_id == int(current_user.id), - ub.ReadBook.read_status == ub.ReadBook.STATUS_FINISHED) + db_filter = db.cc_classes[config.config_read_column].value == True else: - q = q.join(ub.ReadBook, db.Books.id == ub.ReadBook.book_id, isouter=True) \ - .filter(ub.ReadBook.user_id == int(current_user.id), - coalesce(ub.ReadBook.read_status, 0) != ub.ReadBook.STATUS_FINISHED) - return q + db_filter = coalesce(db.cc_classes[config.config_read_column].value, False) != True + except (KeyError, AttributeError, IndexError): + log.error("Custom Column No.{} does not exist in calibre database".format(config.config_read_column)) + return true() + return db_filter def adv_search_extension(q, include_extension_inputs, exclude_extension_inputs): @@ -238,23 +229,7 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): cc = calibre_db.get_cc_columns(config, filter_config_custom_read=True) calibre_db.session.connection().connection.connection.create_function("lower", 1, db.lcase) - if not config.config_read_column: - query = (calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, ub.ReadBook).select_from(db.Books) - .outerjoin(ub.ReadBook, and_(db.Books.id == ub.ReadBook.book_id, - int(current_user.id) == ub.ReadBook.user_id))) - else: - try: - read_column = cc[config.config_read_column] - query = (calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, read_column.value) - .select_from(db.Books) - .outerjoin(read_column, read_column.book == db.Books.id)) - except (KeyError, AttributeError): - log.error("Custom Column No.%d is not existing in calibre database", config.config_read_column) - # Skip linking read column - query = calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, None) - query = query.outerjoin(ub.ArchivedBook, and_(db.Books.id == ub.ArchivedBook.book_id, - int(current_user.id) == ub.ArchivedBook.user_id)) - + query = calibre_db.generate_linked_query(config.config_read_column, db.Books) q = query.outerjoin(db.books_series_link, db.Books.id == db.books_series_link.c.book)\ .outerjoin(db.Series)\ .filter(calibre_db.common_filters(True)) @@ -324,7 +299,7 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): q = q.filter(func.datetime(db.Books.pubdate) > func.datetime(pub_start)) if pub_end: q = q.filter(func.datetime(db.Books.pubdate) < func.datetime(pub_end)) - q = adv_search_read_status(q, read_status) + q = q.filter(adv_search_read_status(read_status)) if publisher: q = q.filter(db.Books.publishers.any(func.lower(db.Publishers.name).ilike("%" + publisher + "%"))) q = adv_search_tag(q, tags['include_tag'], tags['exclude_tag']) diff --git a/cps/web.py b/cps/web.py index 4a2a796b..dcccbc32 100755 --- a/cps/web.py +++ b/cps/web.py @@ -715,9 +715,9 @@ def render_read_books(page, are_read, as_xml=False, order=None): else: db_filter = coalesce(db.cc_classes[config.config_read_column].value, False) != True except (KeyError, AttributeError, IndexError): - log.error("Custom Column No.{} is not existing in calibre database".format(config.config_read_column)) + log.error("Custom Column No.{} does not exist in calibre database".format(config.config_read_column)) if not as_xml: - flash(_("Custom Column No.%(column)d is not existing in calibre database", + flash(_("Custom Column No.%(column)d does not exist in calibre database", column=config.config_read_column), category="error") return redirect(url_for("web.index"))