From acfbd5d998630fd125a9b5a2c91804c73d94d443 Mon Sep 17 00:00:00 2001 From: gedi Date: Wed, 5 Aug 2015 11:50:16 +0300 Subject: [PATCH] allow null values from csv string to be converted to nil --- rows.go | 12 +++++++++++- rows_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/rows.go b/rows.go index 62a4cf0..92ceb92 100644 --- a/rows.go +++ b/rows.go @@ -7,6 +7,16 @@ import ( "strings" ) +// CSVColumnParser is a function which converts trimmed csv +// column string to a []byte representation. +var CSVColumnParser = func(s string) []byte { + switch { + case strings.ToLower(s) == "null": + return nil + } + return []byte(s) +} + // Rows interface allows to construct rows // which also satisfies database/sql/driver.Rows interface type Rows interface { @@ -113,7 +123,7 @@ func (r *rows) FromCSVString(s string) Rows { row := make([]driver.Value, len(r.cols)) for i, v := range res { - row[i] = []byte(strings.TrimSpace(v)) + row[i] = CSVColumnParser(strings.TrimSpace(v)) } r.rows = append(r.rows, row) } diff --git a/rows_test.go b/rows_test.go index 9347340..533d880 100644 --- a/rows_test.go +++ b/rows_test.go @@ -207,3 +207,34 @@ func TODO_TestRowsColumnsError(t *testing.T) { t.Fatal(err) } } + +func TestCSVRowParser(t *testing.T) { + t.Parallel() + rs := NewRows([]string{"col1", "col2"}).FromCSVString("a,NULL") + db, mock, err := New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + defer db.Close() + + mock.ExpectQuery("SELECT").WillReturnRows(rs) + + rw, err := db.Query("SELECT") + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + defer rw.Close() + var col1 string + var col2 []byte + + rw.Next() + if err = rw.Scan(&col1, &col2); err != nil { + t.Fatalf("unexpected error: %s", err) + } + if col1 != "a" { + t.Fatalf("expected col1 to be 'a', but got [%T]:%+v", col1, col1) + } + if col2 != nil { + t.Fatalf("expected col2 to be nil, but got [%T]:%+v", col2, col2) + } +}