package com.gmail.dpierron.calibre.database;
/**
* Abstract the SQL underlying standard requests for calibre2opds
*/
import com.gmail.dpierron.calibre.configuration.Configuration;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public enum DatabaseRequest {
TEST("SELECT COUNT(*) FROM books"),
ALL_TAGS("SELECT DISTINCT id, name " + " FROM tags " + " ORDER BY name "),
ALL_BOOKS("SELECT DISTINCT " + "b.id AS book_id, " + "b.title AS book_title, "
+ "b.sort as book_title_sort, " + "b.series_index AS series_index, "
+ "b.path AS book_path, " + "b.pubdate AS book_pubdate, "
+ "b.timestamp AS book_timestamp, " + "b.last_modified AS book_modified, "
+ "b.isbn AS isbn, " + "b.uuid AS uuid, " + "b.author_sort AS author_sort, "
+ "r.rating AS rating "
+ "FROM books b " + "LEFT OUTER JOIN books_ratings_link brl ON brl.book=b.id "
+ "LEFT OUTER JOIN ratings r ON brl.rating=r.id "),
ALL_AUTHORS("select " + "a.id, " + "a.name, " + "a.sort " + "from authors a " + "order by a.id"),
ALL_PUBLISHERS("select " + "p.id, " + "p.name, " + "p.sort " + "from publishers p " + "order by p.id"),
ALL_SERIES("select " + "s.id, " + "s.name, " + "s.sort as serie_sort " + "from series s " + "order by s.sort"),
ALL_LANGUAGES("select l.id, l.lang_code from languages l"),
BOOKS_SERIES("select book, series from books_series_link"),
BOOKS_TAGS("select book, tag from books_tags_link"),
BOOKS_AUTHORS("select book, author from books_authors_link"),
BOOKS_PUBLISHERS("select book, publisher from books_publishers_link"),
BOOKS_DATA("select book, format, name from data"),
BOOKS_COMMENTS("select book, text from comments"),
// TODO Request to read single comment if this is worth it for RAM usage optimization
// BOOKS_COMMENT("select book, text from comments WHERE id=?"),
BOOKS_LANGUAGES("select book, lang_code from books_languages_link where book = :bookId"),
SAVED_SEARCHES("select val from preferences where key='saved_searches'"),
CUSTOM_COLUMN_DEFINITION("select id, label, name, datatype,is_multiple, normalized from custom_columns"),
// Simple custom columns types
CUSTOM_COLUMN_DATA("select book, value from custom_column_?"),
// Normalised custom column types (not series)
CUSTOM_COLUMN_NORMALIZED_DATA("select bccl.book AS book, cc.value AS value FROM books_custom_column_?_link bccl "
+ "LEFT OUTER JOIN custom_column_? cc ON bccl.value=cc.id"),
// Special case for Series data
CUSTOM_COLUMN_NORMALIZED_DATA_EXTRA("select bccl.book AS book, cc.value AS value, bccl.extra AS extra FROM books_custom_column_?_link bccl "
+ "LEFT OUTER JOIN custom_column_? cc ON bccl.value=cc.id" );
private static final Logger logger = LogManager.getLogger(DatabaseRequest.class);
private String sql;
private PreparedStatement preparedStatement;
private DatabaseRequest(String sql) {
this.sql = sql;
}
public void resetStatement() {
preparedStatement = null;
}
/**
* Generic case where the SQL that is preset is already exactly what is needed
* @return
* @throws RuntimeException
*/
public PreparedStatement getStatement() throws RuntimeException {
return getStatement(sql);
}
/**
* Special case used in custom columns where we need to add an id to the table name
* or to access particular tables by their id.
* @param id
* @return
* @throws RuntimeException
*/
public PreparedStatement getStatementId(String id) throws RuntimeException {
return getStatement(sql.replace("?",id).replace("?",id));
}
/**
* Code to actually set up the statement provided
*
* @param sql
* @return
* @throws RuntimeException
*/
private PreparedStatement getStatement(String sql) throws RuntimeException {
if (preparedStatement == null) {
try {
Connection connection = Database.getConnection();
if (connection == null) {
String e = "Cannot establish a database connection to " + new File(Configuration.instance().getDatabaseFolder(), "metadata.db");
logger.error(e);
throw new RuntimeException(e);
}
preparedStatement = connection.prepareStatement(sql);
} catch (SQLException e) {
logger.error(e);
throw new RuntimeException(e);
}
}
return preparedStatement;
}
public static void reset() {
for (DatabaseRequest databaseRequest : values()) {
databaseRequest.resetStatement();
}
}
}