Add ParseUntypedTextArray

pgxtype-experiment2
Jack Christensen 2017-02-27 19:28:55 -06:00
parent 0f50ce3e83
commit 1b0f18d99f
2 changed files with 118 additions and 22 deletions

View File

@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"io"
"strconv"
"unicode"
"github.com/jackc/pgx/pgio"
@ -118,17 +119,64 @@ func ParseUntypedTextArray(src string) (*UntypedTextArray, error) {
// Array has explicit dimensions
if r == '[' {
// TODO - parse explicit dimensions
panic(explicitDimensions)
buf.UnreadRune()
for {
r, _, err = buf.ReadRune()
if err != nil {
return nil, fmt.Errorf("invalid array: %v", err)
}
if r == '=' {
break
} else if r != '[' {
return nil, fmt.Errorf("invalid array, expected '[' or '=' got %v", r)
}
lower, err := arrayParseInteger(buf)
if err != nil {
return nil, fmt.Errorf("invalid array: %v", err)
}
r, _, err = buf.ReadRune()
if err != nil {
return nil, fmt.Errorf("invalid array: %v", err)
}
if r != ':' {
return nil, fmt.Errorf("invalid array, expected ':' got %v", r)
}
upper, err := arrayParseInteger(buf)
if err != nil {
return nil, fmt.Errorf("invalid array: %v", err)
}
r, _, err = buf.ReadRune()
if err != nil {
return nil, fmt.Errorf("invalid array: %v", err)
}
if r != ']' {
return nil, fmt.Errorf("invalid array, expected ']' got %v", r)
}
explicitDimensions = append(explicitDimensions, ArrayDimension{LowerBound: lower, Length: upper - lower + 1})
}
r, _, err = buf.ReadRune()
if err != nil {
return nil, fmt.Errorf("invalid array: %v", err)
}
}
// Consume all initial opening brackets. This provides number of dimensions.
var implicitDimensions []ArrayDimension
if r != '{' {
return nil, fmt.Errorf("invalid array, expected '{': %v", err)
}
buf.UnreadRune()
implicitDimensions := []ArrayDimension{{LowerBound: 1, Length: 0}}
// Consume all initial opening brackets. This provides number of dimensions.
for {
r, _, err = buf.ReadRune()
if err != nil {
@ -136,6 +184,7 @@ func ParseUntypedTextArray(src string) (*UntypedTextArray, error) {
}
if r == '{' {
implicitDimensions[len(implicitDimensions)-1].Length = 1
implicitDimensions = append(implicitDimensions, ArrayDimension{LowerBound: 1})
} else {
buf.UnreadRune()
@ -144,9 +193,6 @@ func ParseUntypedTextArray(src string) (*UntypedTextArray, error) {
}
currentDim := len(implicitDimensions) - 1
counterDim := currentDim
elemCount := 0
fmt.Println("-------", currentDim, buf.String())
for {
r, _, err = buf.ReadRune()
@ -156,30 +202,24 @@ func ParseUntypedTextArray(src string) (*UntypedTextArray, error) {
switch r {
case '{':
fmt.Println("{", buf.String())
if counterDim == currentDim {
elemCount++
if currentDim == counterDim {
implicitDimensions[currentDim].Length++
}
currentDim++
case ',':
case '}':
fmt.Println("}", buf.String())
if counterDim == currentDim {
implicitDimensions[counterDim].Length = int32(elemCount)
elemCount = 0
}
currentDim--
if currentDim < counterDim {
counterDim = currentDim
}
default:
buf.UnreadRune()
fmt.Println("default", buf.String())
value, err := arrayParseValue(buf)
if err != nil {
return nil, fmt.Errorf("invalid array value: %v", err)
}
if counterDim == currentDim {
elemCount++
if currentDim == counterDim {
implicitDimensions[currentDim].Length++
}
uta.Elements = append(uta.Elements, value)
}
@ -187,7 +227,6 @@ func ParseUntypedTextArray(src string) (*UntypedTextArray, error) {
if currentDim < 0 {
break
}
}
skipWhitespace(buf)
@ -273,3 +312,25 @@ func arrayParseQuotedValue(buf *bytes.Buffer) (string, error) {
s.WriteRune(r)
}
}
func arrayParseInteger(buf *bytes.Buffer) (int32, error) {
s := &bytes.Buffer{}
for {
r, _, err := buf.ReadRune()
if err != nil {
return 0, err
}
if '0' <= r && r <= '9' {
s.WriteRune(r)
} else {
buf.UnreadRune()
n, err := strconv.ParseInt(s.String(), 10, 32)
if err != nil {
return 0, err
}
return int32(n), nil
}
}
}

View File

@ -47,6 +47,41 @@ func TestParseUntypedTextArray(t *testing.T) {
Dimensions: []pgtype.ArrayDimension{{Length: 1, LowerBound: 1}},
},
},
{
source: "{{a,b},{c,d},{e,f}}",
result: pgtype.UntypedTextArray{
Elements: []string{"a", "b", "c", "d", "e", "f"},
Dimensions: []pgtype.ArrayDimension{{Length: 3, LowerBound: 1}, {Length: 2, LowerBound: 1}},
},
},
{
source: "{{{a,b},{c,d},{e,f}},{{a,b},{c,d},{e,f}}}",
result: pgtype.UntypedTextArray{
Elements: []string{"a", "b", "c", "d", "e", "f", "a", "b", "c", "d", "e", "f"},
Dimensions: []pgtype.ArrayDimension{
{Length: 2, LowerBound: 1},
{Length: 3, LowerBound: 1},
{Length: 2, LowerBound: 1},
},
},
},
{
source: "[4:4]={1}",
result: pgtype.UntypedTextArray{
Elements: []string{"1"},
Dimensions: []pgtype.ArrayDimension{{Length: 1, LowerBound: 4}},
},
},
{
source: "[4:5][2:3]={{a,b},{c,d}}",
result: pgtype.UntypedTextArray{
Elements: []string{"a", "b", "c", "d"},
Dimensions: []pgtype.ArrayDimension{
{Length: 2, LowerBound: 4},
{Length: 2, LowerBound: 2},
},
},
},
}
for i, tt := range tests {