2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  folderimpl  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-16 01:34:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"runtime" 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"time" 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-01-21 17:06:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									claims  "github.com/grafana/authlib/types" 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-10 21:20:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/dskit/concurrency" 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-08 22:28:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/infra/db" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/infra/log" 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 18:10:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/infra/metrics" 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 18:19:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/accesscontrol" 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-10 23:48:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/dashboards" 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/folder" 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-29 09:17:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/sqlstore" 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/sqlstore/migrator" 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/util" 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  DEFAULT_BATCH_SIZE  =  999  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								type  FolderStoreImpl  struct  {  
						 
					
						
							
								
									
										
										
										
											2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									db   db . DB 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									log  log . Logger 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// sqlStore implements the store interface.
  
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								var  _  folder . Store  =  ( * FolderStoreImpl ) ( nil )  
						 
					
						
							
								
									
										
										
										
											2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ProvideStore ( db  db . DB )  * FolderStoreImpl  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  & FolderStoreImpl { db :  db ,  log :  log . New ( "folder-store" ) } 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-29 09:17:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( ss  * FolderStoreImpl )  CountInOrg ( ctx  context . Context ,  orgID  int64 )  ( int64 ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									type  result  struct  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Count  int64 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									r  :=  result { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  ss . db . WithDbSession ( ctx ,  func ( sess  * sqlstore . DBSession )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  _ ,  err  :=  sess . SQL ( "SELECT COUNT(*) AS count FROM folder WHERE org_id=?" ,  orgID ) . Get ( & r ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  r . Count ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( ss  * FolderStoreImpl )  Create ( ctx  context . Context ,  cmd  folder . CreateFolderCommand )  ( * folder . Folder ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  cmd . UID  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  folder . ErrBadRequest . Errorf ( "missing UID" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-29 02:07:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-05 03:56:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  cmd . UID  ==  cmd . ParentUID  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  folder . ErrFolderCannotBeParentOfItself 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  foldr  * folder . Folder 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-10 17:41:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/ * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										version  :=  1 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-23 22:44:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										updatedBy  :=  cmd . SignedInUser . UserID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										createdBy  :=  cmd . SignedInUser . UserID 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-10 17:41:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									* / 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-28 23:48:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  lastInsertedID  int64 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-29 02:07:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									err  :=  ss . db . WithDbSession ( ctx ,  func ( sess  * db . Session )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-28 23:48:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										var  sql  string 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-30 23:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										var  args  [ ] any 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  cmd . ParentUID  ==  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-28 23:48:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											sql  =  "INSERT INTO folder(org_id, uid, title, description, created, updated) VALUES(?, ?, ?, ?, ?, ?)" 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-30 23:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											args  =  [ ] any { cmd . OrgID ,  cmd . UID ,  cmd . Title ,  cmd . Description ,  time . Now ( ) ,  time . Now ( ) } 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  cmd . ParentUID  !=  folder . GeneralFolderUID  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  _ ,  err  :=  ss . Get ( ctx ,  folder . GetFolderQuery { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													UID :    & cmd . ParentUID , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													OrgID :  cmd . OrgID , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-10 17:41:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													return  folder . ErrFolderNotFound . Errorf ( "parent folder does not exist" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-28 23:48:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											sql  =  "INSERT INTO folder(org_id, uid, parent_uid, title, description, created, updated) VALUES(?, ?, ?, ?, ?, ?, ?)" 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-30 23:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											args  =  [ ] any { cmd . OrgID ,  cmd . UID ,  cmd . ParentUID ,  cmd . Title ,  cmd . Description ,  time . Now ( ) ,  time . Now ( ) } 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-28 23:48:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  err  error 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										lastInsertedID ,  err  =  sess . WithReturningID ( ss . db . GetDialect ( ) . DriverName ( ) ,  sql ,  args ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-28 23:48:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 18:10:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										metrics . MFolderIDsServiceCount . WithLabelValues ( metrics . Folder ) . Inc ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										foldr ,  err  =  ss . Get ( ctx ,  folder . GetFolderQuery { 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-15 23:30:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ID :  & lastInsertedID ,  // nolint:staticcheck
 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-29 02:07:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-10 21:20:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  foldr . WithURL ( ) ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( ss  * FolderStoreImpl )  Delete ( ctx  context . Context ,  UIDs  [ ] string ,  orgID  int64 )  error  {  
						 
					
						
							
								
									
										
										
										
											2024-01-31 00:26:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  len ( UIDs )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-28 21:35:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  ss . db . WithDbSession ( ctx ,  func ( sess  * db . Session )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-17 03:10:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// covered by UQE_folder_org_id_uid
 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 00:26:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										s  :=  fmt . Sprintf ( "DELETE FROM folder WHERE org_id=? AND uid IN (%s)" ,  strings . Repeat ( "?, " ,  len ( UIDs ) - 1 ) + "?" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sqlArgs  :=  make ( [ ] any ,  0 ,  len ( UIDs ) + 2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sqlArgs  =  append ( sqlArgs ,  s ,  orgID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  _ ,  uid  :=  range  UIDs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											sqlArgs  =  append ( sqlArgs ,  uid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										_ ,  err  :=  sess . Exec ( sqlArgs ... ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 00:26:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  folder . ErrDatabaseError . Errorf ( "failed to delete folders: %w" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-28 21:35:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( ss  * FolderStoreImpl )  Update ( ctx  context . Context ,  cmd  folder . UpdateFolderCommand )  ( * folder . Folder ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2022-12-20 21:00:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									updated  :=  time . Now ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uid  :=  cmd . UID 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-20 21:00:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  foldr  * folder . Folder 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 02:24:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-12 19:28:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  cmd . NewDescription  ==  nil  &&  cmd . NewTitle  ==  nil  &&  cmd . NewParentUID  ==  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 02:24:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  folder . ErrBadRequest . Errorf ( "nothing to update" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-28 21:35:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									err  :=  ss . db . WithDbSession ( ctx ,  func ( sess  * db . Session )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-04 17:04:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										sql  :=  strings . Builder { } 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-26 18:08:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										sql . WriteString ( "UPDATE folder SET " ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-04 17:04:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										columnsToUpdate  :=  [ ] string { "updated = ?" } 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-30 23:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										args  :=  [ ] any { updated } 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  cmd . NewDescription  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-04 17:04:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											columnsToUpdate  =  append ( columnsToUpdate ,  "description = ?" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-20 21:00:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											args  =  append ( args ,  * cmd . NewDescription ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  cmd . NewTitle  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-04 17:04:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											columnsToUpdate  =  append ( columnsToUpdate ,  "title = ?" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-20 21:00:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											args  =  append ( args ,  * cmd . NewTitle ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-12-20 21:00:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  cmd . NewParentUID  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-04 02:24:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  * cmd . NewParentUID  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												columnsToUpdate  =  append ( columnsToUpdate ,  "parent_uid = NULL" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												columnsToUpdate  =  append ( columnsToUpdate ,  "parent_uid = ?" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												args  =  append ( args ,  * cmd . NewParentUID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-08 18:33:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-04 17:04:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  len ( columnsToUpdate )  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  folder . ErrBadRequest . Errorf ( "no columns to update" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-26 18:08:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										sql . WriteString ( strings . Join ( columnsToUpdate ,  ", " ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-17 03:10:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// covered by UQE_folder_org_id_uid
 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-26 18:08:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										sql . WriteString ( " WHERE uid = ? AND org_id = ?" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-20 21:00:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										args  =  append ( args ,  cmd . UID ,  cmd . OrgID ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-04 17:04:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-30 23:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										args  =  append ( [ ] any { sql . String ( ) } ,  args ... ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-04 17:04:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res ,  err  :=  sess . Exec ( args ... ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  folder . ErrDatabaseError . Errorf ( "failed to update folder: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										affected ,  err  :=  res . RowsAffected ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  folder . ErrInternal . Errorf ( "failed to get affected row: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  affected  ==  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-10 20:03:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  folder . ErrInternal . Errorf ( "no folders are updated: %w" ,  folder . ErrFolderNotFound ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-20 21:00:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										foldr ,  err  =  ss . Get ( ctx ,  folder . GetFolderQuery { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											UID :    & uid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											OrgID :  cmd . OrgID , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-28 21:35:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-05-10 21:20:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  foldr . WithURL ( ) ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 01:47:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// If WithFullpath is true it computes also the full path of a folder.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The full path is a string that contains the titles of all parent folders separated by a slash.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// For example, if the folder structure is:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	A
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	└── B
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	    └── C
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The full path of C is "A/B/C".
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The full path of B is "A/B".
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The full path of A is "A".
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// If a folder contains a slash in its title, it is escaped with a backslash.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// For example, if the folder structure is:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	A
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	└── B/C
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The full path of C is "A/B\/C".
  
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( ss  * FolderStoreImpl )  Get ( ctx  context . Context ,  q  folder . GetFolderQuery )  ( * folder . Folder ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									foldr  :=  & folder . Folder { } 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-28 21:35:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									err  :=  ss . db . WithDbSession ( ctx ,  func ( sess  * db . Session )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										exists  :=  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										var  err  error 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 01:47:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										s  :=  strings . Builder { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										s . WriteString ( "SELECT *" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  q . WithFullpath  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s . WriteString ( fmt . Sprintf ( ` , %s AS fullpath ` ,  getFullpathSQL ( ss . db . GetDialect ( ) ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-10 19:22:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  q . WithFullpathUIDs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s . WriteString ( fmt . Sprintf ( ` , %s AS fullpath_uids ` ,  getFullapathUIDsSQL ( ss . db . GetDialect ( ) ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 01:47:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										s . WriteString ( " FROM folder f0" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-10 19:22:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  q . WithFullpath  ||  q . WithFullpathUIDs  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 01:47:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											s . WriteString ( getFullpathJoinsSQL ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										switch  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-06 22:04:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  q . UID  !=  nil : 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-17 03:10:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// covered UQE_folder_uid_org_id
 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 01:47:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											s . WriteString ( " WHERE f0.uid = ? AND f0.org_id = ?" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											exists ,  err  =  sess . SQL ( s . String ( ) ,  q . UID ,  q . OrgID ) . Get ( foldr ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-15 23:30:00 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// nolint:staticcheck
 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  q . ID  !=  nil : 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 01:47:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											s . WriteString ( " WHERE f0.id = ?" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 18:10:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											metrics . MFolderIDsServiceCount . WithLabelValues ( metrics . Folder ) . Inc ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-17 03:10:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// covered by primary key
 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 01:47:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											exists ,  err  =  sess . SQL ( s . String ( ) ,  q . ID ) . Get ( foldr ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  q . Title  !=  nil : 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-17 03:10:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// covered by UQE_folder_org_id_parent_uid_title
 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 01:47:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											s . WriteString ( " WHERE f0.title = ? AND f0.org_id = ?" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 17:29:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											args  :=  [ ] any { * q . Title ,  q . OrgID } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  q . ParentUID  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 01:47:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												s . WriteString ( " AND f0.parent_uid = ?" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 17:29:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												args  =  append ( args ,  * q . ParentUID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 01:47:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												s . WriteString ( " AND f0.parent_uid IS NULL" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 17:29:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											exists ,  err  =  sess . SQL ( s . String ( ) ,  args ... ) . Get ( foldr ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  folder . ErrBadRequest . Errorf ( "one of ID, UID, or Title must be included in the command" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-28 21:35:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  folder . ErrDatabaseError . Errorf ( "failed to get folder: %w" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-28 21:35:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! exists  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-10 23:48:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// embed dashboards.ErrFolderNotFound
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  folder . ErrFolderNotFound . Errorf ( "%w" ,  dashboards . ErrFolderNotFound ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-28 21:35:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-10 23:48:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 01:47:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									foldr . Fullpath  =  strings . TrimLeft ( foldr . Fullpath ,  "/" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-10 19:22:57 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									foldr . FullpathUIDs  =  strings . TrimLeft ( foldr . FullpathUIDs ,  "/" ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-10 21:20:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  foldr . WithURL ( ) ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( ss  * FolderStoreImpl )  GetParents ( ctx  context . Context ,  q  folder . GetParentsQuery )  ( [ ] * folder . Folder ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2023-03-30 16:46:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  q . UID  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  [ ] * folder . Folder { } ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-29 02:07:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  folders  [ ] * folder . Folder 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-02-17 03:10:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// covered by UQE_folder_org_id_uid
 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									recQuery  :=  ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										WITH  RECURSIVE  RecQry  AS  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											SELECT  *  FROM  folder  WHERE  uid  =  ?  AND  org_id  =  ? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											UNION  ALL  SELECT  f . *  FROM  folder  f  INNER  JOIN  RecQry  r  ON  f . uid  =  r . parent_uid  and  f . org_id  =  r . org_id 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-29 02:07:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										SELECT  *  FROM  RecQry ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									` 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-29 02:07:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-03-20 16:27:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									recursiveQueriesAreSupported ,  err  :=  ss . db . RecursiveQueriesAreSupported ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  recursiveQueriesAreSupported  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  true : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  ss . db . WithDbSession ( ctx ,  func ( sess  * db . Session )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											err  :=  sess . SQL ( recQuery ,  q . UID ,  q . OrgID ) . Find ( & folders ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  folder . ErrDatabaseError . Errorf ( "failed to get folder parents: %w" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-09 03:53:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-20 16:27:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-09 03:53:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-10 21:20:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-16 01:34:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  :=  concurrency . ForEachJob ( ctx ,  len ( folders ) ,  runtime . NumCPU ( ) ,  func ( ctx  context . Context ,  idx  int )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-10 21:20:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											folders [ idx ] . WithURL ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ss . log . Debug ( "failed to set URL to folders" ,  "err" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-20 16:27:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ss . log . Debug ( "recursive CTE subquery is not supported; it fallbacks to the iterative implementation" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ss . getParentsMySQL ( ctx ,  q ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-09 03:53:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-25 02:28:53 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  len ( folders )  <  1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// the query is expected to return at least the same folder
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// if it's empty it means that the folder does not exist
 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-26 00:24:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  folder . ErrFolderNotFound . Errorf ( "folder not found" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-25 02:28:53 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-09 03:53:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  util . Reverse ( folders [ 1 : ] ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-02 12:30:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( ss  * FolderStoreImpl )  GetChildren ( ctx  context . Context ,  q  folder . GetChildrenQuery )  ( [ ] * folder . FolderReference ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  folders  [ ] * folder . FolderReference 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-29 02:07:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-28 21:35:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									err  :=  ss . db . WithDbSession ( ctx ,  func ( sess  * db . Session )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										sql  :=  strings . Builder { } 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-30 23:46:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										args  :=  make ( [ ] any ,  0 ,  2 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-17 03:10:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// covered by UQE_folder_org_id_parent_uid_title
 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-19 16:52:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  q . UID  ==  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-16 01:34:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											sql . WriteString ( "SELECT * FROM folder WHERE parent_uid IS NULL AND org_id=?" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-19 16:52:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											args  =  append ( args ,  q . OrgID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-16 01:34:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											sql . WriteString ( "SELECT * FROM folder WHERE parent_uid=? AND org_id=?" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-19 16:52:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											args  =  append ( args ,  q . UID ,  q . OrgID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 01:47:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  len ( q . FolderUIDs )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											sql . WriteString ( " AND uid IN (" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  i ,  uid  :=  range  q . FolderUIDs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  i  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													sql . WriteString ( ", " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												sql . WriteString ( "?" ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-16 01:34:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												args  =  append ( args ,  uid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-14 01:47:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											sql . WriteString ( ")" ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-16 01:34:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 18:19:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// only list k6 folders when requested by a service account - prevents showing k6 folders in the UI for users
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-13 16:18:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  q . SignedInUser  ==  nil  ||  ! q . SignedInUser . IsIdentityType ( claims . TypeServiceAccount )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 18:19:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											sql . WriteString ( " AND uid != ?" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											args  =  append ( args ,  accesscontrol . K6FolderUID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-12-16 01:34:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										sql . WriteString ( " ORDER BY title ASC" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  q . Limit  !=  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-19 16:52:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											var  offset  int64  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  q . Page  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												offset  =  q . Limit  *  ( q . Page  -  1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-26 18:08:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											sql . WriteString ( ss . db . GetDialect ( ) . LimitOffset ( q . Limit ,  offset ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-19 16:52:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  :=  sess . SQL ( sql . String ( ) ,  args ... ) . Find ( & folders ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  folder . ErrDatabaseError . Errorf ( "failed to get folder children: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-10 21:20:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-11-03 21:21:41 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-28 21:35:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  folders ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-26 23:52:01 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2022-10-29 02:07:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( ss  * FolderStoreImpl )  getParentsMySQL ( ctx  context . Context ,  q  folder . GetParentsQuery )  ( folders  [ ] * folder . Folder ,  err  error )  {  
						 
					
						
							
								
									
										
										
										
											2022-11-09 03:53:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									err  =  ss . db . WithDbSession ( ctx ,  func ( sess  * db . Session )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										uid  :=  "" 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-17 03:10:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// covered by UQE_folder_org_id_uid
 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-18 22:12:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ok ,  err  :=  sess . SQL ( "SELECT parent_uid FROM folder WHERE org_id=? AND uid=?" ,  q . OrgID ,  q . UID ) . Get ( & uid ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-09 03:53:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ! ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-26 00:24:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  folder . ErrFolderNotFound . Errorf ( "folder not found" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-09 03:53:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											f  :=  & folder . Folder { } 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-17 03:10:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// covered by UQE_folder_org_id_uid
 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-18 22:12:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ok ,  err  :=  sess . SQL ( "SELECT * FROM folder WHERE org_id=? AND uid=?" ,  q . OrgID ,  uid ) . Get ( f ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-29 02:07:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-09 03:53:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2023-05-10 21:20:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											folders  =  append ( folders ,  f . WithURL ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-09 03:53:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											uid  =  f . ParentUID 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  len ( folders )  >  folder . MaxNestedFolderDepth  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-20 22:47:51 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												return  folder . ErrMaximumDepthReached . Errorf ( "failed to get parent folders iteratively" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-29 02:07:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-28 23:48:44 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  util . Reverse ( folders ) ,  err 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-29 02:07:25 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2022-12-08 21:49:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 00:26:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// TODO use a single query to get the height of a folder
  
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( ss  * FolderStoreImpl )  GetHeight ( ctx  context . Context ,  foldrUID  string ,  orgID  int64 ,  parentUID  * string )  ( int ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2022-12-08 21:49:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									height  :=  - 1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									queue  :=  [ ] string { foldrUID } 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-15 00:07:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  len ( queue )  >  0  &&  height  <=  folder . MaxNestedFolderDepth  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 21:49:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										length  :=  len ( queue ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										height ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										for  i  :=  0 ;  i  <  length ;  i ++  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ele  :=  queue [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											queue  =  queue [ 1 : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  parentUID  !=  nil  &&  * parentUID  ==  ele  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  0 ,  folder . ErrCircularReference 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-19 16:52:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											folders ,  err  :=  ss . GetChildren ( ctx ,  folder . GetChildrenQuery { UID :  ele ,  OrgID :  orgID } ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 21:49:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  0 ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  _ ,  f  :=  range  folders  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												queue  =  append ( queue ,  f . UID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-15 00:07:55 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  height  >  folder . MaxNestedFolderDepth  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ss . log . Warn ( "folder height exceeds the maximum allowed depth, You might have a circular reference" ,  "uid" ,  foldrUID ,  "orgId" ,  orgID ,  "maxDepth" ,  folder . MaxNestedFolderDepth ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-08 21:49:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  height ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2023-11-08 22:28:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// GetFolders returns org folders by their UIDs.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// If UIDs is empty, it returns all folders in the org.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// If WithFullpath is true it computes also the full path of a folder.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The full path is a string that contains the titles of all parent folders separated by a slash.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// For example, if the folder structure is:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	A
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	└── B
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	    └── C
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The full path of C is "A/B/C".
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The full path of B is "A/B".
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The full path of A is "A".
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// If a folder contains a slash in its title, it is escaped with a backslash.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// For example, if the folder structure is:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	A
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	└── B/C
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The full path of C is "A/B\/C".
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// If FullpathUIDs is true it computes a string that contains the UIDs of all parent folders separated by slash.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// For example, if the folder structure is:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	A (uid: "uid1")
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	└── B (uid: "uid2")
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	    └── C (uid: "uid3")
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The full path UIDs of C is "uid1/uid2/uid3".
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The full path UIDs of B is "uid1/uid2".
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The full path UIDs of A is "uid1".
  
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( ss  * FolderStoreImpl )  GetFolders ( ctx  context . Context ,  q  folder . GetFoldersFromStoreQuery )  ( [ ] * folder . Folder ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  q . BatchSize  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										q . BatchSize  =  DEFAULT_BATCH_SIZE 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-08 22:28:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-08 22:28:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  folders  [ ] * folder . Folder 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  ss . db . WithDbSession ( ctx ,  func ( sess  * db . Session )  error  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  batch ( len ( q . UIDs ) ,  int ( q . BatchSize ) ,  func ( start ,  end  int )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											partialFolders  :=  make ( [ ] * folder . Folder ,  0 ,  q . BatchSize ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											partialUIDs  :=  q . UIDs [ start : min ( end ,  len ( q . UIDs ) ) ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s  :=  strings . Builder { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s . WriteString ( ` SELECT f0.id, f0.org_id, f0.uid, f0.parent_uid, f0.title, f0.description, f0.created, f0.updated ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// compute full path column if requested
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  q . WithFullpath  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												s . WriteString ( fmt . Sprintf ( ` , %s AS fullpath ` ,  getFullpathSQL ( ss . db . GetDialect ( ) ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// compute full path UIDs column if requested
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  q . WithFullpathUIDs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												s . WriteString ( fmt . Sprintf ( ` , %s AS fullpath_uids ` ,  getFullapathUIDsSQL ( ss . db . GetDialect ( ) ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s . WriteString ( `  FROM folder f0 ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// join the same table multiple times to compute the full path of a folder
 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  q . WithFullpath  ||  q . WithFullpathUIDs  ||  len ( q . AncestorUIDs )  >  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												s . WriteString ( getFullpathJoinsSQL ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-17 03:10:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// covered by UQE_folder_org_id_uid
 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-26 18:27:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											args  :=  [ ] any { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  q . OrgID  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												s . WriteString ( `  WHERE f0.org_id=? ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												args  =  [ ] any { q . OrgID } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  len ( partialUIDs )  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												s . WriteString ( `  AND f0.uid IN (? `  +  strings . Repeat ( ", ?" ,  len ( partialUIDs ) - 1 )  +  ` ) ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												for  _ ,  uid  :=  range  partialUIDs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													args  =  append ( args ,  uid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 18:19:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// only list k6 folders when requested by a service account - prevents showing k6 folders in the UI for users
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-13 16:18:28 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  q . SignedInUser  ==  nil  ||  ! q . SignedInUser . IsIdentityType ( claims . TypeServiceAccount )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-05 18:19:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												s . WriteString ( " AND f0.uid != ? AND (f0.parent_uid != ? OR f0.parent_uid IS NULL)" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												args  =  append ( args ,  accesscontrol . K6FolderUID ,  accesscontrol . K6FolderUID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  len ( q . AncestorUIDs )  ==  0  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-18 18:56:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  q . Limit  >  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													s . WriteString ( `  ORDER BY f0.title ASC ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													s . WriteString ( `  LIMIT ? OFFSET ? ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													args  =  append ( args ,  q . Limit ,  ( q . Page - 1 ) * q . Limit ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												}  else  if  q . OrderByTitle  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-15 20:05:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													s . WriteString ( `  ORDER BY f0.title ASC ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												err  :=  sess . SQL ( s . String ( ) ,  args ... ) . Find ( & partialFolders ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												folders  =  append ( folders ,  partialFolders ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// filter out folders if they are not in the subtree of the given ancestor folders
 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  :=  batch ( len ( q . AncestorUIDs ) ,  int ( q . BatchSize ) ,  func ( start2 ,  end2  int )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												s2 ,  args2  :=  getAncestorsSQL ( ss . db . GetDialect ( ) ,  q . AncestorUIDs ,  start2 ,  end2 ,  s . String ( ) ,  args ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-15 20:05:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  q . OrderByTitle  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													s2  +=  " ORDER BY f0.title ASC" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												err  :=  sess . SQL ( s2 ,  args2 ... ) . Find ( & partialFolders ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												folders  =  append ( folders ,  partialFolders ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-08 22:28:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Add URLs
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i ,  f  :=  range  folders  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										f . Fullpath  =  strings . TrimLeft ( f . Fullpath ,  "/" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										f . FullpathUIDs  =  strings . TrimLeft ( f . FullpathUIDs ,  "/" ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-08 22:28:49 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										folders [ i ]  =  f . WithURL ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  folders ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-09-30 16:28:47 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( ss  * FolderStoreImpl )  GetDescendants ( ctx  context . Context ,  orgID  int64 ,  ancestor_uid  string )  ( [ ] * folder . Folder ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2024-01-31 00:26:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  folders  [ ] * folder . Folder 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									recursiveQueriesAreSupported ,  err  :=  ss . db . RecursiveQueriesAreSupported ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  recursiveQueriesAreSupported  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  true : 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-17 03:10:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// covered by UQE_folder_org_id_parent_uid_title
 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 00:26:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										recQuery  :=  ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										WITH  RECURSIVE  RecQry  AS  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											SELECT  *  FROM  folder  WHERE  parent_uid  =  ?  AND  org_id  =  ? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											UNION  ALL  SELECT  f . *  FROM  folder  f  INNER  JOIN  RecQry  r  ON  f . parent_uid  =  r . uid  and  f . org_id  =  r . org_id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										SELECT  *  FROM  RecQry ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  ss . db . WithDbSession ( ctx ,  func ( sess  * db . Session )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											err  :=  sess . SQL ( recQuery ,  ancestor_uid ,  orgID ) . Find ( & folders ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  folder . ErrDatabaseError . Errorf ( "failed to get folder descendants: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// this is suboptimal because results is full table scan on f0
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// but it's the best we can do without recursive CTE
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  ss . db . WithDbSession ( ctx ,  func ( sess  * db . Session )  error  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s  :=  strings . Builder { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											args  :=  make ( [ ] any ,  0 ,  1 + folder . MaxNestedFolderDepth ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											args  =  append ( args ,  orgID ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-17 03:10:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											// covered by UQE_folder_org_id_uid
 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-31 00:26:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											s . WriteString ( ` SELECT f0.id, f0.org_id, f0.uid, f0.parent_uid, f0.title, f0.description, f0.created, f0.updated ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s . WriteString ( `  FROM folder f0 ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s . WriteString ( getFullpathJoinsSQL ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s . WriteString ( `  WHERE f0.org_id=? ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s . WriteString ( `  AND ( ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  i  :=  1 ;  i  <=  folder . MaxNestedFolderDepth ;  i ++  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  i  >  1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													s . WriteString ( `  OR  ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												s . WriteString ( fmt . Sprintf ( ` f%d.uid=? ` ,  i ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												args  =  append ( args ,  ancestor_uid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											s . WriteString ( ` ) ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  sess . SQL ( s . String ( ) ,  args ... ) . Find ( & folders ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// Add URLs
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i ,  f  :=  range  folders  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										folders [ i ]  =  f . WithURL ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  folders ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  getFullpathSQL ( dialect  migrator . Dialect )  string  {  
						 
					
						
							
								
									
										
										
										
											2025-03-21 21:18:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									escaped  :=  ` \/ ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  dialect . DriverName ( )  ==  migrator . MySQL  ||  dialect . DriverName ( )  ==  migrator . Spanner  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										escaped  =  ` \\/ ` 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-07 06:12:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									concatCols  :=  make ( [ ] string ,  0 ,  folder . MaxNestedFolderDepth ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-07 06:12:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									concatCols  =  append ( concatCols ,  fmt . Sprintf ( "COALESCE(REPLACE(f0.title, '/', '%s'), '')" ,  escaped ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  i  :=  1 ;  i  <=  folder . MaxNestedFolderDepth ;  i ++  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-07 06:12:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										concatCols  =  append ( [ ] string { fmt . Sprintf ( "COALESCE(REPLACE(f%d.title, '/', '%s'), '')" ,  i ,  escaped ) ,  "'/'" } ,  concatCols ... ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  dialect . Concat ( concatCols ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  getFullapathUIDsSQL ( dialect  migrator . Dialect )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									concatCols  :=  make ( [ ] string ,  0 ,  folder . MaxNestedFolderDepth ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									concatCols  =  append ( concatCols ,  "COALESCE(f0.uid, '')" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  1 ;  i  <=  folder . MaxNestedFolderDepth ;  i ++  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										concatCols  =  append ( [ ] string { fmt . Sprintf ( "COALESCE(f%d.uid, '')" ,  i ) ,  "'/'" } ,  concatCols ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  dialect . Concat ( concatCols ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// getFullpathJoinsSQL returns a SQL fragment that joins the same table multiple times to get the full path of a folder.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  getFullpathJoinsSQL ( )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									joins  :=  make ( [ ] string ,  0 ,  folder . MaxNestedFolderDepth ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  1 ;  i  <=  folder . MaxNestedFolderDepth ;  i ++  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-02-17 03:10:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// covered by UQE_folder_org_id_uid
 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 15:27:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										joins  =  append ( joins ,  fmt . Sprintf ( `  LEFT JOIN folder f%d ON f%d.org_id = f%d.org_id AND f%d.uid = f%d.parent_uid ` ,  i ,  i ,  i - 1 ,  i ,  i - 1 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  strings . Join ( joins ,  "\n" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  getAncestorsSQL ( dialect  migrator . Dialect ,  ancestorUIDs  [ ] string ,  start  int ,  end  int ,  origSQL  string ,  origArgs  [ ] any )  ( string ,  [ ] any )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s2  :=  strings . Builder { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s2 . WriteString ( origSQL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									args2  :=  make ( [ ] any ,  0 ,  len ( ancestorUIDs ) * folder . MaxNestedFolderDepth ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									args2  =  append ( args2 ,  origArgs ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									partialAncestorUIDs  :=  ancestorUIDs [ start : min ( end ,  len ( ancestorUIDs ) ) ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									partialArgs  :=  make ( [ ] any ,  0 ,  len ( partialAncestorUIDs ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  uid  :=  range  partialAncestorUIDs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										partialArgs  =  append ( partialArgs ,  uid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s2 . WriteString ( `  AND ( f0.uid IN (? `  +  strings . Repeat ( ", ?" ,  len ( partialAncestorUIDs ) - 1 )  +  ` ) ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									args2  =  append ( args2 ,  partialArgs ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  1 ;  i  <=  folder . MaxNestedFolderDepth ;  i ++  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										s2 . WriteString ( fmt . Sprintf ( `  OR f%d.uid IN (? ` + strings . Repeat ( ", ?" ,  len ( partialAncestorUIDs ) - 1 ) + ` ) ` ,  i ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										args2  =  append ( args2 ,  partialArgs ... ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s2 . WriteString ( `  ) ` ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  s2 . String ( ) ,  args2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  batch ( count ,  batchSize  int ,  eachFn  func ( start ,  end  int )  error )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  count  ==  0  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  eachFn ( 0 ,  0 ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  i  :=  0 ;  i  <  count ;  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										end  :=  i  +  batchSize 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  end  >  count  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											end  =  count 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  :=  eachFn ( i ,  end ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										i  =  end 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}