diff --git a/go.mod b/go.mod index a814e83e7..3d7c25db4 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,7 @@ require ( gorm.io/driver/mysql v1.6.0 gorm.io/driver/postgres v1.6.0 gorm.io/driver/sqlite v1.6.0 - gorm.io/gorm v1.31.1 + gorm.io/gorm v1.31.2 ) replace github.com/mattn/go-sqlite3 => github.com/gabriel-samfira/go-sqlite3 v0.0.0-20251005121134-bc61ecf9b4c7 diff --git a/go.sum b/go.sum index 20f7a2d18..dee42a12d 100644 --- a/go.sum +++ b/go.sum @@ -296,5 +296,5 @@ gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ= gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8= gorm.io/driver/sqlserver v1.6.0 h1:VZOBQVsVhkHU/NzNhRJKoANt5pZGQAS1Bwc6m6dgfnc= gorm.io/driver/sqlserver v1.6.0/go.mod h1:WQzt4IJo/WHKnckU9jXBLMJIVNMVeTu25dnOzehntWw= -gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg= -gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= +gorm.io/gorm v1.31.2 h1:3o8FXNo9v9S858gil+3LlZA1LkCOzgb4g5BL64FgaCo= +gorm.io/gorm v1.31.2/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= diff --git a/vendor/gorm.io/gorm/callbacks.go b/vendor/gorm.io/gorm/callbacks.go index bd97f0404..9f02cd8b9 100644 --- a/vendor/gorm.io/gorm/callbacks.go +++ b/vendor/gorm.io/gorm/callbacks.go @@ -310,7 +310,7 @@ func sortCallbacks(cs []*callback) (fns []func(*DB), err error) { // if after callback sorted, append current callback to last sorted = append(sorted, c.name) } else if curIdx < sortedIdx { - return fmt.Errorf("conflicting callback %s with before %s", c.name, c.after) + return fmt.Errorf("conflicting callback %s with after %s", c.name, c.after) } } else if idx := getRIndex(names, c.after); idx != -1 { // if after callback exists but haven't sorted diff --git a/vendor/gorm.io/gorm/callbacks/callbacks.go b/vendor/gorm.io/gorm/callbacks/callbacks.go index d681aef36..15835af78 100644 --- a/vendor/gorm.io/gorm/callbacks/callbacks.go +++ b/vendor/gorm.io/gorm/callbacks/callbacks.go @@ -1,3 +1,4 @@ +// Package callbacks provides the default callback functions for GORM operations such as create, query, update, and delete. package callbacks import ( diff --git a/vendor/gorm.io/gorm/callbacks/delete.go b/vendor/gorm.io/gorm/callbacks/delete.go index 07ed6feef..2a90a616d 100644 --- a/vendor/gorm.io/gorm/callbacks/delete.go +++ b/vendor/gorm.io/gorm/callbacks/delete.go @@ -171,12 +171,17 @@ func Delete(config *Config) func(db *gorm.DB) { } if rows, err := db.Statement.ConnPool.QueryContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...); db.AddError(err) == nil { + defer func() { + if err := rows.Close(); err != nil { + _ = db.AddError(err) + } + }() + gorm.Scan(rows, db, mode) if db.Statement.Result != nil { db.Statement.Result.RowsAffected = db.RowsAffected } - db.AddError(rows.Close()) } } } diff --git a/vendor/gorm.io/gorm/callbacks/update.go b/vendor/gorm.io/gorm/callbacks/update.go index 8e2782e16..4ad96d555 100644 --- a/vendor/gorm.io/gorm/callbacks/update.go +++ b/vendor/gorm.io/gorm/callbacks/update.go @@ -87,11 +87,16 @@ func Update(config *Config) func(db *gorm.DB) { if !db.DryRun && db.Error == nil { if ok, mode := hasReturning(db, supportReturning); ok { if rows, err := db.Statement.ConnPool.QueryContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...); db.AddError(err) == nil { + defer func() { + if err := rows.Close(); err != nil { + _ = db.AddError(err) + } + }() + dest := db.Statement.Dest db.Statement.Dest = db.Statement.ReflectValue.Addr().Interface() gorm.Scan(rows, db, mode) db.Statement.Dest = dest - db.AddError(rows.Close()) if db.Statement.Result != nil { db.Statement.Result.RowsAffected = db.RowsAffected diff --git a/vendor/gorm.io/gorm/clause/clause.go b/vendor/gorm.io/gorm/clause/clause.go index 1354fc057..c69e1c9e0 100644 --- a/vendor/gorm.io/gorm/clause/clause.go +++ b/vendor/gorm.io/gorm/clause/clause.go @@ -1,3 +1,4 @@ +// Package clause provides the clause interface and common clause implementations for GORM. package clause // Interface clause interface diff --git a/vendor/gorm.io/gorm/clause/expression.go b/vendor/gorm.io/gorm/clause/expression.go index 3140846ef..cbabde20a 100644 --- a/vendor/gorm.io/gorm/clause/expression.go +++ b/vendor/gorm.io/gorm/clause/expression.go @@ -34,25 +34,7 @@ func (expr Expr) Build(builder Builder) { for _, v := range []byte(expr.SQL) { if v == '?' && len(expr.Vars) > idx { if afterParenthesis || expr.WithoutParentheses { - if _, ok := expr.Vars[idx].(driver.Valuer); ok { - builder.AddVar(builder, expr.Vars[idx]) - } else { - switch rv := reflect.ValueOf(expr.Vars[idx]); rv.Kind() { - case reflect.Slice, reflect.Array: - if rv.Len() == 0 { - builder.AddVar(builder, nil) - } else { - for i := 0; i < rv.Len(); i++ { - if i > 0 { - builder.WriteByte(',') - } - builder.AddVar(builder, rv.Index(i).Interface()) - } - } - default: - builder.AddVar(builder, expr.Vars[idx]) - } - } + processValue(builder, expr.Vars[idx]) } else { builder.AddVar(builder, expr.Vars[idx]) } @@ -130,7 +112,11 @@ func (expr NamedExpr) Build(builder Builder) { } else if v == ' ' || v == ',' || v == ')' || v == '"' || v == '\'' || v == '`' || v == '\r' || v == '\n' || v == ';' { if inName { if nv, ok := namedMap[string(name)]; ok { - builder.AddVar(builder, nv) + if afterParenthesis { + processValue(builder, nv) + } else { + builder.AddVar(builder, nv) + } } else { builder.WriteByte('@') builder.WriteString(string(name)) @@ -142,25 +128,7 @@ func (expr NamedExpr) Build(builder Builder) { builder.WriteByte(v) } else if v == '?' && len(expr.Vars) > idx { if afterParenthesis { - if _, ok := expr.Vars[idx].(driver.Valuer); ok { - builder.AddVar(builder, expr.Vars[idx]) - } else { - switch rv := reflect.ValueOf(expr.Vars[idx]); rv.Kind() { - case reflect.Slice, reflect.Array: - if rv.Len() == 0 { - builder.AddVar(builder, nil) - } else { - for i := 0; i < rv.Len(); i++ { - if i > 0 { - builder.WriteByte(',') - } - builder.AddVar(builder, rv.Index(i).Interface()) - } - } - default: - builder.AddVar(builder, expr.Vars[idx]) - } - } + processValue(builder, expr.Vars[idx]) } else { builder.AddVar(builder, expr.Vars[idx]) } @@ -188,6 +156,31 @@ func (expr NamedExpr) Build(builder Builder) { } } +// processValue handles different value types appropriately for SQL parameter binding +// It checks for driver.Valuer first, then handles slices/arrays, and finally adds single values +func processValue(builder Builder, value interface{}) { + if _, ok := value.(driver.Valuer); ok { + builder.AddVar(builder, value) + return + } + + switch rv := reflect.ValueOf(value); rv.Kind() { + case reflect.Slice, reflect.Array: + if rv.Len() == 0 { + builder.AddVar(builder, nil) + } else { + for i := 0; i < rv.Len(); i++ { + if i > 0 { + builder.WriteByte(',') + } + builder.AddVar(builder, rv.Index(i).Interface()) + } + } + default: + builder.AddVar(builder, value) + } +} + // IN Whether a value is within a set of values type IN struct { Column interface{} diff --git a/vendor/gorm.io/gorm/finisher_api.go b/vendor/gorm.io/gorm/finisher_api.go index e9e35f1bf..1d0825235 100644 --- a/vendor/gorm.io/gorm/finisher_api.go +++ b/vendor/gorm.io/gorm/finisher_api.go @@ -46,11 +46,21 @@ func (db *DB) CreateInBatches(value interface{}, batchSize int) (tx *DB) { } subtx := tx.getInstance() - subtx.Statement.Dest = reflectValue.Slice(i, ends).Interface() + batchSlice := reflect.New(reflectValue.Type()) + batchSlice.Elem().Set(reflectValue.Slice(i, ends)) + subtx.Statement.Dest = batchSlice.Interface() + subtx.callbacks.Create().Execute(subtx) + if subtx.Error != nil { return subtx.Error } + + resultSlice := reflect.Indirect(batchSlice) + for j := 0; j < resultSlice.Len(); j++ { + reflectValue.Index(i + j).Set(resultSlice.Index(j)) + } + rowsAffected += subtx.RowsAffected } return nil @@ -533,13 +543,18 @@ func (db *DB) Scan(dest interface{}) (tx *DB) { tx.Config = &config if rows, err := tx.Rows(); err == nil { + defer func() { + if err := rows.Close(); err != nil { + _ = tx.AddError(err) + } + }() + if rows.Next() { tx.ScanRows(rows, dest) } else { tx.RowsAffected = 0 tx.AddError(rows.Err()) } - tx.AddError(rows.Close()) } currentLogger.Trace(tx.Statement.Context, newLogger.BeginAt, func() (string, int64) { diff --git a/vendor/gorm.io/gorm/generics.go b/vendor/gorm.io/gorm/generics.go index 166d1520d..f5f4bede0 100644 --- a/vendor/gorm.io/gorm/generics.go +++ b/vendor/gorm.io/gorm/generics.go @@ -17,9 +17,13 @@ import ( type result struct { Result sql.Result RowsAffected int64 + Error error } func (info *result) ModifyStatement(stmt *Statement) { + info.Result = nil + info.RowsAffected = 0 + info.Error = nil stmt.Result = info } @@ -659,11 +663,13 @@ func (g execG[T]) FindInBatches(ctx context.Context, batchSize int, fc func(data } func (g execG[T]) Row(ctx context.Context) *sql.Row { - return g.g.apply(ctx).Row() + var r T + return g.g.apply(ctx).Model(r).Row() } func (g execG[T]) Rows(ctx context.Context) (*sql.Rows, error) { - return g.g.apply(ctx).Rows() + var r T + return g.g.apply(ctx).Model(r).Rows() } func (c chainG[T]) processSet(items ...clause.Assigner) setCreateOrUpdateG[T] { diff --git a/vendor/gorm.io/gorm/gorm.go b/vendor/gorm.io/gorm/gorm.go index a209bb09b..a0a10adf9 100644 --- a/vendor/gorm.io/gorm/gorm.go +++ b/vendor/gorm.io/gorm/gorm.go @@ -1,3 +1,5 @@ +// Package gorm is a full-featured, developer-friendly ORM for Golang. +// See https://gorm.io for documentation and community. package gorm import ( @@ -31,7 +33,9 @@ type Config struct { FullSaveAssociations bool // Logger Logger logger.Interface - // NowFunc the function to be used when creating a new timestamp + // NowFunc the function to be used when creating a new timestamp. + // It defaults to time.Now().Local(), so return values in the desired + // location when overriding it for timezone-sensitive applications. NowFunc func() time.Time // DryRun generate sql without execute DryRun bool @@ -124,8 +128,10 @@ type Session struct { QueryFields bool Context context.Context Logger logger.Interface - NowFunc func() time.Time - CreateBatchSize int + // NowFunc overrides the function used when creating a new timestamp + // for this session. + NowFunc func() time.Time + CreateBatchSize int } // Open initialize db session based on dialector @@ -236,6 +242,11 @@ func Open(dialector Dialector, opts ...Option) (db *DB, err error) { if err == nil && !config.DisableAutomaticPing { if pinger, ok := db.ConnPool.(interface{ Ping() error }); ok { err = pinger.Ping() + if err != nil { + if db, _ := db.DB(); db != nil { + _ = db.Close() + } + } } } @@ -404,6 +415,9 @@ func (db *DB) AddError(err error) error { } else { db.Error = fmt.Errorf("%v; %w", db.Error, err) } + if db.Statement != nil && db.Statement.Result != nil { + db.Statement.Result.Error = db.Error + } } return db.Error } diff --git a/vendor/gorm.io/gorm/internal/lru/lru.go b/vendor/gorm.io/gorm/internal/lru/lru.go index 4f21589a0..fbb3b40a3 100644 --- a/vendor/gorm.io/gorm/internal/lru/lru.go +++ b/vendor/gorm.io/gorm/internal/lru/lru.go @@ -1,3 +1,4 @@ +// Package lru provides a thread-safe Least Recently Used (LRU) cache with expirable entries. package lru // golang -lru @@ -18,7 +19,7 @@ type LRU[K comparable, V any] struct { onEvict EvictCallback[K, V] // expirable options - mu sync.Mutex + mu sync.RWMutex ttl time.Duration done chan struct{} @@ -161,8 +162,8 @@ func (c *LRU[K, V]) Get(key K) (value V, ok bool) { // Contains checks if a key is in the cache, without updating the recent-ness // or deleting it for being stale. func (c *LRU[K, V]) Contains(key K) (ok bool) { - c.mu.Lock() - defer c.mu.Unlock() + c.mu.RLock() + defer c.mu.RUnlock() _, ok = c.items[key] return ok } @@ -170,8 +171,8 @@ func (c *LRU[K, V]) Contains(key K) (ok bool) { // Peek returns the key value (or undefined if not found) without updating // the "recently used"-ness of the key. func (c *LRU[K, V]) Peek(key K) (value V, ok bool) { - c.mu.Lock() - defer c.mu.Unlock() + c.mu.RLock() + defer c.mu.RUnlock() var ent *Entry[K, V] if ent, ok = c.items[key]; ok { // Expired item check @@ -208,8 +209,8 @@ func (c *LRU[K, V]) RemoveOldest() (key K, value V, ok bool) { // GetOldest returns the oldest entry func (c *LRU[K, V]) GetOldest() (key K, value V, ok bool) { - c.mu.Lock() - defer c.mu.Unlock() + c.mu.RLock() + defer c.mu.RUnlock() if ent := c.evictList.Back(); ent != nil { return ent.Key, ent.Value, true } @@ -217,8 +218,8 @@ func (c *LRU[K, V]) GetOldest() (key K, value V, ok bool) { } func (c *LRU[K, V]) KeyValues() map[K]V { - c.mu.Lock() - defer c.mu.Unlock() + c.mu.RLock() + defer c.mu.RUnlock() maps := make(map[K]V) now := time.Now() for ent := c.evictList.Back(); ent != nil; ent = ent.PrevEntry() { @@ -234,8 +235,8 @@ func (c *LRU[K, V]) KeyValues() map[K]V { // Keys returns a slice of the keys in the cache, from oldest to newest. // Expired entries are filtered out. func (c *LRU[K, V]) Keys() []K { - c.mu.Lock() - defer c.mu.Unlock() + c.mu.RLock() + defer c.mu.RUnlock() keys := make([]K, 0, len(c.items)) now := time.Now() for ent := c.evictList.Back(); ent != nil; ent = ent.PrevEntry() { @@ -250,8 +251,8 @@ func (c *LRU[K, V]) Keys() []K { // Values returns a slice of the values in the cache, from oldest to newest. // Expired entries are filtered out. func (c *LRU[K, V]) Values() []V { - c.mu.Lock() - defer c.mu.Unlock() + c.mu.RLock() + defer c.mu.RUnlock() values := make([]V, 0, len(c.items)) now := time.Now() for ent := c.evictList.Back(); ent != nil; ent = ent.PrevEntry() { @@ -265,8 +266,8 @@ func (c *LRU[K, V]) Values() []V { // Len returns the number of items in the cache. func (c *LRU[K, V]) Len() int { - c.mu.Lock() - defer c.mu.Unlock() + c.mu.RLock() + defer c.mu.RUnlock() return c.evictList.Length() } diff --git a/vendor/gorm.io/gorm/internal/stmt_store/stmt_store.go b/vendor/gorm.io/gorm/internal/stmt_store/stmt_store.go index a82b2cf5c..6f13ebbc3 100644 --- a/vendor/gorm.io/gorm/internal/stmt_store/stmt_store.go +++ b/vendor/gorm.io/gorm/internal/stmt_store/stmt_store.go @@ -1,3 +1,4 @@ +// Package stmt_store provides an implementation of a statement cache for SQL statements. package stmt_store import ( diff --git a/vendor/gorm.io/gorm/logger/logger.go b/vendor/gorm.io/gorm/logger/logger.go index 8088cde27..0fec15189 100644 --- a/vendor/gorm.io/gorm/logger/logger.go +++ b/vendor/gorm.io/gorm/logger/logger.go @@ -1,3 +1,4 @@ +// Package logger provides a logger interface and its implementation for GORM. package logger import ( diff --git a/vendor/gorm.io/gorm/logger/sql.go b/vendor/gorm.io/gorm/logger/sql.go index ad4787956..899f02673 100644 --- a/vendor/gorm.io/gorm/logger/sql.go +++ b/vendor/gorm.io/gorm/logger/sql.go @@ -85,12 +85,14 @@ func ExplainSQL(sql string, numericPlaceholder *regexp.Regexp, escaper string, a case fmt.Stringer: reflectValue := reflect.ValueOf(v) switch reflectValue.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - vars[idx] = fmt.Sprintf("%d", reflectValue.Interface()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + vars[idx] = strconv.FormatInt(reflectValue.Int(), 10) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + vars[idx] = strconv.FormatUint(reflectValue.Uint(), 10) case reflect.Float32, reflect.Float64: - vars[idx] = fmt.Sprintf("%.6f", reflectValue.Interface()) + vars[idx] = strconv.FormatFloat(reflectValue.Float(), 'f', 6, 64) case reflect.Bool: - vars[idx] = fmt.Sprintf("%t", reflectValue.Interface()) + vars[idx] = strconv.FormatBool(reflectValue.Bool()) case reflect.String: vars[idx] = escaper + strings.ReplaceAll(fmt.Sprintf("%v", v), escaper, escaper+escaper) + escaper default: @@ -124,10 +126,13 @@ func ExplainSQL(sql string, numericPlaceholder *regexp.Regexp, escaper string, a } else if rv.Kind() == reflect.Ptr && !rv.IsZero() { convertParams(reflect.Indirect(rv).Interface(), idx) } else if isNumeric(rv.Kind()) { - if rv.CanInt() || rv.CanUint() { - vars[idx] = fmt.Sprintf("%d", rv.Interface()) - } else { - vars[idx] = fmt.Sprintf("%.6f", rv.Interface()) + switch { + case rv.CanInt(): + vars[idx] = strconv.FormatInt(rv.Int(), 10) + case rv.CanUint(): + vars[idx] = strconv.FormatUint(rv.Uint(), 10) + default: + vars[idx] = strconv.FormatFloat(rv.Float(), 'f', 6, 64) } } else { for _, t := range convertibleTypes { diff --git a/vendor/gorm.io/gorm/migrator/column_type.go b/vendor/gorm.io/gorm/migrator/column_type.go index c6fdd6b2d..e1c5e942d 100644 --- a/vendor/gorm.io/gorm/migrator/column_type.go +++ b/vendor/gorm.io/gorm/migrator/column_type.go @@ -28,7 +28,10 @@ func (ct ColumnType) Name() string { if ct.NameValue.Valid { return ct.NameValue.String } - return ct.SQLColumnType.Name() + if ct.SQLColumnType != nil { + return ct.SQLColumnType.Name() + } + return "" } // DatabaseTypeName returns the database system name of the column type. If an empty @@ -41,7 +44,10 @@ func (ct ColumnType) DatabaseTypeName() string { if ct.DataTypeValue.Valid { return ct.DataTypeValue.String } - return ct.SQLColumnType.DatabaseTypeName() + if ct.SQLColumnType != nil { + return ct.SQLColumnType.DatabaseTypeName() + } + return "" } // ColumnType returns the database type of the column. like `varchar(16)` @@ -64,7 +70,10 @@ func (ct ColumnType) Length() (length int64, ok bool) { if ct.LengthValue.Valid { return ct.LengthValue.Int64, true } - return ct.SQLColumnType.Length() + if ct.SQLColumnType != nil { + return ct.SQLColumnType.Length() + } + return 0, false } // DecimalSize returns the scale and precision of a decimal type. @@ -72,7 +81,10 @@ func (ct ColumnType) DecimalSize() (precision int64, scale int64, ok bool) { if ct.DecimalSizeValue.Valid { return ct.DecimalSizeValue.Int64, ct.ScaleValue.Int64, true } - return ct.SQLColumnType.DecimalSize() + if ct.SQLColumnType != nil { + return ct.SQLColumnType.DecimalSize() + } + return 0, 0, false } // Nullable reports whether the column may be null. @@ -80,7 +92,10 @@ func (ct ColumnType) Nullable() (nullable bool, ok bool) { if ct.NullableValue.Valid { return ct.NullableValue.Bool, true } - return ct.SQLColumnType.Nullable() + if ct.SQLColumnType != nil { + return ct.SQLColumnType.Nullable() + } + return false, false } // Unique reports whether the column may be unique. @@ -93,7 +108,10 @@ func (ct ColumnType) ScanType() reflect.Type { if ct.ScanTypeValue != nil { return ct.ScanTypeValue } - return ct.SQLColumnType.ScanType() + if ct.SQLColumnType != nil { + return ct.SQLColumnType.ScanType() + } + return nil } // Comment returns the comment of current column. diff --git a/vendor/gorm.io/gorm/migrator/migrator.go b/vendor/gorm.io/gorm/migrator/migrator.go index 35107d572..9729e574e 100644 --- a/vendor/gorm.io/gorm/migrator/migrator.go +++ b/vendor/gorm.io/gorm/migrator/migrator.go @@ -1,3 +1,4 @@ +// Package migrator provides the interface and implementation for database schema migration in GORM. package migrator import ( @@ -407,15 +408,15 @@ func (m Migrator) DropColumn(value interface{}, name string) error { }) } -// AlterColumn alter value's `field` column' type based on schema definition +// AlterColumn alter value's `field` column's type based on schema definition func (m Migrator) AlterColumn(value interface{}, field string) error { return m.RunWithValue(value, func(stmt *gorm.Statement) error { if stmt.Schema != nil { if field := stmt.Schema.LookUpField(field); field != nil { - fileType := m.FullDataTypeOf(field) + fieldType := m.FullDataTypeOf(field) return m.DB.Exec( "ALTER TABLE ? ALTER COLUMN ? TYPE ?", - m.CurrentTable(stmt), clause.Column{Name: field.DBName}, fileType, + m.CurrentTable(stmt), clause.Column{Name: field.DBName}, fieldType, ).Error } @@ -559,13 +560,17 @@ func (m Migrator) MigrateColumn(value interface{}, field *schema.Field, columnTy case schema.Bool: v1, _ := strconv.ParseBool(dv) v2, _ := strconv.ParseBool(field.DefaultValue) - alterColumn = v1 != v2 + if v1 != v2 { + alterColumn = true + } case schema.String: if dv != field.DefaultValue && dv != strings.Trim(field.DefaultValue, "'\"") { alterColumn = true } default: - alterColumn = dv != field.DefaultValue + if dv != field.DefaultValue { + alterColumn = true + } } } } diff --git a/vendor/gorm.io/gorm/schema/field.go b/vendor/gorm.io/gorm/schema/field.go index de7974023..521b76599 100644 --- a/vendor/gorm.io/gorm/schema/field.go +++ b/vendor/gorm.io/gorm/schema/field.go @@ -962,6 +962,13 @@ func (field *Field) setupValuerAndSetter(modelType reflect.Type) { serializerType := serializerValue.Type() field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) { if s, ok := v.(*serializer); ok { + if s.fieldValue == nil && s.Serializer == nil { + rv := field.ReflectValueOf(ctx, value) + if rv.IsValid() && rv.CanSet() { + rv.Set(reflect.Zero(field.FieldType)) + } + return nil + } if s.fieldValue != nil { err = oldFieldSetter(ctx, value, s.fieldValue) } else if err = s.Serializer.Scan(ctx, field, value, s.value); err == nil { diff --git a/vendor/gorm.io/gorm/schema/relationship.go b/vendor/gorm.io/gorm/schema/relationship.go index 0535bba40..0b55ee1b2 100644 --- a/vendor/gorm.io/gorm/schema/relationship.go +++ b/vendor/gorm.io/gorm/schema/relationship.go @@ -669,8 +669,9 @@ func (rel *Relationship) ParseConstraint() *Constraint { if r != rel && r.FieldSchema == rel.Schema && len(rel.References) == len(r.References) { matched := true for idx, ref := range r.References { - if !(rel.References[idx].PrimaryKey == ref.PrimaryKey && rel.References[idx].ForeignKey == ref.ForeignKey && - rel.References[idx].PrimaryValue == ref.PrimaryValue) { + if rel.References[idx].PrimaryKey != ref.PrimaryKey || + rel.References[idx].ForeignKey != ref.ForeignKey || + rel.References[idx].PrimaryValue != ref.PrimaryValue { matched = false break } diff --git a/vendor/gorm.io/gorm/schema/schema.go b/vendor/gorm.io/gorm/schema/schema.go index 09697a7ab..b28149566 100644 --- a/vendor/gorm.io/gorm/schema/schema.go +++ b/vendor/gorm.io/gorm/schema/schema.go @@ -1,3 +1,4 @@ +// Package schema provides the Schema struct and related functions for parsing and managing database schemas in GORM. package schema import ( diff --git a/vendor/gorm.io/gorm/utils/utils.go b/vendor/gorm.io/gorm/utils/utils.go index 7e59264be..b3323555e 100644 --- a/vendor/gorm.io/gorm/utils/utils.go +++ b/vendor/gorm.io/gorm/utils/utils.go @@ -1,3 +1,4 @@ +// Package utils provides internal utility functions for GORM. package utils import ( @@ -36,9 +37,14 @@ func sourceDir(file string) string { // - Exclude test files (*_test.go) // - go-gorm/gen's Generated files (*.gen.go) func CallerFrame() runtime.Frame { + // Preserve the original CallerFrame stack depth after introducing callerFrame(). + return callerFrame(4) +} + +func callerFrame(skip int) runtime.Frame { pcs := [13]uintptr{} - // the third caller usually from gorm internal - len := runtime.Callers(3, pcs[:]) + // skip is caller-path sensitive and should be selected by each public helper. + len := runtime.Callers(skip, pcs[:]) frames := runtime.CallersFrames(pcs[:len]) for i := 0; i < len; i++ { // second return value is "more", not "ok" @@ -54,7 +60,8 @@ func CallerFrame() runtime.Frame { // FileWithLineNum return the file name and line number of the current file func FileWithLineNum() string { - frame := CallerFrame() + // Keep FileWithLineNum one frame outer than CallerFrame to preserve pre-v1.31.1 semantics. + frame := callerFrame(4) if frame.PC != 0 { return string(strconv.AppendInt(append([]byte(frame.File), ':'), int64(frame.Line), 10)) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 44c8da3f8..6cdbc1cc6 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -480,7 +480,7 @@ gorm.io/driver/postgres # gorm.io/driver/sqlite v1.6.0 ## explicit; go 1.20 gorm.io/driver/sqlite -# gorm.io/gorm v1.31.1 +# gorm.io/gorm v1.31.2 ## explicit; go 1.18 gorm.io/gorm gorm.io/gorm/callbacks