From 1042f095ee3ecebc5406a7a789de328c9692c7b5 Mon Sep 17 00:00:00 2001 From: Jack Christensen Date: Sun, 30 Jun 2013 09:25:19 -0500 Subject: [PATCH] More pluggable value transcoding --- data_row_reader.go | 63 +++++------------------------- value_transcoder.go | 94 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 54 deletions(-) create mode 100644 value_transcoder.go diff --git a/data_row_reader.go b/data_row_reader.go index d37d0813..55072fe0 100644 --- a/data_row_reader.go +++ b/data_row_reader.go @@ -1,13 +1,9 @@ package pgx -import ( - "fmt" - "strconv" -) - type DataRowReader struct { - mr *MessageReader - fields []FieldDescription + mr *MessageReader + fields []FieldDescription + currentFieldIdx int } func newDataRowReader(mr *MessageReader, fields []FieldDescription) (r *DataRowReader) { @@ -24,55 +20,14 @@ func newDataRowReader(mr *MessageReader, fields []FieldDescription) (r *DataRowR } func (r *DataRowReader) ReadValue() interface{} { + dataType := r.fields[r.currentFieldIdx].DataType + r.currentFieldIdx++ + size := r.mr.ReadInt32() if size > -1 { - switch r.fields[0].DataType { - case oid(16): // bool - s := r.mr.ReadByteString(size) - switch s { - case "t": - return true - case "f": - return false - default: - panic(fmt.Sprintf("Received invalid bool: %v", s)) - } - case oid(20): // int8 - s := r.mr.ReadByteString(size) - n, err := strconv.ParseInt(s, 10, 64) - if err != nil { - panic(fmt.Sprintf("Received invalid int8: %v", s)) - } - return n - case oid(21): // int2 - s := r.mr.ReadByteString(size) - n, err := strconv.ParseInt(s, 10, 16) - if err != nil { - panic(fmt.Sprintf("Received invalid int2: %v", s)) - } - return int16(n) - case oid(23): // int4 - s := r.mr.ReadByteString(size) - n, err := strconv.ParseInt(s, 10, 32) - if err != nil { - panic(fmt.Sprintf("Received invalid int4: %v", s)) - } - return int32(n) - case oid(700): // float4 - s := r.mr.ReadByteString(size) - n, err := strconv.ParseFloat(s, 32) - if err != nil { - panic(fmt.Sprintf("Received invalid float4: %v", s)) - } - return float32(n) - case oid(701): //float8 - s := r.mr.ReadByteString(size) - v, err := strconv.ParseFloat(s, 64) - if err != nil { - panic(fmt.Sprintf("Received invalid float8: %v", s)) - } - return v - default: + if vt, present := valueTranscoders[dataType]; present { + return vt.FromText(r.mr, size) + } else { return r.mr.ReadByteString(size) } } else { diff --git a/value_transcoder.go b/value_transcoder.go new file mode 100644 index 00000000..a072b976 --- /dev/null +++ b/value_transcoder.go @@ -0,0 +1,94 @@ +package pgx + +import ( + "fmt" + "strconv" +) + +type valueTranscoder struct { + FromText func(*MessageReader, int32) interface{} + // FromBinary func(*MessageReader, int32) interface{} + // ToText func(interface{}) string + // ToBinary func(interface{}) []byte +} + +var valueTranscoders map[oid]*valueTranscoder + +func init() { + valueTranscoders = make(map[oid]*valueTranscoder) + + // bool + valueTranscoders[oid(16)] = &valueTranscoder{FromText: decodeBoolFromText} + + // int8 + valueTranscoders[oid(20)] = &valueTranscoder{FromText: decodeInt8FromText} + + // int2 + valueTranscoders[oid(21)] = &valueTranscoder{FromText: decodeInt2FromText} + + // int4 + valueTranscoders[oid(23)] = &valueTranscoder{FromText: decodeInt4FromText} + + // float4 + valueTranscoders[oid(700)] = &valueTranscoder{FromText: decodeFloat4FromText} + + // float8 + valueTranscoders[oid(701)] = &valueTranscoder{FromText: decodeFloat8FromText} +} + +func decodeBoolFromText(mr *MessageReader, size int32) interface{} { + s := mr.ReadByteString(size) + switch s { + case "t": + return true + case "f": + return false + default: + panic(fmt.Sprintf("Received invalid bool: %v", s)) + } +} + +func decodeInt8FromText(mr *MessageReader, size int32) interface{} { + s := mr.ReadByteString(size) + n, err := strconv.ParseInt(s, 10, 64) + if err != nil { + panic(fmt.Sprintf("Received invalid int8: %v", s)) + } + return n +} + +func decodeInt2FromText(mr *MessageReader, size int32) interface{} { + s := mr.ReadByteString(size) + n, err := strconv.ParseInt(s, 10, 16) + if err != nil { + panic(fmt.Sprintf("Received invalid int2: %v", s)) + } + return int16(n) +} + +func decodeInt4FromText(mr *MessageReader, size int32) interface{} { + s := mr.ReadByteString(size) + n, err := strconv.ParseInt(s, 10, 32) + if err != nil { + panic(fmt.Sprintf("Received invalid int4: %v", s)) + } + return int32(n) +} + +func decodeFloat4FromText(mr *MessageReader, size int32) interface{} { + s := mr.ReadByteString(size) + n, err := strconv.ParseFloat(s, 32) + if err != nil { + panic(fmt.Sprintf("Received invalid float4: %v", s)) + } + return float32(n) +} + +func decodeFloat8FromText(mr *MessageReader, size int32) interface{} { + s := mr.ReadByteString(size) + v, err := strconv.ParseFloat(s, 64) + if err != nil { + panic(fmt.Sprintf("Received invalid float8: %v", s)) + } + return v +}