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 }