14 Star 21 Fork 16

openGauss/openGauss-connector-go-pq

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
array_test.go 40.98 KB
一键复制 编辑 原始数据 按行查看 历史
travelliu 提交于 2022-04-15 10:41 . feat: support blob type
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658
package pq
import (
"bytes"
"database/sql"
"database/sql/driver"
"math/rand"
"reflect"
"strings"
"testing"
)
func TestParseArray(t *testing.T) {
for _, tt := range []struct {
input string
delim string
dims []int
elems [][]byte
}{
{`{}`, `,`, nil, [][]byte{}},
{`{NULL}`, `,`, []int{1}, [][]byte{nil}},
{`{a}`, `,`, []int{1}, [][]byte{{'a'}}},
{`{a,b}`, `,`, []int{2}, [][]byte{{'a'}, {'b'}}},
{`{{a,b}}`, `,`, []int{1, 2}, [][]byte{{'a'}, {'b'}}},
{`{{a},{b}}`, `,`, []int{2, 1}, [][]byte{{'a'}, {'b'}}},
{
`{{{a,b},{c,d},{e,f}}}`, `,`, []int{1, 3, 2}, [][]byte{
{'a'}, {'b'}, {'c'}, {'d'}, {'e'}, {'f'},
},
},
{`{""}`, `,`, []int{1}, [][]byte{{}}},
{`{","}`, `,`, []int{1}, [][]byte{{','}}},
{`{",",","}`, `,`, []int{2}, [][]byte{{','}, {','}}},
{`{{",",","}}`, `,`, []int{1, 2}, [][]byte{{','}, {','}}},
{`{{","},{","}}`, `,`, []int{2, 1}, [][]byte{{','}, {','}}},
{
`{{{",",","},{",",","},{",",","}}}`, `,`, []int{1, 3, 2}, [][]byte{
{','}, {','}, {','}, {','}, {','}, {','},
},
},
{`{"\"}"}`, `,`, []int{1}, [][]byte{{'"', '}'}}},
{`{"\"","\""}`, `,`, []int{2}, [][]byte{{'"'}, {'"'}}},
{`{{"\"","\""}}`, `,`, []int{1, 2}, [][]byte{{'"'}, {'"'}}},
{`{{"\""},{"\""}}`, `,`, []int{2, 1}, [][]byte{{'"'}, {'"'}}},
{
`{{{"\"","\""},{"\"","\""},{"\"","\""}}}`, `,`, []int{1, 3, 2}, [][]byte{
{'"'}, {'"'}, {'"'}, {'"'}, {'"'}, {'"'},
},
},
{`{axyzb}`, `xyz`, []int{2}, [][]byte{{'a'}, {'b'}}},
} {
dims, elems, err := parseArray([]byte(tt.input), []byte(tt.delim))
if err != nil {
t.Fatalf("Expected no error for %q, got %q", tt.input, err)
}
if !reflect.DeepEqual(dims, tt.dims) {
t.Errorf("Expected %v dimensions for %q, got %v", tt.dims, tt.input, dims)
}
if !reflect.DeepEqual(elems, tt.elems) {
t.Errorf("Expected %v elements for %q, got %v", tt.elems, tt.input, elems)
}
}
}
func TestParseArrayError(t *testing.T) {
for _, tt := range []struct {
input, err string
}{
{``, "expected '{' at offset 0"},
{`x`, "expected '{' at offset 0"},
{`}`, "expected '{' at offset 0"},
{`{`, "expected '}' at offset 1"},
{`{{}`, "expected '}' at offset 3"},
{`{}}`, "unexpected '}' at offset 2"},
{`{,}`, "unexpected ',' at offset 1"},
{`{,x}`, "unexpected ',' at offset 1"},
{`{x,}`, "unexpected '}' at offset 3"},
{`{x,{`, "unexpected '{' at offset 3"},
{`{x},`, "unexpected ',' at offset 3"},
{`{x}}`, "unexpected '}' at offset 3"},
{`{{x}`, "expected '}' at offset 4"},
{`{""x}`, "unexpected 'x' at offset 3"},
{`{{a},{b,c}}`, "multidimensional arrays must have elements with matching dimensions"},
} {
_, _, err := parseArray([]byte(tt.input), []byte{','})
if err == nil {
t.Fatalf("Expected error for %q, got none", tt.input)
}
if !strings.Contains(err.Error(), tt.err) {
t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err)
}
}
}
func TestArrayScanner(t *testing.T) {
var s sql.Scanner = Array(&[]bool{})
if _, ok := s.(*BoolArray); !ok {
t.Errorf("Expected *BoolArray, got %T", s)
}
s = Array(&[]float64{})
if _, ok := s.(*Float64Array); !ok {
t.Errorf("Expected *Float64Array, got %T", s)
}
s = Array(&[]int64{})
if _, ok := s.(*Int64Array); !ok {
t.Errorf("Expected *Int64Array, got %T", s)
}
s = Array(&[]float32{})
if _, ok := s.(*Float32Array); !ok {
t.Errorf("Expected *Float32Array, got %T", s)
}
s = Array(&[]int32{})
if _, ok := s.(*Int32Array); !ok {
t.Errorf("Expected *Int32Array, got %T", s)
}
s = Array(&[]string{})
if _, ok := s.(*StringArray); !ok {
t.Errorf("Expected *StringArray, got %T", s)
}
s = Array(&[][]byte{})
if _, ok := s.(*ByteaArray); !ok {
t.Errorf("Expected *ByteaArray, got %T", s)
}
for _, tt := range []interface{}{
&[]sql.Scanner{},
&[][]bool{},
&[][]float64{},
&[][]int64{},
&[][]float32{},
&[][]int32{},
&[][]string{},
} {
s = Array(tt)
if _, ok := s.(GenericArray); !ok {
t.Errorf("Expected GenericArray for %T, got %T", tt, s)
}
}
}
func TestArrayValuer(t *testing.T) {
var v driver.Valuer = Array([]bool{})
if _, ok := v.(*BoolArray); !ok {
t.Errorf("Expected *BoolArray, got %T", v)
}
v = Array([]float64{})
if _, ok := v.(*Float64Array); !ok {
t.Errorf("Expected *Float64Array, got %T", v)
}
v = Array([]int64{})
if _, ok := v.(*Int64Array); !ok {
t.Errorf("Expected *Int64Array, got %T", v)
}
v = Array([]float32{})
if _, ok := v.(*Float32Array); !ok {
t.Errorf("Expected *Float32Array, got %T", v)
}
v = Array([]int32{})
if _, ok := v.(*Int32Array); !ok {
t.Errorf("Expected *Int32Array, got %T", v)
}
v = Array([]string{})
if _, ok := v.(*StringArray); !ok {
t.Errorf("Expected *StringArray, got %T", v)
}
v = Array([][]byte{})
if _, ok := v.(*ByteaArray); !ok {
t.Errorf("Expected *ByteaArray, got %T", v)
}
for _, tt := range []interface{}{
nil,
[]driver.Value{},
[][]bool{},
[][]float64{},
[][]int64{},
[][]float32{},
[][]int32{},
[][]string{},
} {
v = Array(tt)
if _, ok := v.(GenericArray); !ok {
t.Errorf("Expected GenericArray for %T, got %T", tt, v)
}
}
}
func TestBoolArrayScanUnsupported(t *testing.T) {
var arr BoolArray
err := arr.Scan(1)
if err == nil {
t.Fatal("Expected error when scanning from int")
}
if !strings.Contains(err.Error(), "int to BoolArray") {
t.Errorf("Expected type to be mentioned when scanning, got %q", err)
}
}
func TestBoolArrayScanEmpty(t *testing.T) {
var arr BoolArray
err := arr.Scan(`{}`)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if arr == nil || len(arr) != 0 {
t.Errorf("Expected empty, got %#v", arr)
}
}
func TestBoolArrayScanNil(t *testing.T) {
arr := BoolArray{true, true, true}
err := arr.Scan(nil)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if arr != nil {
t.Errorf("Expected nil, got %+v", arr)
}
}
var BoolArrayStringTests = []struct {
str string
arr BoolArray
}{
{`{}`, BoolArray{}},
{`{t}`, BoolArray{true}},
{`{f,t}`, BoolArray{false, true}},
}
func TestBoolArrayScanBytes(t *testing.T) {
for _, tt := range BoolArrayStringTests {
bytes := []byte(tt.str)
arr := BoolArray{true, true, true}
err := arr.Scan(bytes)
if err != nil {
t.Fatalf("Expected no error for %q, got %v", bytes, err)
}
if !reflect.DeepEqual(arr, tt.arr) {
t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr)
}
}
}
func BenchmarkBoolArrayScanBytes(b *testing.B) {
var a BoolArray
var x interface{} = []byte(`{t,f,t,f,t,f,t,f,t,f}`)
for i := 0; i < b.N; i++ {
a = BoolArray{}
a.Scan(x)
}
}
func TestBoolArrayScanString(t *testing.T) {
for _, tt := range BoolArrayStringTests {
arr := BoolArray{true, true, true}
err := arr.Scan(tt.str)
if err != nil {
t.Fatalf("Expected no error for %q, got %v", tt.str, err)
}
if !reflect.DeepEqual(arr, tt.arr) {
t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr)
}
}
}
func TestBoolArrayScanError(t *testing.T) {
for _, tt := range []struct {
input, err string
}{
{``, "unable to parse array"},
{`{`, "unable to parse array"},
{`{{t},{f}}`, "cannot convert ARRAY[2][1] to BoolArray"},
{`{NULL}`, `could not parse boolean array index 0: invalid boolean ""`},
{`{a}`, `could not parse boolean array index 0: invalid boolean "a"`},
{`{t,b}`, `could not parse boolean array index 1: invalid boolean "b"`},
{`{t,f,cd}`, `could not parse boolean array index 2: invalid boolean "cd"`},
} {
arr := BoolArray{true, true, true}
err := arr.Scan(tt.input)
if err == nil {
t.Fatalf("Expected error for %q, got none", tt.input)
}
if !strings.Contains(err.Error(), tt.err) {
t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err)
}
if !reflect.DeepEqual(arr, BoolArray{true, true, true}) {
t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr)
}
}
}
func TestBoolArrayValue(t *testing.T) {
result, err := BoolArray(nil).Value()
if err != nil {
t.Fatalf("Expected no error for nil, got %v", err)
}
if result != nil {
t.Errorf("Expected nil, got %q", result)
}
result, err = BoolArray([]bool{}).Value()
if err != nil {
t.Fatalf("Expected no error for empty, got %v", err)
}
if expected := `{}`; !reflect.DeepEqual(result, expected) {
t.Errorf("Expected empty, got %q", result)
}
result, err = BoolArray([]bool{false, true, false}).Value()
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if expected := `{f,t,f}`; !reflect.DeepEqual(result, expected) {
t.Errorf("Expected %q, got %q", expected, result)
}
}
func BenchmarkBoolArrayValue(b *testing.B) {
rand.Seed(1)
x := make([]bool, 10)
for i := 0; i < len(x); i++ {
x[i] = rand.Intn(2) == 0
}
a := BoolArray(x)
for i := 0; i < b.N; i++ {
a.Value()
}
}
func TestByteaArrayScanUnsupported(t *testing.T) {
var arr ByteaArray
err := arr.Scan(1)
if err == nil {
t.Fatal("Expected error when scanning from int")
}
if !strings.Contains(err.Error(), "int to ByteaArray") {
t.Errorf("Expected type to be mentioned when scanning, got %q", err)
}
}
func TestByteaArrayScanEmpty(t *testing.T) {
var arr ByteaArray
err := arr.Scan(`{}`)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if arr == nil || len(arr) != 0 {
t.Errorf("Expected empty, got %#v", arr)
}
}
func TestByteaArrayScanNil(t *testing.T) {
arr := ByteaArray{{2}, {6}, {0, 0}}
err := arr.Scan(nil)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if arr != nil {
t.Errorf("Expected nil, got %+v", arr)
}
}
var ByteaArrayStringTests = []struct {
str string
arr ByteaArray
}{
{`{}`, ByteaArray{}},
{`{NULL}`, ByteaArray{nil}},
{`{"\\xfeff"}`, ByteaArray{{'\xFE', '\xFF'}}},
{`{"\\xdead","\\xbeef"}`, ByteaArray{{'\xDE', '\xAD'}, {'\xBE', '\xEF'}}},
}
func TestByteaArrayScanBytes(t *testing.T) {
for _, tt := range ByteaArrayStringTests {
bytes := []byte(tt.str)
arr := ByteaArray{{2}, {6}, {0, 0}}
err := arr.Scan(bytes)
if err != nil {
t.Fatalf("Expected no error for %q, got %v", bytes, err)
}
if !reflect.DeepEqual(arr, tt.arr) {
t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr)
}
}
}
func BenchmarkByteaArrayScanBytes(b *testing.B) {
var a ByteaArray
var x interface{} = []byte(`{"\\xfe","\\xff","\\xdead","\\xbeef","\\xfe","\\xff","\\xdead","\\xbeef","\\xfe","\\xff"}`)
for i := 0; i < b.N; i++ {
a = ByteaArray{}
a.Scan(x)
}
}
func TestByteaArrayScanString(t *testing.T) {
for _, tt := range ByteaArrayStringTests {
arr := ByteaArray{{2}, {6}, {0, 0}}
err := arr.Scan(tt.str)
if err != nil {
t.Fatalf("Expected no error for %q, got %v", tt.str, err)
}
if !reflect.DeepEqual(arr, tt.arr) {
t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr)
}
}
}
func TestByteaArrayScanError(t *testing.T) {
for _, tt := range []struct {
input, err string
}{
{``, "unable to parse array"},
{`{`, "unable to parse array"},
{`{{"\\xfeff"},{"\\xbeef"}}`, "cannot convert ARRAY[2][1] to ByteaArray"},
{`{"\\abc"}`, "could not parse bytea array index 0: could not parse bytea value"},
} {
arr := ByteaArray{{2}, {6}, {0, 0}}
err := arr.Scan(tt.input)
if err == nil {
t.Fatalf("Expected error for %q, got none", tt.input)
}
if !strings.Contains(err.Error(), tt.err) {
t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err)
}
if !reflect.DeepEqual(arr, ByteaArray{{2}, {6}, {0, 0}}) {
t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr)
}
}
}
func TestByteaArrayValue(t *testing.T) {
result, err := ByteaArray(nil).Value()
if err != nil {
t.Fatalf("Expected no error for nil, got %v", err)
}
if result != nil {
t.Errorf("Expected nil, got %q", result)
}
result, err = ByteaArray([][]byte{}).Value()
if err != nil {
t.Fatalf("Expected no error for empty, got %v", err)
}
if expected := `{}`; !reflect.DeepEqual(result, expected) {
t.Errorf("Expected empty, got %q", result)
}
result, err = ByteaArray([][]byte{{'\xDE', '\xAD', '\xBE', '\xEF'}, {'\xFE', '\xFF'}, {}}).Value()
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if expected := `{"\\xdeadbeef","\\xfeff","\\x"}`; !reflect.DeepEqual(result, expected) {
t.Errorf("Expected %q, got %q", expected, result)
}
}
func BenchmarkByteaArrayValue(b *testing.B) {
rand.Seed(1)
x := make([][]byte, 10)
for i := 0; i < len(x); i++ {
x[i] = make([]byte, len(x))
for j := 0; j < len(x); j++ {
x[i][j] = byte(rand.Int())
}
}
a := ByteaArray(x)
for i := 0; i < b.N; i++ {
a.Value()
}
}
func TestFloat64ArrayScanUnsupported(t *testing.T) {
var arr Float64Array
err := arr.Scan(true)
if err == nil {
t.Fatal("Expected error when scanning from bool")
}
if !strings.Contains(err.Error(), "bool to Float64Array") {
t.Errorf("Expected type to be mentioned when scanning, got %q", err)
}
}
func TestFloat64ArrayScanEmpty(t *testing.T) {
var arr Float64Array
err := arr.Scan(`{}`)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if arr == nil || len(arr) != 0 {
t.Errorf("Expected empty, got %#v", arr)
}
}
func TestFloat64ArrayScanNil(t *testing.T) {
arr := Float64Array{5, 5, 5}
err := arr.Scan(nil)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if arr != nil {
t.Errorf("Expected nil, got %+v", arr)
}
}
var Float64ArrayStringTests = []struct {
str string
arr Float64Array
}{
{`{}`, Float64Array{}},
{`{1.2}`, Float64Array{1.2}},
{`{3.456,7.89}`, Float64Array{3.456, 7.89}},
{`{3,1,2}`, Float64Array{3, 1, 2}},
}
func TestFloat64ArrayScanBytes(t *testing.T) {
for _, tt := range Float64ArrayStringTests {
bytes := []byte(tt.str)
arr := Float64Array{5, 5, 5}
err := arr.Scan(bytes)
if err != nil {
t.Fatalf("Expected no error for %q, got %v", bytes, err)
}
if !reflect.DeepEqual(arr, tt.arr) {
t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr)
}
}
}
func BenchmarkFloat64ArrayScanBytes(b *testing.B) {
var a Float64Array
var x interface{} = []byte(`{1.2,3.4,5.6,7.8,9.01,2.34,5.67,8.90,1.234,5.678}`)
for i := 0; i < b.N; i++ {
a = Float64Array{}
a.Scan(x)
}
}
func TestFloat64ArrayScanString(t *testing.T) {
for _, tt := range Float64ArrayStringTests {
arr := Float64Array{5, 5, 5}
err := arr.Scan(tt.str)
if err != nil {
t.Fatalf("Expected no error for %q, got %v", tt.str, err)
}
if !reflect.DeepEqual(arr, tt.arr) {
t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr)
}
}
}
func TestFloat64ArrayScanError(t *testing.T) {
for _, tt := range []struct {
input, err string
}{
{``, "unable to parse array"},
{`{`, "unable to parse array"},
{`{{5.6},{7.8}}`, "cannot convert ARRAY[2][1] to Float64Array"},
{`{NULL}`, "parsing array element index 0:"},
{`{a}`, "parsing array element index 0:"},
{`{5.6,a}`, "parsing array element index 1:"},
{`{5.6,7.8,a}`, "parsing array element index 2:"},
} {
arr := Float64Array{5, 5, 5}
err := arr.Scan(tt.input)
if err == nil {
t.Fatalf("Expected error for %q, got none", tt.input)
}
if !strings.Contains(err.Error(), tt.err) {
t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err)
}
if !reflect.DeepEqual(arr, Float64Array{5, 5, 5}) {
t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr)
}
}
}
func TestFloat64ArrayValue(t *testing.T) {
result, err := Float64Array(nil).Value()
if err != nil {
t.Fatalf("Expected no error for nil, got %v", err)
}
if result != nil {
t.Errorf("Expected nil, got %q", result)
}
result, err = Float64Array([]float64{}).Value()
if err != nil {
t.Fatalf("Expected no error for empty, got %v", err)
}
if expected := `{}`; !reflect.DeepEqual(result, expected) {
t.Errorf("Expected empty, got %q", result)
}
result, err = Float64Array([]float64{1.2, 3.4, 5.6}).Value()
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if expected := `{1.2,3.4,5.6}`; !reflect.DeepEqual(result, expected) {
t.Errorf("Expected %q, got %q", expected, result)
}
}
func BenchmarkFloat64ArrayValue(b *testing.B) {
rand.Seed(1)
x := make([]float64, 10)
for i := 0; i < len(x); i++ {
x[i] = rand.NormFloat64()
}
a := Float64Array(x)
for i := 0; i < b.N; i++ {
a.Value()
}
}
func TestInt64ArrayScanUnsupported(t *testing.T) {
var arr Int64Array
err := arr.Scan(true)
if err == nil {
t.Fatal("Expected error when scanning from bool")
}
if !strings.Contains(err.Error(), "bool to Int64Array") {
t.Errorf("Expected type to be mentioned when scanning, got %q", err)
}
}
func TestInt64ArrayScanEmpty(t *testing.T) {
var arr Int64Array
err := arr.Scan(`{}`)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if arr == nil || len(arr) != 0 {
t.Errorf("Expected empty, got %#v", arr)
}
}
func TestInt64ArrayScanNil(t *testing.T) {
arr := Int64Array{5, 5, 5}
err := arr.Scan(nil)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if arr != nil {
t.Errorf("Expected nil, got %+v", arr)
}
}
var Int64ArrayStringTests = []struct {
str string
arr Int64Array
}{
{`{}`, Int64Array{}},
{`{12}`, Int64Array{12}},
{`{345,678}`, Int64Array{345, 678}},
}
func TestInt64ArrayScanBytes(t *testing.T) {
for _, tt := range Int64ArrayStringTests {
bytes := []byte(tt.str)
arr := Int64Array{5, 5, 5}
err := arr.Scan(bytes)
if err != nil {
t.Fatalf("Expected no error for %q, got %v", bytes, err)
}
if !reflect.DeepEqual(arr, tt.arr) {
t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr)
}
}
}
func BenchmarkInt64ArrayScanBytes(b *testing.B) {
var a Int64Array
var x interface{} = []byte(`{1,2,3,4,5,6,7,8,9,0}`)
for i := 0; i < b.N; i++ {
a = Int64Array{}
a.Scan(x)
}
}
func TestInt64ArrayScanString(t *testing.T) {
for _, tt := range Int64ArrayStringTests {
arr := Int64Array{5, 5, 5}
err := arr.Scan(tt.str)
if err != nil {
t.Fatalf("Expected no error for %q, got %v", tt.str, err)
}
if !reflect.DeepEqual(arr, tt.arr) {
t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr)
}
}
}
func TestInt64ArrayScanError(t *testing.T) {
for _, tt := range []struct {
input, err string
}{
{``, "unable to parse array"},
{`{`, "unable to parse array"},
{`{{5},{6}}`, "cannot convert ARRAY[2][1] to Int64Array"},
{`{NULL}`, "parsing array element index 0:"},
{`{a}`, "parsing array element index 0:"},
{`{5,a}`, "parsing array element index 1:"},
{`{5,6,a}`, "parsing array element index 2:"},
} {
arr := Int64Array{5, 5, 5}
err := arr.Scan(tt.input)
if err == nil {
t.Fatalf("Expected error for %q, got none", tt.input)
}
if !strings.Contains(err.Error(), tt.err) {
t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err)
}
if !reflect.DeepEqual(arr, Int64Array{5, 5, 5}) {
t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr)
}
}
}
func TestInt64ArrayValue(t *testing.T) {
result, err := Int64Array(nil).Value()
if err != nil {
t.Fatalf("Expected no error for nil, got %v", err)
}
if result != nil {
t.Errorf("Expected nil, got %q", result)
}
result, err = Int64Array([]int64{}).Value()
if err != nil {
t.Fatalf("Expected no error for empty, got %v", err)
}
if expected := `{}`; !reflect.DeepEqual(result, expected) {
t.Errorf("Expected empty, got %q", result)
}
result, err = Int64Array([]int64{1, 2, 3}).Value()
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if expected := `{1,2,3}`; !reflect.DeepEqual(result, expected) {
t.Errorf("Expected %q, got %q", expected, result)
}
}
func BenchmarkInt64ArrayValue(b *testing.B) {
rand.Seed(1)
x := make([]int64, 10)
for i := 0; i < len(x); i++ {
x[i] = rand.Int63()
}
a := Int64Array(x)
for i := 0; i < b.N; i++ {
a.Value()
}
}
func TestFloat32ArrayScanUnsupported(t *testing.T) {
var arr Float32Array
err := arr.Scan(true)
if err == nil {
t.Fatal("Expected error when scanning from bool")
}
if !strings.Contains(err.Error(), "bool to Float32Array") {
t.Errorf("Expected type to be mentioned when scanning, got %q", err)
}
}
func TestFloat32ArrayScanEmpty(t *testing.T) {
var arr Float32Array
err := arr.Scan(`{}`)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if arr == nil || len(arr) != 0 {
t.Errorf("Expected empty, got %#v", arr)
}
}
func TestFloat32ArrayScanNil(t *testing.T) {
arr := Float32Array{5, 5, 5}
err := arr.Scan(nil)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if arr != nil {
t.Errorf("Expected nil, got %+v", arr)
}
}
var Float32ArrayStringTests = []struct {
str string
arr Float32Array
}{
{`{}`, Float32Array{}},
{`{1.2}`, Float32Array{1.2}},
{`{3.456,7.89}`, Float32Array{3.456, 7.89}},
{`{3,1,2}`, Float32Array{3, 1, 2}},
}
func TestFloat32ArrayScanBytes(t *testing.T) {
for _, tt := range Float32ArrayStringTests {
bytes := []byte(tt.str)
arr := Float32Array{5, 5, 5}
err := arr.Scan(bytes)
if err != nil {
t.Fatalf("Expected no error for %q, got %v", bytes, err)
}
if !reflect.DeepEqual(arr, tt.arr) {
t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr)
}
}
}
func BenchmarkFloat32ArrayScanBytes(b *testing.B) {
var a Float32Array
var x interface{} = []byte(`{1.2,3.4,5.6,7.8,9.01,2.34,5.67,8.90,1.234,5.678}`)
for i := 0; i < b.N; i++ {
a = Float32Array{}
a.Scan(x)
}
}
func TestFloat32ArrayScanString(t *testing.T) {
for _, tt := range Float32ArrayStringTests {
arr := Float32Array{5, 5, 5}
err := arr.Scan(tt.str)
if err != nil {
t.Fatalf("Expected no error for %q, got %v", tt.str, err)
}
if !reflect.DeepEqual(arr, tt.arr) {
t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr)
}
}
}
func TestFloat32ArrayScanError(t *testing.T) {
for _, tt := range []struct {
input, err string
}{
{``, "unable to parse array"},
{`{`, "unable to parse array"},
{`{{5.6},{7.8}}`, "cannot convert ARRAY[2][1] to Float32Array"},
{`{NULL}`, "parsing array element index 0:"},
{`{a}`, "parsing array element index 0:"},
{`{5.6,a}`, "parsing array element index 1:"},
{`{5.6,7.8,a}`, "parsing array element index 2:"},
} {
arr := Float32Array{5, 5, 5}
err := arr.Scan(tt.input)
if err == nil {
t.Fatalf("Expected error for %q, got none", tt.input)
}
if !strings.Contains(err.Error(), tt.err) {
t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err)
}
if !reflect.DeepEqual(arr, Float32Array{5, 5, 5}) {
t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr)
}
}
}
func TestFloat32ArrayValue(t *testing.T) {
result, err := Float32Array(nil).Value()
if err != nil {
t.Fatalf("Expected no error for nil, got %v", err)
}
if result != nil {
t.Errorf("Expected nil, got %q", result)
}
result, err = Float32Array([]float32{}).Value()
if err != nil {
t.Fatalf("Expected no error for empty, got %v", err)
}
if expected := `{}`; !reflect.DeepEqual(result, expected) {
t.Errorf("Expected empty, got %q", result)
}
result, err = Float32Array([]float32{1.2, 3.4, 5.6}).Value()
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if expected := `{1.2,3.4,5.6}`; !reflect.DeepEqual(result, expected) {
t.Errorf("Expected %q, got %q", expected, result)
}
}
func BenchmarkFloat32ArrayValue(b *testing.B) {
rand.Seed(1)
x := make([]float32, 10)
for i := 0; i < len(x); i++ {
x[i] = rand.Float32()
}
a := Float32Array(x)
for i := 0; i < b.N; i++ {
a.Value()
}
}
func TestInt32ArrayScanUnsupported(t *testing.T) {
var arr Int32Array
err := arr.Scan(true)
if err == nil {
t.Fatal("Expected error when scanning from bool")
}
if !strings.Contains(err.Error(), "bool to Int32Array") {
t.Errorf("Expected type to be mentioned when scanning, got %q", err)
}
}
func TestInt32ArrayScanEmpty(t *testing.T) {
var arr Int32Array
err := arr.Scan(`{}`)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if arr == nil || len(arr) != 0 {
t.Errorf("Expected empty, got %#v", arr)
}
}
func TestInt32ArrayScanNil(t *testing.T) {
arr := Int32Array{5, 5, 5}
err := arr.Scan(nil)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if arr != nil {
t.Errorf("Expected nil, got %+v", arr)
}
}
var Int32ArrayStringTests = []struct {
str string
arr Int32Array
}{
{`{}`, Int32Array{}},
{`{12}`, Int32Array{12}},
{`{345,678}`, Int32Array{345, 678}},
}
func TestInt32ArrayScanBytes(t *testing.T) {
for _, tt := range Int32ArrayStringTests {
bytes := []byte(tt.str)
arr := Int32Array{5, 5, 5}
err := arr.Scan(bytes)
if err != nil {
t.Fatalf("Expected no error for %q, got %v", bytes, err)
}
if !reflect.DeepEqual(arr, tt.arr) {
t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr)
}
}
}
func BenchmarkInt32ArrayScanBytes(b *testing.B) {
var a Int32Array
var x interface{} = []byte(`{1,2,3,4,5,6,7,8,9,0}`)
for i := 0; i < b.N; i++ {
a = Int32Array{}
a.Scan(x)
}
}
func TestInt32ArrayScanString(t *testing.T) {
for _, tt := range Int32ArrayStringTests {
arr := Int32Array{5, 5, 5}
err := arr.Scan(tt.str)
if err != nil {
t.Fatalf("Expected no error for %q, got %v", tt.str, err)
}
if !reflect.DeepEqual(arr, tt.arr) {
t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr)
}
}
}
func TestInt32ArrayScanError(t *testing.T) {
for _, tt := range []struct {
input, err string
}{
{``, "unable to parse array"},
{`{`, "unable to parse array"},
{`{{5},{6}}`, "cannot convert ARRAY[2][1] to Int32Array"},
{`{NULL}`, "parsing array element index 0:"},
{`{a}`, "parsing array element index 0:"},
{`{5,a}`, "parsing array element index 1:"},
{`{5,6,a}`, "parsing array element index 2:"},
} {
arr := Int32Array{5, 5, 5}
err := arr.Scan(tt.input)
if err == nil {
t.Fatalf("Expected error for %q, got none", tt.input)
}
if !strings.Contains(err.Error(), tt.err) {
t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err)
}
if !reflect.DeepEqual(arr, Int32Array{5, 5, 5}) {
t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr)
}
}
}
func TestInt32ArrayValue(t *testing.T) {
result, err := Int32Array(nil).Value()
if err != nil {
t.Fatalf("Expected no error for nil, got %v", err)
}
if result != nil {
t.Errorf("Expected nil, got %q", result)
}
result, err = Int32Array([]int32{}).Value()
if err != nil {
t.Fatalf("Expected no error for empty, got %v", err)
}
if expected := `{}`; !reflect.DeepEqual(result, expected) {
t.Errorf("Expected empty, got %q", result)
}
result, err = Int32Array([]int32{1, 2, 3}).Value()
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if expected := `{1,2,3}`; !reflect.DeepEqual(result, expected) {
t.Errorf("Expected %q, got %q", expected, result)
}
}
func BenchmarkInt32ArrayValue(b *testing.B) {
rand.Seed(1)
x := make([]int32, 10)
for i := 0; i < len(x); i++ {
x[i] = rand.Int31()
}
a := Int32Array(x)
for i := 0; i < b.N; i++ {
a.Value()
}
}
func TestStringArrayScanUnsupported(t *testing.T) {
var arr StringArray
err := arr.Scan(true)
if err == nil {
t.Fatal("Expected error when scanning from bool")
}
if !strings.Contains(err.Error(), "bool to StringArray") {
t.Errorf("Expected type to be mentioned when scanning, got %q", err)
}
}
func TestStringArrayScanEmpty(t *testing.T) {
var arr StringArray
err := arr.Scan(`{}`)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if arr == nil || len(arr) != 0 {
t.Errorf("Expected empty, got %#v", arr)
}
}
func TestStringArrayScanNil(t *testing.T) {
arr := StringArray{"x", "x", "x"}
err := arr.Scan(nil)
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if arr != nil {
t.Errorf("Expected nil, got %+v", arr)
}
}
var StringArrayStringTests = []struct {
str string
arr StringArray
}{
{`{}`, StringArray{}},
{`{t}`, StringArray{"t"}},
{`{f,1}`, StringArray{"f", "1"}},
{`{"a\\b","c d",","}`, StringArray{"a\\b", "c d", ","}},
}
func TestStringArrayScanBytes(t *testing.T) {
for _, tt := range StringArrayStringTests {
bytes := []byte(tt.str)
arr := StringArray{"x", "x", "x"}
err := arr.Scan(bytes)
if err != nil {
t.Fatalf("Expected no error for %q, got %v", bytes, err)
}
if !reflect.DeepEqual(arr, tt.arr) {
t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, arr)
}
}
}
func BenchmarkStringArrayScanBytes(b *testing.B) {
var a StringArray
var x interface{} = []byte(`{a,b,c,d,e,f,g,h,i,j}`)
var y interface{} = []byte(`{"\a","\b","\c","\d","\e","\f","\g","\h","\i","\j"}`)
for i := 0; i < b.N; i++ {
a = StringArray{}
a.Scan(x)
a = StringArray{}
a.Scan(y)
}
}
func TestStringArrayScanString(t *testing.T) {
for _, tt := range StringArrayStringTests {
arr := StringArray{"x", "x", "x"}
err := arr.Scan(tt.str)
if err != nil {
t.Fatalf("Expected no error for %q, got %v", tt.str, err)
}
if !reflect.DeepEqual(arr, tt.arr) {
t.Errorf("Expected %+v for %q, got %+v", tt.arr, tt.str, arr)
}
}
}
func TestStringArrayScanError(t *testing.T) {
for _, tt := range []struct {
input, err string
}{
{``, "unable to parse array"},
{`{`, "unable to parse array"},
{`{{a},{b}}`, "cannot convert ARRAY[2][1] to StringArray"},
{`{NULL}`, "parsing array element index 0: cannot convert nil to string"},
{`{a,NULL}`, "parsing array element index 1: cannot convert nil to string"},
{`{a,b,NULL}`, "parsing array element index 2: cannot convert nil to string"},
} {
arr := StringArray{"x", "x", "x"}
err := arr.Scan(tt.input)
if err == nil {
t.Fatalf("Expected error for %q, got none", tt.input)
}
if !strings.Contains(err.Error(), tt.err) {
t.Errorf("Expected error to contain %q for %q, got %q", tt.err, tt.input, err)
}
if !reflect.DeepEqual(arr, StringArray{"x", "x", "x"}) {
t.Errorf("Expected destination not to change for %q, got %+v", tt.input, arr)
}
}
}
func TestStringArrayValue(t *testing.T) {
result, err := StringArray(nil).Value()
if err != nil {
t.Fatalf("Expected no error for nil, got %v", err)
}
if result != nil {
t.Errorf("Expected nil, got %q", result)
}
result, err = StringArray([]string{}).Value()
if err != nil {
t.Fatalf("Expected no error for empty, got %v", err)
}
if expected := `{}`; !reflect.DeepEqual(result, expected) {
t.Errorf("Expected empty, got %q", result)
}
result, err = StringArray([]string{`a`, `\b`, `c"`, `d,e`}).Value()
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if expected := `{"a","\\b","c\"","d,e"}`; !reflect.DeepEqual(result, expected) {
t.Errorf("Expected %q, got %q", expected, result)
}
}
func BenchmarkStringArrayValue(b *testing.B) {
x := make([]string, 10)
for i := 0; i < len(x); i++ {
x[i] = strings.Repeat(`abc"def\ghi`, 5)
}
a := StringArray(x)
for i := 0; i < b.N; i++ {
a.Value()
}
}
func TestGenericArrayScanUnsupported(t *testing.T) {
var s string
var ss []string
var nsa [1]sql.NullString
for _, tt := range []struct {
src, dest interface{}
err string
}{
{nil, nil, "destination <nil> is not a pointer to array or slice"},
{nil, true, "destination bool is not a pointer to array or slice"},
{nil, &s, "destination *string is not a pointer to array or slice"},
{nil, ss, "destination []string is not a pointer to array or slice"},
{nil, &nsa, "<nil> to [1]sql.NullString"},
{true, &ss, "bool to []string"},
{`{{x}}`, &ss, "multidimensional ARRAY[1][1] is not implemented"},
{`{{x},{x}}`, &ss, "multidimensional ARRAY[2][1] is not implemented"},
{`{x}`, &ss, "scanning to string is not implemented"},
} {
err := GenericArray{tt.dest}.Scan(tt.src)
if err == nil {
t.Fatalf("Expected error for [%#v %#v]", tt.src, tt.dest)
}
if !strings.Contains(err.Error(), tt.err) {
t.Errorf("Expected error to contain %q for [%#v %#v], got %q", tt.err, tt.src, tt.dest, err)
}
}
}
func TestGenericArrayScanScannerArrayBytes(t *testing.T) {
src, expected, nsa := []byte(`{NULL,abc,"\""}`),
[3]sql.NullString{{}, {String: `abc`, Valid: true}, {String: `"`, Valid: true}},
[3]sql.NullString{{String: ``, Valid: true}, {}, {}}
if err := (GenericArray{&nsa}).Scan(src); err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if !reflect.DeepEqual(nsa, expected) {
t.Errorf("Expected %v, got %v", expected, nsa)
}
}
func TestGenericArrayScanScannerArrayString(t *testing.T) {
src, expected, nsa := `{NULL,"\"",xyz}`,
[3]sql.NullString{{}, {String: `"`, Valid: true}, {String: `xyz`, Valid: true}},
[3]sql.NullString{{String: ``, Valid: true}, {}, {}}
if err := (GenericArray{&nsa}).Scan(src); err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if !reflect.DeepEqual(nsa, expected) {
t.Errorf("Expected %v, got %v", expected, nsa)
}
}
func TestGenericArrayScanScannerSliceEmpty(t *testing.T) {
var nss []sql.NullString
if err := (GenericArray{&nss}).Scan(`{}`); err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if nss == nil || len(nss) != 0 {
t.Errorf("Expected empty, got %#v", nss)
}
}
func TestGenericArrayScanScannerSliceNil(t *testing.T) {
nss := []sql.NullString{{String: ``, Valid: true}, {}}
if err := (GenericArray{&nss}).Scan(nil); err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if nss != nil {
t.Errorf("Expected nil, got %+v", nss)
}
}
func TestGenericArrayScanScannerSliceBytes(t *testing.T) {
src, expected, nss := []byte(`{NULL,abc,"\""}`),
[]sql.NullString{{}, {String: `abc`, Valid: true}, {String: `"`, Valid: true}},
[]sql.NullString{{String: ``, Valid: true}, {}, {}, {}, {}}
if err := (GenericArray{&nss}).Scan(src); err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if !reflect.DeepEqual(nss, expected) {
t.Errorf("Expected %v, got %v", expected, nss)
}
}
func BenchmarkGenericArrayScanScannerSliceBytes(b *testing.B) {
var a GenericArray
var x interface{} = []byte(`{a,b,c,d,e,f,g,h,i,j}`)
var y interface{} = []byte(`{"\a","\b","\c","\d","\e","\f","\g","\h","\i","\j"}`)
for i := 0; i < b.N; i++ {
a = GenericArray{new([]sql.NullString)}
a.Scan(x)
a = GenericArray{new([]sql.NullString)}
a.Scan(y)
}
}
func TestGenericArrayScanScannerSliceString(t *testing.T) {
src, expected, nss := `{NULL,"\"",xyz}`,
[]sql.NullString{{}, {String: `"`, Valid: true}, {String: `xyz`, Valid: true}},
[]sql.NullString{{String: ``, Valid: true}, {}, {}}
if err := (GenericArray{&nss}).Scan(src); err != nil {
t.Fatalf("Expected no error, got %v", err)
}
if !reflect.DeepEqual(nss, expected) {
t.Errorf("Expected %v, got %v", expected, nss)
}
}
type TildeNullInt64 struct{ sql.NullInt64 }
func (TildeNullInt64) ArrayDelimiter() string { return "~" }
func TestGenericArrayScanDelimiter(t *testing.T) {
src, expected, tnis := `{12~NULL~76}`,
[]TildeNullInt64{{sql.NullInt64{Int64: 12, Valid: true}}, {}, {sql.NullInt64{Int64: 76, Valid: true}}},
[]TildeNullInt64{{sql.NullInt64{Int64: 0, Valid: true}}, {}}
if err := (GenericArray{&tnis}).Scan(src); err != nil {
t.Fatalf("Expected no error for %#v, got %v", src, err)
}
if !reflect.DeepEqual(tnis, expected) {
t.Errorf("Expected %v for %#v, got %v", expected, src, tnis)
}
}
func TestGenericArrayScanErrors(t *testing.T) {
var sa [1]string
var nis []sql.NullInt64
var pss *[]string
for _, tt := range []struct {
src, dest interface{}
err string
}{
{nil, pss, "destination *[]string is nil"},
{`{`, &sa, "unable to parse"},
{`{}`, &sa, "cannot convert ARRAY[0] to [1]string"},
{`{x,x}`, &sa, "cannot convert ARRAY[2] to [1]string"},
{`{x}`, &nis, `parsing array element index 0: converting`},
} {
err := GenericArray{tt.dest}.Scan(tt.src)
if err == nil {
t.Fatalf("Expected error for [%#v %#v]", tt.src, tt.dest)
}
if !strings.Contains(err.Error(), tt.err) {
t.Errorf("Expected error to contain %q for [%#v %#v], got %q", tt.err, tt.src, tt.dest, err)
}
}
}
func TestGenericArrayValueUnsupported(t *testing.T) {
_, err := GenericArray{true}.Value()
if err == nil {
t.Fatal("Expected error for bool")
}
if !strings.Contains(err.Error(), "bool to array") {
t.Errorf("Expected type to be mentioned, got %q", err)
}
}
type ByteArrayValuer [1]byte
type ByteSliceValuer []byte
type FuncArrayValuer struct {
delimiter func() string
value func() (driver.Value, error)
}
func (a ByteArrayValuer) Value() (driver.Value, error) { return a[:], nil }
func (b ByteSliceValuer) Value() (driver.Value, error) { return []byte(b), nil }
func (f FuncArrayValuer) ArrayDelimiter() string { return f.delimiter() }
func (f FuncArrayValuer) Value() (driver.Value, error) { return f.value() }
func TestGenericArrayValue(t *testing.T) {
result, err := GenericArray{nil}.Value()
if err != nil {
t.Fatalf("Expected no error for nil, got %v", err)
}
if result != nil {
t.Errorf("Expected nil, got %q", result)
}
for _, tt := range []interface{}{
[]bool(nil),
[][]int(nil),
[]*int(nil),
[]sql.NullString(nil),
} {
result, err := GenericArray{tt}.Value()
if err != nil {
t.Fatalf("Expected no error for %#v, got %v", tt, err)
}
if result != nil {
t.Errorf("Expected nil for %#v, got %q", tt, result)
}
}
Tilde := func(v driver.Value) FuncArrayValuer {
return FuncArrayValuer{
func() string { return "~" },
func() (driver.Value, error) { return v, nil }}
}
for _, tt := range []struct {
result string
input interface{}
}{
{`{}`, []bool{}},
{`{true}`, []bool{true}},
{`{true,false}`, []bool{true, false}},
{`{true,false}`, [2]bool{true, false}},
{`{}`, [][]int{{}}},
{`{}`, [][]int{{}, {}}},
{`{{1}}`, [][]int{{1}}},
{`{{1},{2}}`, [][]int{{1}, {2}}},
{`{{1,2},{3,4}}`, [][]int{{1, 2}, {3, 4}}},
{`{{1,2},{3,4}}`, [2][2]int{{1, 2}, {3, 4}}},
{`{"a","\\b","c\"","d,e"}`, []string{`a`, `\b`, `c"`, `d,e`}},
{`{"a","\\b","c\"","d,e"}`, [][]byte{{'a'}, {'\\', 'b'}, {'c', '"'}, {'d', ',', 'e'}}},
{`{NULL}`, []*int{nil}},
{`{0,NULL}`, []*int{new(int), nil}},
{`{NULL}`, []sql.NullString{{}}},
{`{"\"",NULL}`, []sql.NullString{{String: `"`, Valid: true}, {}}},
{`{"a","b"}`, []ByteArrayValuer{{'a'}, {'b'}}},
{`{{"a","b"},{"c","d"}}`, [][]ByteArrayValuer{{{'a'}, {'b'}}, {{'c'}, {'d'}}}},
{`{"e","f"}`, []ByteSliceValuer{{'e'}, {'f'}}},
{`{{"e","f"},{"g","h"}}`, [][]ByteSliceValuer{{{'e'}, {'f'}}, {{'g'}, {'h'}}}},
{`{1~2}`, []FuncArrayValuer{Tilde(int64(1)), Tilde(int64(2))}},
{`{{1~2}~{3~4}}`, [][]FuncArrayValuer{{Tilde(int64(1)), Tilde(int64(2))}, {Tilde(int64(3)), Tilde(int64(4))}}},
} {
result, err := GenericArray{tt.input}.Value()
if err != nil {
t.Fatalf("Expected no error for %q, got %v", tt.input, err)
}
if !reflect.DeepEqual(result, tt.result) {
t.Errorf("Expected %q for %q, got %q", tt.result, tt.input, result)
}
}
}
func TestGenericArrayValueErrors(t *testing.T) {
v := []interface{}{func() {}}
if _, err := (GenericArray{v}).Value(); err == nil {
t.Errorf("Expected error for %q, got nil", v)
}
v = []interface{}{nil, func() {}}
if _, err := (GenericArray{v}).Value(); err == nil {
t.Errorf("Expected error for %q, got nil", v)
}
}
func BenchmarkGenericArrayValueBools(b *testing.B) {
rand.Seed(1)
x := make([]bool, 10)
for i := 0; i < len(x); i++ {
x[i] = rand.Intn(2) == 0
}
a := GenericArray{x}
for i := 0; i < b.N; i++ {
a.Value()
}
}
func BenchmarkGenericArrayValueFloat64s(b *testing.B) {
rand.Seed(1)
x := make([]float64, 10)
for i := 0; i < len(x); i++ {
x[i] = rand.NormFloat64()
}
a := GenericArray{x}
for i := 0; i < b.N; i++ {
a.Value()
}
}
func BenchmarkGenericArrayValueInt64s(b *testing.B) {
rand.Seed(1)
x := make([]int64, 10)
for i := 0; i < len(x); i++ {
x[i] = rand.Int63()
}
a := GenericArray{x}
for i := 0; i < b.N; i++ {
a.Value()
}
}
func BenchmarkGenericArrayValueByteSlices(b *testing.B) {
x := make([][]byte, 10)
for i := 0; i < len(x); i++ {
x[i] = bytes.Repeat([]byte(`abc"def\ghi`), 5)
}
a := GenericArray{x}
for i := 0; i < b.N; i++ {
a.Value()
}
}
func BenchmarkGenericArrayValueStrings(b *testing.B) {
x := make([]string, 10)
for i := 0; i < len(x); i++ {
x[i] = strings.Repeat(`abc"def\ghi`, 5)
}
a := GenericArray{x}
for i := 0; i < b.N; i++ {
a.Value()
}
}
func TestArrayScanBackend(t *testing.T) {
db := openTestConn(t)
defer db.Close()
for _, tt := range []struct {
s string
d sql.Scanner
e interface{}
}{
{`ARRAY[true, false]`, new(BoolArray), &BoolArray{true, false}},
{`ARRAY[E'\\xdead', E'\\xbeef']`, new(ByteaArray), &ByteaArray{{'\xDE', '\xAD'}, {'\xBE', '\xEF'}}},
{`ARRAY[1.2, 3.4]`, new(Float64Array), &Float64Array{1.2, 3.4}},
{`ARRAY[1, 2, 3]`, new(Int64Array), &Int64Array{1, 2, 3}},
{`ARRAY['a', E'\\b', 'c"', 'd,e']`, new(StringArray), &StringArray{`a`, `\b`, `c"`, `d,e`}},
} {
err := db.QueryRow(`SELECT ` + tt.s).Scan(tt.d)
if err != nil {
t.Errorf("Expected no error when scanning %s into %T, got %v", tt.s, tt.d, err)
}
if !reflect.DeepEqual(tt.d, tt.e) {
t.Errorf("Expected %v when scanning %s into %T, got %v", tt.e, tt.s, tt.d, tt.d)
}
}
}
func TestArrayValueBackend(t *testing.T) {
db := openTestConn(t)
defer db.Close()
for _, tt := range []struct {
s string
v driver.Valuer
}{
{`ARRAY[true, false]`, BoolArray{true, false}},
{`ARRAY[E'\\xdead', E'\\xbeef']`, ByteaArray{{'\xDE', '\xAD'}, {'\xBE', '\xEF'}}},
{`ARRAY[1.2, 3.4]`, Float64Array{1.2, 3.4}},
{`ARRAY[1, 2, 3]`, Int64Array{1, 2, 3}},
{`ARRAY['a', E'\\b', 'c"', 'd,e']`, StringArray{`a`, `\b`, `c"`, `d,e`}},
} {
var x int
err := db.QueryRow(`SELECT 1 WHERE `+tt.s+` <> $1`, tt.v).Scan(&x)
if err != sql.ErrNoRows {
t.Errorf("Expected %v to equal %s, got %v", tt.v, tt.s, err)
}
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/opengauss/openGauss-connector-go-pq.git
git@gitee.com:opengauss/openGauss-connector-go-pq.git
opengauss
openGauss-connector-go-pq
openGauss-connector-go-pq
master

搜索帮助

0d507c66 1850385 C8b1a773 1850385