Skip to content

DB.ScanRows() into int variants skips all rows and returns last row #7602

@Vovan-VE

Description

@Vovan-VE

gorm/scan.go

Lines 179 to 189 in b881483

case *int, *int8, *int16, *int32, *int64,
*uint, *uint8, *uint16, *uint32, *uint64, *uintptr,
*float32, *float64,
*bool, *string, *time.Time,
*sql.NullInt32, *sql.NullInt64, *sql.NullFloat64,
*sql.NullBool, *sql.NullString, *sql.NullTime:
for initialized || rows.Next() {
initialized = false
db.RowsAffected++
db.AddError(rows.Scan(dest))
}

Here must be if rather then for. So now DB.ScanRows() into int variants silently eats all the rows and returns the last one.

Example:

func list[T any](tx *gorm.DB) ([]T, error) {
	result := make([]T, 0)
	rows, err := tx.Raw(
		`(SELECT 10 AS x UNION SELECT 20 UNION SELECT 30) ORDER BY x`,
	).Rows()
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	for rows.Next() {
		var item T
		err = tx.ScanRows(rows, &item)
		if err != nil {
			return nil, err
		}
		result = append(result, item)
	}
	return result, nil
}

func main() {
	db, err := gorm.Open(...)

	type Ref struct{ X int }
	structs, err := list[Ref](tx)
	if err != nil {...}
	fmt.Printf("structs: %#v\n", structs)

	ints, err := list[int](tx)
	if err != nil {...}
	fmt.Printf("ints: %#v\n", ints)
}

output:

structs: []main.Ref{main.Ref{X:10}, main.Ref{X:20}, main.Ref{X:30}}
ints: []int{30}
  • go 1.24
  • gorm 1.30 , 1.31

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions