305 lines
8.4 KiB
Java
305 lines
8.4 KiB
Java
package org.hwo.pulscounter.db;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.sql.Array;
|
|
import java.sql.Connection;
|
|
import java.sql.DriverManager;
|
|
import java.sql.PreparedStatement;
|
|
import java.sql.ResultSet;
|
|
import java.sql.SQLException;
|
|
import java.util.ArrayList;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.UUID;
|
|
|
|
import org.hsqldb.jdbc.JDBCArrayBasic;
|
|
import org.hsqldb.types.Type;
|
|
import org.hwo.ArrayHelper;
|
|
import org.hwo.ObjectTable;
|
|
import org.hwo.ObjectTable.ObjectSet;
|
|
import org.hwo.pulscounter.PulsCounterApplication;
|
|
import org.hwo.pulscounter.SnapShot;
|
|
import org.hwo.pulscounter.simplescript.SimpleScript;
|
|
import org.hwo.sql.Schema;
|
|
|
|
import static org.hwo.logging.Logging.*;
|
|
import static org.hwo.logging.LogLevel.*;
|
|
|
|
public class PulsCounterDatabase {
|
|
|
|
private Connection dbConnection;
|
|
|
|
public PulsCounterDatabase(){
|
|
|
|
try {
|
|
getClass().getClassLoader().loadClass("org.hsqldb.jdbcDriver");
|
|
dbConnection = DriverManager.getConnection("jdbc:hsqldb:file:synololog-hsql", "SA", "");
|
|
log(INFO,"HSQLDB Version: %s",dbConnection.getMetaData().getDatabaseProductVersion());
|
|
|
|
Schema schema = new Schema(dbConnection);
|
|
schema.print();
|
|
|
|
} catch (SQLException e) {
|
|
e.printStackTrace();
|
|
} catch (ClassNotFoundException e) {
|
|
log(ERROR,"HyperSQL Driver could not be loaded. [%s]",e.toString());
|
|
}
|
|
|
|
InputStream is = getClass().getResourceAsStream("/org/hwo/pulscounter/db/schema/schema.sql");
|
|
|
|
if (is == null){
|
|
log(ERROR,"Database schema file not found");
|
|
} else {
|
|
try {
|
|
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
|
|
|
do {
|
|
String sql = br.readLine();
|
|
if (sql == null){
|
|
break;
|
|
}
|
|
|
|
sql = sql.trim();
|
|
|
|
if (!sql.equals("") && !sql.startsWith("//")){
|
|
log(sql);
|
|
executeSimpleSQL(sql);
|
|
}
|
|
|
|
}while (true);
|
|
|
|
} catch (IOException e) {
|
|
log(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void close(){
|
|
try {
|
|
dbConnection.close();
|
|
} catch (SQLException e) {
|
|
log(ERROR,"Exception while closing database: %s",e.toString());
|
|
}
|
|
}
|
|
|
|
private ResultSet executeSimpleSQL(String query,Object... args){
|
|
|
|
try {
|
|
PreparedStatement stmt = dbConnection.prepareStatement(query);
|
|
int i = 0;
|
|
|
|
try {
|
|
for (i=0;i<args.length;i++){
|
|
if (Array.class.isInstance(args[i]))
|
|
stmt.setArray(i+1, (Array)args[i]);
|
|
else
|
|
stmt.setObject(i+1, args[i]);
|
|
}
|
|
} catch (SQLException e){
|
|
log(ERROR,"Exception while binding: %d = %s",i,args[i]);
|
|
throw e;
|
|
}
|
|
stmt.execute();
|
|
|
|
ResultSet result = stmt.getResultSet();
|
|
|
|
stmt.closeOnCompletion();
|
|
|
|
return result;
|
|
|
|
} catch (SQLException e) {
|
|
log(ERROR,"SQL Statement failed: %s",query);
|
|
log(ERROR,"Exception: %s", e.toString());
|
|
e.printStackTrace();
|
|
if (e.getCause() != null){
|
|
log(ERROR,"Caused-By: %s",e.getCause().toString());
|
|
e.getCause().printStackTrace();
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private String executeVerySimpleQuery(String query,Object... args){
|
|
ResultSet result = executeSimpleSQL(query,args);
|
|
if (result != null){
|
|
try {
|
|
if (result.next()){
|
|
return result.getString(1);
|
|
}
|
|
} catch (SQLException e) {
|
|
log(ERROR,"SQL Statement failed: %s",query);
|
|
log(ERROR,"Exception: %s", e.toString());
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private Object executeSimpleQueryObject(String query,Object... args){
|
|
ResultSet result = executeSimpleSQL(query,args);
|
|
if (result != null){
|
|
try {
|
|
if (result.next()){
|
|
return result.getObject(1);
|
|
}
|
|
} catch (SQLException e) {
|
|
log(ERROR,"SQL Statement failed: %s",query);
|
|
log(ERROR,"Exception: %s", e.toString());
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
public String getProperty(String name){
|
|
return executeVerySimpleQuery("SELECT value FROM props WHERE name=?", name);
|
|
}
|
|
public void setProperty(String name,String value){
|
|
executeSimpleSQL("MERGE INTO props USING (VALUES(?,?)) as p(name,value) ON props.name = p.name WHEN MATCHED THEN UPDATE SET props.value = p.value WHEN NOT MATCHED THEN INSERT VALUES uuid(), p.name, p.value", name,value);
|
|
}
|
|
public void removeProperty(String name){
|
|
executeSimpleSQL("DELETE FROM props WHERE props.name = ?", name);
|
|
}
|
|
|
|
public String getSchemaVersion(){
|
|
return getProperty("db.schema.version");
|
|
}
|
|
|
|
public void storeSnapshots(SnapShot[] snapShots){
|
|
for (SnapShot snapShot: snapShots){
|
|
storeSnapshot(snapShot);
|
|
}
|
|
}
|
|
|
|
private void storeSnapshot(SnapShot snapShot){
|
|
log(INFO,"db store snapshot [%d]",snapShot.getIndex());
|
|
|
|
executeVerySimpleQuery("INSERT INTO snapshots (id,device,snap_id,timestamp,counters,analogs,inputs,outputs,pullups,inverts,field0) VALUES(uuid(),?,?,?,?,?,?,?,?,?,?)",
|
|
snapShot.getDeviceSerial(),
|
|
snapShot.getIndex(),
|
|
snapShot.getTimestamp(),
|
|
snapShot.getValues(),
|
|
snapShot.getAnalog(),
|
|
snapShot.getInputmask(),
|
|
snapShot.getOutputmask(),
|
|
snapShot.getPullupmask(),
|
|
snapShot.getInvertmask(),
|
|
snapShot.getField0()
|
|
);
|
|
}
|
|
|
|
public void deleteSnapshot(SnapShot snapShot){
|
|
log(INFO,"db delete snapshot [%d]",snapShot.getIndex());
|
|
executeVerySimpleQuery("DELETE FROM snapshots WHERE device=? AND snap_id=?", snapShot.getDeviceSerial(),snapShot.getIndex());
|
|
}
|
|
|
|
|
|
public int highestSnapShot(int deviceSerial){
|
|
Integer ind = (Integer)executeSimpleQueryObject("SELECT max(snap_id) FROM snapshots WHERE device=? GROUP BY device", deviceSerial);
|
|
if (ind == null){
|
|
return -1;
|
|
} else {
|
|
return ind;
|
|
}
|
|
}
|
|
|
|
public Integer[] getKnownDevices(){
|
|
List<Integer> devices = new LinkedList<>();
|
|
|
|
ResultSet result = executeSimpleSQL("SELECT DISTINCT device FROM snapshots ORDER BY device");
|
|
try {
|
|
while (result.next()){
|
|
devices.add( result.getInt(1));
|
|
}
|
|
} catch (SQLException e) {
|
|
log(e);
|
|
}
|
|
return devices.toArray(new Integer[0]);
|
|
}
|
|
|
|
public SnapShot[] loadSnapshots(int fromTimestamp,int deviceSerial){
|
|
List<SnapShot> snapshots = new LinkedList<>();
|
|
|
|
ResultSet result = executeSimpleSQL("SELECT id,device,snap_id,timestamp,counters,analogs,inputs,outputs,pullups,inverts,field0 FROM snapshots WHERE timestamp >= ? AND device = ? ORDER BY device,timestamp", fromTimestamp, deviceSerial);
|
|
try {
|
|
while (result.next()){
|
|
|
|
SnapShot ss = new SnapShot(result);
|
|
snapshots.add(ss);
|
|
}
|
|
} catch (SQLException e) {
|
|
log(e);
|
|
}
|
|
|
|
return snapshots.toArray(new SnapShot[0]);
|
|
}
|
|
|
|
public SimpleScript[] getSimpleScripts(){
|
|
ResultSet result = executeSimpleSQL("SELECT id,name,description,elements FROM scripts");
|
|
ArrayList<SimpleScript> r = new ArrayList<>();
|
|
|
|
try {
|
|
|
|
while (result.next()){
|
|
r.add(new SimpleScript(UUID.fromString(result.getString(1)), result.getString(2), result.getString(3), ArrayHelper.cast((Object[])result.getArray(4).getArray(),new Integer[0])));
|
|
}
|
|
|
|
} catch (SQLException e) {
|
|
log(e);
|
|
}
|
|
|
|
|
|
return r.toArray(new SimpleScript[0]);
|
|
}
|
|
public void removeSimpleScript(UUID id){
|
|
executeSimpleQueryObject("DELETE FROM scripts WHERE id=?", id);
|
|
}
|
|
public void storeSimpleScript(SimpleScript simpleScript){
|
|
|
|
|
|
/* executeSimpleQueryObject("MERGE INTO scripts USING (VALUES ?,?,?,?) AS ins(uid,name,desc,elements) ON scripts.id=ins.uid WHEN MATCHED THEN UPDATE SET scripts.name=ins.name,scripts.description=ins.desc,scripts.elements=ins.elements WHEN NOT MATCHED THEN INSERT (id,name,description,elements) VALUES(ins.uid,ins.name,ins.desc,ins.elements)",
|
|
simpleScript.getId().toString(),
|
|
simpleScript.getName(),
|
|
simpleScript.getDescription(),
|
|
simpleScript.getSimpleScriptElementsAsInt()
|
|
);
|
|
*/
|
|
executeSimpleSQL("DELETE FROM scripts WHERE id=?",simpleScript.getId());
|
|
executeSimpleSQL("INSERT INTO scripts VALUES(?,?,?,?)",
|
|
simpleScript.getId(),
|
|
simpleScript.getName(),
|
|
simpleScript.getDescription(),
|
|
simpleScript.getSimpleScriptElementsAsInteger()
|
|
);
|
|
|
|
}
|
|
|
|
|
|
public ObjectTable getSnapshotsAsTable(int deviceSerial){
|
|
ObjectTable ot = new ObjectTable();
|
|
|
|
for (SnapShot ss: loadSnapshots(0,deviceSerial)){
|
|
ot.add( ss.getCSVRecord(true).getValuesAsArray() );
|
|
|
|
}
|
|
return ot;
|
|
}
|
|
|
|
public void calulateTableDeltas(ObjectTable objectTable){
|
|
ObjectSet tmp = objectTable.new ObjectSet();
|
|
|
|
for (ObjectSet row: objectTable.getRows()){
|
|
for (int p=4;p<36;p++){
|
|
int i = row.getInteger(p) - tmp.getInteger(p);
|
|
tmp.set(p,row.getInteger(p));
|
|
row.set(p,i);;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|