2
0

Add more ColumnType support

This commit is contained in:
Timothée Peignier
2017-08-18 18:22:08 -07:00
parent d49a78dd73
commit 0f84f73c7b
4 changed files with 202 additions and 3 deletions
+20
View File
@@ -70,6 +70,7 @@ import (
"encoding/binary"
"fmt"
"io"
"reflect"
"strings"
"sync"
@@ -415,10 +416,29 @@ func (r *Rows) Columns() []string {
return names
}
// ColumnTypeDatabaseTypeName return the database system type name.
func (r *Rows) ColumnTypeDatabaseTypeName(index int) string {
return strings.ToUpper(r.rows.FieldDescriptions()[index].DataTypeName)
}
// ColumnTypeLength returns the length of the column type if the column is a
// variable length type. If the column is not a variable length type ok
// should return false.
func (r *Rows) ColumnTypeLength(index int) (int64, bool) {
return r.rows.FieldDescriptions()[index].Length()
}
// ColumnTypePrecisionScale should return the precision and scale for decimal
// types. If not applicable, ok should be false.
func (r *Rows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
return r.rows.FieldDescriptions()[index].PrecisionScale()
}
// ColumnTypeScanType returns the value type that can be used to scan types into.
func (r *Rows) ColumnTypeScanType(index int) reflect.Type {
return r.rows.FieldDescriptions()[index].Type()
}
func (r *Rows) Close() error {
r.rows.Close()
return nil
+127
View File
@@ -5,6 +5,8 @@ import (
"context"
"database/sql"
"fmt"
"math"
"reflect"
"testing"
"time"
@@ -1258,3 +1260,128 @@ func TestStmtQueryContextCancel(t *testing.T) {
t.Errorf("mock server err: %v", err)
}
}
func TestRowsColumnTypes(t *testing.T) {
columnTypesTests := []struct {
Name string
TypeName string
Length struct {
Len int64
OK bool
}
DecimalSize struct {
Precision int64
Scale int64
OK bool
}
ScanType reflect.Type
}{
{
Name: "a",
TypeName: "INT4",
Length: struct {
Len int64
OK bool
}{
Len: 0,
OK: false,
},
DecimalSize: struct {
Precision int64
Scale int64
OK bool
}{
Precision: 0,
Scale: 0,
OK: false,
},
ScanType: reflect.TypeOf(int32(0)),
}, {
Name: "bar",
TypeName: "TEXT",
Length: struct {
Len int64
OK bool
}{
Len: math.MaxInt64,
OK: true,
},
DecimalSize: struct {
Precision int64
Scale int64
OK bool
}{
Precision: 0,
Scale: 0,
OK: false,
},
ScanType: reflect.TypeOf(""),
}, {
Name: "dec",
TypeName: "NUMERIC",
Length: struct {
Len int64
OK bool
}{
Len: 0,
OK: false,
},
DecimalSize: struct {
Precision int64
Scale int64
OK bool
}{
Precision: 9,
Scale: 2,
OK: true,
},
ScanType: reflect.TypeOf(float64(0)),
},
}
db := openDB(t)
defer closeDB(t, db)
rows, err := db.Query("SELECT 1 AS a, text 'bar' AS bar, 1.28::numeric(9, 2) AS dec")
if err != nil {
t.Fatal(err)
}
columns, err := rows.ColumnTypes()
if err != nil {
t.Fatal(err)
}
if len(columns) != 3 {
t.Errorf("expected 3 columns found %d", len(columns))
}
for i, tt := range columnTypesTests {
c := columns[i]
if c.Name() != tt.Name {
t.Errorf("(%d) got: %s, want: %s", i, c.Name(), tt.Name)
}
if c.DatabaseTypeName() != tt.TypeName {
t.Errorf("(%d) got: %s, want: %s", i, c.DatabaseTypeName(), tt.TypeName)
}
l, ok := c.Length()
if l != tt.Length.Len {
t.Errorf("(%d) got: %d, want: %d", i, l, tt.Length.Len)
}
if ok != tt.Length.OK {
t.Errorf("(%d) got: %t, want: %t", i, ok, tt.Length.OK)
}
p, s, ok := c.DecimalSize()
if p != tt.DecimalSize.Precision {
t.Errorf("(%d) got: %d, want: %d", i, p, tt.DecimalSize.Precision)
}
if s != tt.DecimalSize.Scale {
t.Errorf("(%d) got: %d, want: %d", i, s, tt.DecimalSize.Scale)
}
if ok != tt.DecimalSize.OK {
t.Errorf("(%d) got: %t, want: %t", i, ok, tt.DecimalSize.OK)
}
if c.ScanType() != tt.ScanType {
t.Errorf("(%d) got: %v, want: %v", i, c.ScanType(), tt.ScanType)
}
}
}