Skip to content

Commit 1601ba4

Browse files
committed
feat: support conversion of custom types
fix: return error for unsupported type
1 parent 240a930 commit 1601ba4

File tree

2 files changed

+114
-10
lines changed

2 files changed

+114
-10
lines changed

chunk.go

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"fmt"
2323
"io"
2424
"net"
25+
"reflect"
2526
"strconv"
2627
"strings"
2728
"time"
@@ -221,20 +222,49 @@ func (this *Value) readBufferAt(chunk *Chunk, offset uint64) (uint64, error) {
221222
return 0, errors.New("Unsuported type")
222223
}
223224

224-
func protocolBufferFromValue(v interface{}) [][]byte {
225+
func protocolBufferFromValue(v interface{}) ([][]byte, error) {
225226
switch v := v.(type) {
226227
case nil:
227-
return protocolBufferFromNull()
228-
case int, int8, int16, int32, int64:
229-
return protocolBufferFromInt(v)
230-
case float32, float64:
231-
return protocolBufferFromFloat(v)
228+
return protocolBufferFromNull(), nil
229+
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
230+
return protocolBufferFromInt(v), nil
231+
case float32:
232+
return protocolBufferFromFloat(float64(v)), nil
233+
case float64:
234+
return protocolBufferFromFloat(v), nil
232235
case string:
233-
return protocolBufferFromString(v, true)
236+
return protocolBufferFromString(v, true), nil
234237
case []byte:
235-
return protocolBufferFromBytes(v)
238+
return protocolBufferFromBytes(v), nil
236239
default:
237-
return make([][]byte, 0)
240+
rv := reflect.ValueOf(v)
241+
if !rv.IsValid() {
242+
return protocolBufferFromNull(), nil
243+
}
244+
if rv.Kind() == reflect.Pointer {
245+
if rv.IsNil() {
246+
return protocolBufferFromNull(), nil
247+
}
248+
return protocolBufferFromValue(rv.Elem().Interface())
249+
}
250+
251+
switch rv.Kind() {
252+
case reflect.String:
253+
return protocolBufferFromString(rv.String(), true), nil
254+
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
255+
return protocolBufferFromInt(rv.Int()), nil
256+
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
257+
return protocolBufferFromInt(rv.Uint()), nil
258+
case reflect.Float32, reflect.Float64:
259+
return protocolBufferFromFloat(rv.Convert(reflect.TypeOf(float64(0))).Float()), nil
260+
case reflect.Bool:
261+
if rv.Bool() {
262+
return protocolBufferFromInt(1), nil
263+
}
264+
return protocolBufferFromInt(0), nil
265+
default:
266+
return nil, fmt.Errorf("unsupported parameter type %T", v)
267+
}
238268
}
239269
}
240270

@@ -371,7 +401,11 @@ func (this *SQCloud) sendArray(command string, values []interface{}) (int, error
371401
// convert values to buffers encoded with whe sqlitecloud protocol
372402
buffers := [][]byte{protocolBufferFromString(command, true)[0]}
373403
for _, v := range values {
374-
buffers = append(buffers, protocolBufferFromValue(v)...)
404+
valueBuffers, err := protocolBufferFromValue(v)
405+
if err != nil {
406+
return 0, err
407+
}
408+
buffers = append(buffers, valueBuffers...)
375409
}
376410

377411
// calculate the array header

chunk_internal_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package sqlitecloud
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"testing"
7+
)
8+
9+
type testStringEnum string
10+
type testIntEnum int
11+
12+
func TestProtocolBufferFromValueSupportsStringAlias(t *testing.T) {
13+
val := testStringEnum("active")
14+
buffers, err := protocolBufferFromValue(val)
15+
if err != nil {
16+
t.Fatalf("unexpected error: %v", err)
17+
}
18+
19+
if len(buffers) != 1 {
20+
t.Fatalf("expected 1 buffer, got %d", len(buffers))
21+
}
22+
got := string(buffers[0])
23+
want := fmt.Sprintf("%c%d %s\x00", CMD_ZEROSTRING, len("active")+1, "active")
24+
if got != want {
25+
t.Fatalf("unexpected encoded value: want %q got %q", want, got)
26+
}
27+
}
28+
29+
func TestProtocolBufferFromValueSupportsIntAliasPointer(t *testing.T) {
30+
raw := testIntEnum(7)
31+
buffers, err := protocolBufferFromValue(&raw)
32+
if err != nil {
33+
t.Fatalf("unexpected error: %v", err)
34+
}
35+
36+
if len(buffers) != 1 {
37+
t.Fatalf("expected 1 buffer, got %d", len(buffers))
38+
}
39+
got := string(buffers[0])
40+
want := fmt.Sprintf("%c%d ", CMD_INT, 7)
41+
if got != want {
42+
t.Fatalf("unexpected encoded value: want %q got %q", want, got)
43+
}
44+
}
45+
46+
func TestProtocolBufferFromValueSupportsFloat32(t *testing.T) {
47+
buffers, err := protocolBufferFromValue(float32(2.5))
48+
if err != nil {
49+
t.Fatalf("unexpected error: %v", err)
50+
}
51+
52+
if len(buffers) != 1 {
53+
t.Fatalf("expected 1 buffer, got %d", len(buffers))
54+
}
55+
got := string(buffers[0])
56+
if !strings.HasPrefix(got, fmt.Sprintf("%c", CMD_FLOAT)) {
57+
t.Fatalf("expected float buffer prefix, got %q", got)
58+
}
59+
}
60+
61+
func TestProtocolBufferFromValueUnsupportedTypeReturnsError(t *testing.T) {
62+
type unsupported struct {
63+
Name string
64+
}
65+
66+
_, err := protocolBufferFromValue(unsupported{Name: "x"})
67+
if err == nil {
68+
t.Fatalf("expected error for unsupported type")
69+
}
70+
}

0 commit comments

Comments
 (0)