Repository: genjidb/genji
Pull request #330 (2020-11-19 13:52:23)

Fix creating document from struct with known types
I think that converting struct to Document is a very complex topic (just look at json/encoding), but #260 introduced behavior that is incompatible with one that was previously (see tests).

codecov-io: # [Codecov](https://codecov.io/gh/genjidb/genji/pull/330?src=pr&el=h1) Report
> Merging [#330](https://codecov.io/gh/genjidb/genji/pull/330?src=pr&el=desc) (9fbc7d2) into [main](https://codecov.io/gh/genjidb/genji/commit/7d37cc6756ecdc4f2db0e4b05b98ebd17de07f5a?el=desc) (7d37cc6) will **decrease** coverage by `0.01%`.
> The diff coverage is `55.55%`.

[![Impacted file tree graph](https://codecov.io/gh/genjidb/genji/pull/330/graphs/tree.svg?width=650&height=150&src=pr&token=nwR1GpvtyH)](https://codecov.io/gh/genjidb/genji/pull/330?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##             main     #330      +/-   ##
==========================================
- Coverage   61.72%   61.70%   -0.02%     
==========================================
  Files          75       75              
  Lines        6866     6866              
==========================================
- Hits         4238     4237       -1     
  Misses       2073     2073              
- Partials      555      556       +1     
```


| [Impacted Files](https://codecov.io/gh/genjidb/genji/pull/330?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [document/create.go](https://codecov.io/gh/genjidb/genji/pull/330/diff?src=pr&el=tree#diff-ZG9jdW1lbnQvY3JlYXRlLmdv) | `67.85% <55.55%> (-1.43%)` | :arrow_down: |
| [document/scan.go](https://codecov.io/gh/genjidb/genji/pull/330/diff?src=pr&el=tree#diff-ZG9jdW1lbnQvc2Nhbi5nbw==) | `64.43% <0.00%> (+0.51%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/genjidb/genji/pull/330?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/genjidb/genji/pull/330?src=pr&el=footer). Last update [7d37cc6...9fbc7d2](https://codecov.io/gh/genjidb/genji/pull/330?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/document/create.go b/document/create.go
index d69c3972..f80047f6 100644
--- a/document/create.go
+++ b/document/create.go
@@ -122,18 +122,16 @@ func newFromStruct(ref reflect.Value) (Document, error) {
 
 		sf := tp.Field(i)
 
-		if f.Kind() == reflect.Struct {
+		isUnexported := sf.PkgPath != ""
+
+		if sf.Anonymous {
+			if isUnexported && f.Kind() != reflect.Struct {
+				continue
+			}
 			d, err := newFromStruct(f)
 			if err != nil {
 				return nil, err
 			}
-
-			if !sf.Anonymous {
-				fb.Add(strings.ToLower(sf.Name), NewDocumentValue(d))
-				continue
-			}
-
-			// Embedded struct.
 			err = d.Iterate(func(field string, value Value) error {
 				fb.Add(field, value)
 				return nil
@@ -141,12 +139,14 @@ func newFromStruct(ref reflect.Value) (Document, error) {
 			if err != nil {
 				return nil, err
 			}
-
+			continue
+		} else if isUnexported {
 			continue
 		}
 
-		if sf.PkgPath != "" {
-			continue
+		v, err := NewValue(f.Interface())
+		if err != nil {
+			return nil, err
 		}
 
 		field := strings.ToLower(sf.Name)
@@ -154,15 +154,9 @@ func newFromStruct(ref reflect.Value) (Document, error) {
 			if gtag == "-" {
 				continue
 			}
-
 			field = gtag
 		}
 
-		v, err := NewValue(f.Interface())
-		if err != nil {
-			return nil, err
-		}
-
 		fb.Add(field, v)
 	}
 


Test patch:
diff --git a/document/document_test.go b/document/document_test.go
index 960cd059..0d054573 100644
--- a/document/document_test.go
+++ b/document/document_test.go
@@ -4,6 +4,7 @@ import (
 	"encoding/json"
 	"errors"
 	"testing"
+	"time"
 
 	"github.com/genjidb/genji/document"
 	"github.com/genjidb/genji/sql/parser"
@@ -295,6 +296,8 @@ func TestNewFromStruct(t *testing.T) {
 
 		*group
 
+		BB time.Time // some has special encoding as Document
+
 		// unexported fields should be ignored
 		t int
 	}
@@ -319,6 +322,7 @@ func TestNewFromStruct(t *testing.T) {
 		group: &group{
 			Ig: 100,
 		},
+		BB: time.Date(2020, 11, 15, 16, 37, 10, 20, time.UTC),
 	}
 
 	q := 5
@@ -394,6 +398,8 @@ func TestNewFromStruct(t *testing.T) {
 				require.EqualValues(t, document.NullValue, v.Type)
 			case 27:
 				require.EqualValues(t, document.IntegerValue, v.Type)
+			case 28:
+				require.EqualValues(t, document.TextValue, v.Type)
 			default:
 				require.FailNowf(t, "", "unknown field %q", f)
 			}
@@ -403,7 +409,7 @@ func TestNewFromStruct(t *testing.T) {
 			return nil
 		})
 		require.NoError(t, err)
-		require.Equal(t, 28, counter)
+		require.Equal(t, 29, counter)
 	})
 
 	t.Run("GetByField", func(t *testing.T) {
@@ -482,6 +488,14 @@ func TestNewFromStruct(t *testing.T) {
 		v, err = a.GetByIndex(1)
 		require.NoError(t, err)
 		require.EqualValues(t, 2, v.V.(int64))
+
+		v, err = doc.GetByField("bb")
+		require.NoError(t, err)
+		var timeStr string
+		require.NoError(t, v.Scan(&timeStr))
+		parsedTime, err := time.Parse(time.RFC3339Nano, timeStr)
+		require.NoError(t, err)
+		require.Equal(t, u.BB, parsedTime)
 	})
 }