|
|
|
|
@@ -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.stock.Constants.*;
|
|
|
|
|
import static java.lang.System.Logger.Level.ERROR;
|
|
|
|
|
import static java.lang.System.Logger.Level.WARNING;
|
|
|
|
|
import static java.text.MessageFormat.format;
|
|
|
|
|
|
|
|
|
|
import de.srsoftware.tools.Tuple;
|
|
|
|
|
import de.srsoftware.tools.jdbc.Query;
|
|
|
|
|
import de.srsoftware.umbrella.core.BaseDb;
|
|
|
|
|
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.Location;
|
|
|
|
|
import java.sql.Connection;
|
|
|
|
|
import java.sql.ResultSet;
|
|
|
|
|
import java.sql.SQLException;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Collection;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
super(connection);
|
|
|
|
|
}
|
|
|
|
|
@@ -39,10 +58,24 @@ public class SqliteDb extends BaseDb implements StockDb {
|
|
|
|
|
createPropertiesTable();
|
|
|
|
|
createItemPropsTable();
|
|
|
|
|
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() {
|
|
|
|
|
@@ -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
|
|
|
|
|
public Collection<Item> listItems(long companyId) throws UmbrellaException {
|
|
|
|
|
return List.of();
|
|
|
|
|
@@ -95,27 +136,16 @@ public class SqliteDb extends BaseDb implements StockDb {
|
|
|
|
|
return List.of();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void transformLocationsTable(){
|
|
|
|
|
private void transformTables(){
|
|
|
|
|
try {
|
|
|
|
|
var tempTable = "locations_temp";
|
|
|
|
|
db.setAutoCommit(false);
|
|
|
|
|
{ // create intermediate table
|
|
|
|
|
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)";
|
|
|
|
|
sql = format(sql, OWNER, ID, PARENT_LOCATION_ID, NAME, DESCRIPTION);
|
|
|
|
|
db.prepareStatement(sql).execute();
|
|
|
|
|
}
|
|
|
|
|
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();
|
|
|
|
|
createIntermediateLocationTable();
|
|
|
|
|
createIntermediateItemsTable();
|
|
|
|
|
var oldLocationIdsToNew = transformLocations();
|
|
|
|
|
transformItems(oldLocationIdsToNew);
|
|
|
|
|
|
|
|
|
|
var query = insertInto(tempTable, OWNER, ID, PARENT_LOCATION_ID, NAME, DESCRIPTION);
|
|
|
|
|
for (var location : locations){
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
db.setAutoCommit(true);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
try {
|
|
|
|
|
@@ -126,4 +156,72 @@ public class SqliteDb extends BaseDb implements StockDb {
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|