Browse Source

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>
module/stock.v2
Stephan Richter 3 weeks ago
parent
commit
3bdf7dbab6
  1. 2
      stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java
  2. 74
      stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java

2
stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java

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

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

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

Loading…
Cancel
Save