Selaa lähdekoodia

Return a helpful error when using UDT in proto 2

When using UDT's in a protocol which does not support UDT's
return a more helpful error indicating that protocol version 3
or above should be used.
Chris Bannister 10 vuotta sitten
vanhempi
commit
e2ff1deadd
2 muutettua tiedostoa jossa 62 lisäystä ja 1 poistoa
  1. 18 0
      marshal.go
  2. 44 1
      udt_test.go

+ 18 - 0
marshal.go

@@ -7,12 +7,14 @@ package gocql
 import (
 	"bytes"
 	"encoding/binary"
+	"errors"
 	"fmt"
 	"math"
 	"math/big"
 	"net"
 	"reflect"
 	"strconv"
+	"strings"
 	"time"
 
 	"speter.net/go/exp/math/dec/inf"
@@ -22,6 +24,10 @@ var (
 	bigOne = big.NewInt(1)
 )
 
+var (
+	ErrorUDTUnavailable = errors.New("UDT are not available on protocols less than 3, please update config")
+)
+
 // Marshaler is the interface implemented by objects that can marshal
 // themselves into values understood by Cassandra.
 type Marshaler interface {
@@ -86,6 +92,12 @@ func Marshal(info TypeInfo, value interface{}) ([]byte, error) {
 	case TypeUDT:
 		return marshalUDT(info, value)
 	}
+
+	// detect protocol 2 UDT
+	if strings.HasPrefix(info.Custom(), "org.apache.cassandra.db.marshal.UserType") && info.Version() < 3 {
+		return nil, ErrorUDTUnavailable
+	}
+
 	// TODO(tux21b): add the remaining types
 	return nil, fmt.Errorf("can not marshal %T into %s", value, info)
 }
@@ -135,6 +147,12 @@ func Unmarshal(info TypeInfo, data []byte, value interface{}) error {
 	case TypeUDT:
 		return unmarshalUDT(info, data, value)
 	}
+
+	// detect protocol 2 UDT
+	if strings.HasPrefix(info.Custom(), "org.apache.cassandra.db.marshal.UserType") && info.Version() < 3 {
+		return ErrorUDTUnavailable
+	}
+
 	// TODO(tux21b): add the remaining types
 	return fmt.Errorf("can not unmarshal %s into %T", info, value)
 }

+ 44 - 1
udt_test.go

@@ -86,12 +86,13 @@ func TestUDT_Marshaler(t *testing.T) {
 		t.Errorf("expeceted lon to be be %d got %d", expLon, pos.Lon)
 	}
 }
+
 func TestUDT_Reflect(t *testing.T) {
-	// Uses reflection instead of implementing the marshaling type
 	if *flagProto < protoVersion3 {
 		t.Skip("UDT are only available on protocol >= 3")
 	}
 
+	// Uses reflection instead of implementing the marshaling type
 	session := createSession(t)
 	defer session.Close()
 
@@ -137,3 +138,45 @@ func TestUDT_Reflect(t *testing.T) {
 		t.Fatal("exepcted to get %+v got %+v", insertedHorse, retrievedHorse)
 	}
 }
+
+func TestUDT_Proto2error(t *testing.T) {
+	if *flagProto > protoVersion2 {
+		t.Skip("protocol less than 3 required to check erorr")
+	}
+
+	// Uses reflection instead of implementing the marshaling type
+	session := createSession(t)
+	defer session.Close()
+
+	err := createTable(session, `CREATE TYPE horse(
+		name text,
+		owner text);`)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = createTable(session, `CREATE TABLE horse_race(
+		position int,
+		horse frozen<horse>,
+
+		primary key(position)
+	);`)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	type horse struct {
+		Name  string `cql:"name"`
+		Owner string `cql:"owner"`
+	}
+
+	insertedHorse := &horse{
+		Name:  "pony",
+		Owner: "jim",
+	}
+
+	err = session.Query("INSERT INTO horse_race(position, horse) VALUES(?, ?)", 1, insertedHorse).Exec()
+	if err != ErrorUDTUnavailable {
+		t.Fatalf("expected to get %v got %v", ErrorUDTUnavailable, err)
+	}
+}