Improve prepared statement performance
* Do not use bufio.Writer - use net.Conn directly * Use byte slice instead of bytes.Buffer when building query message * Use binary.BigEndian.* instead of binary.Write
This commit is contained in:
@@ -49,9 +49,9 @@ type ConnConfig struct {
|
|||||||
// Use ConnPool to manage access to multiple database connections from multiple
|
// Use ConnPool to manage access to multiple database connections from multiple
|
||||||
// goroutines.
|
// goroutines.
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
conn net.Conn // the underlying TCP or unix domain socket connection
|
conn net.Conn // the underlying TCP or unix domain socket connection
|
||||||
reader *bufio.Reader // buffered reader to improve read performance
|
reader *bufio.Reader // buffered reader to improve read performance
|
||||||
writer *bufio.Writer // buffered writer to avoid sending tiny packets
|
wbuf [1024]byte
|
||||||
buf *bytes.Buffer // work buffer to avoid constant alloc and dealloc
|
buf *bytes.Buffer // work buffer to avoid constant alloc and dealloc
|
||||||
bufSize int // desired size of buf
|
bufSize int // desired size of buf
|
||||||
Pid int32 // backend pid
|
Pid int32 // backend pid
|
||||||
@@ -196,7 +196,6 @@ func Connect(config ConnConfig) (c *Conn, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.reader = bufio.NewReader(c.conn)
|
c.reader = bufio.NewReader(c.conn)
|
||||||
c.writer = bufio.NewWriter(c.conn)
|
|
||||||
|
|
||||||
msg := newStartupMessage()
|
msg := newStartupMessage()
|
||||||
msg.options["user"] = c.config.User
|
msg.options["user"] = c.config.User
|
||||||
@@ -242,7 +241,7 @@ func (c *Conn) Close() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.txMsg('X', c.getBuf(), true)
|
err = c.txMsg('X', c.getBuf())
|
||||||
c.die(errors.New("Closed"))
|
c.die(errors.New("Closed"))
|
||||||
c.logger.Info("Closed connection")
|
c.logger.Info("Closed connection")
|
||||||
return err
|
return err
|
||||||
@@ -598,7 +597,7 @@ func (c *Conn) Prepare(name, sql string) (ps *PreparedStatement, err error) {
|
|||||||
buf.WriteString(sql)
|
buf.WriteString(sql)
|
||||||
buf.WriteByte(0)
|
buf.WriteByte(0)
|
||||||
binary.Write(buf, binary.BigEndian, int16(0))
|
binary.Write(buf, binary.BigEndian, int16(0))
|
||||||
err = c.txMsg('P', buf, false)
|
err = c.txMsg('P', buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -608,13 +607,13 @@ func (c *Conn) Prepare(name, sql string) (ps *PreparedStatement, err error) {
|
|||||||
buf.WriteByte('S')
|
buf.WriteByte('S')
|
||||||
buf.WriteString(name)
|
buf.WriteString(name)
|
||||||
buf.WriteByte(0)
|
buf.WriteByte(0)
|
||||||
err = c.txMsg('D', buf, false)
|
err = c.txMsg('D', buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// sync
|
// sync
|
||||||
err = c.txMsg('S', c.getBuf(), true)
|
err = c.txMsg('S', c.getBuf())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -763,7 +762,7 @@ func (c *Conn) sendSimpleQuery(sql string, arguments ...interface{}) (err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.txMsg('Q', buf, true)
|
return c.txMsg('Q', buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) sendPreparedQuery(ps *PreparedStatement, arguments ...interface{}) (err error) {
|
func (c *Conn) sendPreparedQuery(ps *PreparedStatement, arguments ...interface{}) (err error) {
|
||||||
@@ -772,69 +771,57 @@ func (c *Conn) sendPreparedQuery(ps *PreparedStatement, arguments ...interface{}
|
|||||||
}
|
}
|
||||||
|
|
||||||
// bind
|
// bind
|
||||||
buf := c.getBuf()
|
wbuf := newWriteBuf(c.wbuf[0:0], 'B')
|
||||||
buf.WriteString("")
|
wbuf.WriteByte(0)
|
||||||
buf.WriteByte(0)
|
wbuf.WriteCString(ps.Name)
|
||||||
buf.WriteString(ps.Name)
|
|
||||||
buf.WriteByte(0)
|
wbuf.WriteInt16(int16(len(ps.ParameterOids)))
|
||||||
binary.Write(buf, binary.BigEndian, int16(len(ps.ParameterOids)))
|
|
||||||
for _, oid := range ps.ParameterOids {
|
for _, oid := range ps.ParameterOids {
|
||||||
transcoder := ValueTranscoders[oid]
|
transcoder := ValueTranscoders[oid]
|
||||||
if transcoder == nil {
|
if transcoder == nil {
|
||||||
transcoder = defaultTranscoder
|
transcoder = defaultTranscoder
|
||||||
}
|
}
|
||||||
binary.Write(buf, binary.BigEndian, transcoder.EncodeFormat)
|
wbuf.WriteInt16(transcoder.EncodeFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
binary.Write(buf, binary.BigEndian, int16(len(arguments)))
|
wbuf.WriteInt16(int16(len(arguments)))
|
||||||
for i, oid := range ps.ParameterOids {
|
for i, oid := range ps.ParameterOids {
|
||||||
if arguments[i] != nil {
|
if arguments[i] != nil {
|
||||||
transcoder := ValueTranscoders[oid]
|
transcoder := ValueTranscoders[oid]
|
||||||
if transcoder == nil {
|
if transcoder == nil {
|
||||||
transcoder = defaultTranscoder
|
transcoder = defaultTranscoder
|
||||||
}
|
}
|
||||||
err = transcoder.EncodeTo(buf, arguments[i])
|
err = transcoder.EncodeTo(wbuf, arguments[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
binary.Write(buf, binary.BigEndian, int32(-1))
|
wbuf.WriteInt32(int32(-1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binary.Write(buf, binary.BigEndian, int16(len(ps.FieldDescriptions)))
|
wbuf.WriteInt16(int16(len(ps.FieldDescriptions)))
|
||||||
for _, fd := range ps.FieldDescriptions {
|
for _, fd := range ps.FieldDescriptions {
|
||||||
transcoder := ValueTranscoders[fd.DataType]
|
transcoder := ValueTranscoders[fd.DataType]
|
||||||
if transcoder != nil && transcoder.DecodeBinary != nil {
|
if transcoder != nil && transcoder.DecodeBinary != nil {
|
||||||
binary.Write(buf, binary.BigEndian, int16(1))
|
wbuf.WriteInt16(1)
|
||||||
} else {
|
} else {
|
||||||
binary.Write(buf, binary.BigEndian, int16(0))
|
wbuf.WriteInt16(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.txMsg('B', buf, false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// execute
|
// execute
|
||||||
buf = c.getBuf()
|
wbuf.startMsg('E')
|
||||||
buf.WriteString("")
|
wbuf.WriteByte(0)
|
||||||
buf.WriteByte(0)
|
wbuf.WriteInt32(0)
|
||||||
binary.Write(buf, binary.BigEndian, int32(0))
|
|
||||||
err = c.txMsg('E', buf, false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// sync
|
// sync
|
||||||
err = c.txMsg('S', c.getBuf(), true)
|
wbuf.startMsg('S')
|
||||||
if err != nil {
|
wbuf.closeMsg()
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
_, err = c.conn.Write(wbuf.buf)
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute executes sql. sql can be either a prepared statement name or an SQL string.
|
// Execute executes sql. sql can be either a prepared statement name or an SQL string.
|
||||||
@@ -1126,16 +1113,12 @@ func (c *Conn) startTLS() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) txStartupMessage(msg *startupMessage) (err error) {
|
func (c *Conn) txStartupMessage(msg *startupMessage) error {
|
||||||
_, err = c.writer.Write(msg.Bytes())
|
_, err := c.conn.Write(msg.Bytes())
|
||||||
if err != nil {
|
return err
|
||||||
return
|
|
||||||
}
|
|
||||||
err = c.writer.Flush()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) txMsg(identifier byte, buf *bytes.Buffer, flush bool) (err error) {
|
func (c *Conn) txMsg(identifier byte, buf *bytes.Buffer) (err error) {
|
||||||
if !c.alive {
|
if !c.alive {
|
||||||
return DeadConnError
|
return DeadConnError
|
||||||
}
|
}
|
||||||
@@ -1146,25 +1129,21 @@ func (c *Conn) txMsg(identifier byte, buf *bytes.Buffer, flush bool) (err error)
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
err = binary.Write(c.writer, binary.BigEndian, identifier)
|
err = binary.Write(c.conn, binary.BigEndian, identifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = binary.Write(c.writer, binary.BigEndian, int32(buf.Len()+4))
|
err = binary.Write(c.conn, binary.BigEndian, int32(buf.Len()+4))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = buf.WriteTo(c.writer)
|
_, err = buf.WriteTo(c.conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if flush {
|
|
||||||
err = c.writer.Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1179,7 +1158,7 @@ func (c *Conn) txPasswordMessage(password string) (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = c.txMsg('p', buf, true)
|
err = c.txMsg('p', buf)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1198,6 +1177,5 @@ func (c *Conn) getBuf() *bytes.Buffer {
|
|||||||
func (c *Conn) die(err error) {
|
func (c *Conn) die(err error) {
|
||||||
c.alive = false
|
c.alive = false
|
||||||
c.causeOfDeath = err
|
c.causeOfDeath = err
|
||||||
c.writer.Flush()
|
|
||||||
c.conn.Close()
|
c.conn.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package pgx_test
|
package pgx_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/jackc/pgx"
|
"github.com/jackc/pgx"
|
||||||
"io"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
@@ -57,19 +55,15 @@ func decodePointFromText(mr *pgx.MessageReader, size int32) interface{} {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodePoint(w io.Writer, value interface{}) error {
|
func encodePoint(w *pgx.WriteBuf, value interface{}) error {
|
||||||
p, ok := value.(Point)
|
p, ok := value.(Point)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Expected Point, received %T", value)
|
return fmt.Errorf("Expected Point, received %T", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := fmt.Sprintf("point(%v,%v)", p.x, p.y)
|
s := fmt.Sprintf("point(%v,%v)", p.x, p.y)
|
||||||
|
w.WriteInt32(int32(len(s)))
|
||||||
|
w.WriteBytes([]byte(s))
|
||||||
|
|
||||||
err := binary.Write(w, binary.BigEndian, int32(len(s)))
|
return nil
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = io.WriteString(w, s)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|||||||
+51
@@ -67,3 +67,54 @@ type PgError struct {
|
|||||||
func (self PgError) Error() string {
|
func (self PgError) Error() string {
|
||||||
return self.Severity + ": " + self.Message + " (SQLSTATE " + self.Code + ")"
|
return self.Severity + ": " + self.Message + " (SQLSTATE " + self.Code + ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newWriteBuf(buf []byte, t byte) *WriteBuf {
|
||||||
|
buf = append(buf, t, 0, 0, 0, 0)
|
||||||
|
return &WriteBuf{buf: buf, sizeIdx: 1}
|
||||||
|
}
|
||||||
|
|
||||||
|
type WriteBuf struct {
|
||||||
|
buf []byte
|
||||||
|
sizeIdx int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WriteBuf) startMsg(t byte) {
|
||||||
|
wb.closeMsg()
|
||||||
|
wb.buf = append(wb.buf, t, 0, 0, 0, 0)
|
||||||
|
wb.sizeIdx = len(wb.buf) - 4
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WriteBuf) closeMsg() {
|
||||||
|
binary.BigEndian.PutUint32(wb.buf[wb.sizeIdx:wb.sizeIdx+4], uint32(len(wb.buf)-wb.sizeIdx))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WriteBuf) WriteByte(b byte) {
|
||||||
|
wb.buf = append(wb.buf, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WriteBuf) WriteCString(s string) {
|
||||||
|
wb.buf = append(wb.buf, []byte(s)...)
|
||||||
|
wb.buf = append(wb.buf, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WriteBuf) WriteInt16(n int16) {
|
||||||
|
b := make([]byte, 2)
|
||||||
|
binary.BigEndian.PutUint16(b, uint16(n))
|
||||||
|
wb.buf = append(wb.buf, b...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WriteBuf) WriteInt32(n int32) {
|
||||||
|
b := make([]byte, 4)
|
||||||
|
binary.BigEndian.PutUint32(b, uint32(n))
|
||||||
|
wb.buf = append(wb.buf, b...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WriteBuf) WriteInt64(n int64) {
|
||||||
|
b := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint64(b, uint64(n))
|
||||||
|
wb.buf = append(wb.buf, b...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WriteBuf) WriteBytes(b []byte) {
|
||||||
|
wb.buf = append(wb.buf, b...)
|
||||||
|
}
|
||||||
|
|||||||
+48
-93
@@ -2,10 +2,8 @@ package pgx
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"math"
|
"math"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -21,7 +19,7 @@ type ValueTranscoder struct {
|
|||||||
// DecodeBinary decodes values returned from the server in binary format
|
// DecodeBinary decodes values returned from the server in binary format
|
||||||
DecodeBinary func(*MessageReader, int32) interface{}
|
DecodeBinary func(*MessageReader, int32) interface{}
|
||||||
// EncodeTo encodes values to send to the server
|
// EncodeTo encodes values to send to the server
|
||||||
EncodeTo func(io.Writer, interface{}) error
|
EncodeTo func(*WriteBuf, interface{}) error
|
||||||
// EncodeFormat is the format values are encoded for transmission.
|
// EncodeFormat is the format values are encoded for transmission.
|
||||||
// 0 = text
|
// 0 = text
|
||||||
// 1 = binary
|
// 1 = binary
|
||||||
@@ -162,23 +160,22 @@ func decodeBoolFromBinary(mr *MessageReader, size int32) interface{} {
|
|||||||
return b != 0
|
return b != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeBool(w io.Writer, value interface{}) error {
|
func encodeBool(w *WriteBuf, value interface{}) error {
|
||||||
v, ok := value.(bool)
|
v, ok := value.(bool)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Expected bool, received %T", value)
|
return fmt.Errorf("Expected bool, received %T", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := binary.Write(w, binary.BigEndian, int32(1))
|
w.WriteInt32(1)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var n byte
|
var n byte
|
||||||
if v {
|
if v {
|
||||||
n = 1
|
n = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return binary.Write(w, binary.BigEndian, n)
|
w.WriteByte(n)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeInt8FromText(mr *MessageReader, size int32) interface{} {
|
func decodeInt8FromText(mr *MessageReader, size int32) interface{} {
|
||||||
@@ -197,7 +194,7 @@ func decodeInt8FromBinary(mr *MessageReader, size int32) interface{} {
|
|||||||
return mr.ReadInt64()
|
return mr.ReadInt64()
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeInt8(w io.Writer, value interface{}) error {
|
func encodeInt8(w *WriteBuf, value interface{}) error {
|
||||||
var v int64
|
var v int64
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case int8:
|
case int8:
|
||||||
@@ -225,12 +222,10 @@ func encodeInt8(w io.Writer, value interface{}) error {
|
|||||||
return fmt.Errorf("Expected integer representable in int64, received %T %v", value, value)
|
return fmt.Errorf("Expected integer representable in int64, received %T %v", value, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := binary.Write(w, binary.BigEndian, int32(8))
|
w.WriteInt32(8)
|
||||||
if err != nil {
|
w.WriteInt64(v)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return binary.Write(w, binary.BigEndian, v)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeInt2FromText(mr *MessageReader, size int32) interface{} {
|
func decodeInt2FromText(mr *MessageReader, size int32) interface{} {
|
||||||
@@ -249,7 +244,7 @@ func decodeInt2FromBinary(mr *MessageReader, size int32) interface{} {
|
|||||||
return mr.ReadInt16()
|
return mr.ReadInt16()
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeInt2(w io.Writer, value interface{}) error {
|
func encodeInt2(w *WriteBuf, value interface{}) error {
|
||||||
var v int16
|
var v int16
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case int8:
|
case int8:
|
||||||
@@ -292,12 +287,10 @@ func encodeInt2(w io.Writer, value interface{}) error {
|
|||||||
return fmt.Errorf("Expected integer representable in int16, received %T %v", value, value)
|
return fmt.Errorf("Expected integer representable in int16, received %T %v", value, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := binary.Write(w, binary.BigEndian, int32(2))
|
w.WriteInt32(2)
|
||||||
if err != nil {
|
w.WriteInt16(v)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return binary.Write(w, binary.BigEndian, v)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeInt4FromText(mr *MessageReader, size int32) interface{} {
|
func decodeInt4FromText(mr *MessageReader, size int32) interface{} {
|
||||||
@@ -316,7 +309,7 @@ func decodeInt4FromBinary(mr *MessageReader, size int32) interface{} {
|
|||||||
return mr.ReadInt32()
|
return mr.ReadInt32()
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeInt4(w io.Writer, value interface{}) error {
|
func encodeInt4(w *WriteBuf, value interface{}) error {
|
||||||
var v int32
|
var v int32
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case int8:
|
case int8:
|
||||||
@@ -353,12 +346,10 @@ func encodeInt4(w io.Writer, value interface{}) error {
|
|||||||
return fmt.Errorf("Expected integer representable in int32, received %T %v", value, value)
|
return fmt.Errorf("Expected integer representable in int32, received %T %v", value, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := binary.Write(w, binary.BigEndian, int32(4))
|
w.WriteInt32(4)
|
||||||
if err != nil {
|
w.WriteInt32(v)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return binary.Write(w, binary.BigEndian, v)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeFloat4FromText(mr *MessageReader, size int32) interface{} {
|
func decodeFloat4FromText(mr *MessageReader, size int32) interface{} {
|
||||||
@@ -380,7 +371,7 @@ func decodeFloat4FromBinary(mr *MessageReader, size int32) interface{} {
|
|||||||
return *(*float32)(p)
|
return *(*float32)(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeFloat4(w io.Writer, value interface{}) error {
|
func encodeFloat4(w *WriteBuf, value interface{}) error {
|
||||||
var v float32
|
var v float32
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case float32:
|
case float32:
|
||||||
@@ -394,12 +385,12 @@ func encodeFloat4(w io.Writer, value interface{}) error {
|
|||||||
return fmt.Errorf("Expected float representable in float32, received %T %v", value, value)
|
return fmt.Errorf("Expected float representable in float32, received %T %v", value, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := binary.Write(w, binary.BigEndian, int32(4))
|
w.WriteInt32(4)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return binary.Write(w, binary.BigEndian, v)
|
p := unsafe.Pointer(&v)
|
||||||
|
w.WriteInt32(*(*int32)(p))
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeFloat8FromText(mr *MessageReader, size int32) interface{} {
|
func decodeFloat8FromText(mr *MessageReader, size int32) interface{} {
|
||||||
@@ -421,7 +412,7 @@ func decodeFloat8FromBinary(mr *MessageReader, size int32) interface{} {
|
|||||||
return *(*float64)(p)
|
return *(*float64)(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeFloat8(w io.Writer, value interface{}) error {
|
func encodeFloat8(w *WriteBuf, value interface{}) error {
|
||||||
var v float64
|
var v float64
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case float32:
|
case float32:
|
||||||
@@ -432,31 +423,28 @@ func encodeFloat8(w io.Writer, value interface{}) error {
|
|||||||
return fmt.Errorf("Expected float representable in float64, received %T %v", value, value)
|
return fmt.Errorf("Expected float representable in float64, received %T %v", value, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := binary.Write(w, binary.BigEndian, int32(8))
|
w.WriteInt32(8)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return binary.Write(w, binary.BigEndian, v)
|
p := unsafe.Pointer(&v)
|
||||||
|
w.WriteInt64(*(*int64)(p))
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeTextFromText(mr *MessageReader, size int32) interface{} {
|
func decodeTextFromText(mr *MessageReader, size int32) interface{} {
|
||||||
return mr.ReadString(size)
|
return mr.ReadString(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeText(w io.Writer, value interface{}) error {
|
func encodeText(w *WriteBuf, value interface{}) error {
|
||||||
s, ok := value.(string)
|
s, ok := value.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Expected string, received %T", value)
|
return fmt.Errorf("Expected string, received %T", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := binary.Write(w, binary.BigEndian, int32(len(s)))
|
w.WriteInt32(int32(len(s)))
|
||||||
if err != nil {
|
w.WriteBytes([]byte(s))
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = io.WriteString(w, s)
|
return nil
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeByteaFromText(mr *MessageReader, size int32) interface{} {
|
func decodeByteaFromText(mr *MessageReader, size int32) interface{} {
|
||||||
@@ -468,19 +456,16 @@ func decodeByteaFromText(mr *MessageReader, size int32) interface{} {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeBytea(w io.Writer, value interface{}) error {
|
func encodeBytea(w *WriteBuf, value interface{}) error {
|
||||||
b, ok := value.([]byte)
|
b, ok := value.([]byte)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Expected []byte, received %T", value)
|
return fmt.Errorf("Expected []byte, received %T", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := binary.Write(w, binary.BigEndian, int32(len(b)))
|
w.WriteInt32(int32(len(b)))
|
||||||
if err != nil {
|
w.WriteBytes(b)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = w.Write(b)
|
return nil
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeDateFromText(mr *MessageReader, size int32) interface{} {
|
func decodeDateFromText(mr *MessageReader, size int32) interface{} {
|
||||||
@@ -492,20 +477,14 @@ func decodeDateFromText(mr *MessageReader, size int32) interface{} {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeDate(w io.Writer, value interface{}) error {
|
func encodeDate(w *WriteBuf, value interface{}) error {
|
||||||
t, ok := value.(time.Time)
|
t, ok := value.(time.Time)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Expected time.Time, received %T", value)
|
return fmt.Errorf("Expected time.Time, received %T", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := t.Format("2006-01-02")
|
s := t.Format("2006-01-02")
|
||||||
err := binary.Write(w, binary.BigEndian, int32(len(s)))
|
return encodeText(w, s)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = io.WriteString(w, s)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeTimestampTzFromText(mr *MessageReader, size int32) interface{} {
|
func decodeTimestampTzFromText(mr *MessageReader, size int32) interface{} {
|
||||||
@@ -531,20 +510,14 @@ func decodeTimestampTzFromBinary(mr *MessageReader, size int32) interface{} {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeTimestampTz(w io.Writer, value interface{}) error {
|
func encodeTimestampTz(w *WriteBuf, value interface{}) error {
|
||||||
t, ok := value.(time.Time)
|
t, ok := value.(time.Time)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Expected time.Time, received %T", value)
|
return fmt.Errorf("Expected time.Time, received %T", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := t.Format("2006-01-02 15:04:05.999999 -0700")
|
s := t.Format("2006-01-02 15:04:05.999999 -0700")
|
||||||
err := binary.Write(w, binary.BigEndian, int32(len(s)))
|
return encodeText(w, s)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = io.WriteString(w, s)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeInt2ArrayFromText(mr *MessageReader, size int32) interface{} {
|
func decodeInt2ArrayFromText(mr *MessageReader, size int32) interface{} {
|
||||||
@@ -594,7 +567,7 @@ func int16SliceToArrayString(nums []int16) (string, error) {
|
|||||||
return w.String(), nil
|
return w.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeInt2Array(w io.Writer, value interface{}) error {
|
func encodeInt2Array(w *WriteBuf, value interface{}) error {
|
||||||
v, ok := value.([]int16)
|
v, ok := value.([]int16)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Expected []int16, received %T", value)
|
return fmt.Errorf("Expected []int16, received %T", value)
|
||||||
@@ -605,13 +578,7 @@ func encodeInt2Array(w io.Writer, value interface{}) error {
|
|||||||
return fmt.Errorf("Failed to encode []int16: %v", err)
|
return fmt.Errorf("Failed to encode []int16: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = binary.Write(w, binary.BigEndian, int32(len(s)))
|
return encodeText(w, s)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = io.WriteString(w, s)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeInt4ArrayFromText(mr *MessageReader, size int32) interface{} {
|
func decodeInt4ArrayFromText(mr *MessageReader, size int32) interface{} {
|
||||||
@@ -662,7 +629,7 @@ func int32SliceToArrayString(nums []int32) (string, error) {
|
|||||||
return w.String(), nil
|
return w.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeInt4Array(w io.Writer, value interface{}) error {
|
func encodeInt4Array(w *WriteBuf, value interface{}) error {
|
||||||
v, ok := value.([]int32)
|
v, ok := value.([]int32)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Expected []int32, received %T", value)
|
return fmt.Errorf("Expected []int32, received %T", value)
|
||||||
@@ -673,13 +640,7 @@ func encodeInt4Array(w io.Writer, value interface{}) error {
|
|||||||
return fmt.Errorf("Failed to encode []int32: %v", err)
|
return fmt.Errorf("Failed to encode []int32: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = binary.Write(w, binary.BigEndian, int32(len(s)))
|
return encodeText(w, s)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = io.WriteString(w, s)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeInt8ArrayFromText(mr *MessageReader, size int32) interface{} {
|
func decodeInt8ArrayFromText(mr *MessageReader, size int32) interface{} {
|
||||||
@@ -730,7 +691,7 @@ func int64SliceToArrayString(nums []int64) (string, error) {
|
|||||||
return w.String(), nil
|
return w.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeInt8Array(w io.Writer, value interface{}) error {
|
func encodeInt8Array(w *WriteBuf, value interface{}) error {
|
||||||
v, ok := value.([]int64)
|
v, ok := value.([]int64)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Expected []int64, received %T", value)
|
return fmt.Errorf("Expected []int64, received %T", value)
|
||||||
@@ -741,11 +702,5 @@ func encodeInt8Array(w io.Writer, value interface{}) error {
|
|||||||
return fmt.Errorf("Failed to encode []int64: %v", err)
|
return fmt.Errorf("Failed to encode []int64: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = binary.Write(w, binary.BigEndian, int32(len(s)))
|
return encodeText(w, s)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = io.WriteString(w, s)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user