func TestQueryRowCoreTypes(t *testing.T) { t.Parallel() conn := mustConnect(t, *defaultConnConfig) defer closeConn(t, conn) type allTypes struct { s string f32 float32 f64 float64 b bool t time.Time oid pgx.Oid } var actual, zero allTypes tests := []struct { sql string queryArgs []interface{} scanArgs []interface{} expected allTypes }{ {"select $1::text", []interface{}{"Jack"}, []interface{}{&actual.s}, allTypes{s: "Jack"}}, {"select $1::float4", []interface{}{float32(1.23)}, []interface{}{&actual.f32}, allTypes{f32: 1.23}}, {"select $1::float8", []interface{}{float64(1.23)}, []interface{}{&actual.f64}, allTypes{f64: 1.23}}, {"select $1::bool", []interface{}{true}, []interface{}{&actual.b}, allTypes{b: true}}, {"select $1::timestamptz", []interface{}{time.Unix(123, 5000)}, []interface{}{&actual.t}, allTypes{t: time.Unix(123, 5000)}}, {"select $1::timestamp", []interface{}{time.Date(2010, 1, 2, 3, 4, 5, 0, time.Local)}, []interface{}{&actual.t}, allTypes{t: time.Date(2010, 1, 2, 3, 4, 5, 0, time.Local)}}, {"select $1::date", []interface{}{time.Date(1987, 1, 2, 0, 0, 0, 0, time.Local)}, []interface{}{&actual.t}, allTypes{t: time.Date(1987, 1, 2, 0, 0, 0, 0, time.Local)}}, {"select $1::oid", []interface{}{pgx.Oid(42)}, []interface{}{&actual.oid}, allTypes{oid: 42}}, } for i, tt := range tests { actual = zero err := conn.QueryRow(tt.sql, tt.queryArgs...).Scan(tt.scanArgs...) if err != nil { t.Errorf("%d. Unexpected failure: %v (sql -> %v, queryArgs -> %v)", i, err, tt.sql, tt.queryArgs) } if actual != tt.expected { t.Errorf("%d. Expected %v, got %v (sql -> %v, queryArgs -> %v)", i, tt.expected, actual, tt.sql, tt.queryArgs) } ensureConnValid(t, conn) // Check that Scan errors when a core type is null err = conn.QueryRow(tt.sql, nil).Scan(tt.scanArgs...) if err == nil { t.Errorf("%d. Expected null to cause error, but it didn't (sql -> %v)", i, tt.sql) } if err != nil && !strings.Contains(err.Error(), "Cannot decode null") { t.Errorf(`%d. Expected null to cause error "Cannot decode null..." but it was %v (sql -> %v)`, i, err, tt.sql) } ensureConnValid(t, conn) } }
func TestConnQueryValues(t *testing.T) { t.Parallel() conn := mustConnect(t, *defaultConnConfig) defer closeConn(t, conn) var rowCount int32 rows, err := conn.Query("select 'foo'::text, 'bar'::varchar, n, null, n::oid from generate_series(1,$1) n", 10) if err != nil { t.Fatalf("conn.Query failed: %v", err) } defer rows.Close() for rows.Next() { rowCount++ values, err := rows.Values() if err != nil { t.Fatalf("rows.Values failed: %v", err) } if len(values) != 5 { t.Errorf("Expected rows.Values to return 5 values, but it returned %d", len(values)) } if values[0] != "foo" { t.Errorf(`Expected values[0] to be "foo", but it was %v`, values[0]) } if values[1] != "bar" { t.Errorf(`Expected values[1] to be "bar", but it was %v`, values[1]) } if values[2] != rowCount { t.Errorf(`Expected values[2] to be %d, but it was %d`, rowCount, values[2]) } if values[3] != nil { t.Errorf(`Expected values[3] to be %v, but it was %d`, nil, values[3]) } if values[4] != pgx.Oid(rowCount) { t.Errorf(`Expected values[4] to be %d, but it was %d`, rowCount, values[4]) } } if rows.Err() != nil { t.Fatalf("conn.Query failed: %v", err) } if rowCount != 10 { t.Error("Select called onDataRow wrong number of times") } }