# Buggy code
def modify_database_object(
    input_elements, db_book_object, db_object, db_session, db_type
):
    # passing input_elements not as a list may lead to undesired results
    if not isinstance(input_elements, list):
        raise TypeError(str(input_elements) + " should be passed as a list")

    input_elements = [x for x in input_elements if x != ""]
    # we have all input element (authors, series, tags) names now
    # 1. search for elements to remove
    del_elements = []
    for c_elements in db_book_object:
        found = False
        if db_type == "languages":
            type_elements = c_elements.lang_code
        elif db_type == "custom":
            type_elements = c_elements.value
        else:
            type_elements = c_elements.name
        for inp_element in input_elements:
            if inp_element.lower() == type_elements.lower():
                found = True
                break
        # if the element was not found in the new list, add it to remove list
        if not found:
            del_elements.append(c_elements)
    # 2. search for elements that need to be added
    add_elements = []
    for inp_element in input_elements:
        found = False
        for c_elements in db_book_object:
            if db_type == "languages":
                type_elements = c_elements.lang_code
            elif db_type == "custom":
                type_elements = c_elements.value
            else:
                type_elements = c_elements.name
            if inp_element == type_elements:
                found = True
                break
        if not found:
            add_elements.append(inp_element)
    # if there are elements to remove, we remove them now
    if len(del_elements) > 0:
        for del_element in del_elements:
            db_book_object.remove(del_element)
            if len(del_element.books) == 0:
                db_session.delete(del_element)
    # if there are elements to add, we add them now!
    if len(add_elements) > 0:
        if db_type == "languages":
            db_filter = db_object.lang_code
        elif db_type == "custom":
            db_filter = db_object.value
        else:
            db_filter = db_object.name
        for add_element in add_elements:
            # check if a element with that name exists
            db_element = (
                db_session.query(db_object).filter(db_filter == add_element).first()
            )
            # if no element is found add it
            # if new_element is None:
            if db_type == "author":
                new_element = db_object(
                    add_element,
                    helper.get_sorted_author(add_element.replace("|", ",")),
                    "",
                )
            elif db_type == "series":
                new_element = db_object(add_element, add_element)
            elif db_type == "custom":
                new_element = db_object(value=add_element)
            elif db_type == "publisher":
                new_element = db_object(add_element, None)
            else:  # db_type should be tag or language
                new_element = db_object(add_element)
            if db_element is None:
                db_session.add(new_element)
                db_book_object.append(new_element)
            else:
                if db_type == "custom" and db_element.value != add_element:
                    new_element.value = add_element
                    # new_element = db_element
                elif db_type == "language" and db_element.lang_code != add_element:
                    db_element.lang_code = add_element
                    # new_element = db_element
                elif db_type == "series" and db_element.name != add_element:
                    db_element.name = add_element  # = add_element # new_element = db_object(add_element, add_element)
                    db_element.sort = add_element
                    # new_element = db_element
                elif db_type == "author" and db_element.name != add_element:
                    db_element.name = add_element
                    db_element.sort = add_element.replace("|", ",")
                    # new_element = db_element
                if db_type == "publisher" and db_element.name != add_element:
                    db_element.name = add_element
                    db_element.sort = None
                    # new_element = db_element
                elif db_element.name != add_element:
                    db_element.name = add_element
                    # new_element = db_element
                # add element to book
                db_book_object.append(db_element)


# Traceback (OperationalError)
ERROR:cps.web:Exception on /book/125 [GET]
Traceback (most recent call last):
File "/Users/jgillman/Code/calibre-web/vendor/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/Users/jgillman/Code/calibre-web/vendor/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/jgillman/Code/calibre-web/vendor/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/jgillman/Code/calibre-web/vendor/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/jgillman/Code/calibre-web/vendor/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/jgillman/Code/calibre-web/vendor/flask_login.py", line 717, in decorated_view
return func(*args, **kwargs)
File "/Users/jgillman/Code/calibre-web/cps/web.py", line 381, in show_book
return render_template('detail.html', entry=entries,  cc=cc, title=entries.title, books_shelfs=book_in_shelfs)
File "/Users/jgillman/Code/calibre-web/vendor/flask/templating.py", line 128, in render_template
context, ctx.app)
File "/Users/jgillman/Code/calibre-web/vendor/flask/templating.py", line 110, in _render
rv = template.render(context)
File "/Users/jgillman/Code/calibre-web/vendor/jinja2/environment.py", line 969, in render
return self.environment.handle_exception(exc_info, True)
File "/Users/jgillman/Code/calibre-web/vendor/jinja2/environment.py", line 742, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/jgillman/Code/calibre-web/cps/templates/detail.html", line 1, in top-level template code
{% extends "layout.html" %}
File "/Users/jgillman/Code/calibre-web/cps/templates/layout.html", line 136, in top-level template code
{% block body %}{% endblock %}
File "/Users/jgillman/Code/calibre-web/cps/templates/detail.html", line 66, in block "body"
{% if entry['custom_column_' ~ c.id]|length > 0 %}
File "/Users/jgillman/Code/calibre-web/vendor/jinja2/environment.py", line 387, in getitem
return getattr(obj, attr)
File "/Users/jgillman/Code/calibre-web/vendor/sqlalchemy/orm/attributes.py", line 316, in __get__
return self.impl.get(instance_state(instance), dict_)
File "/Users/jgillman/Code/calibre-web/vendor/sqlalchemy/orm/attributes.py", line 613, in get
value = self.callable_(state, passive)
File "/Users/jgillman/Code/calibre-web/vendor/sqlalchemy/orm/strategies.py", line 524, in _load_for_state
return self._emit_lazyload(session, state, ident_key, passive)
File "/Users/jgillman/Code/calibre-web/vendor/sqlalchemy/orm/strategies.py", line 585, in _emit_lazyload
result = q.all()
File "/Users/jgillman/Code/calibre-web/vendor/sqlalchemy/orm/query.py", line 2241, in all
return list(self)
File "/Users/jgillman/Code/calibre-web/vendor/sqlalchemy/orm/query.py", line 2353, in __iter__
return self._execute_and_instances(context)
File "/Users/jgillman/Code/calibre-web/vendor/sqlalchemy/orm/query.py", line 2368, in _execute_and_instances
result = conn.execute(querycontext.statement, self._params)
File "/Users/jgillman/Code/calibre-web/vendor/sqlalchemy/engine/base.py", line 662, in execute
params)
File "/Users/jgillman/Code/calibre-web/vendor/sqlalchemy/engine/base.py", line 761, in _execute_clauseelement
compiled_sql, distilled_params
File "/Users/jgillman/Code/calibre-web/vendor/sqlalchemy/engine/base.py", line 874, in _execute_context
context)
File "/Users/jgillman/Code/calibre-web/vendor/sqlalchemy/engine/base.py", line 1024, in _handle_dbapi_exception
exc_info
File "/Users/jgillman/Code/calibre-web/vendor/sqlalchemy/util/compat.py", line 196, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb)
File "/Users/jgillman/Code/calibre-web/vendor/sqlalchemy/engine/base.py", line 867, in _execute_context
context)
File "/Users/jgillman/Code/calibre-web/vendor/sqlalchemy/engine/default.py", line 324, in do_execute
cursor.execute(statement, parameters)
OperationalError: (OperationalError) no such table: books_custom_column_1_link u'SELECT custom_column_1.id AS custom_column_1_id, custom_column_1.value AS custom_column_1_value \
nFROM custom_column_1, books_custom_column_1_link \nWHERE ? = books_custom_column_1_link.book AND custom_column_1.id = books_custom_column_1_link.value' (125,)
ERROR:tornado.access:500 GET /book/125 (::1) 89.60ms

# Fixed code
def modify_database_object(
    input_elements, db_book_object, db_object, db_session, db_type
):
    # passing input_elements not as a list may lead to undesired results
    if not isinstance(input_elements, list):
        raise TypeError(str(input_elements) + " should be passed as a list")

    input_elements = [x for x in input_elements if x != ""]
    # we have all input element (authors, series, tags) names now
    # 1. search for elements to remove
    del_elements = []
    for c_elements in db_book_object:
        found = False
        if db_type == "languages":
            type_elements = c_elements.lang_code
        elif db_type == "custom":
            type_elements = c_elements.value
        else:
            type_elements = c_elements.name
        for inp_element in input_elements:
            if inp_element.lower() == type_elements.lower():
                # if inp_element == type_elements:
                found = True
                break
        # if the element was not found in the new list, add it to remove list
        if not found:
            del_elements.append(c_elements)
    # 2. search for elements that need to be added
    add_elements = []
    for inp_element in input_elements:
        found = False
        for c_elements in db_book_object:
            if db_type == "languages":
                type_elements = c_elements.lang_code
            elif db_type == "custom":
                type_elements = c_elements.value
            else:
                type_elements = c_elements.name
            if inp_element == type_elements:
                found = True
                break
        if not found:
            add_elements.append(inp_element)
    # if there are elements to remove, we remove them now
    if len(del_elements) > 0:
        for del_element in del_elements:
            db_book_object.remove(del_element)
            if len(del_element.books) == 0:
                db_session.delete(del_element)
    # if there are elements to add, we add them now!
    if len(add_elements) > 0:
        if db_type == "languages":
            db_filter = db_object.lang_code
        elif db_type == "custom":
            db_filter = db_object.value
        else:
            db_filter = db_object.name
        for add_element in add_elements:
            # check if a element with that name exists
            db_element = (
                db_session.query(db_object).filter(db_filter == add_element).first()
            )
            # if no element is found add it
            # if new_element is None:
            if db_type == "author":
                new_element = db_object(
                    add_element,
                    helper.get_sorted_author(add_element.replace("|", ",")),
                    "",
                )
            elif db_type == "series":
                new_element = db_object(add_element, add_element)
            elif db_type == "custom":
                new_element = db_object(value=add_element)
            elif db_type == "publisher":
                new_element = db_object(add_element, None)
            else:  # db_type should be tag or language
                new_element = db_object(add_element)
            if db_element is None:
                db_session.add(new_element)
                db_book_object.append(new_element)
            else:
                if db_type == "custom":
                    if db_element.value != add_element:
                        new_element.value = add_element
                        # new_element = db_element
                elif db_type == "languages":
                    if db_element.lang_code != add_element:
                        db_element.lang_code = add_element
                        # new_element = db_element
                elif db_type == "series":
                    if db_element.name != add_element:
                        db_element.name = add_element  # = add_element # new_element = db_object(add_element, add_element)
                        db_element.sort = add_element
                        # new_element = db_element
                elif db_type == "author":
                    if db_element.name != add_element:
                        db_element.name = add_element
                        db_element.sort = add_element.replace("|", ",")
                        # new_element = db_element
                elif db_type == "publisher":
                    if db_element.name != add_element:
                        db_element.name = add_element
                        db_element.sort = None
                        # new_element = db_element
                elif db_element.name != add_element:
                    db_element.name = add_element
                    # new_element = db_element
                # add element to book
                db_book_object.append(db_element)