@@ -93,8 +93,6 @@ def _create_private_workspace_query(
9393 return (
9494 sql .select (
9595 * _FOLDER_DB_MODEL_COLS ,
96- # NOTE: design INVARIANT:
97- # a user in his private workspace owns his folders
9896 sql .func .json_build_object (
9997 "read" ,
10098 sa .text ("true" ),
@@ -132,8 +130,6 @@ def _create_shared_workspace_query(
132130 shared_workspace_query = (
133131 sql .select (
134132 * _FOLDER_DB_MODEL_COLS ,
135- # NOTE: design INVARIANT:
136- # a user access rights to a folder in a SHARED workspace is inherited from the workspace
137133 workspace_access_rights_subquery .c .my_access_rights ,
138134 )
139135 .select_from (
@@ -160,12 +156,12 @@ def _create_shared_workspace_query(
160156 return shared_workspace_query
161157
162158
163- def _to_sql_expression ( table : sa . Table , order_by : OrderBy ):
159+ def _to_expression ( order_by : OrderBy ):
164160 direction_func : Callable = {
165161 OrderDirection .ASC : sql .asc ,
166162 OrderDirection .DESC : sql .desc ,
167163 }[order_by .direction ]
168- return direction_func (table .columns [order_by .field ])
164+ return direction_func (folders_v2 .columns [order_by .field ])
169165
170166
171167async def list_ ( # pylint: disable=too-many-arguments,too-many-branches
@@ -249,9 +245,7 @@ async def list_( # pylint: disable=too-many-arguments,too-many-branches
249245
250246 # Ordering and pagination
251247 list_query = (
252- combined_query .order_by (_to_sql_expression (folders_v2 , order_by ))
253- .offset (offset )
254- .limit (limit )
248+ combined_query .order_by (_to_expression (order_by )).offset (offset ).limit (limit )
255249 )
256250
257251 async with pass_or_acquire_connection (get_asyncpg_engine (app ), connection ) as conn :
@@ -279,8 +273,9 @@ async def list_trashed_folders(
279273) -> tuple [int , list [FolderDB ]]:
280274 """
281275 NOTE: this is app-wide i.e. no product, user or workspace filtered
276+ TODO: check with MD about workspaces
282277 """
283- base_query = sql .select (* _FOLDER_DB_MODEL_COLS ).where (
278+ base_query = sql .select (_FOLDER_DB_MODEL_COLS ).where (
284279 folders_v2 .c .trashed .is_not (None )
285280 )
286281
@@ -299,9 +294,7 @@ async def list_trashed_folders(
299294
300295 # Ordering and pagination
301296 list_query = (
302- base_query .order_by (_to_sql_expression (folders_v2 , order_by ))
303- .offset (offset )
304- .limit (limit )
297+ base_query .order_by (_to_expression (order_by )).offset (offset ).limit (limit )
305298 )
306299
307300 async with pass_or_acquire_connection (get_asyncpg_engine (app ), connection ) as conn :
@@ -467,24 +460,6 @@ async def delete_recursively(
467460 )
468461
469462
470- def _create_folder_hierarchy_cte (base_query : Select ):
471- folder_hierarchy_cte = base_query .cte (name = "folder_hierarchy" , recursive = True )
472-
473- # Step 2: Define the recursive case
474- folder_alias = aliased (folders_v2 )
475- recursive_query = sql .select (
476- folder_alias .c .folder_id , folder_alias .c .parent_folder_id
477- ).select_from (
478- folder_alias .join (
479- folder_hierarchy_cte ,
480- folder_alias .c .parent_folder_id == folder_hierarchy_cte .c .folder_id ,
481- )
482- )
483-
484- # Step 3: Combine base and recursive cases into a CTE
485- return folder_hierarchy_cte .union_all (recursive_query )
486-
487-
488463async def get_projects_recursively_only_if_user_is_owner (
489464 app : web .Application ,
490465 connection : AsyncConnection | None = None ,
@@ -511,9 +486,21 @@ async def get_projects_recursively_only_if_user_is_owner(
511486 (folders_v2 .c .folder_id == folder_id ) # <-- specified folder id
512487 & (folders_v2 .c .product_name == product_name )
513488 )
489+ folder_hierarchy_cte = base_query .cte (name = "folder_hierarchy" , recursive = True )
514490
515- # Step 2,3
516- folder_hierarchy_cte = _create_folder_hierarchy_cte (base_query )
491+ # Step 2: Define the recursive case
492+ folder_alias = aliased (folders_v2 )
493+ recursive_query = sql .select (
494+ folder_alias .c .folder_id , folder_alias .c .parent_folder_id
495+ ).select_from (
496+ folder_alias .join (
497+ folder_hierarchy_cte ,
498+ folder_alias .c .parent_folder_id == folder_hierarchy_cte .c .folder_id ,
499+ )
500+ )
501+
502+ # Step 3: Combine base and recursive cases into a CTE
503+ folder_hierarchy_cte = folder_hierarchy_cte .union_all (recursive_query )
517504
518505 # Step 4: Execute the query to get all descendants
519506 final_query = sql .select (folder_hierarchy_cte )
@@ -557,9 +544,21 @@ async def get_all_folders_and_projects_ids_recursively(
557544 (folders_v2 .c .folder_id == folder_id ) # <-- specified folder id
558545 & (folders_v2 .c .product_name == product_name )
559546 )
547+ folder_hierarchy_cte = base_query .cte (name = "folder_hierarchy" , recursive = True )
560548
561- # Step 2, 3
562- folder_hierarchy_cte = _create_folder_hierarchy_cte (base_query )
549+ # Step 2: Define the recursive case
550+ folder_alias = aliased (folders_v2 )
551+ recursive_query = sql .select (
552+ folder_alias .c .folder_id , folder_alias .c .parent_folder_id
553+ ).select_from (
554+ folder_alias .join (
555+ folder_hierarchy_cte ,
556+ folder_alias .c .parent_folder_id == folder_hierarchy_cte .c .folder_id ,
557+ )
558+ )
559+
560+ # Step 3: Combine base and recursive cases into a CTE
561+ folder_hierarchy_cte = folder_hierarchy_cte .union_all (recursive_query )
563562
564563 # Step 4: Execute the query to get all descendants
565564 final_query = sql .select (folder_hierarchy_cte )
@@ -594,9 +593,21 @@ async def get_folders_recursively(
594593 (folders_v2 .c .folder_id == folder_id ) # <-- specified folder id
595594 & (folders_v2 .c .product_name == product_name )
596595 )
596+ folder_hierarchy_cte = base_query .cte (name = "folder_hierarchy" , recursive = True )
597+
598+ # Step 2: Define the recursive case
599+ folder_alias = aliased (folders_v2 )
600+ recursive_query = sql .select (
601+ folder_alias .c .folder_id , folder_alias .c .parent_folder_id
602+ ).select_from (
603+ folder_alias .join (
604+ folder_hierarchy_cte ,
605+ folder_alias .c .parent_folder_id == folder_hierarchy_cte .c .folder_id ,
606+ )
607+ )
597608
598- # Step 2, 3
599- folder_hierarchy_cte = _create_folder_hierarchy_cte ( base_query )
609+ # Step 3: Combine base and recursive cases into a CTE
610+ folder_hierarchy_cte = folder_hierarchy_cte . union_all ( recursive_query )
600611
601612 # Step 4: Execute the query to get all descendants
602613 final_query = sql .select (folder_hierarchy_cte )
0 commit comments