2
0

Handle json/jsonb in binary to support CopyTo

fixes #189
This commit is contained in:
Jack Christensen
2016-10-01 10:58:04 -05:00
parent a9199847a8
commit f7b6b3f077
4 changed files with 111 additions and 9 deletions
+49 -6
View File
@@ -91,23 +91,25 @@ func init() {
"bool": BinaryFormatCode,
"bytea": BinaryFormatCode,
"char": BinaryFormatCode,
"cid": BinaryFormatCode,
"cidr": BinaryFormatCode,
"date": BinaryFormatCode,
"float4": BinaryFormatCode,
"float8": BinaryFormatCode,
"json": BinaryFormatCode,
"jsonb": BinaryFormatCode,
"inet": BinaryFormatCode,
"int2": BinaryFormatCode,
"int4": BinaryFormatCode,
"int8": BinaryFormatCode,
"oid": BinaryFormatCode,
"tid": BinaryFormatCode,
"xid": BinaryFormatCode,
"cid": BinaryFormatCode,
"record": BinaryFormatCode,
"text": BinaryFormatCode,
"tid": BinaryFormatCode,
"timestamp": BinaryFormatCode,
"timestamptz": BinaryFormatCode,
"varchar": BinaryFormatCode,
"xid": BinaryFormatCode,
}
}
@@ -889,9 +891,12 @@ func Encode(wbuf *WriteBuf, oid Oid, arg interface{}) error {
return Encode(wbuf, oid, arg)
}
if oid == JsonOid || oid == JsonbOid {
if oid == JsonOid {
return encodeJSON(wbuf, oid, arg)
}
if oid == JsonbOid {
return encodeJSONB(wbuf, oid, arg)
}
switch arg := arg.(type) {
case []string:
@@ -1914,7 +1919,7 @@ func decodeJSON(vr *ValueReader, d interface{}) error {
return nil
}
if vr.Type().DataType != JsonOid && vr.Type().DataType != JsonbOid {
if vr.Type().DataType != JsonOid {
vr.Fatal(ProtocolError(fmt.Sprintf("Cannot decode oid %v into json", vr.Type().DataType)))
}
@@ -1927,7 +1932,7 @@ func decodeJSON(vr *ValueReader, d interface{}) error {
}
func encodeJSON(w *WriteBuf, oid Oid, value interface{}) error {
if oid != JsonOid && oid != JsonbOid {
if oid != JsonOid {
return fmt.Errorf("cannot encode JSON into oid %v", oid)
}
@@ -1942,6 +1947,44 @@ func encodeJSON(w *WriteBuf, oid Oid, value interface{}) error {
return nil
}
func decodeJSONB(vr *ValueReader, d interface{}) error {
if vr.Len() == -1 {
return nil
}
if vr.Type().DataType != JsonbOid {
vr.Fatal(ProtocolError(fmt.Sprintf("Cannot decode oid %v into jsonb", vr.Type().DataType)))
}
bytes := vr.ReadBytes(vr.Len())
if bytes[0] != 1 {
vr.Fatal(ProtocolError(fmt.Sprintf("Unknown jsonb format byte: %x", bytes[0])))
}
err := json.Unmarshal(bytes[1:], d)
if err != nil {
vr.Fatal(err)
}
return err
}
func encodeJSONB(w *WriteBuf, oid Oid, value interface{}) error {
if oid != JsonbOid {
return fmt.Errorf("cannot encode JSON into oid %v", oid)
}
s, err := json.Marshal(value)
if err != nil {
return fmt.Errorf("Failed to encode json from type: %T", value)
}
w.WriteInt32(int32(len(s) + 1))
w.WriteByte(1) // JSONB format header
w.WriteBytes(s)
return nil
}
func decodeDate(vr *ValueReader) time.Time {
var zeroTime time.Time