168 lines
5.6 KiB
Java
168 lines
5.6 KiB
Java
package de.srsoftware.widerhall.data;
|
|
|
|
import de.srsoftware.widerhall.Configuration;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import java.sql.Connection;
|
|
import java.sql.DriverManager;
|
|
import java.sql.ResultSet;
|
|
import java.sql.SQLException;
|
|
import java.util.*;
|
|
|
|
import static de.srsoftware.widerhall.Util.t;
|
|
import static de.srsoftware.widerhall.Constants.*;
|
|
|
|
public class Database {
|
|
public static final String HASHED_PASS = "hashedPassword";
|
|
public static final String SALT = "salt";
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(Database.class);
|
|
private static final String VARCHAR = "VARCHAR(255)";
|
|
private static Database singleton = null;
|
|
private final Connection conn;
|
|
|
|
public Request insertInto(String tbName) {
|
|
return query("INSERT INTO "+tbName);
|
|
}
|
|
|
|
public class Request{
|
|
|
|
private final String sql;
|
|
private final HashMap<String,List<Object>> where = new HashMap<>();
|
|
private final HashMap<String,Object> values = new HashMap<>();
|
|
|
|
public Request(String sql) {
|
|
this.sql = sql;
|
|
}
|
|
|
|
public Request where(String key, Object ... values) {
|
|
for (var val : values) where(key,val);
|
|
return this;
|
|
}
|
|
|
|
public Request where(String key, Object value) {
|
|
var list = where.get(key);
|
|
if (list == null) where.put(key,list = new ArrayList<>());
|
|
list.add(value);
|
|
return this;
|
|
}
|
|
|
|
public Request values(Map<String,Object> newValues) {
|
|
values.putAll(newValues);
|
|
return this;
|
|
}
|
|
|
|
public Request values(String key, Object value) {
|
|
values.put(key,value);
|
|
return this;
|
|
}
|
|
|
|
public void run() throws SQLException {
|
|
var sb = new StringBuilder(sql);
|
|
var args = new ArrayList<>();
|
|
if (!values.isEmpty()){
|
|
var keys = new ArrayList<String>();
|
|
for (var entry : values.entrySet()) {
|
|
keys.add(entry.getKey());
|
|
args.add(entry.getValue());
|
|
}
|
|
sb.append("(")
|
|
.append(String.join(", ",keys))
|
|
.append(")")
|
|
.append(" VALUES ");
|
|
var arr = new String[args.size()];
|
|
Arrays.fill(arr,"?");
|
|
var marks = String.join(", ",arr);
|
|
sb.append("(").append(marks).append(")");
|
|
}
|
|
var sql = sb.toString();
|
|
LOG.debug(sql);
|
|
try {
|
|
var stmt = conn.prepareStatement(sql);
|
|
if (!args.isEmpty()) {
|
|
for (int i = 0; i < args.size(); i++) stmt.setObject(i+1, args.get(i));
|
|
}
|
|
stmt.execute();
|
|
} catch (SQLException sqle) {
|
|
throw new SQLException(t("Query '{}' failed:",sql),sqle);
|
|
}
|
|
}
|
|
|
|
public ResultSet exec() throws SQLException {
|
|
var sb = new StringBuilder(sql);
|
|
var args = new ArrayList<>();
|
|
if (!where.isEmpty()){
|
|
var clauses = new ArrayList<String>();
|
|
sb.append(" WHERE ");
|
|
|
|
for (var entry : where.entrySet()){
|
|
var arr = new String[entry.getValue().size()];
|
|
Arrays.fill(arr,"?");
|
|
var marks = String.join(", ",arr);
|
|
clauses.add("("+entry.getKey()+" IN ("+marks+"))");
|
|
args.addAll(entry.getValue());
|
|
}
|
|
sb.append(String.join(" AND ",clauses));
|
|
|
|
}
|
|
var sql = sb.toString();
|
|
LOG.debug(sql);
|
|
try {
|
|
var stmt = Database.this.conn.prepareStatement(sql);
|
|
if (!args.isEmpty()) {
|
|
for (int i = 0; i < args.size(); i++) stmt.setObject(i+1, args.get(i));
|
|
}
|
|
return stmt.executeQuery();
|
|
} catch (SQLException sqle) {
|
|
throw new SQLException(t("Query '{}' failed:",sql),sqle);
|
|
}
|
|
}
|
|
}
|
|
|
|
public Database(Connection connection) {
|
|
this.conn = connection;
|
|
}
|
|
|
|
public static Database open() {
|
|
if (singleton == null){
|
|
Configuration config = Configuration.instance();
|
|
var dbFile = config.dbFile();
|
|
String url = "jdbc:sqlite:"+dbFile;
|
|
LOG.debug("Opening {}",url);
|
|
dbFile.getParentFile().mkdirs();
|
|
try {
|
|
singleton = new Database(DriverManager.getConnection(url)).assertTables();
|
|
} catch (SQLException sqle) {
|
|
sqle.printStackTrace();
|
|
}
|
|
}
|
|
return singleton;
|
|
}
|
|
|
|
private Database assertTables() throws SQLException {
|
|
if (!tableExists("Users")) createUsersTable();
|
|
return this;
|
|
}
|
|
|
|
private void createUsersTable() throws SQLException {
|
|
query("CREATE TABLE Users ("+EMAIL+" "+ VARCHAR +", "+SALT+" "+VARCHAR+", "+HASHED_PASS+" "+VARCHAR+", "+NAME+" "+VARCHAR+");").run();
|
|
}
|
|
|
|
private boolean tableExists(String tbName) throws SQLException {
|
|
try {
|
|
ResultSet rs = query("SELECT EXISTS (SELECT name FROM sqlite_schema WHERE type='table' AND name='" + tbName + "')").exec();
|
|
int val = 0;
|
|
if (rs.next()) val = rs.getInt(1);
|
|
rs.close();
|
|
return val > 0;
|
|
} catch (SQLException e) {
|
|
throw new SQLException(t("Was not able to check existence of table {}!",tbName),e);
|
|
}
|
|
}
|
|
|
|
public Request query(String sql) {
|
|
return new Request(sql);
|
|
}
|
|
}
|