mirror of https://github.com/jackc/pgx.git
pgtype.JSON(B).Value now returns []byte
Allows scanning jsonb column into *json.RawMessage. fixes #409pull/414/head
parent
6556ef67cb
commit
5297846239
|
@ -12,6 +12,13 @@
|
||||||
* Fix StartReplication() syntax (steampunkcoder)
|
* Fix StartReplication() syntax (steampunkcoder)
|
||||||
* Fix precision loss for test format geometric types
|
* Fix precision loss for test format geometric types
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
* pgtype.JSON(B).Value now returns []byte instead of string. This allows
|
||||||
|
database/sql to scan json(b) into \*json.RawMessage. This is a tiny behavior
|
||||||
|
change, but database/sql Scan should automatically convert []byte to string, so
|
||||||
|
there shouldn't be any incompatibility.
|
||||||
|
|
||||||
# 3.1.0 (January 15, 2018)
|
# 3.1.0 (January 15, 2018)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
|
@ -152,7 +152,7 @@ func (dst *JSON) Scan(src interface{}) error {
|
||||||
func (src *JSON) Value() (driver.Value, error) {
|
func (src *JSON) Value() (driver.Value, error) {
|
||||||
switch src.Status {
|
switch src.Status {
|
||||||
case Present:
|
case Present:
|
||||||
return string(src.Bytes), nil
|
return src.Bytes, nil
|
||||||
case Null:
|
case Null:
|
||||||
return nil, nil
|
return nil, nil
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -495,6 +495,10 @@ func (r *Rows) Next(dest []driver.Value) error {
|
||||||
r.values[i] = &pgtype.Int4{}
|
r.values[i] = &pgtype.Int4{}
|
||||||
case pgtype.Int8OID:
|
case pgtype.Int8OID:
|
||||||
r.values[i] = &pgtype.Int8{}
|
r.values[i] = &pgtype.Int8{}
|
||||||
|
case pgtype.JSONOID:
|
||||||
|
r.values[i] = &pgtype.JSON{}
|
||||||
|
case pgtype.JSONBOID:
|
||||||
|
r.values[i] = &pgtype.JSONB{}
|
||||||
case pgtype.OIDOID:
|
case pgtype.OIDOID:
|
||||||
r.values[i] = &pgtype.OIDValue{}
|
r.values[i] = &pgtype.OIDValue{}
|
||||||
case pgtype.TimestampOID:
|
case pgtype.TimestampOID:
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -1466,3 +1467,22 @@ func TestSimpleQueryLifeCycle(t *testing.T) {
|
||||||
|
|
||||||
ensureConnValid(t, db)
|
ensureConnValid(t, db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/jackc/pgx/issues/409
|
||||||
|
func TestScanJSONIntoJSONRawMessage(t *testing.T) {
|
||||||
|
db := openDB(t)
|
||||||
|
defer closeDB(t, db)
|
||||||
|
|
||||||
|
var msg json.RawMessage
|
||||||
|
|
||||||
|
err := db.QueryRow("select '{}'::jsonb").Scan(&msg)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("QueryRow / Scan failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes.Compare([]byte("{}"), []byte(msg)) != 0 {
|
||||||
|
t.Fatalf("Expected %v, got %v", []byte("{}"), msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureConnValid(t, db)
|
||||||
|
}
|
||||||
|
|
26
values.go
26
values.go
|
@ -31,6 +31,32 @@ func convertSimpleArgument(ci *pgtype.ConnInfo, arg interface{}) (interface{}, e
|
||||||
}
|
}
|
||||||
|
|
||||||
switch arg := arg.(type) {
|
switch arg := arg.(type) {
|
||||||
|
|
||||||
|
// https://github.com/jackc/pgx/issues/409 Changed JSON and JSONB to surface
|
||||||
|
// []byte to database/sql instead of string. But that caused problems with the
|
||||||
|
// simple protocol because the driver.Valuer case got taken before the
|
||||||
|
// pgtype.TextEncoder case. And driver.Valuer needed to be first in the usual
|
||||||
|
// case because of https://github.com/jackc/pgx/issues/339. So instead we
|
||||||
|
// special case JSON and JSONB.
|
||||||
|
case *pgtype.JSON:
|
||||||
|
buf, err := arg.EncodeText(ci, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if buf == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return string(buf), nil
|
||||||
|
case *pgtype.JSONB:
|
||||||
|
buf, err := arg.EncodeText(ci, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if buf == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return string(buf), nil
|
||||||
|
|
||||||
case driver.Valuer:
|
case driver.Valuer:
|
||||||
return callValuerValue(arg)
|
return callValuerValue(arg)
|
||||||
case pgtype.TextEncoder:
|
case pgtype.TextEncoder:
|
||||||
|
|
Loading…
Reference in New Issue