import traceback
import warnings


def _execute_select_statements(statements, database):
    """Execute a list of select statements in one atomic transaction.

    If any statement fails, the transaction is rolled back, and a warning is issued.

    Args:
        statements (list or sqlalchemy statement): List of sqlalchemy select statements.
        database (sqlalchemy.MetaData): The bind argument must be set.


    Returns:
        result (list): List of selection results. A selection result is a list of
        tuples where each tuple is a selected row.

    """
    if not isinstance(statements, (list, tuple)):
        statements = [statements]

    results = []
    engine = database.bind
    conn = engine.connect()
    # acquire lock
    trans = conn.begin()
    try:
        for stat in statements:
            res = conn.execute(stat)
            results.append(list(res))
            res.close()
        # release lock
        trans.commit()
        conn.close()
    except (KeyboardInterrupt, SystemExit):
        trans.rollback()
        conn.close()
        raise
    except Exception:
        exception_info = traceback.format_exc()
        warnings.warn(
            "Unable to read from database. Try again later. The traceback was:\n\n"
            f"{exception_info}"
        )

        trans.rollback()
        conn.close()
        results = [[] for stat in statements]

    return results