summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/lib
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/lib')
-rw-r--r--vendor/github.com/lib/pq/.travis.yml1
-rw-r--r--vendor/github.com/lib/pq/conn.go34
-rw-r--r--vendor/github.com/lib/pq/encode.go12
-rw-r--r--vendor/github.com/lib/pq/encode_test.go9
-rw-r--r--vendor/github.com/lib/pq/oid/gen.go59
-rw-r--r--vendor/github.com/lib/pq/oid/types.go172
-rw-r--r--vendor/github.com/lib/pq/rows.go93
-rw-r--r--vendor/github.com/lib/pq/rows_test.go220
8 files changed, 561 insertions, 39 deletions
diff --git a/vendor/github.com/lib/pq/.travis.yml b/vendor/github.com/lib/pq/.travis.yml
index 1a4656c53..452515c66 100644
--- a/vendor/github.com/lib/pq/.travis.yml
+++ b/vendor/github.com/lib/pq/.travis.yml
@@ -5,6 +5,7 @@ go:
- 1.6.x
- 1.7.x
- 1.8.x
+ - 1.9.x
- master
sudo: true
diff --git a/vendor/github.com/lib/pq/conn.go b/vendor/github.com/lib/pq/conn.go
index 1725ab0d3..338a0bc18 100644
--- a/vendor/github.com/lib/pq/conn.go
+++ b/vendor/github.com/lib/pq/conn.go
@@ -706,7 +706,7 @@ func (noRows) RowsAffected() (int64, error) {
// Decides which column formats to use for a prepared statement. The input is
// an array of type oids, one element per result column.
-func decideColumnFormats(colTyps []oid.Oid, forceText bool) (colFmts []format, colFmtData []byte) {
+func decideColumnFormats(colTyps []fieldDesc, forceText bool) (colFmts []format, colFmtData []byte) {
if len(colTyps) == 0 {
return nil, colFmtDataAllText
}
@@ -718,8 +718,8 @@ func decideColumnFormats(colTyps []oid.Oid, forceText bool) (colFmts []format, c
allBinary := true
allText := true
- for i, o := range colTyps {
- switch o {
+ for i, t := range colTyps {
+ switch t.OID {
// This is the list of types to use binary mode for when receiving them
// through a prepared statement. If a type appears in this list, it
// must also be implemented in binaryDecode in encode.go.
@@ -1155,7 +1155,7 @@ type stmt struct {
colNames []string
colFmts []format
colFmtData []byte
- colTyps []oid.Oid
+ colTyps []fieldDesc
paramTyps []oid.Oid
closed bool
}
@@ -1318,7 +1318,7 @@ type rows struct {
cn *conn
finish func()
colNames []string
- colTyps []oid.Oid
+ colTyps []fieldDesc
colFmts []format
done bool
rb readBuf
@@ -1406,7 +1406,7 @@ func (rs *rows) Next(dest []driver.Value) (err error) {
dest[i] = nil
continue
}
- dest[i] = decode(&conn.parameterStatus, rs.rb.next(l), rs.colTyps[i], rs.colFmts[i])
+ dest[i] = decode(&conn.parameterStatus, rs.rb.next(l), rs.colTyps[i].OID, rs.colFmts[i])
}
return
case 'T':
@@ -1573,7 +1573,7 @@ func (cn *conn) readParseResponse() {
}
}
-func (cn *conn) readStatementDescribeResponse() (paramTyps []oid.Oid, colNames []string, colTyps []oid.Oid) {
+func (cn *conn) readStatementDescribeResponse() (paramTyps []oid.Oid, colNames []string, colTyps []fieldDesc) {
for {
t, r := cn.recv1()
switch t {
@@ -1599,7 +1599,7 @@ func (cn *conn) readStatementDescribeResponse() (paramTyps []oid.Oid, colNames [
}
}
-func (cn *conn) readPortalDescribeResponse() (colNames []string, colFmts []format, colTyps []oid.Oid) {
+func (cn *conn) readPortalDescribeResponse() (colNames []string, colFmts []format, colTyps []fieldDesc) {
t, r := cn.recv1()
switch t {
case 'T':
@@ -1695,31 +1695,33 @@ func (cn *conn) readExecuteResponse(protocolState string) (res driver.Result, co
}
}
-func parseStatementRowDescribe(r *readBuf) (colNames []string, colTyps []oid.Oid) {
+func parseStatementRowDescribe(r *readBuf) (colNames []string, colTyps []fieldDesc) {
n := r.int16()
colNames = make([]string, n)
- colTyps = make([]oid.Oid, n)
+ colTyps = make([]fieldDesc, n)
for i := range colNames {
colNames[i] = r.string()
r.next(6)
- colTyps[i] = r.oid()
- r.next(6)
+ colTyps[i].OID = r.oid()
+ colTyps[i].Len = r.int16()
+ colTyps[i].Mod = r.int32()
// format code not known when describing a statement; always 0
r.next(2)
}
return
}
-func parsePortalRowDescribe(r *readBuf) (colNames []string, colFmts []format, colTyps []oid.Oid) {
+func parsePortalRowDescribe(r *readBuf) (colNames []string, colFmts []format, colTyps []fieldDesc) {
n := r.int16()
colNames = make([]string, n)
colFmts = make([]format, n)
- colTyps = make([]oid.Oid, n)
+ colTyps = make([]fieldDesc, n)
for i := range colNames {
colNames[i] = r.string()
r.next(6)
- colTyps[i] = r.oid()
- r.next(6)
+ colTyps[i].OID = r.oid()
+ colTyps[i].Len = r.int16()
+ colTyps[i].Mod = r.int32()
colFmts[i] = format(r.int16())
}
return
diff --git a/vendor/github.com/lib/pq/encode.go b/vendor/github.com/lib/pq/encode.go
index 88a322cda..3b0d365f2 100644
--- a/vendor/github.com/lib/pq/encode.go
+++ b/vendor/github.com/lib/pq/encode.go
@@ -367,8 +367,15 @@ func ParseTimestamp(currentLocation *time.Location, str string) (time.Time, erro
timeSep := daySep + 3
day := p.mustAtoi(str, daySep+1, timeSep)
+ minLen := monSep + len("01-01") + 1
+
+ isBC := strings.HasSuffix(str, " BC")
+ if isBC {
+ minLen += 3
+ }
+
var hour, minute, second int
- if len(str) > monSep+len("01-01")+1 {
+ if len(str) > minLen {
p.expect(str, ' ', timeSep)
minSep := timeSep + 3
p.expect(str, ':', minSep)
@@ -424,7 +431,8 @@ func ParseTimestamp(currentLocation *time.Location, str string) (time.Time, erro
tzOff = tzSign * ((tzHours * 60 * 60) + (tzMin * 60) + tzSec)
}
var isoYear int
- if remainderIdx+3 <= len(str) && str[remainderIdx:remainderIdx+3] == " BC" {
+
+ if isBC {
isoYear = 1 - year
remainderIdx += 3
} else {
diff --git a/vendor/github.com/lib/pq/encode_test.go b/vendor/github.com/lib/pq/encode_test.go
index 3a0f7286e..837d45bec 100644
--- a/vendor/github.com/lib/pq/encode_test.go
+++ b/vendor/github.com/lib/pq/encode_test.go
@@ -37,6 +37,8 @@ var timeTests = []struct {
}{
{"22001-02-03", time.Date(22001, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))},
{"2001-02-03", time.Date(2001, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))},
+ {"0001-12-31 BC", time.Date(0, time.December, 31, 0, 0, 0, 0, time.FixedZone("", 0))},
+ {"2001-02-03 BC", time.Date(-2000, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))},
{"2001-02-03 04:05:06", time.Date(2001, time.February, 3, 4, 5, 6, 0, time.FixedZone("", 0))},
{"2001-02-03 04:05:06.000001", time.Date(2001, time.February, 3, 4, 5, 6, 1000, time.FixedZone("", 0))},
{"2001-02-03 04:05:06.00001", time.Date(2001, time.February, 3, 4, 5, 6, 10000, time.FixedZone("", 0))},
@@ -86,15 +88,22 @@ func TestParseTs(t *testing.T) {
}
var timeErrorTests = []string{
+ "BC",
+ " BC",
"2001",
"2001-2-03",
"2001-02-3",
"2001-02-03 ",
+ "2001-02-03 B",
"2001-02-03 04",
"2001-02-03 04:",
"2001-02-03 04:05",
+ "2001-02-03 04:05 B",
+ "2001-02-03 04:05 BC",
"2001-02-03 04:05:",
"2001-02-03 04:05:6",
+ "2001-02-03 04:05:06 B",
+ "2001-02-03 04:05:06BC",
"2001-02-03 04:05:06.123 B",
}
diff --git a/vendor/github.com/lib/pq/oid/gen.go b/vendor/github.com/lib/pq/oid/gen.go
index cd4aea808..7c634cdc5 100644
--- a/vendor/github.com/lib/pq/oid/gen.go
+++ b/vendor/github.com/lib/pq/oid/gen.go
@@ -10,10 +10,22 @@ import (
"log"
"os"
"os/exec"
+ "strings"
_ "github.com/lib/pq"
)
+// OID represent a postgres Object Identifier Type.
+type OID struct {
+ ID int
+ Type string
+}
+
+// Name returns an upper case version of the oid type.
+func (o OID) Name() string {
+ return strings.ToUpper(o.Type)
+}
+
func main() {
datname := os.Getenv("PGDATABASE")
sslmode := os.Getenv("PGSSLMODE")
@@ -30,6 +42,25 @@ func main() {
if err != nil {
log.Fatal(err)
}
+ rows, err := db.Query(`
+ SELECT typname, oid
+ FROM pg_type WHERE oid < 10000
+ ORDER BY oid;
+ `)
+ if err != nil {
+ log.Fatal(err)
+ }
+ oids := make([]*OID, 0)
+ for rows.Next() {
+ var oid OID
+ if err = rows.Scan(&oid.Type, &oid.ID); err != nil {
+ log.Fatal(err)
+ }
+ oids = append(oids, &oid)
+ }
+ if err = rows.Err(); err != nil {
+ log.Fatal(err)
+ }
cmd := exec.Command("gofmt")
cmd.Stderr = os.Stderr
w, err := cmd.StdinPipe()
@@ -45,30 +76,18 @@ func main() {
if err != nil {
log.Fatal(err)
}
- fmt.Fprintln(w, "// generated by 'go run gen.go'; do not edit")
+ fmt.Fprintln(w, "// Code generated by gen.go. DO NOT EDIT.")
fmt.Fprintln(w, "\npackage oid")
fmt.Fprintln(w, "const (")
- rows, err := db.Query(`
- SELECT typname, oid
- FROM pg_type WHERE oid < 10000
- ORDER BY oid;
- `)
- if err != nil {
- log.Fatal(err)
- }
- var name string
- var oid int
- for rows.Next() {
- err = rows.Scan(&name, &oid)
- if err != nil {
- log.Fatal(err)
- }
- fmt.Fprintf(w, "T_%s Oid = %d\n", name, oid)
- }
- if err = rows.Err(); err != nil {
- log.Fatal(err)
+ for _, oid := range oids {
+ fmt.Fprintf(w, "T_%s Oid = %d\n", oid.Type, oid.ID)
}
fmt.Fprintln(w, ")")
+ fmt.Fprintln(w, "var TypeName = map[Oid]string{")
+ for _, oid := range oids {
+ fmt.Fprintf(w, "T_%s: \"%s\",\n", oid.Type, oid.Name())
+ }
+ fmt.Fprintln(w, "}")
w.Close()
cmd.Wait()
}
diff --git a/vendor/github.com/lib/pq/oid/types.go b/vendor/github.com/lib/pq/oid/types.go
index a3390c23a..ecc84c2c8 100644
--- a/vendor/github.com/lib/pq/oid/types.go
+++ b/vendor/github.com/lib/pq/oid/types.go
@@ -1,4 +1,4 @@
-// generated by 'go run gen.go'; do not edit
+// Code generated by gen.go. DO NOT EDIT.
package oid
@@ -171,3 +171,173 @@ const (
T_regrole Oid = 4096
T__regrole Oid = 4097
)
+
+var TypeName = map[Oid]string{
+ T_bool: "BOOL",
+ T_bytea: "BYTEA",
+ T_char: "CHAR",
+ T_name: "NAME",
+ T_int8: "INT8",
+ T_int2: "INT2",
+ T_int2vector: "INT2VECTOR",
+ T_int4: "INT4",
+ T_regproc: "REGPROC",
+ T_text: "TEXT",
+ T_oid: "OID",
+ T_tid: "TID",
+ T_xid: "XID",
+ T_cid: "CID",
+ T_oidvector: "OIDVECTOR",
+ T_pg_ddl_command: "PG_DDL_COMMAND",
+ T_pg_type: "PG_TYPE",
+ T_pg_attribute: "PG_ATTRIBUTE",
+ T_pg_proc: "PG_PROC",
+ T_pg_class: "PG_CLASS",
+ T_json: "JSON",
+ T_xml: "XML",
+ T__xml: "_XML",
+ T_pg_node_tree: "PG_NODE_TREE",
+ T__json: "_JSON",
+ T_smgr: "SMGR",
+ T_index_am_handler: "INDEX_AM_HANDLER",
+ T_point: "POINT",
+ T_lseg: "LSEG",
+ T_path: "PATH",
+ T_box: "BOX",
+ T_polygon: "POLYGON",
+ T_line: "LINE",
+ T__line: "_LINE",
+ T_cidr: "CIDR",
+ T__cidr: "_CIDR",
+ T_float4: "FLOAT4",
+ T_float8: "FLOAT8",
+ T_abstime: "ABSTIME",
+ T_reltime: "RELTIME",
+ T_tinterval: "TINTERVAL",
+ T_unknown: "UNKNOWN",
+ T_circle: "CIRCLE",
+ T__circle: "_CIRCLE",
+ T_money: "MONEY",
+ T__money: "_MONEY",
+ T_macaddr: "MACADDR",
+ T_inet: "INET",
+ T__bool: "_BOOL",
+ T__bytea: "_BYTEA",
+ T__char: "_CHAR",
+ T__name: "_NAME",
+ T__int2: "_INT2",
+ T__int2vector: "_INT2VECTOR",
+ T__int4: "_INT4",
+ T__regproc: "_REGPROC",
+ T__text: "_TEXT",
+ T__tid: "_TID",
+ T__xid: "_XID",
+ T__cid: "_CID",
+ T__oidvector: "_OIDVECTOR",
+ T__bpchar: "_BPCHAR",
+ T__varchar: "_VARCHAR",
+ T__int8: "_INT8",
+ T__point: "_POINT",
+ T__lseg: "_LSEG",
+ T__path: "_PATH",
+ T__box: "_BOX",
+ T__float4: "_FLOAT4",
+ T__float8: "_FLOAT8",
+ T__abstime: "_ABSTIME",
+ T__reltime: "_RELTIME",
+ T__tinterval: "_TINTERVAL",
+ T__polygon: "_POLYGON",
+ T__oid: "_OID",
+ T_aclitem: "ACLITEM",
+ T__aclitem: "_ACLITEM",
+ T__macaddr: "_MACADDR",
+ T__inet: "_INET",
+ T_bpchar: "BPCHAR",
+ T_varchar: "VARCHAR",
+ T_date: "DATE",
+ T_time: "TIME",
+ T_timestamp: "TIMESTAMP",
+ T__timestamp: "_TIMESTAMP",
+ T__date: "_DATE",
+ T__time: "_TIME",
+ T_timestamptz: "TIMESTAMPTZ",
+ T__timestamptz: "_TIMESTAMPTZ",
+ T_interval: "INTERVAL",
+ T__interval: "_INTERVAL",
+ T__numeric: "_NUMERIC",
+ T_pg_database: "PG_DATABASE",
+ T__cstring: "_CSTRING",
+ T_timetz: "TIMETZ",
+ T__timetz: "_TIMETZ",
+ T_bit: "BIT",
+ T__bit: "_BIT",
+ T_varbit: "VARBIT",
+ T__varbit: "_VARBIT",
+ T_numeric: "NUMERIC",
+ T_refcursor: "REFCURSOR",
+ T__refcursor: "_REFCURSOR",
+ T_regprocedure: "REGPROCEDURE",
+ T_regoper: "REGOPER",
+ T_regoperator: "REGOPERATOR",
+ T_regclass: "REGCLASS",
+ T_regtype: "REGTYPE",
+ T__regprocedure: "_REGPROCEDURE",
+ T__regoper: "_REGOPER",
+ T__regoperator: "_REGOPERATOR",
+ T__regclass: "_REGCLASS",
+ T__regtype: "_REGTYPE",
+ T_record: "RECORD",
+ T_cstring: "CSTRING",
+ T_any: "ANY",
+ T_anyarray: "ANYARRAY",
+ T_void: "VOID",
+ T_trigger: "TRIGGER",
+ T_language_handler: "LANGUAGE_HANDLER",
+ T_internal: "INTERNAL",
+ T_opaque: "OPAQUE",
+ T_anyelement: "ANYELEMENT",
+ T__record: "_RECORD",
+ T_anynonarray: "ANYNONARRAY",
+ T_pg_authid: "PG_AUTHID",
+ T_pg_auth_members: "PG_AUTH_MEMBERS",
+ T__txid_snapshot: "_TXID_SNAPSHOT",
+ T_uuid: "UUID",
+ T__uuid: "_UUID",
+ T_txid_snapshot: "TXID_SNAPSHOT",
+ T_fdw_handler: "FDW_HANDLER",
+ T_pg_lsn: "PG_LSN",
+ T__pg_lsn: "_PG_LSN",
+ T_tsm_handler: "TSM_HANDLER",
+ T_anyenum: "ANYENUM",
+ T_tsvector: "TSVECTOR",
+ T_tsquery: "TSQUERY",
+ T_gtsvector: "GTSVECTOR",
+ T__tsvector: "_TSVECTOR",
+ T__gtsvector: "_GTSVECTOR",
+ T__tsquery: "_TSQUERY",
+ T_regconfig: "REGCONFIG",
+ T__regconfig: "_REGCONFIG",
+ T_regdictionary: "REGDICTIONARY",
+ T__regdictionary: "_REGDICTIONARY",
+ T_jsonb: "JSONB",
+ T__jsonb: "_JSONB",
+ T_anyrange: "ANYRANGE",
+ T_event_trigger: "EVENT_TRIGGER",
+ T_int4range: "INT4RANGE",
+ T__int4range: "_INT4RANGE",
+ T_numrange: "NUMRANGE",
+ T__numrange: "_NUMRANGE",
+ T_tsrange: "TSRANGE",
+ T__tsrange: "_TSRANGE",
+ T_tstzrange: "TSTZRANGE",
+ T__tstzrange: "_TSTZRANGE",
+ T_daterange: "DATERANGE",
+ T__daterange: "_DATERANGE",
+ T_int8range: "INT8RANGE",
+ T__int8range: "_INT8RANGE",
+ T_pg_shseclabel: "PG_SHSECLABEL",
+ T_regnamespace: "REGNAMESPACE",
+ T__regnamespace: "_REGNAMESPACE",
+ T_regrole: "REGROLE",
+ T__regrole: "_REGROLE",
+}
diff --git a/vendor/github.com/lib/pq/rows.go b/vendor/github.com/lib/pq/rows.go
new file mode 100644
index 000000000..c6aa5b9a3
--- /dev/null
+++ b/vendor/github.com/lib/pq/rows.go
@@ -0,0 +1,93 @@
+package pq
+
+import (
+ "math"
+ "reflect"
+ "time"
+
+ "github.com/lib/pq/oid"
+)
+
+const headerSize = 4
+
+type fieldDesc struct {
+ // The object ID of the data type.
+ OID oid.Oid
+ // The data type size (see pg_type.typlen).
+ // Note that negative values denote variable-width types.
+ Len int
+ // The type modifier (see pg_attribute.atttypmod).
+ // The meaning of the modifier is type-specific.
+ Mod int
+}
+
+func (fd fieldDesc) Type() reflect.Type {
+ switch fd.OID {
+ case oid.T_int8:
+ return reflect.TypeOf(int64(0))
+ case oid.T_int4:
+ return reflect.TypeOf(int32(0))
+ case oid.T_int2:
+ return reflect.TypeOf(int16(0))
+ case oid.T_varchar, oid.T_text:
+ return reflect.TypeOf("")
+ case oid.T_bool:
+ return reflect.TypeOf(false)
+ case oid.T_date, oid.T_time, oid.T_timetz, oid.T_timestamp, oid.T_timestamptz:
+ return reflect.TypeOf(time.Time{})
+ case oid.T_bytea:
+ return reflect.TypeOf([]byte(nil))
+ default:
+ return reflect.TypeOf(new(interface{})).Elem()
+ }
+}
+
+func (fd fieldDesc) Name() string {
+ return oid.TypeName[fd.OID]
+}
+
+func (fd fieldDesc) Length() (length int64, ok bool) {
+ switch fd.OID {
+ case oid.T_text, oid.T_bytea:
+ return math.MaxInt64, true
+ case oid.T_varchar, oid.T_bpchar:
+ return int64(fd.Mod - headerSize), true
+ default:
+ return 0, false
+ }
+}
+
+func (fd fieldDesc) PrecisionScale() (precision, scale int64, ok bool) {
+ switch fd.OID {
+ case oid.T_numeric, oid.T__numeric:
+ mod := fd.Mod - headerSize
+ precision = int64((mod >> 16) & 0xffff)
+ scale = int64(mod & 0xffff)
+ return precision, scale, true
+ default:
+ return 0, 0, false
+ }
+}
+
+// ColumnTypeScanType returns the value type that can be used to scan types into.
+func (rs *rows) ColumnTypeScanType(index int) reflect.Type {
+ return rs.colTyps[index].Type()
+}
+
+// ColumnTypeDatabaseTypeName return the database system type name.
+func (rs *rows) ColumnTypeDatabaseTypeName(index int) string {
+ return rs.colTyps[index].Name()
+}
+
+// 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 (rs *rows) ColumnTypeLength(index int) (length int64, ok bool) {
+ return rs.colTyps[index].Length()
+}
+
+// ColumnTypePrecisionScale should return the precision and scale for decimal
+// types. If not applicable, ok should be false.
+func (rs *rows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
+ return rs.colTyps[index].PrecisionScale()
+}
diff --git a/vendor/github.com/lib/pq/rows_test.go b/vendor/github.com/lib/pq/rows_test.go
new file mode 100644
index 000000000..3033bc01b
--- /dev/null
+++ b/vendor/github.com/lib/pq/rows_test.go
@@ -0,0 +1,220 @@
+// +build go1.8
+
+package pq
+
+import (
+ "math"
+ "reflect"
+ "testing"
+
+ "github.com/lib/pq/oid"
+)
+
+func TestDataTypeName(t *testing.T) {
+ tts := []struct {
+ typ oid.Oid
+ name string
+ }{
+ {oid.T_int8, "INT8"},
+ {oid.T_int4, "INT4"},
+ {oid.T_int2, "INT2"},
+ {oid.T_varchar, "VARCHAR"},
+ {oid.T_text, "TEXT"},
+ {oid.T_bool, "BOOL"},
+ {oid.T_numeric, "NUMERIC"},
+ {oid.T_date, "DATE"},
+ {oid.T_time, "TIME"},
+ {oid.T_timetz, "TIMETZ"},
+ {oid.T_timestamp, "TIMESTAMP"},
+ {oid.T_timestamptz, "TIMESTAMPTZ"},
+ {oid.T_bytea, "BYTEA"},
+ }
+
+ for i, tt := range tts {
+ dt := fieldDesc{OID: tt.typ}
+ if name := dt.Name(); name != tt.name {
+ t.Errorf("(%d) got: %s want: %s", i, name, tt.name)
+ }
+ }
+}
+
+func TestDataType(t *testing.T) {
+ tts := []struct {
+ typ oid.Oid
+ kind reflect.Kind
+ }{
+ {oid.T_int8, reflect.Int64},
+ {oid.T_int4, reflect.Int32},
+ {oid.T_int2, reflect.Int16},
+ {oid.T_varchar, reflect.String},
+ {oid.T_text, reflect.String},
+ {oid.T_bool, reflect.Bool},
+ {oid.T_date, reflect.Struct},
+ {oid.T_time, reflect.Struct},
+ {oid.T_timetz, reflect.Struct},
+ {oid.T_timestamp, reflect.Struct},
+ {oid.T_timestamptz, reflect.Struct},
+ {oid.T_bytea, reflect.Slice},
+ }
+
+ for i, tt := range tts {
+ dt := fieldDesc{OID: tt.typ}
+ if kind := dt.Type().Kind(); kind != tt.kind {
+ t.Errorf("(%d) got: %s want: %s", i, kind, tt.kind)
+ }
+ }
+}
+
+func TestDataTypeLength(t *testing.T) {
+ tts := []struct {
+ typ oid.Oid
+ len int
+ mod int
+ length int64
+ ok bool
+ }{
+ {oid.T_int4, 0, -1, 0, false},
+ {oid.T_varchar, 65535, 9, 5, true},
+ {oid.T_text, 65535, -1, math.MaxInt64, true},
+ {oid.T_bytea, 65535, -1, math.MaxInt64, true},
+ }
+
+ for i, tt := range tts {
+ dt := fieldDesc{OID: tt.typ, Len: tt.len, Mod: tt.mod}
+ if l, k := dt.Length(); k != tt.ok || l != tt.length {
+ t.Errorf("(%d) got: %d, %t want: %d, %t", i, l, k, tt.length, tt.ok)
+ }
+ }
+}
+
+func TestDataTypePrecisionScale(t *testing.T) {
+ tts := []struct {
+ typ oid.Oid
+ mod int
+ precision, scale int64
+ ok bool
+ }{
+ {oid.T_int4, -1, 0, 0, false},
+ {oid.T_numeric, 589830, 9, 2, true},
+ {oid.T_text, -1, 0, 0, false},
+ }
+
+ for i, tt := range tts {
+ dt := fieldDesc{OID: tt.typ, Mod: tt.mod}
+ p, s, k := dt.PrecisionScale()
+ if k != tt.ok {
+ t.Errorf("(%d) got: %t want: %t", i, k, tt.ok)
+ }
+ if p != tt.precision {
+ t.Errorf("(%d) wrong precision got: %d want: %d", i, p, tt.precision)
+ }
+ if s != tt.scale {
+ t.Errorf("(%d) wrong scale got: %d want: %d", i, s, tt.scale)
+ }
+ }
+}
+
+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(""),
+ },
+ }
+
+ db := openTestConn(t)
+ defer db.Close()
+
+ 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)
+ }
+ }
+}