@ -8,23 +8,42 @@ import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException ;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException ;
import static de.srsoftware.umbrella.stock.Constants.* ;
import static de.srsoftware.umbrella.stock.Constants.* ;
import static java.lang.System.Logger.Level.ERROR ;
import static java.lang.System.Logger.Level.ERROR ;
import static java.lang.System.Logger.Level.WARNING ;
import static java.text.MessageFormat.format ;
import static java.text.MessageFormat.format ;
import de.srsoftware.tools.Tuple ;
import de.srsoftware.tools.Tuple ;
import de.srsoftware.tools.jdbc.Query ;
import de.srsoftware.umbrella.core.BaseDb ;
import de.srsoftware.umbrella.core.BaseDb ;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException ;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException ;
import de.srsoftware.umbrella.core.model.Hash ;
import de.srsoftware.umbrella.core.model.Item ;
import de.srsoftware.umbrella.core.model.Item ;
import de.srsoftware.umbrella.core.model.Location ;
import de.srsoftware.umbrella.core.model.Location ;
import java.sql.Connection ;
import java.sql.Connection ;
import java.sql.ResultSet ;
import java.sql.SQLException ;
import java.sql.SQLException ;
import java.util.ArrayList ;
import java.util.* ;
import java.util.Collection ;
import java.util.HashMap ;
import java.util.List ;
public class SqliteDb extends BaseDb implements StockDb {
public class SqliteDb extends BaseDb implements StockDb {
private record LegacyLocation ( String id , String parent , String name , String description ) {
public static LegacyLocation of ( ResultSet rs ) throws SQLException {
return new LegacyLocation ( rs . getString ( ID ) , rs . getString ( LOCATION_ID ) , rs . getString ( NAME ) , rs . getString ( DESCRIPTION ) ) ;
}
public long owner ( ) {
var parts = id . split ( ":" ) ;
if ( parts . length ! = 3 ) throw databaseException ( "Expected legacy location id to be of the form ss:dd:ss, encountered {0}!" , id ) ;
try {
var owner = Long . parseLong ( parts [ 1 ] ) ;
switch ( parts [ 0 ] ) {
case "company" : return - owner ;
case "user" : return owner ;
case null , default : throw databaseException ( "Expected legacy location id to start with 'company:' or 'user:', encountered {0}!" , id ) ;
}
} catch ( NumberFormatException nfe ) {
throw databaseException ( "Expected legacy location id to be of the form ss:dd:ss, encountered {0}!" , id ) ;
}
}
} ;
public SqliteDb ( Connection connection ) {
public SqliteDb ( Connection connection ) {
super ( connection ) ;
super ( connection ) ;
}
}
@ -39,10 +58,24 @@ public class SqliteDb extends BaseDb implements StockDb {
createPropertiesTable ( ) ;
createPropertiesTable ( ) ;
createItemPropsTable ( ) ;
createItemPropsTable ( ) ;
case 1 :
case 1 :
transformLocationsTable ( ) ;
dropTokenTable ( ) ;
case 2 :
transformTables ( ) ;
replaceLocationsTable ( ) ;
}
}
return setCurrentVersion ( 2 ) ;
return setCurrentVersion ( 3 ) ;
}
private void createIntermediateItemsTable ( ) throws SQLException { // create intermediate table
var sql = "CREATE TABLE IF NOT EXISTS items_temp ({0} LONG NOT NULL, {1} LONG NOT NULL, {2} VARCHAR(255), {3} VARCHAR(255) NOT NULL, {4} LONG NOT NULL, PRIMARY KEY({0}, {1}))" ;
sql = format ( sql , OWNER , ID , CODE , NAME , LOCATION_ID ) ;
db . prepareStatement ( sql ) . execute ( ) ;
}
private void createIntermediateLocationTable ( ) throws SQLException { // create intermediate table
var sql = "CREATE TABLE IF NOT EXISTS locations_temp ({0} INTEGER PRIMARY KEY, {1} INT DEFAULT NULL, {2} LONG NOT NULL, {3} VARCHAR(255) NOT NULL, {4} TEXT)" ;
sql = format ( sql , ID , PARENT_LOCATION_ID , OWNER , NAME , DESCRIPTION ) ;
db . prepareStatement ( sql ) . execute ( ) ;
}
}
private void createItemsTable ( ) {
private void createItemsTable ( ) {
@ -85,6 +118,14 @@ public class SqliteDb extends BaseDb implements StockDb {
}
}
}
}
private void dropTokenTable ( ) {
try {
db . prepareStatement ( "DROP TABLE IF EXISTS tokens" ) . execute ( ) ;
} catch ( SQLException e ) {
throw databaseException ( "Failed to drop table tokens!" ) ;
}
}
@Override
@Override
public Collection < Item > listItems ( long companyId ) throws UmbrellaException {
public Collection < Item > listItems ( long companyId ) throws UmbrellaException {
return List . of ( ) ;
return List . of ( ) ;
@ -95,27 +136,16 @@ public class SqliteDb extends BaseDb implements StockDb {
return List . of ( ) ;
return List . of ( ) ;
}
}
private void transformLocations Table ( ) {
private void transformTables ( ) {
try {
try {
var tempTable = "locations_temp" ;
db . setAutoCommit ( false ) ;
db . setAutoCommit ( false ) ;
{ // create intermediate table
createIntermediateLocationTable ( ) ;
var sql = "CREATE TABLE IF NOT EXISTS locations_temp ({0} LONG NOT NULL, {1} LONG NOT NULL, {2} LONG DEFAULT NULL, {3} VARCHAR(255) NOT NULL, {4} TEXT)" ;
createIntermediateItemsTable ( ) ;
sql = format ( sql , OWNER , ID , PARENT_LOCATION_ID , NAME , DESCRIPTION ) ;
var oldLocationIdsToNew = transformLocations ( ) ;
db . prepareStatement ( sql ) . execute ( ) ;
transformItems ( oldLocationIdsToNew ) ;
}
var locations = new ArrayList < Location > ( ) ;
{ // fill intermediate table
var rs = select ( ALL ) . from ( tempTable ) . exec ( db ) ;
while ( rs . next ( ) ) locations . add ( Location . ofLegacy ( rs ) ) ;
rs . close ( ) ;
var query = insertInto ( tempTable , OWNER , ID , PARENT_LOCATION_ID , NAME , DESCRIPTION ) ;
for ( var location : locations ) {
}
}
db . setAutoCommit ( true ) ;
db . setAutoCommit ( true ) ;
} catch ( Exception e ) {
} catch ( Exception e ) {
try {
try {
@ -126,4 +156,72 @@ public class SqliteDb extends BaseDb implements StockDb {
throw databaseException ( "Failed to transform {0} table!" , TABLE_LOCATIONS ) ;
throw databaseException ( "Failed to transform {0} table!" , TABLE_LOCATIONS ) ;
}
}
}
}
private void replaceLocationsTable ( ) {
try {
db . setAutoCommit ( false ) ;
db . prepareStatement ( format ( "DROP TABLE {0}" , TABLE_LOCATIONS ) ) . execute ( ) ;
db . prepareStatement ( format ( "ALTER TABLE {0} RENAME TO {1}" , "locations_temp" , TABLE_LOCATIONS ) ) . execute ( ) ;
db . setAutoCommit ( true ) ;
} catch ( SQLException e ) {
throw databaseException ( "Failed to replace locations table!" ) ;
}
}
private void transformItems ( Map < String , Long > oldLocationIdsToNew ) throws SQLException {
var rs = select ( ALL ) . from ( TABLE_ITEMS ) . exec ( db ) ;
var insert = insertInto ( "items_temp" , OWNER , ID , CODE , NAME , LOCATION_ID ) ;
while ( rs . next ( ) ) {
var oldId = rs . getString ( ID ) ;
var parts = oldId . split ( ":" ) ;
var owner = 0L ;
var id = 0L ;
try {
owner = Long . parseLong ( parts [ 1 ] ) ;
id = Long . parseLong ( parts [ 2 ] ) ;
} catch ( NumberFormatException e ) {
throw databaseException ( "Expected item id to be of format ss:dd:dd, but encountered \"{0}\"" , oldId ) ;
}
var ownerIsCompany = switch ( parts [ 0 ] ) {
case "company" - > true ;
case "user" - > false ;
case null , default - > throw databaseException ( "Expected item id to start with 'company:' or 'user:', encountered \"{0}\"" , oldId ) ;
} ;
var oldLocationId = rs . getString ( LOCATION_ID ) ;
var locationId = oldLocationIdsToNew . get ( oldLocationId ) ;
if ( locationId = = null ) throw databaseException ( "Item {0} of {1} {2} refers to location {3}, which is unknown!" , id , parts [ 1 ] , owner , oldLocationId ) ;
insert . values ( ownerIsCompany ? - owner : owner , id , rs . getString ( CODE ) , rs . getString ( NAME ) , locationId ) . execute ( db ) . getGeneratedKeys ( ) ;
}
rs . close ( ) ;
insert . execute ( db ) ;
}
private Map < String , Long > transformLocations ( ) throws SQLException {
var locations = new ArrayList < LegacyLocation > ( ) ;
var oldToNew = new HashMap < String , Long > ( ) ;
var rs = select ( ALL ) . from ( TABLE_LOCATIONS ) . exec ( db ) ;
while ( rs . next ( ) ) locations . add ( LegacyLocation . of ( rs ) ) ;
rs . close ( ) ;
var query = insertInto ( "locations_temp" , PARENT_LOCATION_ID , OWNER , NAME , DESCRIPTION ) ;
while ( ! locations . isEmpty ( ) ) {
var legacyLocation = locations . removeFirst ( ) ;
var parentRef = nullIfEmpty ( legacyLocation . parent ( ) ) ;
Long parentId = null ;
if ( parentRef ! = null ) {
parentId = oldToNew . get ( parentRef ) ;
if ( parentId = = null ) { // parent not processed, re-add to end of queue
LOG . log ( WARNING , "Postpoining {0}, as {1} is not present…" , legacyLocation . id , legacyLocation . parent ) ;
locations . add ( legacyLocation ) ;
continue ;
}
}
rs = query . values ( parentId , legacyLocation . owner ( ) , legacyLocation . name ( ) , legacyLocation . description ( ) ) . execute ( db ) . getGeneratedKeys ( ) ;
var id = rs . getLong ( 1 ) ;
oldToNew . put ( legacyLocation . id ( ) , id ) ;
rs . close ( ) ;
}
return oldToNew ;
}
}
}