-- Migration: Update tablos table ID from SERIAL to random 24-character string -- This migration changes the tablos.id column from SERIAL to TEXT with random 24-character string IDs -- Step 1: Create function to generate random 24-character strings CREATE OR REPLACE FUNCTION generate_random_string(length INTEGER DEFAULT 24) RETURNS TEXT LANGUAGE plpgsql AS $$ DECLARE chars TEXT := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; result TEXT := ''; i INTEGER := 0; BEGIN FOR i IN 1..length LOOP result := result || substr(chars, floor(random() * length(chars) + 1)::INTEGER, 1); END LOOP; RETURN result; END; $$; -- Step 2: Drop existing foreign key constraints ALTER TABLE tablo_invites DROP CONSTRAINT IF EXISTS fk_tablo_invitations_tablo_id; ALTER TABLE tablo_access DROP CONSTRAINT IF EXISTS fk_tablo_access_tablo_id; -- Step 3: Drop the trigger that creates tablo_access records DROP TRIGGER IF EXISTS trigger_create_tablo_access ON tablos; -- Step 4: Create temporary columns for the new ID structure ALTER TABLE tablos ADD COLUMN new_id TEXT; ALTER TABLE tablo_invites ADD COLUMN new_tablo_id TEXT; ALTER TABLE tablo_access ADD COLUMN new_tablo_id TEXT; -- Step 5: Generate new random IDs for existing tablos UPDATE tablos SET new_id = generate_random_string(24); -- Step 6: Update foreign key references UPDATE tablo_invites SET new_tablo_id = ( SELECT new_id FROM tablos WHERE tablos.id = tablo_invites.tablo_id ); UPDATE tablo_access SET new_tablo_id = ( SELECT new_id FROM tablos WHERE tablos.id = tablo_access.tablo_id ); -- Step 7: Drop old columns ALTER TABLE tablo_invites DROP COLUMN tablo_id CASCADE; ALTER TABLE tablo_access DROP COLUMN tablo_id CASCADE; ALTER TABLE tablos DROP COLUMN id CASCADE; -- Step 8: Rename new columns to original names ALTER TABLE tablos RENAME COLUMN new_id TO id; ALTER TABLE tablo_invites RENAME COLUMN new_tablo_id TO tablo_id; ALTER TABLE tablo_access RENAME COLUMN new_tablo_id TO tablo_id; -- Step 9: Add constraints and indexes ALTER TABLE tablos ADD PRIMARY KEY (id); ALTER TABLE tablos ALTER COLUMN id SET NOT NULL; ALTER TABLE tablos ALTER COLUMN id SET DEFAULT generate_random_string(24); -- Step 10: Re-add foreign key constraints ALTER TABLE tablo_invites ADD CONSTRAINT fk_tablo_invitations_tablo_id FOREIGN KEY (tablo_id) REFERENCES tablos(id) ON DELETE CASCADE; ALTER TABLE tablo_access ADD CONSTRAINT fk_tablo_access_tablo_id FOREIGN KEY (tablo_id) REFERENCES tablos(id) ON DELETE CASCADE; -- Step 11: Ensure NOT NULL constraints on foreign keys ALTER TABLE tablo_invites ALTER COLUMN tablo_id SET NOT NULL; ALTER TABLE tablo_access ALTER COLUMN tablo_id SET NOT NULL; -- Step 12: Recreate the trigger function with updated signature CREATE OR REPLACE FUNCTION create_tablo_access_for_owner() RETURNS TRIGGER SECURITY DEFINER AS $$ BEGIN -- Insert a tablo_access record for the tablo owner INSERT INTO tablo_access ( tablo_id, user_id, granted_by, is_active, is_admin ) VALUES ( NEW.id, -- tablo_id: the newly created tablo's id (now TEXT) NEW.owner_id, -- user_id: the tablo owner gets access NEW.owner_id, -- granted_by: self-granted by the owner TRUE, -- is_active: access is active TRUE -- is_admin: owner has admin privileges ); RETURN NEW; END; $$ LANGUAGE plpgsql; -- Step 13: Recreate the trigger CREATE TRIGGER trigger_create_tablo_access AFTER INSERT ON tablos FOR EACH ROW EXECUTE FUNCTION create_tablo_access_for_owner(); -- Step 14: Add comment to document the changes COMMENT ON FUNCTION generate_random_string(INTEGER) IS 'Generates a random alphanumeric string of specified length (default 24 characters)'; COMMENT ON COLUMN tablos.id IS 'Primary key: random 24-character alphanumeric string'; COMMENT ON COLUMN tablo_invites.tablo_id IS 'Foreign key reference to tablos.id (24-character string)'; COMMENT ON COLUMN tablo_access.tablo_id IS 'Foreign key reference to tablos.id (24-character string)';