168 lines
3.8 KiB
Go
168 lines
3.8 KiB
Go
package sqimple
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"code.aneur.in/go/record"
|
|
)
|
|
|
|
func ScanOneRecord(rows *sql.Rows) (record.Record, error) {
|
|
records, err := ScanRecords(rows)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(records) == 0 {
|
|
return nil, errors.New("no rows")
|
|
}
|
|
|
|
return records[0], nil
|
|
}
|
|
|
|
// ScanRecords transforms SQL row data into record.Record objects, making them easier to handle with type safety.
|
|
//
|
|
// https://go.dev/ref/spec#Types
|
|
func ScanRecords(rows *sql.Rows) ([]record.Record, error) {
|
|
columns, err := rows.ColumnTypes()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
data := []record.Record{}
|
|
|
|
for rows.Next() {
|
|
values := []any{}
|
|
for _, column := range columns {
|
|
switch column.ScanType().Name() {
|
|
case "bool":
|
|
var value bool
|
|
values = append(values, &value)
|
|
case "byte":
|
|
var value byte
|
|
values = append(values, &value)
|
|
case "complex64":
|
|
var value complex64
|
|
values = append(values, &value)
|
|
case "complex128":
|
|
var value complex128
|
|
values = append(values, &value)
|
|
case "float32":
|
|
var value float32
|
|
values = append(values, &value)
|
|
case "float64":
|
|
var value float64
|
|
values = append(values, &value)
|
|
case "int":
|
|
var value int
|
|
values = append(values, &value)
|
|
case "int8":
|
|
var value int8
|
|
values = append(values, &value)
|
|
case "int16":
|
|
var value int16
|
|
values = append(values, &value)
|
|
case "int32":
|
|
var value int32
|
|
values = append(values, &value)
|
|
case "int64":
|
|
var value int64
|
|
values = append(values, &value)
|
|
case "rune":
|
|
var value rune
|
|
values = append(values, &value)
|
|
case "string":
|
|
var value string
|
|
values = append(values, &value)
|
|
case "uint":
|
|
var value uint
|
|
values = append(values, &value)
|
|
case "uint8":
|
|
var value uint8
|
|
values = append(values, &value)
|
|
case "uint16":
|
|
var value uint16
|
|
values = append(values, &value)
|
|
case "uint32":
|
|
var value uint32
|
|
values = append(values, &value)
|
|
case "uint64":
|
|
var value uint64
|
|
values = append(values, &value)
|
|
default:
|
|
return nil, fmt.Errorf("unknown scan type %q", column.ScanType().Name())
|
|
}
|
|
}
|
|
|
|
err := rows.Scan(values...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
row := record.Record{}
|
|
for i, column := range columns {
|
|
switch column.ScanType().Name() {
|
|
case "bool":
|
|
value := values[i].(*bool)
|
|
row[column.Name()] = *value
|
|
case "byte":
|
|
value := values[i].(*byte)
|
|
row[column.Name()] = *value
|
|
case "complex64":
|
|
value := values[i].(*complex64)
|
|
row[column.Name()] = *value
|
|
case "complex128":
|
|
value := values[i].(*complex128)
|
|
row[column.Name()] = *value
|
|
case "float32":
|
|
value := values[i].(*float32)
|
|
row[column.Name()] = *value
|
|
case "float64":
|
|
value := values[i].(*float64)
|
|
row[column.Name()] = *value
|
|
case "int":
|
|
value := values[i].(*int)
|
|
row[column.Name()] = *value
|
|
case "int8":
|
|
value := values[i].(*int8)
|
|
row[column.Name()] = *value
|
|
case "int16":
|
|
value := values[i].(*int16)
|
|
row[column.Name()] = *value
|
|
case "int32":
|
|
value := values[i].(*int32)
|
|
row[column.Name()] = *value
|
|
case "int64":
|
|
value := values[i].(*int64)
|
|
row[column.Name()] = *value
|
|
case "rune":
|
|
value := values[i].(*rune)
|
|
row[column.Name()] = *value
|
|
case "string":
|
|
value := values[i].(*string)
|
|
row[column.Name()] = *value
|
|
case "uint":
|
|
value := values[i].(*uint)
|
|
row[column.Name()] = *value
|
|
case "uint8":
|
|
value := values[i].(*uint8)
|
|
row[column.Name()] = *value
|
|
case "uint16":
|
|
value := values[i].(*uint16)
|
|
row[column.Name()] = *value
|
|
case "uint32":
|
|
value := values[i].(*uint32)
|
|
row[column.Name()] = *value
|
|
case "uint64":
|
|
value := values[i].(*uint64)
|
|
row[column.Name()] = *value
|
|
}
|
|
}
|
|
|
|
data = append(data, row)
|
|
}
|
|
|
|
return data, nil
|
|
}
|