@@ -362,6 +362,40 @@ func addDisplayNameColumn(db *gorm.DB, quotedTableName string, driverName string
362362	return  nil 
363363}
364364
365+ // This helper function enforces a composite unique index on a given model. 
366+ // It checks both the existence of a database-level constraint and the corresponding index. 
367+ // This function serves as a safety fallback in case AutoMigrate fails to create the index 
368+ // due to GORM's conservative merge strategy or legacy residual indexes from earlier versions. 
369+ // 
370+ // This is particularly critical when upgrading from GORM v1 to v2, as v1's tag-based index 
371+ // declarations were often silently ignored or misapplied, especially when partial indexes 
372+ // (e.g., on "Name" only) were created before a composite index (e.g., on "Name"+"Namespace"). 
373+ // 
374+ // Arguments: 
375+ // - db: the active GORM database connection 
376+ // - model: the target model (passed by reference) 
377+ // - indexName: the logical name of the composite unique index as defined in the model's GORM tag 
378+ func  ensureUniqueCompositeIndex (db  * gorm.DB , model  interface {}, indexName  string ) {
379+ 	if  ! db .Migrator ().HasConstraint (model , indexName ) {
380+ 		if  err  :=  db .Migrator ().CreateConstraint (model , indexName ); err  !=  nil  {
381+ 			glog .Fatalf ("Failed to create constraint %s. Error: %v" , indexName , err )
382+ 		}
383+ 	}
384+ 	if  ! db .Migrator ().HasIndex (model , indexName ) {
385+ 		if  err  :=  db .Migrator ().CreateIndex (model , indexName ); err  !=  nil  {
386+ 			glog .Fatalf ("Failed to create index %s. Error: %v" , indexName , err )
387+ 		}
388+ 	}
389+ }
390+ 
391+ // This helper function enforces a composite unique index on a given model. 
392+ // Refer to ensureUniqueCompositeIndex for details. 
393+ // func ensureIndex(db *gorm.DB, model interface{}, indexName string) { 
394+ // 	if err := db.Migrator().CreateIndex(model, indexName); err != nil { 
395+ // 		glog.Fatalf("Failed to create index %s. Error: %s", indexName, err) 
396+ // 	} 
397+ // } 
398+ 
365399func  InitDBClient (initConnectionTimeout  time.Duration ) * storage.DB  {
366400	// Allowed driverName values: 
367401	// 1) To use MySQL, use `mysql` 
@@ -452,14 +486,14 @@ func InitDBClient(initConnectionTimeout time.Duration) *storage.DB {
452486		glog .Fatalf ("Failed to update the resource reference payload type. Error: %s" , response )
453487	}
454488
455- 	// NOTE: Manual AddIndex/AddUniqueIndex calls have been removed. 
456- 	// All index definitions are now declared via GORM struct tags in the  model types: 
457- 	//   – experimentuuid_createatinsec 
458- 	 //   – experimentuuid_conditions_finishedatinsec 
459- 	//   – namespace_createatinsec  
460- 	//   – namespace_conditions_finishedatinsec  
461- 	//   – name_namespace_index  
462- 	// See the `index:` and `uniqueIndex:` tags in  model.Run and model.Pipeline.  
489+ 	ensureUniqueCompositeIndex ( db ,  & model. Pipeline {},  "namespace_name" ) 
490+ 	ensureUniqueCompositeIndex ( db ,  & model. Experiment {},  "idx_name_namespace" ) 
491+ 	ensureUniqueCompositeIndex ( db ,  & model. PipelineVersion {},  "idx_pipelineid_name" ) 
492+ 
493+ 	// ensureIndex(db, &model.Run{}, "experimentuuid_createatinsec")  
494+ 	// ensureIndex(db, &model.Run{}, "experimentuuid_conditions_finishedatinsec")  
495+ 	// ensureIndex(db, &model.Run{}, "namespace_createatinsec")  
496+ 	// ensureIndex(db, & model.Run{}, "namespace_conditions_finishedatinsec")  
463497
464498	// Manual AddForeignKey() calls have been removed. 
465499	// Foreign key constraints are now defined and managed by GORM via struct tags 'constraint' 
0 commit comments