func (t *DBTest) TestLargeWriteRead(c *C) { src := bytes.Repeat([]byte{0x1}, 1e6) var dst []byte _, err := t.db.QueryOne(pg.Scan(&dst), "SELECT ?", src) c.Assert(err, IsNil) c.Assert(dst, DeepEquals, src) }
func (t *DBTest) TestTime(c *C) { for _, test := range timeTests { var tm time.Time _, err := t.db.QueryOne(pg.Scan(&tm), "SELECT ?", test.str) c.Assert(err, IsNil) c.Assert(tm.Unix(), Equals, test.wanted.Unix(), Commentf("str=%q", test.str)) } }
func ExampleDB_WithTimeout() { var count int // Use bigger timeout since this query is known to be slow. _, err := db.WithTimeout(time.Minute).QueryOne(pg.Scan(&count), ` SELECT count(*) FROM big_table `) if err != nil { panic(err) } }
func ExampleDB_Prepare() { stmt, err := db.Prepare(`SELECT $1::text, $2::text`) if err != nil { panic(err) } var s1, s2 string _, err = stmt.QueryOne(pg.Scan(&s1, &s2), "foo", "bar") fmt.Println(s1, s2, err) // Output: foo bar <nil> }
func (t *LoaderTest) TestLoaderError(c *C) { tx, err := t.db.Begin() c.Assert(err, IsNil) defer tx.Rollback() loader := errLoader("my error") _, err = tx.QueryOne(loader, "SELECT 1, 2") c.Assert(err.Error(), Equals, "my error") // Verify that client is still functional. var n1, n2 int _, err = tx.QueryOne(pg.Scan(&n1, &n2), "SELECT 1, 2") c.Assert(err, IsNil) c.Assert(n1, Equals, 1) c.Assert(n2, Equals, 2) }
func BenchmarkQueryRowScan(b *testing.B) { db := pg.Connect(pgOptions()) defer db.Close() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { var n int64 _, err := db.QueryOne(pg.Scan(&n), `SELECT ? AS num`, 1) if err != nil { b.Fatal(err) } if n != 1 { b.Fatalf("got %d, wanted 1", n) } } }) }
func BenchmarkQueryRowStmtScan(b *testing.B) { db := pg.Connect(pgOptions()) defer db.Close() stmt, err := db.Prepare(`SELECT $1::bigint AS num`) if err != nil { b.Fatal(err) } defer stmt.Close() b.ResetTimer() for i := 0; i < b.N; i++ { var n int64 _, err := stmt.QueryOne(pg.Scan(&n), 1) if err != nil { b.Fatal(err) } if n != 1 { b.Fatalf("got %d, wanted 1", n) } } }
func (t *DBTest) TestScan(c *C) { var dst int _, err := t.db.QueryOne(pg.Scan(&dst), "SELECT 1") c.Assert(err, IsNil) c.Assert(dst, Equals, 1) }
func TestConversion(t *testing.T) { conversionTests := []conversionTest{ {src: true, dst: nil, wanterr: "pg: Decode(nil)"}, {src: true, dst: new(uintptr), wanterr: "pg: Decode(unsupported uintptr)"}, {src: true, dst: true, wanterr: "pg: Decode(nonsettable bool)"}, {src: true, dst: (*bool)(nil), wanterr: "pg: Decode(nonsettable *bool)"}, {src: nil, dst: new(*bool), pgtype: "bool", wantnil: true}, {src: nil, dst: new(bool), pgtype: "bool", wantzero: true}, {src: true, dst: new(bool), pgtype: "bool"}, {src: true, dst: new(*bool), pgtype: "bool"}, {src: nil, dst: new(string), pgtype: "text", wantzero: true}, {src: nil, dst: new(*string), pgtype: "text", wantnil: true}, {src: "hello world", dst: new(string), pgtype: "text"}, {src: "hello world", dst: new(*string), pgtype: "text"}, {src: "'\"\000", dst: new(string), wanted: `'"`, pgtype: "text"}, {src: []byte("hello world\000"), dst: new([]byte), pgtype: "bytea"}, {src: []byte{}, dst: new([]byte), pgtype: "bytea", wantzero: true}, {src: nil, dst: new([]byte), pgtype: "bytea", wantnil: true}, {src: int(math.MaxInt32), dst: new(int), pgtype: "int"}, {src: int(math.MinInt32), dst: new(int), pgtype: "int"}, {src: nil, dst: new(int), pgtype: "int", wantzero: true}, {src: int(math.MaxInt32), dst: new(*int), pgtype: "int"}, {src: nil, dst: new(*int), pgtype: "int", wantnil: true}, {src: int8(math.MaxInt8), dst: new(int8), pgtype: "smallint"}, {src: int8(math.MinInt8), dst: new(int8), pgtype: "smallint"}, {src: int16(math.MaxInt16), dst: new(int16), pgtype: "smallint"}, {src: int16(math.MinInt16), dst: new(int16), pgtype: "smallint"}, {src: int32(math.MaxInt32), dst: new(int32), pgtype: "int"}, {src: int32(math.MinInt32), dst: new(int32), pgtype: "int"}, {src: int64(math.MaxInt64), dst: new(int64), pgtype: "bigint"}, {src: int64(math.MinInt64), dst: new(int64), pgtype: "bigint"}, {src: uint(math.MaxUint32), dst: new(uint), pgtype: "bigint"}, {src: uint8(math.MaxUint8), dst: new(uint8), pgtype: "smallint"}, {src: uint16(math.MaxUint16), dst: new(uint16), pgtype: "int"}, {src: uint32(math.MaxUint32), dst: new(uint32), pgtype: "bigint"}, {src: uint64(math.MaxUint64), dst: new(uint64)}, {src: float32(math.MaxFloat32), dst: new(float32), pgtype: "decimal"}, {src: float32(math.SmallestNonzeroFloat32), dst: new(float32), pgtype: "decimal"}, {src: float64(math.MaxFloat64), dst: new(float64), pgtype: "decimal"}, {src: float64(math.SmallestNonzeroFloat64), dst: new(float64), pgtype: "decimal"}, {src: nil, dst: new([]int), pgtype: "jsonb", wantnil: true}, {src: []int(nil), dst: new([]int), pgtype: "jsonb", wantnil: true}, {src: []int{}, dst: new([]int), pgtype: "jsonb", wantzero: true}, {src: []int{1, 2, 3}, dst: new([]int), pgtype: "jsonb"}, {src: IntSlice{1, 2, 3}, dst: new(IntSlice), pgtype: "jsonb"}, { src: nil, dst: &types.Array{[]int(nil)}, pgtype: "int[]", wantzero: true, }, { src: types.Array{[]int(nil)}, dst: &types.Array{[]int(nil)}, pgtype: "int[]", wantzero: true, }, { src: types.Array{[]int{}}, dst: &types.Array{[]int(nil)}, pgtype: "int[]", }, { src: types.Array{[]int{1, 2, 3}}, dst: &types.Array{[]int(nil)}, pgtype: "int[]", }, {src: nil, dst: new([]int64), pgtype: "jsonb", wantnil: true}, {src: []int64(nil), dst: new([]int64), pgtype: "jsonb", wantnil: true}, {src: []int64{}, dst: new([]int64), pgtype: "jsonb", wantzero: true}, {src: []int64{1, 2, 3}, dst: new([]int64), pgtype: "jsonb"}, {src: Int64Slice{1, 2, 3}, dst: new(Int64Slice), pgtype: "jsonb"}, { src: nil, dst: &types.Array{[]int64(nil)}, pgtype: "bigint[]", wantzero: true, }, { src: types.Array{[]int64(nil)}, dst: &types.Array{[]int64(nil)}, pgtype: "bigint[]", wantzero: true, }, { src: types.Array{[]int64{}}, dst: &types.Array{[]int64(nil)}, pgtype: "bigint[]", }, { src: types.Array{[]int64{1, 2, 3}}, dst: &types.Array{[]int64(nil)}, pgtype: "bigint[]", }, {src: nil, dst: new([]float64), pgtype: "jsonb", wantnil: true}, {src: []float64(nil), dst: new([]float64), pgtype: "jsonb", wantnil: true}, {src: []float64{1.1, 2.22, 3.333}, dst: new([]float64), pgtype: "jsonb"}, {src: Float64Slice{1.1, 2.22, 3.333}, dst: new(Float64Slice), pgtype: "jsonb"}, { src: nil, dst: &types.Array{[]float64(nil)}, pgtype: "decimal[]", wantzero: true, }, { src: types.Array{[]float64(nil)}, dst: &types.Array{[]float64(nil)}, pgtype: "decimal[]", wantzero: true, }, { src: types.Array{[]float64{}}, dst: &types.Array{[]float64(nil)}, pgtype: "decimal[]", }, { src: types.Array{[]float64{1.1, 2.22, 3.333}}, dst: &types.Array{[]float64(nil)}, pgtype: "decimal[]", }, {src: nil, dst: new([]string), pgtype: "jsonb", wantnil: true}, {src: []string(nil), dst: new([]string), pgtype: "jsonb", wantnil: true}, {src: []string{}, dst: new([]string), pgtype: "jsonb", wantzero: true}, {src: []string{"foo\n", "bar {}", "'\\\""}, dst: new([]string), pgtype: "jsonb"}, {src: StringSlice{"foo", "bar"}, dst: new(StringSlice), pgtype: "jsonb"}, { src: nil, dst: &types.Array{[]string(nil)}, pgtype: "text[]", wantzero: true, }, { src: types.Array{[]string(nil)}, dst: &types.Array{[]string(nil)}, pgtype: "text[]", wantzero: true, }, { src: types.Array{[]string{}}, dst: &types.Array{[]string(nil)}, pgtype: "text[]", }, { src: types.Array{[]string{"one", "two", "three"}}, dst: &types.Array{[]string(nil)}, pgtype: "text[]", }, { src: nil, dst: new(map[string]string), pgtype: "jsonb", wantnil: true, }, { src: map[string]string(nil), dst: new(map[string]string), pgtype: "jsonb", wantnil: true, }, { src: map[string]string{"foo\n =>": "bar\n =>", "'\\\"": "'\\\""}, dst: new(map[string]string), pgtype: "jsonb", }, {src: &sql.NullBool{}, dst: &sql.NullBool{}, pgtype: "bool"}, {src: &sql.NullBool{Valid: true}, dst: &sql.NullBool{}, pgtype: "bool"}, {src: &sql.NullBool{Valid: true, Bool: true}, dst: &sql.NullBool{}, pgtype: "bool"}, {src: &sql.NullString{}, dst: &sql.NullString{}, pgtype: "text"}, {src: &sql.NullString{Valid: true}, dst: &sql.NullString{}, pgtype: "text"}, {src: &sql.NullString{Valid: true, String: "foo"}, dst: &sql.NullString{}, pgtype: "text"}, {src: &sql.NullInt64{}, dst: &sql.NullInt64{}, pgtype: "bigint"}, {src: &sql.NullInt64{Valid: true}, dst: &sql.NullInt64{}, pgtype: "bigint"}, {src: &sql.NullInt64{Valid: true, Int64: math.MaxInt64}, dst: &sql.NullInt64{}, pgtype: "bigint"}, {src: &sql.NullFloat64{}, dst: &sql.NullFloat64{}, pgtype: "decimal"}, {src: &sql.NullFloat64{Valid: true}, dst: &sql.NullFloat64{}, pgtype: "decimal"}, {src: &sql.NullFloat64{Valid: true, Float64: math.MaxFloat64}, dst: &sql.NullFloat64{}, pgtype: "decimal"}, {src: nil, dst: &customStrSlice{}, wantnil: true}, {src: customStrSlice{}, dst: &customStrSlice{}, wantzero: true}, {src: customStrSlice{"one", "two"}, dst: &customStrSlice{}}, {src: time.Time{}, dst: &time.Time{}, pgtype: "timestamp"}, {src: time.Now(), dst: &time.Time{}, pgtype: "timestamp"}, {src: time.Now().UTC(), dst: &time.Time{}, pgtype: "timestamp"}, {src: nil, dst: &time.Time{}, pgtype: "timestamp", wantzero: true}, {src: time.Now(), dst: new(*time.Time), pgtype: "timestamp"}, {src: nil, dst: new(*time.Time), pgtype: "timestamp", wantnil: true}, {src: time.Time{}, dst: &time.Time{}, pgtype: "timestamptz"}, {src: time.Now(), dst: &time.Time{}, pgtype: "timestamptz"}, {src: time.Now().UTC(), dst: &time.Time{}, pgtype: "timestamptz"}, {src: nil, dst: &time.Time{}, pgtype: "timestamptz", wantzero: true}, {src: time.Now(), dst: new(*time.Time), pgtype: "timestamptz"}, {src: nil, dst: new(*time.Time), pgtype: "timestamptz", wantnil: true}, {src: 1, dst: new(pg.Ints), wanted: pg.Ints{1}}, {src: "hello", dst: new(pg.Strings), wanted: pg.Strings{"hello"}}, {src: 1, dst: new(pg.IntSet), wanted: pg.IntSet{1: struct{}{}}}, {src: nil, dst: new(*JSONMap), wantnil: true, pgtype: "json"}, {src: nil, dst: new(JSONMap), wantnil: true, pgtype: "json"}, {src: JSONMap{}, dst: &JSONMap{}, pgtype: "json"}, {src: JSONMap{"foo": "bar"}, dst: &JSONMap{}, pgtype: "json"}, {src: JSONMap{"foo": "bar"}, dst: new(*JSONMap), pgtype: "json"}, {src: `{"foo": "bar"}`, dst: &JSONField{}, wanted: JSONField{Foo: "bar"}}, {src: nil, dst: new(*Struct), wantnil: true, pgtype: "json"}, {src: nil, dst: new(Struct), wantzero: true, pgtype: "json"}, {src: Struct{}, dst: &Struct{}, pgtype: "json"}, {src: Struct{Foo: "bar"}, dst: &Struct{}, pgtype: "json"}, {src: Struct{Foo: "bar"}, dst: new(*Struct), pgtype: "json"}, {src: `{"foo": "bar"}`, dst: new(Struct), wanted: Struct{Foo: "bar"}}, } db := pg.Connect(pgOptions()) db.Exec("CREATE EXTENSION hstore") defer db.Exec("DROP EXTENSION hstore") for i, test := range conversionTests { test.i = i var err error if _, ok := test.dst.(orm.ColumnScanner); ok { _, err = db.QueryOne(test.dst, "SELECT (?) AS dst", test.src) } else { dst := struct{ Dst interface{} }{Dst: test.dst} _, err = db.QueryOne(&dst, "SELECT (?) AS dst", test.src) } test.Assert(t, err) } for i, test := range conversionTests { test.i = i if test.pgtype == "" { continue } stmt, err := db.Prepare(fmt.Sprintf("SELECT ($1::%s) AS dst", test.pgtype)) if err != nil { t.Fatal(err) } if _, ok := test.dst.(orm.ColumnScanner); ok { _, err = stmt.QueryOne(test.dst, test.src) } else { dst := struct{ Dst interface{} }{Dst: test.dst} _, err = stmt.QueryOne(&dst, test.src) } test.Assert(t, err) if err := stmt.Close(); err != nil { t.Fatal(err) } } for i, test := range conversionTests { test.i = i if _, ok := test.dst.(orm.ColumnScanner); ok { continue } _, err := db.QueryOne(pg.Scan(test.dst), "SELECT (?) AS dst", test.src) test.Assert(t, err) } for i, test := range conversionTests { test.i = i if _, ok := test.dst.(orm.ColumnScanner); ok { continue } if test.pgtype == "" { continue } stmt, err := db.Prepare(fmt.Sprintf("SELECT ($1::%s) AS dst", test.pgtype)) if err != nil { t.Fatal(err) } _, err = stmt.QueryOne(pg.Scan(test.dst), test.src) test.Assert(t, err) if err := stmt.Close(); err != nil { t.Fatal(err) } } }
func ExampleDB_QueryOne_Scan() { var s1, s2 string _, err := db.QueryOne(pg.Scan(&s1, &s2), `SELECT ?, ?`, "foo", "bar") fmt.Println(s1, s2, err) // Output: foo bar <nil> }