QuickShop/src/main/java/org/maxgamer/quickshop/Database/Database.java

199 lines
5.3 KiB
Java

package org.maxgamer.quickshop.Database;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
public class Database {
private DatabaseCore core;
/**
* Creates a new database and validates its connection.
*
* If the connection is invalid, this will throw a ConnectionException.
*
* @param core
* The core for the database, either MySQL or SQLite.
* @throws ConnectionException
* If the connection was invalid
*/
public Database(DatabaseCore core) throws ConnectionException {
try {
try {
if (!core.getConnection().isValid(10)) {
throw new ConnectionException("Database doesn not appear to be valid!");
}
} catch (AbstractMethodError e) {
// You don't need to validate this core.
}
} catch (SQLException e) {
throw new ConnectionException(e.getMessage());
}
this.core = core;
}
/**
* Returns the database core object, that this database runs on.
*
* @return the database core object, that this database runs on.
*/
public DatabaseCore getCore() {
return core;
}
/**
* Fetches the connection to this database for querying. Try to avoid doing
* this in the main thread.
*
* @return Fetches the connection to this database for querying.
*/
public Connection getConnection() {
return core.getConnection();
}
/**
* Executes the given statement either immediately, or soon.
*
* @param query
* The query
* @param objs
* The string values for each ? in the given query.
*/
public void execute(String query, Object... objs) {
BufferStatement bs = new BufferStatement(query, objs);
core.queue(bs);
}
/**
* Returns true if the table exists
*
* @param table
* The table to check for
* @return True if the table is found
*/
public boolean hasTable(String table) throws SQLException {
ResultSet rs = getConnection().getMetaData().getTables(null, null, "%", null);
while (rs.next()) {
if (table.equalsIgnoreCase(rs.getString("TABLE_NAME"))) {
rs.close();
return true;
}
}
rs.close();
return false;
}
/**
* Closes the database
*/
public void close() {
this.core.close();
}
/**
* Returns true if the given table has the given column
*
* @param table
* The table
* @param column
* The column
* @return True if the given table has the given column
* @throws SQLException
* If the database isn't connected
*/
public boolean hasColumn(String table, String column) throws SQLException {
if (!hasTable(table))
return false;
String query = "SELECT * FROM " + table + " LIMIT 0,1";
try {
PreparedStatement ps = this.getConnection().prepareStatement(query);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
rs.getString(column); // Throws an exception if it can't find
// that column
return true;
}
} catch (SQLException e) {
return false;
}
return false; // Uh, wtf.
}
/**
* Represents a connection error, generally when the server can't connect to
* MySQL or something.
*/
public static class ConnectionException extends Exception {
private static final long serialVersionUID = 8348749992936357317L;
public ConnectionException(String msg) {
super(msg);
}
}
/**
* Copies the contents of this database into the given database. Does not
* delete the contents of this database, or change any settings. This may
* take a long time, and will print out progress reports to System.out
*
* This method does not create the tables in the new database. You need to
* do that yourself.
*
* @param db
* The database to copy data to
* @throws SQLException
* if an error occurs.
*/
public void copyTo(Database db) throws SQLException {
ResultSet rs = getConnection().getMetaData().getTables(null, null, "%", null);
List<String> tables = new LinkedList<String>();
while (rs.next()) {
tables.add(rs.getString("TABLE_NAME"));
}
rs.close();
core.flush();
// For each table
for (String table : tables) {
if (table.toLowerCase().startsWith("sqlite_autoindex_"))
continue;
System.out.println("Copying " + table);
// Wipe the old records
db.getConnection().prepareStatement("DELETE FROM " + table).execute();
// Fetch all the data from the existing database
rs = getConnection().prepareStatement("SELECT * FROM " + table).executeQuery();
int n = 0;
// Build the query
String query = "INSERT INTO " + table + " VALUES (";
// Append another placeholder for the value
query += "?";
for (int i = 2; i <= rs.getMetaData().getColumnCount(); i++) {
// Add the rest of the placeholders and values. This is so we
// have (?, ?, ?) and not (?, ?, ?, ).
query += ", ?";
}
// End the query
query += ")";
PreparedStatement ps = db.getConnection().prepareStatement(query);
while (rs.next()) {
n++;
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
ps.setObject(i, rs.getObject(i));
}
ps.addBatch();
if (n % 100 == 0) {
ps.executeBatch();
System.out.println(n + " records copied...");
}
}
ps.executeBatch();
// Close the resultset of that table
rs.close();
}
// Success!
db.getConnection().close();
this.getConnection().close();
}
}