2016-09-13 10:52:27 +02:00
package org.hwo.pulscounter.db ;
2016-09-20 09:22:29 +02:00
import java.io.BufferedReader ;
import java.io.IOException ;
import java.io.InputStream ;
import java.io.InputStreamReader ;
2016-10-26 19:21:57 +02:00
import java.sql.Array ;
2016-09-13 10:52:27 +02:00
import java.sql.Connection ;
import java.sql.DriverManager ;
import java.sql.PreparedStatement ;
import java.sql.ResultSet ;
import java.sql.SQLException ;
2016-10-26 19:21:57 +02:00
import java.util.ArrayList ;
2016-09-15 16:52:11 +02:00
import java.util.LinkedList ;
import java.util.List ;
import java.util.UUID ;
2016-09-13 10:52:27 +02:00
2016-10-26 19:21:57 +02:00
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 ;
2016-09-13 10:52:27 +02:00
import org.hwo.pulscounter.SnapShot ;
2016-10-13 08:29:02 +02:00
import org.hwo.pulscounter.simplescript.SimpleScript ;
2016-10-26 19:21:57 +02:00
import org.hwo.sql.Schema ;
2016-09-13 10:52:27 +02:00
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" , "" ) ;
2016-10-26 19:21:57 +02:00
log ( INFO , "HSQLDB Version: %s" , dbConnection . getMetaData ( ) . getDatabaseProductVersion ( ) ) ;
Schema schema = new Schema ( dbConnection ) ;
schema . print ( ) ;
2016-09-13 10:52:27 +02:00
} catch ( SQLException e ) {
e . printStackTrace ( ) ;
} catch ( ClassNotFoundException e ) {
log ( ERROR , "HyperSQL Driver could not be loaded. [%s]" , e . toString ( ) ) ;
}
2016-09-20 09:22:29 +02:00
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 ) ;
}
}
2016-09-13 10:52:27 +02:00
}
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 ) ;
2016-10-26 19:21:57 +02:00
int i = 0 ;
2016-09-13 10:52:27 +02:00
2016-10-26 19:21:57 +02:00
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 ;
2016-09-13 10:52:27 +02:00
}
stmt . execute ( ) ;
ResultSet result = stmt . getResultSet ( ) ;
stmt . closeOnCompletion ( ) ;
return result ;
} catch ( SQLException e ) {
log ( ERROR , "SQL Statement failed: %s" , query ) ;
2017-03-10 15:11:01 +01:00
log ( e ) ;
2016-10-26 19:21:57 +02:00
if ( e . getCause ( ) ! = null ) {
log ( ERROR , "Caused-By: %s" , e . getCause ( ) . toString ( ) ) ;
e . getCause ( ) . printStackTrace ( ) ;
}
2016-09-13 10:52:27 +02:00
}
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 ) ;
2017-03-10 15:11:01 +01:00
log ( e ) ;
2016-09-13 10:52:27 +02:00
}
}
return null ;
}
2016-09-15 16:52:11 +02:00
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 ) ;
2017-03-10 15:11:01 +01:00
log ( e ) ;
2016-09-15 16:52:11 +02:00
}
}
return null ;
}
2016-09-13 10:52:27 +02:00
public String getProperty ( String name ) {
2016-09-15 16:52:11 +02:00
return executeVerySimpleQuery ( "SELECT value FROM props WHERE name=?" , name ) ;
2016-09-13 10:52:27 +02:00
}
public void setProperty ( String name , String value ) {
2016-09-15 16:52:11 +02:00
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 ) ;
2016-09-13 10:52:27 +02:00
}
public void removeProperty ( String name ) {
2016-09-15 16:52:11 +02:00
executeSimpleSQL ( "DELETE FROM props WHERE props.name = ?" , name ) ;
2016-09-13 10:52:27 +02:00
}
public String getSchemaVersion ( ) {
return getProperty ( "db.schema.version" ) ;
}
public void storeSnapshots ( SnapShot [ ] snapShots ) {
2016-09-13 12:07:01 +02:00
for ( SnapShot snapShot : snapShots ) {
storeSnapshot ( snapShot ) ;
}
}
private void storeSnapshot ( SnapShot snapShot ) {
2016-09-15 16:52:11 +02:00
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(),?,?,?,?,?,?,?,?,?,?)" ,
2016-09-13 12:07:01 +02:00
snapShot . getDeviceSerial ( ) ,
2016-09-15 16:52:11 +02:00
snapShot . getIndex ( ) ,
2016-09-13 12:07:01 +02:00
snapShot . getTimestamp ( ) ,
snapShot . getValues ( ) ,
snapShot . getAnalog ( ) ,
snapShot . getInputmask ( ) ,
snapShot . getOutputmask ( ) ,
snapShot . getPullupmask ( ) ,
2016-09-15 16:52:11 +02:00
snapShot . getInvertmask ( ) ,
snapShot . getField0 ( )
) ;
}
2016-11-21 16:08:15 +01:00
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 ( ) ) ;
}
2016-09-15 16:52:11 +02:00
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 ;
}
}
2016-10-26 19:21:57 +02:00
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 ) {
2016-09-15 16:52:11 +02:00
List < SnapShot > snapshots = new LinkedList < > ( ) ;
2016-09-13 12:07:01 +02:00
2016-10-26 19:21:57 +02:00
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 ) ;
2016-09-15 16:52:11 +02:00
try {
while ( result . next ( ) ) {
SnapShot ss = new SnapShot ( result ) ;
snapshots . add ( ss ) ;
}
} catch ( SQLException e ) {
log ( e ) ;
}
2016-09-13 10:52:27 +02:00
2016-09-15 16:52:11 +02:00
return snapshots . toArray ( new SnapShot [ 0 ] ) ;
2016-09-13 10:52:27 +02:00
}
2016-10-13 08:29:02 +02:00
public SimpleScript [ ] getSimpleScripts ( ) {
2016-10-26 19:21:57 +02:00
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 ( ) ,
2016-11-17 16:37:45 +01:00
simpleScript . getSimpleScriptElementsAsInteger ( )
2016-10-26 19:21:57 +02:00
) ;
}
public ObjectTable getSnapshotsAsTable ( int deviceSerial ) {
ObjectTable ot = new ObjectTable ( ) ;
for ( SnapShot ss : loadSnapshots ( 0 , deviceSerial ) ) {
ot . add ( ss . getCSVRecord ( true ) . getValuesAsArray ( ) ) ;
}
return ot ;
2016-10-13 08:29:02 +02:00
}
2016-10-26 19:21:57 +02:00
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 ) ; ;
}
}
}
2016-09-13 10:52:27 +02:00
}