Browse Source

working on transformation of stock tables

module/stock.v2
Stephan Richter 3 weeks ago
parent
commit
b361731cab
  1. 2
      build.gradle.kts
  2. 1
      core/src/main/java/de/srsoftware/umbrella/core/Constants.java
  3. 51
      core/src/main/java/de/srsoftware/umbrella/core/model/Location.java
  4. 148
      stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java

2
build.gradle.kts

@ -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")

1
core/src/main/java/de/srsoftware/umbrella/core/Constants.java

@ -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";

51
core/src/main/java/de/srsoftware/umbrella/core/model/Location.java

@ -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);
} }
} }

148
stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java

@ -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;
}
} }

Loading…
Cancel
Save