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(){}
|
private Constants(){}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static final String CONFIG_DATABASE = "umbrella.modules.stock.database";
|
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 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 PROPERTY_ID = "prop_id";
|
||||||
public static final String TABLE_ITEMS = "items";
|
public static final String TABLE_ITEMS = "items";
|
||||||
public static final String TABLE_ITEM_PROPERTIES = "item_props";
|
public static final String TABLE_ITEM_PROPERTIES = "item_props";
|
||||||
|
|||||||
@@ -1,18 +1,26 @@
|
|||||||
/* © SRSoftware 2025 */
|
/* © SRSoftware 2025 */
|
||||||
package de.srsoftware.umbrella.stock;
|
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.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.text.MessageFormat.format;
|
import static java.text.MessageFormat.format;
|
||||||
|
|
||||||
|
import de.srsoftware.tools.Tuple;
|
||||||
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.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SqliteDb extends BaseDb implements StockDb {
|
public class SqliteDb extends BaseDb implements StockDb {
|
||||||
@@ -29,8 +37,11 @@ public class SqliteDb extends BaseDb implements StockDb {
|
|||||||
createItemsTable();
|
createItemsTable();
|
||||||
createPropertiesTable();
|
createPropertiesTable();
|
||||||
createItemPropsTable();
|
createItemPropsTable();
|
||||||
|
case 1:
|
||||||
|
transformLocationsTable();
|
||||||
|
|
||||||
}
|
}
|
||||||
return setCurrentVersion(1);
|
return setCurrentVersion(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createItemsTable() {
|
private void createItemsTable() {
|
||||||
@@ -83,5 +94,64 @@ public class SqliteDb extends BaseDb implements StockDb {
|
|||||||
return List.of();
|
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