What a mess
This commit is contained in:
147
migrations/migrate_unique_items_table.py
Normal file
147
migrations/migrate_unique_items_table.py
Normal file
@@ -0,0 +1,147 @@
|
||||
"""
|
||||
Migration: Create unique_items table and refactor item tracking
|
||||
|
||||
This creates a proper architecture where:
|
||||
1. unique_items table stores individual item instances with their properties
|
||||
2. inventory/dropped_items reference unique_item_id instead of duplicating data
|
||||
3. When item is picked up, only the reference changes (dropped_items -> inventory)
|
||||
4. When item decays/breaks, delete from unique_items (cascades to references)
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from api.database import DatabaseSession, engine, metadata
|
||||
from sqlalchemy import text
|
||||
|
||||
async def migrate():
|
||||
"""Create unique_items table and refactor references"""
|
||||
|
||||
async with DatabaseSession() as session:
|
||||
print("Starting migration: Create unique_items table...")
|
||||
|
||||
# Step 1: Create unique_items table
|
||||
try:
|
||||
await session.execute(text("""
|
||||
CREATE TABLE IF NOT EXISTS unique_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
item_id VARCHAR NOT NULL,
|
||||
durability INTEGER,
|
||||
max_durability INTEGER,
|
||||
tier INTEGER DEFAULT 1,
|
||||
unique_stats JSONB,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
"""))
|
||||
print("✓ Created unique_items table")
|
||||
except Exception as e:
|
||||
print(f"✗ Error creating unique_items table: {e}")
|
||||
return
|
||||
|
||||
# Step 2: Add unique_item_id to inventory (nullable for now)
|
||||
try:
|
||||
await session.execute(text(
|
||||
"ALTER TABLE inventory ADD COLUMN IF NOT EXISTS unique_item_id INTEGER REFERENCES unique_items(id) ON DELETE CASCADE"
|
||||
))
|
||||
print("✓ Added unique_item_id to inventory")
|
||||
except Exception as e:
|
||||
print(f"✗ unique_item_id may already exist in inventory: {e}")
|
||||
|
||||
# Step 3: Add unique_item_id to dropped_items (nullable for now)
|
||||
try:
|
||||
await session.execute(text(
|
||||
"ALTER TABLE dropped_items ADD COLUMN IF NOT EXISTS unique_item_id INTEGER REFERENCES unique_items(id) ON DELETE CASCADE"
|
||||
))
|
||||
print("✓ Added unique_item_id to dropped_items")
|
||||
except Exception as e:
|
||||
print(f"✗ unique_item_id may already exist in dropped_items: {e}")
|
||||
|
||||
# Step 4: Migrate existing inventory items with durability to unique_items
|
||||
print("\nMigrating existing inventory items to unique_items...")
|
||||
result = await session.execute(text("""
|
||||
SELECT id, item_id, durability, max_durability, tier, unique_stats
|
||||
FROM inventory
|
||||
WHERE durability IS NOT NULL OR tier IS NOT NULL OR unique_stats IS NOT NULL
|
||||
"""))
|
||||
inventory_items = result.fetchall()
|
||||
|
||||
migrated_count = 0
|
||||
for inv_item in inventory_items:
|
||||
# Create unique_item entry
|
||||
result = await session.execute(text("""
|
||||
INSERT INTO unique_items (item_id, durability, max_durability, tier, unique_stats)
|
||||
VALUES (:item_id, :durability, :max_durability, :tier, :unique_stats)
|
||||
RETURNING id
|
||||
"""), {
|
||||
'item_id': inv_item.item_id,
|
||||
'durability': inv_item.durability,
|
||||
'max_durability': inv_item.max_durability,
|
||||
'tier': inv_item.tier,
|
||||
'unique_stats': inv_item.unique_stats
|
||||
})
|
||||
unique_item_id = result.fetchone()[0]
|
||||
|
||||
# Update inventory to reference it
|
||||
await session.execute(text("""
|
||||
UPDATE inventory
|
||||
SET unique_item_id = :unique_item_id
|
||||
WHERE id = :inv_id
|
||||
"""), {
|
||||
'unique_item_id': unique_item_id,
|
||||
'inv_id': inv_item.id
|
||||
})
|
||||
migrated_count += 1
|
||||
|
||||
print(f"✓ Migrated {migrated_count} inventory items to unique_items")
|
||||
|
||||
# Step 5: Migrate existing dropped_items with durability to unique_items
|
||||
print("\nMigrating existing dropped items to unique_items...")
|
||||
result = await session.execute(text("""
|
||||
SELECT id, item_id, durability, max_durability, tier, unique_stats
|
||||
FROM dropped_items
|
||||
WHERE durability IS NOT NULL OR tier IS NOT NULL OR unique_stats IS NOT NULL
|
||||
"""))
|
||||
dropped_items_list = result.fetchall()
|
||||
|
||||
migrated_dropped = 0
|
||||
for dropped_item in dropped_items_list:
|
||||
# Create unique_item entry
|
||||
result = await session.execute(text("""
|
||||
INSERT INTO unique_items (item_id, durability, max_durability, tier, unique_stats)
|
||||
VALUES (:item_id, :durability, :max_durability, :tier, :unique_stats)
|
||||
RETURNING id
|
||||
"""), {
|
||||
'item_id': dropped_item.item_id,
|
||||
'durability': dropped_item.durability,
|
||||
'max_durability': dropped_item.max_durability,
|
||||
'tier': dropped_item.tier,
|
||||
'unique_stats': dropped_item.unique_stats
|
||||
})
|
||||
unique_item_id = result.fetchone()[0]
|
||||
|
||||
# Update dropped_items to reference it
|
||||
await session.execute(text("""
|
||||
UPDATE dropped_items
|
||||
SET unique_item_id = :unique_item_id
|
||||
WHERE id = :dropped_id
|
||||
"""), {
|
||||
'unique_item_id': unique_item_id,
|
||||
'dropped_id': dropped_item.id
|
||||
})
|
||||
migrated_dropped += 1
|
||||
|
||||
print(f"✓ Migrated {migrated_dropped} dropped items to unique_items")
|
||||
|
||||
# Step 6: Drop old columns from inventory (keep for backward compatibility for now)
|
||||
# We'll drop these in a future migration after verifying everything works
|
||||
print("\n⚠️ Old durability/tier columns still exist for backward compatibility")
|
||||
print(" They can be safely removed in a future migration")
|
||||
|
||||
await session.commit()
|
||||
print("\n✅ Migration completed successfully!")
|
||||
print(f"\n📊 Summary:")
|
||||
print(f" - Created unique_items table")
|
||||
print(f" - Migrated {migrated_count} inventory items")
|
||||
print(f" - Migrated {migrated_dropped} dropped items")
|
||||
print(f" - Total unique items: {migrated_count + migrated_dropped}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(migrate())
|
||||
Reference in New Issue
Block a user