// Package database define database operation functions package database import ( "context" "fmt" "modelRT/constants" "modelRT/model" "modelRT/sql" "gorm.io/gorm" ) type parameterInitializationRoute struct { TableName string `gorm:"column:name"` ModelName string `gorm:"column:tag"` AttributeGroup string `gorm:"column:group_name"` } // QueryParameterInitializationRecords loads every parameter accepted by the // data-object query API. Dynamic parameters are resolved through // project_manager; component parameters are read directly from component. func QueryParameterInitializationRecords(ctx context.Context, db *gorm.DB) ([]model.ParameterInitializationRecord, error) { if db == nil { return nil, fmt.Errorf("postgres client is nil") } var routes []parameterInitializationRoute if err := db.WithContext(ctx). Raw( compactParameterSQL(sql.ParameterInitializationRoutes), constants.SupportedDynamicParameterAttributeGroups(), ). Scan(&routes).Error; err != nil { return nil, fmt.Errorf("query parameter initialization routes: %w", err) } if err := validateParameterInitializationRoutes(routes); err != nil { return nil, err } records := make([]model.ParameterInitializationRecord, 0) for _, route := range routes { quotedTableName := `"` + route.TableName + `"` query := compactParameterSQL( fmt.Sprintf(sql.DynamicParameterInitializationRows, quotedTableName), ) var tableRecords []model.ParameterInitializationRecord if err := db.WithContext(ctx). Raw(query, route.TableName, route.ModelName, route.AttributeGroup). Scan(&tableRecords).Error; err != nil { return nil, fmt.Errorf( "query parameter initialization table %q for model %q group %q: %w", route.TableName, route.ModelName, route.AttributeGroup, err, ) } if err := validateParameterInitializationRecords(tableRecords); err != nil { return nil, fmt.Errorf("validate parameter initialization table %q: %w", route.TableName, err) } records = append(records, tableRecords...) } var componentRecords []model.ParameterInitializationRecord if err := db.WithContext(ctx). Raw(compactParameterSQL(sql.ComponentParameterInitializationRows)). Scan(&componentRecords).Error; err != nil { return nil, fmt.Errorf("query component parameter initialization records: %w", err) } if err := validateParameterInitializationRecords(componentRecords); err != nil { return nil, fmt.Errorf("validate component parameter initialization records: %w", err) } records = append(records, componentRecords...) return records, nil } func validateParameterInitializationRoutes(routes []parameterInitializationRoute) error { seen := make(map[string]struct{}, len(routes)) for _, route := range routes { if !validParameterTableName(route.TableName) { return fmt.Errorf("project_manager contains unsupported parameter table name %q", route.TableName) } if !constants.IsSupportedParameterAttributeGroup(route.AttributeGroup) || route.AttributeGroup == constants.ComponentParameterAttributeGroup { return fmt.Errorf("project_manager contains unsupported dynamic attribute group %q", route.AttributeGroup) } key := route.ModelName + "\x00" + route.AttributeGroup if _, exists := seen[key]; exists { return fmt.Errorf( "model %q and attribute group %q match more than one project_manager record", route.ModelName, route.AttributeGroup, ) } seen[key] = struct{}{} } return nil } func validateParameterInitializationRecords(records []model.ParameterInitializationRecord) error { for _, record := range records { switch record.DynamicRecordCount { case 1: case 0: return fmt.Errorf( "component %q has no %q parameter record", record.ComponentTag, record.AttributeGroup, ) default: return fmt.Errorf( "component %q has %d %q parameter records", record.ComponentTag, record.DynamicRecordCount, record.AttributeGroup, ) } if record.AttributeName == "" || record.AttributeType == "" { return fmt.Errorf( "component %q group %q contains an invalid parameter column", record.ComponentTag, record.AttributeGroup, ) } switch record.DescriptionCount { case 0: return fmt.Errorf("parameter description not found for attribute %q", record.AttributeName) case 1: if !record.Description.Valid { return fmt.Errorf("parameter description is null for attribute %q", record.AttributeName) } default: return fmt.Errorf("ambiguous parameter description for attribute %q", record.AttributeName) } } return nil }