Refactor prepared statement path to use ValueTranscoder
This commit is contained in:
+12
-31
@@ -9,8 +9,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConnectionParameters struct {
|
type ConnectionParameters struct {
|
||||||
@@ -350,37 +348,20 @@ func (c *Connection) sendPreparedQuery(ps *PreparedStatement, arguments ...inter
|
|||||||
buf.WriteByte(0)
|
buf.WriteByte(0)
|
||||||
buf.WriteString(ps.Name)
|
buf.WriteString(ps.Name)
|
||||||
buf.WriteByte(0)
|
buf.WriteByte(0)
|
||||||
binary.Write(buf, binary.BigEndian, int16(0))
|
binary.Write(buf, binary.BigEndian, int16(len(ps.ParameterOids)))
|
||||||
binary.Write(buf, binary.BigEndian, int16(len(arguments)))
|
for _, oid := range ps.ParameterOids {
|
||||||
for _, iArg := range arguments {
|
transcoder := valueTranscoders[oid]
|
||||||
var s string
|
if transcoder == nil {
|
||||||
switch arg := iArg.(type) {
|
panic(fmt.Sprintf("can't encode %#v", oid))
|
||||||
case string:
|
|
||||||
s = arg
|
|
||||||
case int16:
|
|
||||||
s = strconv.FormatInt(int64(arg), 10)
|
|
||||||
case int32:
|
|
||||||
s = strconv.FormatInt(int64(arg), 10)
|
|
||||||
case int64:
|
|
||||||
s = strconv.FormatInt(int64(arg), 10)
|
|
||||||
case float32:
|
|
||||||
s = strconv.FormatFloat(float64(arg), 'f', -1, 32)
|
|
||||||
case float64:
|
|
||||||
s = strconv.FormatFloat(arg, 'f', -1, 64)
|
|
||||||
case []byte:
|
|
||||||
s = `E'\\x` + hex.EncodeToString(arg) + `'`
|
|
||||||
default:
|
|
||||||
panic("Unable to encode type: " + reflect.TypeOf(arg).String())
|
|
||||||
}
|
}
|
||||||
binary.Write(buf, binary.BigEndian, int32(len(s)))
|
binary.Write(buf, binary.BigEndian, transcoder.EncodeFormat)
|
||||||
buf.WriteString(s)
|
}
|
||||||
|
|
||||||
|
binary.Write(buf, binary.BigEndian, int16(len(arguments)))
|
||||||
|
for i, oid := range ps.ParameterOids {
|
||||||
|
transcoder := valueTranscoders[oid]
|
||||||
|
transcoder.EncodeTo(buf, arguments[i])
|
||||||
}
|
}
|
||||||
// for _, pd := range ps.ParameterOids {
|
|
||||||
// transcoder := valueTranscoders[pd]
|
|
||||||
// if transcoder == nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
binary.Write(buf, binary.BigEndian, int16(0))
|
binary.Write(buf, binary.BigEndian, int16(0))
|
||||||
|
|
||||||
err = c.txMsg('B', buf)
|
err = c.txMsg('B', buf)
|
||||||
|
|||||||
+81
-8
@@ -1,15 +1,16 @@
|
|||||||
package pgx
|
package pgx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type valueTranscoder struct {
|
type valueTranscoder struct {
|
||||||
DecodeText func(*MessageReader, int32) interface{}
|
DecodeText func(*MessageReader, int32) interface{}
|
||||||
DecodeBinary func(*MessageReader, int32) interface{}
|
DecodeBinary func(*MessageReader, int32) interface{}
|
||||||
EncodeTo func(io.Writer, interface{})
|
EncodeTo func(*bytes.Buffer, interface{})
|
||||||
EncodeFormat int16
|
EncodeFormat int16
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,22 +20,42 @@ func init() {
|
|||||||
valueTranscoders = make(map[oid]*valueTranscoder)
|
valueTranscoders = make(map[oid]*valueTranscoder)
|
||||||
|
|
||||||
// bool
|
// bool
|
||||||
valueTranscoders[oid(16)] = &valueTranscoder{DecodeText: decodeBoolFromText}
|
valueTranscoders[oid(16)] = &valueTranscoder{
|
||||||
|
DecodeText: decodeBoolFromText,
|
||||||
|
EncodeTo: encodeBool}
|
||||||
|
|
||||||
// int8
|
// int8
|
||||||
valueTranscoders[oid(20)] = &valueTranscoder{DecodeText: decodeInt8FromText}
|
valueTranscoders[oid(20)] = &valueTranscoder{
|
||||||
|
DecodeText: decodeInt8FromText,
|
||||||
|
EncodeTo: encodeInt8}
|
||||||
|
|
||||||
// int2
|
// int2
|
||||||
valueTranscoders[oid(21)] = &valueTranscoder{DecodeText: decodeInt2FromText}
|
valueTranscoders[oid(21)] = &valueTranscoder{
|
||||||
|
DecodeText: decodeInt2FromText,
|
||||||
|
EncodeTo: encodeInt2}
|
||||||
|
|
||||||
// int4
|
// int4
|
||||||
valueTranscoders[oid(23)] = &valueTranscoder{DecodeText: decodeInt4FromText}
|
valueTranscoders[oid(23)] = &valueTranscoder{
|
||||||
|
DecodeText: decodeInt4FromText,
|
||||||
|
EncodeTo: encodeInt4}
|
||||||
|
|
||||||
|
// text
|
||||||
|
valueTranscoders[oid(25)] = &valueTranscoder{
|
||||||
|
DecodeText: decodeTextFromText,
|
||||||
|
EncodeTo: encodeText}
|
||||||
|
|
||||||
// float4
|
// float4
|
||||||
valueTranscoders[oid(700)] = &valueTranscoder{DecodeText: decodeFloat4FromText}
|
valueTranscoders[oid(700)] = &valueTranscoder{
|
||||||
|
DecodeText: decodeFloat4FromText,
|
||||||
|
EncodeTo: encodeFloat4}
|
||||||
|
|
||||||
// float8
|
// float8
|
||||||
valueTranscoders[oid(701)] = &valueTranscoder{DecodeText: decodeFloat8FromText}
|
valueTranscoders[oid(701)] = &valueTranscoder{
|
||||||
|
DecodeText: decodeFloat8FromText,
|
||||||
|
EncodeTo: encodeFloat8}
|
||||||
|
|
||||||
|
// varchar -- same as text
|
||||||
|
valueTranscoders[oid(1043)] = valueTranscoders[oid(25)]
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeBoolFromText(mr *MessageReader, size int32) interface{} {
|
func decodeBoolFromText(mr *MessageReader, size int32) interface{} {
|
||||||
@@ -49,6 +70,13 @@ func decodeBoolFromText(mr *MessageReader, size int32) interface{} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeBool(buf *bytes.Buffer, value interface{}) {
|
||||||
|
v := value.(bool)
|
||||||
|
s := strconv.FormatBool(v)
|
||||||
|
binary.Write(buf, binary.BigEndian, int32(len(s)))
|
||||||
|
buf.WriteString(s)
|
||||||
|
}
|
||||||
|
|
||||||
func decodeInt8FromText(mr *MessageReader, size int32) interface{} {
|
func decodeInt8FromText(mr *MessageReader, size int32) interface{} {
|
||||||
s := mr.ReadByteString(size)
|
s := mr.ReadByteString(size)
|
||||||
n, err := strconv.ParseInt(s, 10, 64)
|
n, err := strconv.ParseInt(s, 10, 64)
|
||||||
@@ -58,6 +86,13 @@ func decodeInt8FromText(mr *MessageReader, size int32) interface{} {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeInt8(buf *bytes.Buffer, value interface{}) {
|
||||||
|
v := value.(int64)
|
||||||
|
s := strconv.FormatInt(int64(v), 10)
|
||||||
|
binary.Write(buf, binary.BigEndian, int32(len(s)))
|
||||||
|
buf.WriteString(s)
|
||||||
|
}
|
||||||
|
|
||||||
func decodeInt2FromText(mr *MessageReader, size int32) interface{} {
|
func decodeInt2FromText(mr *MessageReader, size int32) interface{} {
|
||||||
s := mr.ReadByteString(size)
|
s := mr.ReadByteString(size)
|
||||||
n, err := strconv.ParseInt(s, 10, 16)
|
n, err := strconv.ParseInt(s, 10, 16)
|
||||||
@@ -67,6 +102,13 @@ func decodeInt2FromText(mr *MessageReader, size int32) interface{} {
|
|||||||
return int16(n)
|
return int16(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeInt2(buf *bytes.Buffer, value interface{}) {
|
||||||
|
v := value.(int16)
|
||||||
|
s := strconv.FormatInt(int64(v), 10)
|
||||||
|
binary.Write(buf, binary.BigEndian, int32(len(s)))
|
||||||
|
buf.WriteString(s)
|
||||||
|
}
|
||||||
|
|
||||||
func decodeInt4FromText(mr *MessageReader, size int32) interface{} {
|
func decodeInt4FromText(mr *MessageReader, size int32) interface{} {
|
||||||
s := mr.ReadByteString(size)
|
s := mr.ReadByteString(size)
|
||||||
n, err := strconv.ParseInt(s, 10, 32)
|
n, err := strconv.ParseInt(s, 10, 32)
|
||||||
@@ -76,6 +118,13 @@ func decodeInt4FromText(mr *MessageReader, size int32) interface{} {
|
|||||||
return int32(n)
|
return int32(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeInt4(buf *bytes.Buffer, value interface{}) {
|
||||||
|
v := value.(int32)
|
||||||
|
s := strconv.FormatInt(int64(v), 10)
|
||||||
|
binary.Write(buf, binary.BigEndian, int32(len(s)))
|
||||||
|
buf.WriteString(s)
|
||||||
|
}
|
||||||
|
|
||||||
func decodeFloat4FromText(mr *MessageReader, size int32) interface{} {
|
func decodeFloat4FromText(mr *MessageReader, size int32) interface{} {
|
||||||
s := mr.ReadByteString(size)
|
s := mr.ReadByteString(size)
|
||||||
n, err := strconv.ParseFloat(s, 32)
|
n, err := strconv.ParseFloat(s, 32)
|
||||||
@@ -85,6 +134,13 @@ func decodeFloat4FromText(mr *MessageReader, size int32) interface{} {
|
|||||||
return float32(n)
|
return float32(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeFloat4(buf *bytes.Buffer, value interface{}) {
|
||||||
|
v := value.(float32)
|
||||||
|
s := strconv.FormatFloat(float64(v), 'e', -1, 32)
|
||||||
|
binary.Write(buf, binary.BigEndian, int32(len(s)))
|
||||||
|
buf.WriteString(s)
|
||||||
|
}
|
||||||
|
|
||||||
func decodeFloat8FromText(mr *MessageReader, size int32) interface{} {
|
func decodeFloat8FromText(mr *MessageReader, size int32) interface{} {
|
||||||
s := mr.ReadByteString(size)
|
s := mr.ReadByteString(size)
|
||||||
v, err := strconv.ParseFloat(s, 64)
|
v, err := strconv.ParseFloat(s, 64)
|
||||||
@@ -93,3 +149,20 @@ func decodeFloat8FromText(mr *MessageReader, size int32) interface{} {
|
|||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodeFloat8(buf *bytes.Buffer, value interface{}) {
|
||||||
|
v := value.(float64)
|
||||||
|
s := strconv.FormatFloat(float64(v), 'e', -1, 64)
|
||||||
|
binary.Write(buf, binary.BigEndian, int32(len(s)))
|
||||||
|
buf.WriteString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeTextFromText(mr *MessageReader, size int32) interface{} {
|
||||||
|
return mr.ReadByteString(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeText(buf *bytes.Buffer, value interface{}) {
|
||||||
|
s := value.(string)
|
||||||
|
binary.Write(buf, binary.BigEndian, int32(len(s)))
|
||||||
|
buf.WriteString(s)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user