diff --git a/gorm.go b/gorm.go index a209bb09b..27897cd04 100644 --- a/gorm.go +++ b/gorm.go @@ -41,6 +41,11 @@ type Config struct { // default maxsize=int64 Max value and ttl=1h PrepareStmtMaxSize int PrepareStmtTTL time.Duration + // PrepareStmtAutoSave sets autosave_prepared_statements for PostgreSQL + // Valid values: true or false + // This helps handle prepared statement cache invalidation when schema changes + // Only applicable for PostgreSQL + PrepareStmtAutoSave *bool // DisableAutomaticPing DisableAutomaticPing bool @@ -239,6 +244,10 @@ func Open(dialector Dialector, opts ...Option) (db *DB, err error) { } } + if err == nil && config.PrepareStmtAutoSave != nil { + err = db.configureAutoSave(context.Background()) + } + if err != nil { config.Logger.Error(context.Background(), "failed to initialize database, got error %v", err) } @@ -543,3 +552,28 @@ func (db *DB) ToSQL(queryFn func(tx *DB) *DB) string { return db.Dialector.Explain(stmt.SQL.String(), stmt.Vars...) } + +// configureAutoSave sets the autosave_prepared_statements parameter for PostgreSQL +// This helps handle prepared statement cache invalidation when schema changes +// Only applicable for PostgreSQL databases +func (db *DB) configureAutoSave(ctx context.Context) error { + if db.PrepareStmtAutoSave == nil { + return nil + } + + // Only PostgreSQL supports autosave_prepared_statements parameter + if db.Dialector.Name() != "postgres" { + db.Logger.Warn(ctx, "PrepareStmtAutoSave is only supported for PostgreSQL, skipping for %s", db.Dialector.Name()) + return nil + } + + value := *db.PrepareStmtAutoSave + + // Execute SET command on the connection + sql := fmt.Sprintf("SET autosave_prepared_statements = %v", value) + if err := db.Exec(sql).Error; err != nil { + return fmt.Errorf("failed to set autosave_prepared_statements on PostgreSQL: %w", err) + } + + return nil +}