diff --git a/rows.go b/rows.go new file mode 100644 index 0000000..5c3948e --- /dev/null +++ b/rows.go @@ -0,0 +1,52 @@ +package fireboltgosdk + +import ( + "database/sql/driver" + "io" +) + +type fireboltRows struct { + response QueryResponse + cursorPosition int +} + +func (f *fireboltRows) Columns() []string { + numColumns := len(f.response.Meta) + result := make([]string, 0, numColumns) + + for _, column := range f.response.Meta { + result = append(result, column.Name) + } + + return result +} + +func (f *fireboltRows) Close() error { + f.cursorPosition = len(f.response.Data) + return nil +} + +func (f *fireboltRows) Next(dest []driver.Value) error { + if f.cursorPosition == len(f.response.Data) { + return io.EOF + } + + for i, column := range f.response.Meta { + val := f.response.Data[f.cursorPosition][i] + switch column.Type { + case "Int32": + dest[i] = int32(val.(float64)) + case "Int64": + dest[i] = int64(val.(float64)) + case "Float32": + dest[i] = float32(val.(float64)) + case "Float64": + dest[i] = val.(float64) + default: + dest[i] = val + } + } + + f.cursorPosition++ + return nil +} diff --git a/rows_test.go b/rows_test.go new file mode 100644 index 0000000..57e2eb5 --- /dev/null +++ b/rows_test.go @@ -0,0 +1,73 @@ +package fireboltgosdk + +import ( + "database/sql/driver" + "encoding/json" + "io" + "reflect" + "testing" +) + +func assert(val bool, t *testing.T, err string) { + if !val { + t.Errorf(err) + } +} + +func mockRows() driver.Rows { + resultJson := "{\"query\":{\"query_id\":\"16FF2A0300ECA753\"},\"meta\":[{\"name\":\"int_col\",\"type\":\"Int32\"},{\"name\":\"bigint_col\",\"type\":\"Int64\"},{\"name\":\"float_col\",\"type\":\"Float32\"},{\"name\":\"double_col\",\"type\":\"Float64\"},{\"name\":\"text_col\",\"type\":\"String\"},{\"name\":\"date_col\",\"type\":\"Date\"},{\"name\":\"timestamp_col\",\"type\":\"DateTime\"},{\"name\":\"bool_col\",\"type\":\"UInt8\"},{\"name\":\"array_col\",\"type\":\"Array(Int32)\"},{\"name\":\"nested_array_col\",\"type\":\"Array(Array(String))\"}],\"data\":[[2,1,0.312321,123213.321321,\"text\",\"1970-01-01\",\"1970-01-01 00:00:00\",1,[1,2,3],[[]]],[2,1,0.312321,123213.321321,\"text\",\"1970-01-01\",\"1970-01-01 00:00:00\",1,[1,2,3],[[]]],[3,5,0.312321,123213.321321,\"text\",\"1970-01-01\",\"1970-01-01 00:00:00\",1,[5,2,3,2],[[\"TEST\",\"TEST1\"],[\"TEST3\"]]]],\"rows\":3,\"statistics\":{\"elapsed\":0.001797702,\"rows_read\":3,\"bytes_read\":293,\"time_before_execution\":0.001251613,\"time_to_execute\":0.000544098,\"scanned_bytes_cache\":2003,\"scanned_bytes_storage\":0}}" + var response QueryResponse + err := json.Unmarshal([]byte(resultJson), &response) + if err != nil { + panic("Error in test code") + } + return &fireboltRows{response, 0} +} + +func TestRowsColumns(t *testing.T) { + rows := mockRows() + + columnNames := []string{"int_col", "bigint_col", "float_col", "double_col", "text_col", "date_col", "timestamp_col", "bool_col", "array_col", "nested_array_col"} + if !reflect.DeepEqual(rows.Columns(), columnNames) { + t.Errorf("column lists are not equal") + } +} + +func TestRowsClose(t *testing.T) { + rows := mockRows() + if rows.Close() != nil { + t.Errorf("Closing rows was not successful") + } + + var dest []driver.Value + if rows.Next(dest) != io.EOF { + t.Errorf("Next of closed rows didn't return EOF") + } +} + +func TestRowsNext(t *testing.T) { + rows := mockRows() + var dest = make([]driver.Value, 10) + err := rows.Next(dest) + + assert(err == nil, t, "Next shouldn't return an error") + assert(dest[0] == int32(2), t, "results not equal for int32") + assert(dest[1] == int64(1), t, "results not equal for int64") + assert(dest[2] == float32(0.312321), t, "results not equal for float32") + assert(dest[3] == float64(123213.321321), t, "results not equal for float64") + assert(dest[4] == "text", t, "results not equal for string") + + err = rows.Next(dest) + assert(err == nil, t, "Next shouldn't return an error") + + err = rows.Next(dest) + assert(err == nil, t, "Next shouldn't return an error") + + assert(dest[0] == int32(3), t, "results not equal for int32") + assert(dest[1] == int64(5), t, "results not equal for int64") + assert(dest[2] == float32(0.312321), t, "results not equal for float32") + assert(dest[3] == float64(123213.321321), t, "results not equal for float64") + assert(dest[4] == "text", t, "results not equal for string") + + assert(io.EOF == rows.Next(dest), t, "Next should return io.EOF if no data available anymore") +}