287 lines
6.3 KiB
Go
287 lines
6.3 KiB
Go
|
|
package stardb
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"reflect"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
// StarResult represents a single row result
|
||
|
|
type StarResult struct {
|
||
|
|
result []interface{}
|
||
|
|
columns []string
|
||
|
|
columnIndex map[string]int
|
||
|
|
columnsType []reflect.Type
|
||
|
|
}
|
||
|
|
|
||
|
|
// Result returns the raw result slice
|
||
|
|
func (r *StarResult) Result() []interface{} {
|
||
|
|
return r.result
|
||
|
|
}
|
||
|
|
|
||
|
|
// Columns returns column names
|
||
|
|
func (r *StarResult) Columns() []string {
|
||
|
|
return r.columns
|
||
|
|
}
|
||
|
|
|
||
|
|
// ColumnsType returns column types
|
||
|
|
func (r *StarResult) ColumnsType() []reflect.Type {
|
||
|
|
return r.columnsType
|
||
|
|
}
|
||
|
|
|
||
|
|
// IsNil checks if a column value is nil
|
||
|
|
func (r *StarResult) IsNil(name string) bool {
|
||
|
|
index, ok := r.columnIndex[name]
|
||
|
|
if !ok {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
return r.result[index] == nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustString returns column value as string
|
||
|
|
func (r *StarResult) MustString(name string) string {
|
||
|
|
index, ok := r.columnIndex[name]
|
||
|
|
if !ok {
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
return convertToString(r.result[index])
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustInt returns column value as int
|
||
|
|
func (r *StarResult) MustInt(name string) int {
|
||
|
|
return int(r.MustInt64(name))
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustInt32 returns column value as int32
|
||
|
|
func (r *StarResult) MustInt32(name string) int32 {
|
||
|
|
return int32(r.MustInt64(name))
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustInt64 returns column value as int64
|
||
|
|
func (r *StarResult) MustInt64(name string) int64 {
|
||
|
|
index, ok := r.columnIndex[name]
|
||
|
|
if !ok {
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
return convertToInt64(r.result[index])
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustUint64 returns column value as uint64
|
||
|
|
func (r *StarResult) MustUint64(name string) uint64 {
|
||
|
|
index, ok := r.columnIndex[name]
|
||
|
|
if !ok {
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
return convertToUint64(r.result[index])
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustFloat32 returns column value as float32
|
||
|
|
func (r *StarResult) MustFloat32(name string) float32 {
|
||
|
|
return float32(r.MustFloat64(name))
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustFloat64 returns column value as float64
|
||
|
|
func (r *StarResult) MustFloat64(name string) float64 {
|
||
|
|
index, ok := r.columnIndex[name]
|
||
|
|
if !ok {
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
return convertToFloat64(r.result[index])
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustBool returns column value as bool
|
||
|
|
func (r *StarResult) MustBool(name string) bool {
|
||
|
|
index, ok := r.columnIndex[name]
|
||
|
|
if !ok {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
return convertToBool(r.result[index])
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustBytes returns column value as []byte
|
||
|
|
func (r *StarResult) MustBytes(name string) []byte {
|
||
|
|
index, ok := r.columnIndex[name]
|
||
|
|
if !ok {
|
||
|
|
return []byte{}
|
||
|
|
}
|
||
|
|
if b, ok := r.result[index].([]byte); ok {
|
||
|
|
return b
|
||
|
|
}
|
||
|
|
return []byte(r.MustString(name))
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustDate returns column value as time.Time
|
||
|
|
func (r *StarResult) MustDate(name, layout string) time.Time {
|
||
|
|
index, ok := r.columnIndex[name]
|
||
|
|
if !ok {
|
||
|
|
return time.Time{}
|
||
|
|
}
|
||
|
|
return convertToTime(r.result[index], layout)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Scan scans the result into provided pointers
|
||
|
|
// Usage: row.Scan(&id, &name, &email)
|
||
|
|
func (r *StarResult) Scan(dest ...interface{}) error {
|
||
|
|
if len(dest) != len(r.result) {
|
||
|
|
return fmt.Errorf("expected %d destination arguments, got %d", len(r.result), len(dest))
|
||
|
|
}
|
||
|
|
|
||
|
|
for i, d := range dest {
|
||
|
|
if err := convertAssign(d, r.result[i]); err != nil {
|
||
|
|
return fmt.Errorf("error scanning column %d: %v", i, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// convertAssign assigns src to dest
|
||
|
|
func convertAssign(dest, src interface{}) error {
|
||
|
|
switch d := dest.(type) {
|
||
|
|
case *string:
|
||
|
|
*d = convertToString(src)
|
||
|
|
case *int:
|
||
|
|
*d = int(convertToInt64(src))
|
||
|
|
case *int32:
|
||
|
|
*d = int32(convertToInt64(src))
|
||
|
|
case *int64:
|
||
|
|
*d = convertToInt64(src)
|
||
|
|
case *uint64:
|
||
|
|
*d = convertToUint64(src)
|
||
|
|
case *float32:
|
||
|
|
*d = float32(convertToFloat64(src))
|
||
|
|
case *float64:
|
||
|
|
*d = convertToFloat64(src)
|
||
|
|
case *bool:
|
||
|
|
*d = convertToBool(src)
|
||
|
|
case *time.Time:
|
||
|
|
if t, ok := src.(time.Time); ok {
|
||
|
|
*d = t
|
||
|
|
}
|
||
|
|
case *[]byte:
|
||
|
|
if b, ok := src.([]byte); ok {
|
||
|
|
*d = b
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
return fmt.Errorf("unsupported Scan type: %T", dest)
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// StarResultCol represents a single column result
|
||
|
|
type StarResultCol struct {
|
||
|
|
result []interface{}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Result returns the raw result slice
|
||
|
|
func (c *StarResultCol) Result() []interface{} {
|
||
|
|
return c.result
|
||
|
|
}
|
||
|
|
|
||
|
|
// Len returns the number of values
|
||
|
|
func (c *StarResultCol) Len() int {
|
||
|
|
return len(c.result)
|
||
|
|
}
|
||
|
|
|
||
|
|
// IsNil returns slice of nil checks for each row
|
||
|
|
func (c *StarResultCol) IsNil() []bool {
|
||
|
|
result := make([]bool, len(c.result))
|
||
|
|
for i, v := range c.result {
|
||
|
|
result[i] = (v == nil)
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustString returns all values as strings
|
||
|
|
func (c *StarResultCol) MustString() []string {
|
||
|
|
result := make([]string, len(c.result))
|
||
|
|
for i, v := range c.result {
|
||
|
|
result[i] = convertToString(v)
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustInt returns all values as ints
|
||
|
|
func (c *StarResultCol) MustInt() []int {
|
||
|
|
result := make([]int, len(c.result))
|
||
|
|
for i, v := range c.result {
|
||
|
|
result[i] = int(convertToInt64(v))
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustInt32 returns all values as int32
|
||
|
|
func (c *StarResultCol) MustInt32() []int32 {
|
||
|
|
result := make([]int32, len(c.result))
|
||
|
|
for i, v := range c.result {
|
||
|
|
result[i] = int32(convertToInt64(v))
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustInt64 returns all values as int64
|
||
|
|
func (c *StarResultCol) MustInt64() []int64 {
|
||
|
|
result := make([]int64, len(c.result))
|
||
|
|
for i, v := range c.result {
|
||
|
|
result[i] = convertToInt64(v)
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustUint64 returns all values as uint64
|
||
|
|
func (c *StarResultCol) MustUint64() []uint64 {
|
||
|
|
result := make([]uint64, len(c.result))
|
||
|
|
for i, v := range c.result {
|
||
|
|
result[i] = convertToUint64(v)
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustFloat32 returns all values as float32
|
||
|
|
func (c *StarResultCol) MustFloat32() []float32 {
|
||
|
|
result := make([]float32, len(c.result))
|
||
|
|
for i, v := range c.result {
|
||
|
|
result[i] = float32(convertToFloat64(v))
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustFloat64 returns all values as float64
|
||
|
|
func (c *StarResultCol) MustFloat64() []float64 {
|
||
|
|
result := make([]float64, len(c.result))
|
||
|
|
for i, v := range c.result {
|
||
|
|
result[i] = convertToFloat64(v)
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustBool returns all values as bool
|
||
|
|
func (c *StarResultCol) MustBool() []bool {
|
||
|
|
result := make([]bool, len(c.result))
|
||
|
|
for i, v := range c.result {
|
||
|
|
result[i] = convertToBool(v)
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustBytes returns all values as []byte
|
||
|
|
func (c *StarResultCol) MustBytes() [][]byte {
|
||
|
|
result := make([][]byte, len(c.result))
|
||
|
|
for i, v := range c.result {
|
||
|
|
if b, ok := v.([]byte); ok {
|
||
|
|
result[i] = b
|
||
|
|
} else {
|
||
|
|
result[i] = []byte(convertToString(v))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
// MustDate returns all values as time.Time
|
||
|
|
func (c *StarResultCol) MustDate(layout string) []time.Time {
|
||
|
|
result := make([]time.Time, len(c.result))
|
||
|
|
for i, v := range c.result {
|
||
|
|
result[i] = convertToTime(v, layout)
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|