jmoiron / sqlx

general purpose extensions to golang's database/sql
http://jmoiron.github.io/sqlx/
MIT License
16.3k stars 1.09k forks source link

Getting Select() to return a tuple of unspecified size? #862

Open marhar opened 1 year ago

marhar commented 1 year ago

I'm looking for a way to read a slice of slices, so I can write some general purpose routines to do, e.g., query formatting. Something like Python dbapi cursor.fetchall(), which returns data in the shape of [(1,2,3),(4,5,6)] etc.

Trying this

          results := make([][]interface{}, 0)
          err := db.Select(&results, randomSelectString)

results in an error such as

non-struct dest type slice with >1 columns (5)
gurza commented 1 year ago

@marhar sqlx expects the target to be a slice of structs because it wants to map columns to struct fields.

You can perform raw database queries using database/sql to achieve a similar effect as Python's fetchall(). Something like this

rows, err := db.Query(randomSelectString)
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

results := make([][]interface{}, 0)
cols, _ := rows.Columns()

for rows.Next() {
    columns := make([]interface{}, len(cols))
    columnPointers := make([]interface{}, len(cols))
    for i := range columns {
        columnPointers[i] = &columns[i]
    }

    if err := rows.Scan(columnPointers...); err != nil {
        log.Fatal(err)
    }

    results = append(results, columns)
}

err = rows.Err()
if err != nil {
    log.Fatal(err)
}

This is a bit inconvenient compared to using sqlx and scanning into a slice of struct, but it's the trade-off for being able to handle arbitrary query result structures.

gurza commented 1 year ago

@marhar did you solve your problem?