""" This module contains a Caribou migration. Migration Name: uuids Migration Version: 20250228112643 """ import uuid def upgrade(connection): """Several major upgrades - Update all table's id columns to be UUIDs. - Update the user's table `user` column to be named `username` - Update the chatbot's table `user_id` column to reference the `id` column in the user's table, thus changing the foreign key constraint. """ # First, create temporary tables with the new schema connection.execute(""" CREATE TABLE users_new ( id TEXT not null PRIMARY KEY, username varchar(255) not null UNIQUE, last_updated_at TIMESTAMP default CURRENT_TIMESTAMP, created_at TIMESTAMP default CURRENT_TIMESTAMP, external_auth JSON ); """) # Fetch users to generate UUIDs in Python users = connection.execute( "SELECT user, last_updated_at, created_at, external_auth FROM users" ).fetchall() # Copy data from old users table to new users table, using Python-generated UUIDs for user in users: new_uuid = uuid.uuid4().hex # Safely handle JSON connection.execute( """ INSERT INTO users_new (id, username, last_updated_at, created_at, external_auth) VALUES (?, ?, ?, ?, ?) """, (new_uuid, user[0], user[1], user[2], user[3]), ) # Create temporary quotes table with new schema connection.execute(""" CREATE TABLE quotes_new ( id TEXT not null PRIMARY KEY, quote varchar(255) not null UNIQUE, author varchar(255), channel varchar(255), created_at TIMESTAMP default CURRENT_TIMESTAMP, last_updated_at TIMESTAMP default CURRENT_TIMESTAMP ); """) # Fetch quotes to generate UUIDs in Python quotes = connection.execute( "SELECT quote, author, channel, created_at, last_updated_at FROM quotes" ).fetchall() # Copy data from old quotes table to new quotes table, using Python-generated UUIDs for quote in quotes: new_uuid = uuid.uuid4().hex connection.execute( """ INSERT INTO quotes_new (id, quote, author, channel, created_at, last_updated_at) VALUES (?, ?, ?, ?, ?, ?) """, (new_uuid, quote[0], quote[1], quote[2], quote[3], quote[4]), ) # Create mapping table to store the relationship between old user IDs and new UUIDs connection.execute(""" CREATE TEMPORARY TABLE user_id_mapping ( old_user VARCHAR(255) not null, new_id TEXT not null ); """) # Populate the mapping table connection.execute(""" INSERT INTO user_id_mapping (old_user, new_id) SELECT username, id FROM users_new; """) # Create temporary chatbot table with new schema connection.execute(""" CREATE TABLE chatbot_new ( id TEXT not null PRIMARY KEY, user_id TEXT not null UNIQUE, automatic_generation_timer INTEGER default 300 not null, automatic_quote_timer INTEGER default 500 not null, mods VARCHAR(255), created_at TIMESTAMP default CURRENT_TIMESTAMP, last_updated_at TIMESTAMP default CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users_new (id) ); """) # Fetch chatbot data to generate UUIDs in Python chatbots = connection.execute( "SELECT user_id, automatic_generation_timer, automatic_quote_timer, mods, created_at, last_updated_at FROM chatbot" ).fetchall() # Copy data from old chatbot table to new chatbot table with updated foreign key for chatbot in chatbots: # Get the new UUID for the user user_mapping = connection.execute( "SELECT new_id FROM user_id_mapping WHERE old_user = ?", (chatbot[0],) ).fetchone() new_user_id = user_mapping[0] if user_mapping else None if new_user_id: new_chatbot_uuid = uuid.uuid4().hex connection.execute( """ INSERT INTO chatbot_new (id, user_id, automatic_generation_timer, automatic_quote_timer, mods, created_at, last_updated_at) VALUES (?, ?, ?, ?, ?, ?, ?) """, ( new_chatbot_uuid, new_user_id, chatbot[1], chatbot[2], chatbot[3], chatbot[4], chatbot[5], ), ) # Drop old tables connection.execute("DROP TABLE chatbot;") connection.execute("DROP TABLE quotes;") connection.execute("DROP TABLE users;") # Rename new tables to original names connection.execute("ALTER TABLE users_new RENAME TO users;") connection.execute("ALTER TABLE quotes_new RENAME TO quotes;") connection.execute("ALTER TABLE chatbot_new RENAME TO chatbot;") # Drop temporary mapping table connection.execute("DROP TABLE user_id_mapping;") # Commit all changes connection.commit() def downgrade(connection): # add your downgrade step here pass