You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
5.6 KiB
167 lines
5.6 KiB
package de.srsoftware.widerhall.data; |
|
|
|
import de.srsoftware.widerhall.Configuration; |
|
import org.slf4j.Logger; |
|
import org.slf4j.LoggerFactory; |
|
|
|
import java.io.File; |
|
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; |
|
|
|
public class Database { |
|
public static final String EMAIL = "email"; |
|
public static final String NAME = "name"; |
|
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 static Connection conn; |
|
|
|
public Request insertInto(String tbName) { |
|
return query("INSERT INTO "+tbName); |
|
} |
|
|
|
public class Request{ |
|
|
|
private final String sql; |
|
private HashMap<String,List<Object>> where = new HashMap<>(); |
|
private 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<Object>()); |
|
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<Object>(); |
|
if (!values.isEmpty()){ |
|
var keys = new ArrayList<String>(); |
|
for (var entry : values.entrySet()) { |
|
keys.add(entry.getKey()); |
|
args.add(entry.getValue()); |
|
} |
|
sb.append("("+String.join(", ",keys)+")"); |
|
sb.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<Object>(); |
|
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 = 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); |
|
} |
|
}
|
|
|