فهرست منبع

added handling of 'database/sql' module NULL datatypes

Dmitry Litvinov 7 سال پیش
والد
کامیت
bd6208ef88
2فایلهای تغییر یافته به همراه153 افزوده شده و 11 حذف شده
  1. 41 0
      write.go
  2. 112 11
      write_test.go

+ 41 - 0
write.go

@@ -1,6 +1,7 @@
 package xlsx
 
 import (
+	"database/sql"
 	"fmt"
 	"reflect"
 	"time"
@@ -41,6 +42,26 @@ func (r *Row) WriteSlice(e interface{}, cols int) int {
 		case fmt.Stringer: // check Stringer first
 			cell := r.AddCell()
 			cell.SetString(t.String())
+		case sql.NullString:  // check null sql types nulls = ''
+			cell := r.AddCell()
+			if cell.SetString(``); t.Valid {
+				cell.SetValue(t.String)
+			}
+		case sql.NullBool:
+			cell := r.AddCell()
+			if cell.SetString(``); t.Valid {
+				cell.SetBool(t.Bool)
+			}
+		case sql.NullInt64:
+			cell := r.AddCell()
+			if cell.SetString(``); t.Valid {
+				cell.SetValue(t.Int64)
+			}
+		case sql.NullFloat64:
+			cell := r.AddCell()
+			if cell.SetString(``); t.Valid {
+				cell.SetValue(t.Float64)
+			}
 		default:
 			switch val.Kind() { // underlying type of slice
 			case reflect.String, reflect.Int, reflect.Int8,
@@ -93,6 +114,26 @@ func (r *Row) WriteStruct(e interface{}, cols int) int {
 		case fmt.Stringer: // check Stringer first
 			cell := r.AddCell()
 			cell.SetString(t.String())
+		case sql.NullString: // check null sql types nulls = ''
+			cell := r.AddCell()
+			if cell.SetString(``); t.Valid {
+				cell.SetValue(t.String)
+			}
+		case sql.NullBool:
+			cell := r.AddCell()
+			if cell.SetString(``); t.Valid {
+				cell.SetBool(t.Bool)
+			}
+		case sql.NullInt64:
+			cell := r.AddCell()
+			if cell.SetString(``); t.Valid {
+				cell.SetValue(t.Int64)
+			}
+		case sql.NullFloat64:
+			cell := r.AddCell()
+			if cell.SetString(``); t.Valid {
+				cell.SetValue(t.Float64)
+			}
 		default:
 			switch f.Kind() {
 			case reflect.String, reflect.Int, reflect.Int8,

+ 112 - 11
write_test.go

@@ -1,6 +1,7 @@
 package xlsx
 
 import (
+	"database/sql"
 	"math"
 	"time"
 
@@ -26,13 +27,21 @@ func (r *RowSuite) TestWriteStruct(c *C) {
 	sheet, _ := f.AddSheet("Test1")
 	row := sheet.AddRow()
 	type e struct {
-		FirstName   string
-		Age         int
-		GPA         float64
-		LikesPHP    bool
-		Stringer    testStringerImpl
-		StringerPtr *testStringerImpl
-		Time        time.Time
+		FirstName       string
+		Age             int
+		GPA             float64
+		LikesPHP        bool
+		Stringer        testStringerImpl
+		StringerPtr     *testStringerImpl
+		Time            time.Time
+		LastName        sql.NullString
+		HasPhd          sql.NullBool
+		GithubStars     sql.NullInt64
+		Raiting         sql.NullFloat64
+		NullLastName    sql.NullString
+		NullHasPhd      sql.NullBool
+		NullGithubStars sql.NullInt64
+		NullRaiting     sql.NullFloat64
 	}
 	testStruct := e{
 		"Eric",
@@ -42,15 +51,23 @@ func (r *RowSuite) TestWriteStruct(c *C) {
 		testStringerImpl{"Stringer"},
 		&testStringerImpl{"Pointer to Stringer"},
 		time.Unix(0, 0),
+		sql.NullString{`Smith`, true},
+		sql.NullBool{false, true},
+		sql.NullInt64{100, true},
+		sql.NullFloat64{0.123, true},
+		sql.NullString{`What ever`, false},
+		sql.NullBool{true, false},
+		sql.NullInt64{100, false},
+		sql.NullFloat64{0.123, false},
 	}
 	cnt := row.WriteStruct(&testStruct, -1)
-	c.Assert(cnt, Equals, 7)
+	c.Assert(cnt, Equals, 15)
 	c.Assert(row, NotNil)
 
 	var (
-		c0, c4, c5 string
-		err        error
-		c6         float64
+		c0, c4, c5, c7, c11, c12, c13, c14 string
+		err                                error
+		c6                                 float64
 	)
 	if c0, err = row.Cells[0].FormattedValue(); err != nil {
 		c.Error(err)
@@ -67,6 +84,26 @@ func (r *RowSuite) TestWriteStruct(c *C) {
 	if c6, err = row.Cells[6].Float(); err != nil {
 		c.Error(err)
 	}
+	if c7, err = row.Cells[7].FormattedValue(); err != nil {
+		c.Error(err)
+	}
+
+	c8 := row.Cells[8].Bool()
+	c9, e9 := row.Cells[9].Int()
+	c10, e10 := row.Cells[10].Float()
+
+	if c11, err = row.Cells[11].FormattedValue(); err != nil {
+		c.Error(err)
+	}
+	if c12, err = row.Cells[12].FormattedValue(); err != nil {
+		c.Error(err)
+	}
+	if c13, err = row.Cells[13].FormattedValue(); err != nil {
+		c.Error(err)
+	}
+	if c14, err = row.Cells[14].FormattedValue(); err != nil {
+		c.Error(err)
+	}
 
 	c.Assert(c0, Equals, "Eric")
 	c.Assert(c1, Equals, 20)
@@ -75,9 +112,20 @@ func (r *RowSuite) TestWriteStruct(c *C) {
 	c.Assert(c4, Equals, "Stringer")
 	c.Assert(c5, Equals, "Pointer to Stringer")
 	c.Assert(math.Floor(c6), Equals, 25569.0)
+	c.Assert(c7, Equals, `Smith`)
+	c.Assert(c8, Equals, false)
+	c.Assert(c9, Equals, 100)
+	c.Assert(c10, Equals, 0.123)
+	c.Assert(c11, Equals, ``)
+	c.Assert(c12, Equals, ``)
+	c.Assert(c13, Equals, ``)
+	c.Assert(c14, Equals, ``)
 
 	c.Assert(e1, Equals, nil)
 	c.Assert(e2, Equals, nil)
+	c.Assert(e9, Equals, nil)
+	c.Assert(e10, Equals, nil)
+
 }
 
 // Test if we can write a slice to a row
@@ -93,6 +141,10 @@ func (r *RowSuite) TestWriteSlice(c *C) {
 	type interfaceA []interface{}
 	type stringerA []testStringerImpl
 	type stringerPtrA []*testStringerImpl
+	type nullStringA []sql.NullString
+	type nullBoolA []sql.NullBool
+	type nullFloatA []sql.NullFloat64
+	type nullIntA []sql.NullInt64
 
 	s0 := strA{"Eric"}
 	row0 := sheet.AddRow()
@@ -181,4 +233,53 @@ func (r *RowSuite) TestWriteSlice(c *C) {
 	c.Assert(s7_ret, Equals, -1)
 	s7_ret = row7.WriteSlice([]string{s7}, -1)
 	c.Assert(s7_ret, Equals, -1)
+
+	s8 := nullStringA{sql.NullString{"Smith", true}, sql.NullString{`What ever`, false}}
+	row8 := sheet.AddRow()
+	row8.WriteSlice(&s8, -1)
+	c.Assert(row8, NotNil)
+
+	if val, err := row8.Cells[0].FormattedValue(); err != nil {
+		c.Error(err)
+	} else {
+		c.Assert(val, Equals, "Smith")
+	}
+	// check second cell on empty string ""
+
+	if val2, err := row8.Cells[1].FormattedValue(); err != nil {
+		c.Error(err)
+	} else {
+		c.Assert(val2, Equals, "")
+	}
+
+	s9 := nullBoolA{sql.NullBool{false, true}, sql.NullBool{true, false}}
+	row9 := sheet.AddRow()
+	row9.WriteSlice(&s9, -1)
+	c.Assert(row9, NotNil)
+	c9 := row9.Cells[0].Bool()
+	c9Null := row9.Cells[1].String()
+	c.Assert(c9, Equals, false)
+	c.Assert(c9Null, Equals, "")
+
+	s10 := nullIntA{sql.NullInt64{100, true}, sql.NullInt64{100, false}}
+	row10 := sheet.AddRow()
+	row10.WriteSlice(&s10, -1)
+	c.Assert(row10, NotNil)
+	c10, e10 := row10.Cells[0].Int()
+	c10Null, e10Null := row10.Cells[1].FormattedValue()
+	c.Assert(e10, Equals, nil)
+	c.Assert(c10, Equals, 100)
+	c.Assert(e10Null, Equals, nil)
+	c.Assert(c10Null, Equals, "")
+
+	s11 := nullFloatA{sql.NullFloat64{0.123, true}, sql.NullFloat64{0.123, false}}
+	row11 := sheet.AddRow()
+	row11.WriteSlice(&s11, -1)
+	c.Assert(row11, NotNil)
+	c11, e11 := row11.Cells[0].Float()
+	c11Null, e11Null := row11.Cells[1].FormattedValue()
+	c.Assert(e11, Equals, nil)
+	c.Assert(c11, Equals, 0.123)
+	c.Assert(e11Null, Equals, nil)
+	c.Assert(c11Null, Equals, "")
 }