|
@@ -0,0 +1,79 @@
|
|
|
|
+"""Update file table path
|
|
|
|
+
|
|
|
|
+Revision ID: c29facfe716b
|
|
|
|
+Revises: c69f45358db4
|
|
|
|
+Create Date: 2024-10-20 17:02:35.241684
|
|
|
|
+
|
|
|
|
+"""
|
|
|
|
+
|
|
|
|
+from alembic import op
|
|
|
|
+import sqlalchemy as sa
|
|
|
|
+import json
|
|
|
|
+from sqlalchemy.sql import table, column
|
|
|
|
+from sqlalchemy import String, Text, JSON, and_
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+revision = "c29facfe716b"
|
|
|
|
+down_revision = "c69f45358db4"
|
|
|
|
+branch_labels = None
|
|
|
|
+depends_on = None
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def upgrade():
|
|
|
|
+ # 1. Add the `path` column to the "file" table.
|
|
|
|
+ op.add_column("file", sa.Column("path", sa.Text(), nullable=True))
|
|
|
|
+
|
|
|
|
+ # 2. Convert the `meta` column from Text/JSONField to `JSON()`
|
|
|
|
+ # Use Alembic's default batch_op for dialect compatibility.
|
|
|
|
+ with op.batch_alter_table("file", schema=None) as batch_op:
|
|
|
|
+ batch_op.alter_column(
|
|
|
|
+ "meta",
|
|
|
|
+ type_=sa.JSON(),
|
|
|
|
+ existing_type=sa.Text(),
|
|
|
|
+ existing_nullable=True,
|
|
|
|
+ nullable=True,
|
|
|
|
+ postgresql_using="meta::json",
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ # 3. Migrate legacy data from `meta` JSONField
|
|
|
|
+ # Fetch and process `meta` data from the table, add values to the new `path` column as necessary.
|
|
|
|
+ # We will use SQLAlchemy core bindings to ensure safety across different databases.
|
|
|
|
+
|
|
|
|
+ file_table = table(
|
|
|
|
+ "file", column("id", String), column("meta", JSON), column("path", Text)
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ # Create connection to the database
|
|
|
|
+ connection = op.get_bind()
|
|
|
|
+
|
|
|
|
+ # Get the rows where `meta` has a path and `path` column is null (new column)
|
|
|
|
+ # Loop through each row in the result set to update the path
|
|
|
|
+ results = connection.execute(
|
|
|
|
+ sa.select(file_table.c.id, file_table.c.meta).where(
|
|
|
|
+ and_(file_table.c.path.is_(None), file_table.c.meta.isnot(None))
|
|
|
|
+ )
|
|
|
|
+ ).fetchall()
|
|
|
|
+
|
|
|
|
+ # Iterate over each row to extract and update the `path` from `meta` column
|
|
|
|
+ for row in results:
|
|
|
|
+ if "path" in row.meta:
|
|
|
|
+ # Extract the `path` field from the `meta` JSON
|
|
|
|
+ path = row.meta.get("path")
|
|
|
|
+
|
|
|
|
+ # Update the `file` table with the new `path` value
|
|
|
|
+ connection.execute(
|
|
|
|
+ file_table.update()
|
|
|
|
+ .where(file_table.c.id == row.id)
|
|
|
|
+ .values({"path": path})
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def downgrade():
|
|
|
|
+ # 1. Remove the `path` column
|
|
|
|
+ op.drop_column("file", "path")
|
|
|
|
+
|
|
|
|
+ # 2. Revert the `meta` column back to Text/JSONField
|
|
|
|
+ with op.batch_alter_table("file", schema=None) as batch_op:
|
|
|
|
+ batch_op.alter_column(
|
|
|
|
+ "meta", type_=sa.Text(), existing_type=sa.JSON(), existing_nullable=True
|
|
|
|
+ )
|