| 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 |
| |
| s = 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(&[]string{}) |
| if _, ok := s.(*StringArray); !ok { |
| t.Errorf("Expected *StringArray, got %T", s) |
| } |
| |
| for _, tt := range []interface{}{ |
| &[]sql.Scanner{}, |
| &[][]bool{}, |
| &[][]float64{}, |
| &[][]int64{}, |
| &[][]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 |
| |
| v = 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([]string{}) |
| if _, ok := v.(*StringArray); !ok { |
| t.Errorf("Expected *StringArray, got %T", v) |
| } |
| |
| for _, tt := range []interface{}{ |
| nil, |
| []driver.Value{}, |
| [][]bool{}, |
| [][]float64{}, |
| [][]int64{}, |
| [][]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 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) { |
| var v []interface{} |
| |
| 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) |
| } |
| } |
| } |