Skip to content

Commit

Permalink
Refactor pgio and types to append buffers
Browse files Browse the repository at this point in the history
  • Loading branch information
jackc committed May 3, 2017
1 parent ab21bc4 commit 6b906ca
Show file tree
Hide file tree
Showing 73 changed files with 1,349 additions and 2,438 deletions.
10 changes: 4 additions & 6 deletions aclitem.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package pgtype
import (
"database/sql/driver"
"fmt"
"io"
)

// Aclitem is used for PostgreSQL's aclitem data type. A sample aclitem
Expand Down Expand Up @@ -83,16 +82,15 @@ func (dst *Aclitem) DecodeText(ci *ConnInfo, src []byte) error {
return nil
}

func (src *Aclitem) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) {
func (src *Aclitem) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return true, nil
return nil, nil
case Undefined:
return false, errUndefined
return nil, errUndefined
}

_, err := io.WriteString(w, src.String)
return false, err
return append(buf, src.String...), nil
}

// Scan implements the database/sql Scanner interface.
Expand Down
60 changes: 18 additions & 42 deletions aclitem_array.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
package pgtype

import (
"bytes"
"database/sql/driver"
"fmt"
"io"

"github.com/jackc/pgx/pgio"
)

type AclitemArray struct {
Expand Down Expand Up @@ -120,23 +116,19 @@ func (dst *AclitemArray) DecodeText(ci *ConnInfo, src []byte) error {
return nil
}

func (src *AclitemArray) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) {
func (src *AclitemArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return true, nil
return nil, nil
case Undefined:
return false, errUndefined
return nil, errUndefined
}

if len(src.Dimensions) == 0 {
_, err := io.WriteString(w, "{}")
return false, err
return append(buf, '{', '}'), nil
}

err := EncodeTextArrayDimensions(w, src.Dimensions)
if err != nil {
return false, err
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)

// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
Expand All @@ -149,51 +141,36 @@ func (src *AclitemArray) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}

inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
err = pgio.WriteByte(w, ',')
if err != nil {
return false, err
}
buf = append(buf, ',')
}

for _, dec := range dimElemCounts {
if i%dec == 0 {
err = pgio.WriteByte(w, '{')
if err != nil {
return false, err
}
buf = append(buf, '{')
}
}

elemBuf := &bytes.Buffer{}
null, err := elem.EncodeText(ci, elemBuf)
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return false, err
return nil, err
}
if null {
_, err = io.WriteString(w, `NULL`)
if err != nil {
return false, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
_, err = io.WriteString(w, QuoteArrayElementIfNeeded(elemBuf.String()))
if err != nil {
return false, err
}
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}

for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
err = pgio.WriteByte(w, '}')
if err != nil {
return false, err
}
buf = append(buf, '}')
}
}
}

return false, nil
return buf, nil
}

// Scan implements the database/sql Scanner interface.
Expand All @@ -216,14 +193,13 @@ func (dst *AclitemArray) Scan(src interface{}) error {

// Value implements the database/sql/driver Valuer interface.
func (src *AclitemArray) Value() (driver.Value, error) {
buf := &bytes.Buffer{}
null, err := src.EncodeText(nil, buf)
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if null {
if buf == nil {
return nil, nil
}

return buf.String(), nil
return string(buf), nil
}
65 changes: 15 additions & 50 deletions array.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,39 +60,23 @@ func (dst *ArrayHeader) DecodeBinary(ci *ConnInfo, src []byte) (int, error) {
return rp, nil
}

func (src *ArrayHeader) EncodeBinary(ci *ConnInfo, w io.Writer) error {
_, err := pgio.WriteInt32(w, int32(len(src.Dimensions)))
if err != nil {
return err
}
func (src *ArrayHeader) EncodeBinary(ci *ConnInfo, buf []byte) []byte {
buf = pgio.AppendInt32(buf, int32(len(src.Dimensions)))

var containsNull int32
if src.ContainsNull {
containsNull = 1
}
_, err = pgio.WriteInt32(w, containsNull)
if err != nil {
return err
}
buf = pgio.AppendInt32(buf, containsNull)

_, err = pgio.WriteInt32(w, src.ElementOid)
if err != nil {
return err
}
buf = pgio.AppendInt32(buf, src.ElementOid)

for i := range src.Dimensions {
_, err = pgio.WriteInt32(w, src.Dimensions[i].Length)
if err != nil {
return err
}

_, err = pgio.WriteInt32(w, src.Dimensions[i].LowerBound)
if err != nil {
return err
}
buf = pgio.AppendInt32(buf, src.Dimensions[i].Length)
buf = pgio.AppendInt32(buf, src.Dimensions[i].LowerBound)
}

return nil
return buf
}

type UntypedTextArray struct {
Expand Down Expand Up @@ -331,7 +315,7 @@ func arrayParseInteger(buf *bytes.Buffer) (int32, error) {
}
}

func EncodeTextArrayDimensions(w io.Writer, dimensions []ArrayDimension) error {
func EncodeTextArrayDimensions(buf []byte, dimensions []ArrayDimension) []byte {
var customDimensions bool
for _, dim := range dimensions {
if dim.LowerBound != 1 {
Expand All @@ -340,37 +324,18 @@ func EncodeTextArrayDimensions(w io.Writer, dimensions []ArrayDimension) error {
}

if !customDimensions {
return nil
return buf
}

for _, dim := range dimensions {
err := pgio.WriteByte(w, '[')
if err != nil {
return err
}

_, err = io.WriteString(w, strconv.FormatInt(int64(dim.LowerBound), 10))
if err != nil {
return err
}

err = pgio.WriteByte(w, ':')
if err != nil {
return err
}

_, err = io.WriteString(w, strconv.FormatInt(int64(dim.LowerBound+dim.Length-1), 10))
if err != nil {
return err
}

err = pgio.WriteByte(w, ']')
if err != nil {
return err
}
buf = append(buf, '[')
buf = append(buf, strconv.FormatInt(int64(dim.LowerBound), 10)...)
buf = append(buf, ':')
buf = append(buf, strconv.FormatInt(int64(dim.LowerBound+dim.Length-1), 10)...)
buf = append(buf, ']')
}

return pgio.WriteByte(w, '=')
return append(buf, '=')
}

var quoteArrayReplacer = strings.NewReplacer(`\`, `\\`, `"`, `\"`)
Expand Down
29 changes: 12 additions & 17 deletions bool.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package pgtype
import (
"database/sql/driver"
"fmt"
"io"
"strconv"
)

Expand Down Expand Up @@ -90,42 +89,38 @@ func (dst *Bool) DecodeBinary(ci *ConnInfo, src []byte) error {
return nil
}

func (src *Bool) EncodeText(ci *ConnInfo, w io.Writer) (bool, error) {
func (src *Bool) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return true, nil
return nil, nil
case Undefined:
return false, errUndefined
return nil, errUndefined
}

var buf []byte
if src.Bool {
buf = []byte{'t'}
buf = append(buf, 't')
} else {
buf = []byte{'f'}
buf = append(buf, 'f')
}

_, err := w.Write(buf)
return false, err
return buf, nil
}

func (src *Bool) EncodeBinary(ci *ConnInfo, w io.Writer) (bool, error) {
func (src *Bool) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return true, nil
return nil, nil
case Undefined:
return false, errUndefined
return nil, errUndefined
}

var buf []byte
if src.Bool {
buf = []byte{1}
buf = append(buf, 1)
} else {
buf = []byte{0}
buf = append(buf, 0)
}

_, err := w.Write(buf)
return false, err
return buf, nil
}

// Scan implements the database/sql Scanner interface.
Expand Down
Loading

0 comments on commit 6b906ca

Please sign in to comment.