working on table transformation:
idea is to transform ids of the form 'company:1:42', where company:1 is the owner and '42' is the company-relative id to separate columns owner and id, where owner is a positive long for users and a negative long for companies. however, as the id field would then only require a company-relative uniqueness, this currently cannot be done: The legacy id filed has a unique constraint, which cannot be released in SQLite. So a new table will have to be created as an intermediate step. Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -5,8 +5,10 @@ public class Constants {
|
||||
private Constants(){}
|
||||
|
||||
|
||||
|
||||
public static final String CONFIG_DATABASE = "umbrella.modules.stock.database";
|
||||
public static final String ITEM_ID = "item_id"; public static final String LOCATION_ID = "location_id";
|
||||
public static final String OWNER = "owner";
|
||||
public static final String PROPERTY_ID = "prop_id";
|
||||
public static final String TABLE_ITEMS = "items";
|
||||
public static final String TABLE_ITEM_PROPERTIES = "item_props";
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
/* © SRSoftware 2025 */
|
||||
package de.srsoftware.umbrella.stock;
|
||||
|
||||
import static de.srsoftware.tools.Optionals.nullIfEmpty;
|
||||
import static de.srsoftware.tools.jdbc.Query.select;
|
||||
import static de.srsoftware.tools.jdbc.Query.update;
|
||||
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.text.MessageFormat.format;
|
||||
|
||||
import de.srsoftware.tools.Tuple;
|
||||
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.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class SqliteDb extends BaseDb implements StockDb {
|
||||
@@ -29,8 +37,11 @@ public class SqliteDb extends BaseDb implements StockDb {
|
||||
createItemsTable();
|
||||
createPropertiesTable();
|
||||
createItemPropsTable();
|
||||
case 1:
|
||||
transformLocationsTable();
|
||||
|
||||
}
|
||||
return setCurrentVersion(1);
|
||||
return setCurrentVersion(2);
|
||||
}
|
||||
|
||||
private void createItemsTable() {
|
||||
@@ -83,5 +94,64 @@ public class SqliteDb extends BaseDb implements StockDb {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
|
||||
private void transformLocationsTable(){
|
||||
try {
|
||||
db.setAutoCommit(false);
|
||||
var sql = "ALTER TABLE {0} ADD COLUMN {1} LONG NOT NULL DEFAULT ``";
|
||||
sql = format(sql,TABLE_LOCATIONS,OWNER);
|
||||
db.prepareStatement(sql).execute();
|
||||
var rs = select(ID,LOCATION_ID).from(TABLE_LOCATIONS).exec(db);
|
||||
var queue = new ArrayList<Tuple<String,String>>();
|
||||
var map = new HashMap<String, Long>(); // map from old ids to new numeric ids
|
||||
var ids = new HashMap<Long, Long>(); // map from owner to last inserted id
|
||||
while (rs.next()) queue.add(Tuple.of(rs.getString(ID),nullIfEmpty(rs.getString(LOCATION_ID))));
|
||||
rs.close();
|
||||
var query = update(TABLE_LOCATIONS).set(ID,LOCATION_ID,OWNER).prepare(db);
|
||||
while (!queue.isEmpty()) {
|
||||
var entry = queue.removeFirst();
|
||||
var oldId = entry.a;
|
||||
var oldLoc = nullIfEmpty(entry.b);
|
||||
if (oldLoc != null && !map.containsKey(oldLoc)) {
|
||||
queue.add(entry);
|
||||
continue;
|
||||
}
|
||||
var parts = oldId.split(":");
|
||||
if (parts.length != 3) throw new IllegalArgumentException(format("Expected 'xxx:dd:yy', got {0}",oldId));
|
||||
long ownerId;
|
||||
try {
|
||||
ownerId = Long.parseLong(parts[1]);
|
||||
} catch (NumberFormatException nfe){
|
||||
throw new IllegalArgumentException(format("Expected 'xxx:dd:yy', got {0}",oldId));
|
||||
}
|
||||
switch (parts[0]){
|
||||
case "company":
|
||||
ownerId = -ownerId;
|
||||
break;
|
||||
case "user":
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(format("Expected 'company:dd:dd' or 'user:dd:dd', got {0}",oldId));
|
||||
}
|
||||
Long location = null;
|
||||
if (oldLoc != null){
|
||||
var expected = String.join(":",parts[0],parts[1],"");
|
||||
if (!oldLoc.startsWith(expected)) throw new IllegalArgumentException(format("Expected location_id to start with {1}, got {0}",oldId,expected));
|
||||
location = Long.parseLong(oldLoc.substring(expected.length()));
|
||||
}
|
||||
var itemId = ids.get(ownerId);
|
||||
if (itemId == null) itemId = 1L;
|
||||
ids.put(ownerId,itemId+1);
|
||||
query.apply(itemId,location,ownerId);
|
||||
map.put(oldId,itemId);
|
||||
}
|
||||
db.setAutoCommit(true);
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
db.rollback();
|
||||
} catch (SQLException ignored) {
|
||||
}
|
||||
LOG.log(ERROR,"Failed to transform {0} table!",TABLE_LOCATIONS,e);
|
||||
throw databaseException("Failed to transform {0} table!",TABLE_LOCATIONS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user