working on transformation of stock tables
This commit is contained in:
@@ -41,7 +41,7 @@ subprojects {
|
|||||||
testImplementation(platform("org.junit:junit-bom:5.10.0"))
|
testImplementation(platform("org.junit:junit-bom:5.10.0"))
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
implementation("de.srsoftware:configuration.api:1.0.2")
|
implementation("de.srsoftware:configuration.api:1.0.2")
|
||||||
implementation("de.srsoftware:tools.jdbc:2.0.0")
|
implementation("de.srsoftware:tools.jdbc:2.0.2")
|
||||||
implementation("de.srsoftware:tools.http:6.0.5")
|
implementation("de.srsoftware:tools.http:6.0.5")
|
||||||
implementation("de.srsoftware:tools.mime:1.1.3")
|
implementation("de.srsoftware:tools.mime:1.1.3")
|
||||||
implementation("de.srsoftware:tools.logging:1.3.2")
|
implementation("de.srsoftware:tools.logging:1.3.2")
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ public class Constants {
|
|||||||
|
|
||||||
private Constants(){}
|
private Constants(){}
|
||||||
|
|
||||||
|
|
||||||
public static final String ADDRESS = "address";
|
public static final String ADDRESS = "address";
|
||||||
public static final String ALLOWED_STATES = "allowed_states";
|
public static final String ALLOWED_STATES = "allowed_states";
|
||||||
public static final String ATTACHMENTS = "attachments";
|
public static final String ATTACHMENTS = "attachments";
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ 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;
|
||||||
|
|
||||||
public class Location {
|
public class Location {
|
||||||
long owner;
|
private long owner;
|
||||||
boolean ownerIsCompany = false;
|
private boolean ownerIsCompany = false;
|
||||||
private long id;
|
private long id;
|
||||||
private Long parentLocationId;
|
private Long parentLocationId;
|
||||||
private String name;
|
private String name;
|
||||||
@@ -25,36 +25,29 @@ public class Location {
|
|||||||
this.description = description;
|
this.description = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final long id(){
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String description() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
public static Location of(ResultSet rs){
|
public static Location of(ResultSet rs){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Location ofLegacy(ResultSet rs) throws SQLException {
|
|
||||||
var id = rs.getString(ID);
|
|
||||||
var parent = rs.getString(LOCATION_ID);
|
public long ownerCoded(){
|
||||||
var name = rs.getString(NAME);
|
return ownerIsCompany ? -owner : owner;
|
||||||
var description = rs.getString(DESCRIPTION);
|
}
|
||||||
var ownerIsCompany = false;
|
|
||||||
var parts = id.split(":");
|
public Long parent(){
|
||||||
if (parts.length != 3) throw databaseException("Legacy id expected to be of format ss:dd:ss, encountered {0}",id);
|
return parentLocationId;
|
||||||
switch (parts[0]){
|
|
||||||
case "company":
|
|
||||||
ownerIsCompany = true; break;
|
|
||||||
case "user":
|
|
||||||
break;
|
|
||||||
case null, default:
|
|
||||||
throw databaseException("Legacy id expected to start with 'company' or 'user', encountered {0}",id);
|
|
||||||
}
|
|
||||||
var owner = 0L;
|
|
||||||
try {
|
|
||||||
owner = Long.parseLong(parts[1]);
|
|
||||||
} catch (NumberFormatException nfe){
|
|
||||||
throw databaseException("Legacy id expected to be of format ss:dd:ss, encountered {0}",id);
|
|
||||||
}
|
|
||||||
Long parentLocationId = null;
|
|
||||||
if (parent != null){
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
return new Location(owner, ownerIsCompany, id, parentLocationId, name, description);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 transformLocationsTable(){
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user