@@ -111,18 +111,31 @@ def upgrade() -> None:
111111
112112def downgrade () -> None :
113113 # ### commands auto generated by Alembic - please adjust! ###
114+ #
115+ # This downgrade restores the original enum-based role columns by:
116+ # 1. Creating the enum types
117+ # 2. Adding role columns as nullable
118+ # 3. Populating role values from role_id via the role table
119+ # 4. Making the columns NOT NULL
120+ # 5. Dropping the role_id columns and constraints
121+ #
122+ # Note: The original schema did NOT have server_default on invitation/org_invitation
123+ # role columns, but membership/org_membership did have defaults.
124+
125+ # Step 1: Create enum types
114126 sa .Enum ("VIEWER" , "EDITOR" , "ADMIN" , name = "workspacerole" ).create (op .get_bind ())
115127 sa .Enum ("MEMBER" , "ADMIN" , "OWNER" , name = "orgrole" ).create (op .get_bind ())
128+
129+ # Step 2: Add role columns as nullable
116130 op .add_column (
117131 "organization_membership" ,
118132 sa .Column (
119133 "role" ,
120134 postgresql .ENUM (
121135 "MEMBER" , "ADMIN" , "OWNER" , name = "orgrole" , create_type = False
122136 ),
123- server_default = sa .text ("'MEMBER'::orgrole" ),
124137 autoincrement = False ,
125- nullable = False ,
138+ nullable = True ,
126139 ),
127140 )
128141 op .add_column (
@@ -133,28 +146,18 @@ def downgrade() -> None:
133146 "MEMBER" , "ADMIN" , "OWNER" , name = "orgrole" , create_type = False
134147 ),
135148 autoincrement = False ,
136- nullable = False ,
149+ nullable = True ,
137150 ),
138151 )
139- op .drop_constraint (
140- op .f ("fk_organization_invitation_role_id_role" ),
141- "organization_invitation" ,
142- type_ = "foreignkey" ,
143- )
144- op .drop_index (
145- op .f ("ix_organization_invitation_role_id" ), table_name = "organization_invitation"
146- )
147- op .drop_column ("organization_invitation" , "role_id" )
148152 op .add_column (
149153 "membership" ,
150154 sa .Column (
151155 "role" ,
152156 postgresql .ENUM (
153157 "VIEWER" , "EDITOR" , "ADMIN" , name = "workspacerole" , create_type = False
154158 ),
155- server_default = sa .text ("'EDITOR'::workspacerole" ),
156159 autoincrement = False ,
157- nullable = False ,
160+ nullable = True ,
158161 ),
159162 )
160163 op .add_column (
@@ -165,9 +168,77 @@ def downgrade() -> None:
165168 "VIEWER" , "EDITOR" , "ADMIN" , name = "workspacerole" , create_type = False
166169 ),
167170 autoincrement = False ,
168- nullable = False ,
171+ nullable = True ,
169172 ),
170173 )
174+
175+ # Step 3: Populate role values from role_id via the role table
176+ # Organization membership: role_id -> role.slug -> uppercase enum
177+ op .execute (
178+ """
179+ UPDATE organization_membership om
180+ SET role = UPPER(r.slug)::orgrole
181+ FROM role r
182+ WHERE om.role_id = r.id
183+ """
184+ )
185+
186+ # Organization invitation: role_id -> role.slug -> uppercase enum
187+ op .execute (
188+ """
189+ UPDATE organization_invitation oi
190+ SET role = UPPER(r.slug)::orgrole
191+ FROM role r
192+ WHERE oi.role_id = r.id
193+ """
194+ )
195+
196+ # Workspace membership: role_id -> role.slug -> uppercase enum
197+ op .execute (
198+ """
199+ UPDATE membership m
200+ SET role = UPPER(r.slug)::workspacerole
201+ FROM role r
202+ WHERE m.role_id = r.id
203+ """
204+ )
205+
206+ # Workspace invitation: role_id -> role.slug -> uppercase enum
207+ op .execute (
208+ """
209+ UPDATE invitation i
210+ SET role = UPPER(r.slug)::workspacerole
211+ FROM role r
212+ WHERE i.role_id = r.id
213+ """
214+ )
215+
216+ # Step 4: Make columns NOT NULL and add server_default where original schema had it
217+ op .alter_column ("organization_membership" , "role" , nullable = False )
218+ op .alter_column (
219+ "organization_membership" ,
220+ "role" ,
221+ server_default = sa .text ("'MEMBER'::orgrole" ),
222+ )
223+ op .alter_column ("organization_invitation" , "role" , nullable = False )
224+ op .alter_column ("membership" , "role" , nullable = False )
225+ op .alter_column (
226+ "membership" ,
227+ "role" ,
228+ server_default = sa .text ("'EDITOR'::workspacerole" ),
229+ )
230+ op .alter_column ("invitation" , "role" , nullable = False )
231+
232+ # Step 5: Drop role_id columns and constraints
233+ op .drop_constraint (
234+ op .f ("fk_organization_invitation_role_id_role" ),
235+ "organization_invitation" ,
236+ type_ = "foreignkey" ,
237+ )
238+ op .drop_index (
239+ op .f ("ix_organization_invitation_role_id" ), table_name = "organization_invitation"
240+ )
241+ op .drop_column ("organization_invitation" , "role_id" )
171242 op .drop_constraint (
172243 op .f ("fk_invitation_role_id_role" ), "invitation" , type_ = "foreignkey"
173244 )
0 commit comments