Преглед изворни кода

Merge pull request #107 from cwandrews/master

A helper function that returns a []map[string]interface{} of the data a query returned
Ben Hood пре 11 година
родитељ
комит
55355af39f
2 измењених фајлова са 213 додато и 0 уклоњено
  1. 106 0
      cassandra_test.go
  2. 107 0
      helpers.go

+ 106 - 0
cassandra_test.go

@@ -304,3 +304,109 @@ var pageTestData = []*Page{
 		Modified: time.Date(2013, time.August, 13, 9, 52, 3, 0, time.UTC),
 		Modified: time.Date(2013, time.August, 13, 9, 52, 3, 0, time.UTC),
 	},
 	},
 }
 }
+
+func TestSliceMap(t *testing.T) {
+	session := createSession(t)
+	defer session.Close()
+	if err := session.Query(`CREATE TABLE slice_map_table (
+			testuuid       timeuuid PRIMARY KEY,
+			testvarchar    varchar,
+			testbigint     bigint,
+			testblob       blob,
+			testbool       boolean,
+			testfloat	   float,
+			testdouble	   double,
+			testint        int,
+			testset        set<int>,
+			testmap        map<varchar, varchar>
+		)`).Exec(); err != nil {
+		t.Fatal("create table:", err)
+	}
+	m := make(map[string]interface{})
+	m["testuuid"] = TimeUUID()
+	m["testvarchar"] = "Test VarChar"
+	m["testbigint"] = time.Now().Unix()
+	m["testblob"] = []byte("test blob")
+	m["testbool"] = true
+	m["testfloat"] = float32(4.564)
+	m["testdouble"] = float64(4.815162342)
+	m["testint"] = 2343
+	m["testset"] = []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
+	m["testmap"] = map[string]string{"field1": "val1", "field2": "val2", "field3": "val3"}
+	sliceMap := []map[string]interface{}{m}
+	if err := session.Query(`INSERT INTO slice_map_table (testuuid, testvarchar, testbigint, testblob, testbool, testfloat, testdouble, testint, testset, testmap) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
+		m["testuuid"], m["testvarchar"], m["testbigint"], m["testblob"], m["testbool"], m["testfloat"], m["testdouble"], m["testint"], m["testset"], m["testmap"]).Exec(); err != nil {
+		t.Fatal("insert:", err)
+	}
+	if returned, retErr := session.Query(`SELECT * FROM slice_map_table`).Iter().SliceMap(); retErr != nil {
+		t.Fatal("select:", retErr)
+	} else {
+		if sliceMap[0]["testuuid"] != returned[0]["testuuid"] {
+			t.Fatal("returned testuuid did not match")
+		}
+		if sliceMap[0]["testvarchar"] != returned[0]["testvarchar"] {
+			t.Fatal("returned testvarchar did not match")
+		}
+		if sliceMap[0]["testbigint"] != returned[0]["testbigint"] {
+			t.Fatal("returned testbigint did not match")
+		}
+		if !reflect.DeepEqual(sliceMap[0]["testblob"], returned[0]["testblob"]) {
+			t.Fatal("returned testblob did not match")
+		}
+		if sliceMap[0]["testbool"] != returned[0]["testbool"] {
+			t.Fatal("returned testbool did not match")
+		}
+		if sliceMap[0]["testfloat"] != returned[0]["testfloat"] {
+			t.Fatal("returned testfloat did not match")
+		}
+		if sliceMap[0]["testdouble"] != returned[0]["testdouble"] {
+			t.Fatal("returned testdouble did not match")
+		}
+		if sliceMap[0]["testint"] != returned[0]["testint"] {
+			t.Fatal("returned testint did not match")
+		}
+		if !reflect.DeepEqual(sliceMap[0]["testset"], returned[0]["testset"]) {
+			t.Fatal("returned testset did not match")
+		}
+		if !reflect.DeepEqual(sliceMap[0]["testmap"], returned[0]["testmap"]) {
+			t.Fatal("returned testmap did not match")
+		}
+	}
+
+	// Test for MapScan()
+	testMap := make(map[string]interface{})
+	if !session.Query(`SELECT * FROM slice_map_table`).Iter().MapScan(testMap) {
+		t.Fatal("MapScan failed to work with one row")
+	}
+	if sliceMap[0]["testuuid"] != testMap["testuuid"] {
+		t.Fatal("returned testuuid did not match")
+	}
+	if sliceMap[0]["testvarchar"] != testMap["testvarchar"] {
+		t.Fatal("returned testvarchar did not match")
+	}
+	if sliceMap[0]["testbigint"] != testMap["testbigint"] {
+		t.Fatal("returned testbigint did not match")
+	}
+	if !reflect.DeepEqual(sliceMap[0]["testblob"], testMap["testblob"]) {
+		t.Fatal("returned testblob did not match")
+	}
+	if sliceMap[0]["testbool"] != testMap["testbool"] {
+		t.Fatal("returned testbool did not match")
+	}
+	if sliceMap[0]["testfloat"] != testMap["testfloat"] {
+		t.Fatal("returned testfloat did not match")
+	}
+	if sliceMap[0]["testdouble"] != testMap["testdouble"] {
+		t.Fatal("returned testdouble did not match")
+	}
+	if sliceMap[0]["testint"] != testMap["testint"] {
+		t.Fatal("returned testint did not match")
+	}
+	if !reflect.DeepEqual(sliceMap[0]["testset"], testMap["testset"]) {
+		t.Fatal("returned testset did not match")
+	}
+	if !reflect.DeepEqual(sliceMap[0]["testmap"], testMap["testmap"]) {
+		t.Fatal("returned testmap did not match")
+	}
+
+}

+ 107 - 0
helpers.go

@@ -0,0 +1,107 @@
+package gocql
+
+import "reflect"
+
+type rowData struct {
+	Columns []string
+	Values []interface{}
+}
+
+// New creates a pointer to an empty version of whatever type 
+// is referenced by the TypeInfo receiver
+func (t *TypeInfo) New() interface{} {
+	return reflect.New(goType(t)).Interface()
+}
+
+func goType(t *TypeInfo) reflect.Type {
+	switch t.Type {
+	case TypeVarchar, TypeAscii:
+		return reflect.TypeOf(*new(string))
+	case TypeBigInt, TypeCounter, TypeTimestamp:
+		return reflect.TypeOf(*new(int64))
+	case TypeBlob:
+		return reflect.TypeOf(*new([]byte))
+	case TypeBoolean:
+		return reflect.TypeOf(*new(bool))
+	case TypeFloat:
+		return reflect.TypeOf(*new(float32))
+	case TypeDouble:
+		return reflect.TypeOf(*new(float64))
+	case TypeInt:
+		return reflect.TypeOf(*new(int))
+	case TypeUUID, TypeTimeUUID:
+		return reflect.TypeOf(*new(UUID))
+	case TypeList, TypeSet:
+		return reflect.SliceOf(goType(t.Elem))
+	case TypeMap:
+		return reflect.MapOf(goType(t.Key), goType(t.Elem))
+	default:
+		return nil
+	}
+}
+
+func dereference(i interface{}) interface{} {
+	return reflect.Indirect(reflect.ValueOf(i)).Interface()
+}
+
+func (r *rowData) rowMap(m map[string]interface{}) {
+	for i, column := range r.Columns {
+		m[column] = dereference(r.Values[i])
+	}
+}
+
+func (iter *Iter) rowData() (rowData, error) {
+	if iter.err != nil {
+		return rowData{}, iter.err
+	}
+	columns := make([]string, 0)
+	values := make([]interface{}, 0)
+	for _, column := range iter.Columns() {
+		val := column.TypeInfo.New()
+		columns = append(columns, column.Name)
+		values = append(values, val)
+	}
+	rowData := rowData{
+		Columns: columns,
+		Values: values,
+	}
+	return rowData, nil
+}
+
+// SliceMap is a helper function to make the API easier to use
+// returns the data from the query in the form of []map[string]interface{}
+func (iter *Iter) SliceMap() ([]map[string]interface{}, error) {
+	if iter.err != nil {
+		return nil, iter.err
+	}
+
+	// Not checking for the error because we just did
+	rowData, _ := iter.rowData()
+	dataToReturn := make([]map[string]interface{}, 0)
+	for iter.Scan(rowData.Values...) {
+		m := make(map[string]interface{})
+		rowData.rowMap(m)
+		dataToReturn = append(dataToReturn, m)
+	}
+	if iter.err != nil {
+		return nil, iter.err
+	}
+	return dataToReturn, nil
+}
+
+// MapScan takes a map[string]interface{} and populates it with a row
+// That is returned from cassandra.
+func (iter *Iter) MapScan(m map[string]interface{}) bool {
+	if iter.err != nil {
+		return false
+	}
+
+	// Not checking for the error because we just did
+	rowData, _ := iter.rowData()
+
+	if iter.Scan(rowData.Values...) {
+		rowData.rowMap(m)	
+		return true
+	}
+	return false
+}