瀏覽代碼

Correctly unmarshal null UDT responses

When a UDT column is null it's data will be empty, when this is the
case set the unmarshal target to its zero value if possible and
return.
Chris Bannister 10 年之前
父節點
當前提交
08c272cd69
共有 2 個文件被更改,包括 62 次插入1 次删除
  1. 8 1
      marshal.go
  2. 54 0
      udt_test.go

+ 8 - 1
marshal.go

@@ -1381,8 +1381,15 @@ func unmarshalUDT(info TypeInfo, data []byte, value interface{}) error {
 		}
 	}
 
-	udt := info.(UDTTypeInfo)
+	if len(data) == 0 {
+		if k.CanSet() {
+			k.Set(reflect.Zero(k.Type()))
+		}
+
+		return nil
+	}
 
+	udt := info.(UDTTypeInfo)
 	for _, e := range udt.Elements {
 		size := readInt(data[:4])
 		data = data[4:]

+ 54 - 0
udt_test.go

@@ -187,3 +187,57 @@ func TestUDT_Proto2error(t *testing.T) {
 		t.Fatalf("expected to get %v got %v", ErrorUDTUnavailable, err)
 	}
 }
+
+func TestUDT_NullObject(t *testing.T) {
+	if *flagProto < protoVersion3 {
+		t.Skip("UDT are only available on protocol >= 3")
+	}
+
+	session := createSession(t)
+	defer session.Close()
+
+	err := createTable(session, `CREATE TYPE udt_null_type(
+		name text,
+		owner text);`)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = createTable(session, `CREATE TABLE udt_null_table(
+		id uuid,
+		udt_col frozen<udt_null_type>,
+
+		primary key(id)
+	);`)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	type col struct {
+		Name  string `cql:"name"`
+		Owner string `cql:"owner"`
+	}
+
+	id := TimeUUID()
+	err = session.Query("INSERT INTO udt_null_table(id) VALUES(?)", id).Exec()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	readCol := &col{
+		Name:  "temp",
+		Owner: "temp",
+	}
+
+	err = session.Query("SELECT udt_col FROM udt_null_table WHERE id = ?", id).Scan(readCol)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if readCol.Name != "" {
+		t.Errorf("expected empty string to be returned for null udt: got %q", readCol.Name)
+	}
+	if readCol.Owner != "" {
+		t.Errorf("expected empty string to be returned for null udt: got %q", readCol.Owner)
+	}
+}