Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Add ns precision support to time values #2940

Merged
merged 2 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions client/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,21 @@ import (
ccid "github.com/sourcenetwork/defradb/internal/core/cid"
)

// CborEncodingOptions returns the set of cbor encoding options to be used whenever
// encoding defra documents.
//
// It is the canonical encoding options that ensure consistent serialization of
// indeterministic datastructures, like Go Maps, plus nano-second precision for
// time values (not canon).
func CborEncodingOptions() cbor.EncOptions {
// Important: CanonicalEncOptions ensures consistent serialization of
// indeterministic datastructures, like Go Maps

opts := cbor.CanonicalEncOptions()
opts.Time = cbor.TimeRFC3339Nano
return opts
}

// This is the main implementation starting point for accessing the internal Document API
// which provides API access to the various operations available for Documents, i.e. CRUD.
//
Expand Down Expand Up @@ -659,9 +674,7 @@ func (doc *Document) Bytes() ([]byte, error) {
return nil, err
}

// Important: CanonicalEncOptions ensures consistent serialization of
// indeterministic datastructures, like Go Maps
em, err := cbor.CanonicalEncOptions().EncMode()
em, err := CborEncodingOptions().EncMode()
if err != nil {
return nil, err
}
Expand Down
3 changes: 1 addition & 2 deletions client/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
package client

import (
"github.com/fxamacker/cbor/v2"
"github.com/sourcenetwork/immutable"
)

Expand Down Expand Up @@ -60,7 +59,7 @@ func (val *FieldValue) SetType(t CType) {
}

func (val FieldValue) Bytes() ([]byte, error) {
em, err := cbor.EncOptions{Time: cbor.TimeRFC3339}.EncMode()
em, err := CborEncodingOptions().EncMode()
if err != nil {
return nil, err
}
Expand Down
3 changes: 3 additions & 0 deletions docs/data_format_changes/i2927-time-ns-precision.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Add ns precision support to time values

Adds nanosecond precision to DateTime values. As a result the serialization format of DateTime values has changed.
3 changes: 1 addition & 2 deletions internal/db/merge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"testing"
"time"

"github.com/fxamacker/cbor/v2"
"github.com/ipld/go-ipld-prime"
"github.com/ipld/go-ipld-prime/linking"
cidlink "github.com/ipld/go-ipld-prime/linking/cid"
Expand Down Expand Up @@ -286,7 +285,7 @@ func (d *dagBuilder) generateCompositeUpdate(lsys *linking.LinkSystem, fields ma
}

func encodeValue(val any) []byte {
em, err := cbor.EncOptions{Time: cbor.TimeRFC3339}.EncMode()
em, err := client.CborEncodingOptions().EncMode()
if err != nil {
// safe to panic here as this is a test
panic(err)
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/index/create_unique_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ func TestUniqueQueryWithIndex_UponAddingDocWithSameDateTime_Error(t *testing.T)
"birthday": "2000-07-23T03:00:00-00:00"
}`,
ExpectedError: db.NewErrCanNotIndexNonUniqueFields(
"bae-2000529a-8b27-539b-91e9-c35f431fb78e",
"bae-7e20b26e-5d93-572a-9724-d8f862efbe63",
errors.NewKV("birthday", testUtils.MustParseTime("2000-07-23T03:00:00-00:00")),
).Error(),
},
Expand Down
104 changes: 104 additions & 0 deletions tests/integration/mutation/create/field_kinds/date_time_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright 2024 Democratized Data Foundation
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package field_kinds

import (
"testing"
"time"

testUtils "github.com/sourcenetwork/defradb/tests/integration"
)

func TestMutationCreateFieldKinds_WithDateTime(t *testing.T) {
test := testUtils.TestCase{
Actions: []any{
testUtils.SchemaUpdate{
Schema: `
type User {
time: DateTime
}
`,
},
testUtils.CreateDoc{
DocMap: map[string]any{
"time": "2017-07-23T03:46:56.000Z",
},
},
testUtils.Request{
Request: `query {
User {
time
}
}`,
Results: map[string]any{
"User": []map[string]any{
{
"time": time.Date(2017, time.July, 23, 3, 46, 56, 0, time.UTC),
},
},
},
},
},
}

testUtils.ExecuteTestCase(t, test)
}

func TestMutationCreateFieldKinds_WithDateTimesNanoSecondsAppart(t *testing.T) {
test := testUtils.TestCase{
Actions: []any{
testUtils.SchemaUpdate{
Schema: `
type User {
time: DateTime
}
`,
},
testUtils.CreateDoc{
DocMap: map[string]any{
"time": "2017-07-23T03:46:56.000Z",
},
},
testUtils.CreateDoc{
DocMap: map[string]any{
"time": "2017-07-23T03:46:56.000000001Z",
},
},
testUtils.CreateDoc{
DocMap: map[string]any{
"time": "2017-07-23T03:46:56.000000002Z",
},
},
testUtils.Request{
Request: `query {
User {
time
}
}`,
Results: map[string]any{
"User": []map[string]any{
{
"time": time.Date(2017, time.July, 23, 3, 46, 56, 1, time.UTC),
},
{
"time": time.Date(2017, time.July, 23, 3, 46, 56, 0, time.UTC),
},
{
"time": time.Date(2017, time.July, 23, 3, 46, 56, 2, time.UTC),
},
},
},
},
},
}

testUtils.ExecuteTestCase(t, test)
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,11 @@ func TestMutationUpdate_WithDateTimeField_MultipleDocs(t *testing.T) {
Results: map[string]any{
"update_Users": []map[string]any{
{
"name": "Fred",
"name": "John",
"created_at": testUtils.MustParseTime("2031-07-23T03:23:23Z"),
},
{
"name": "John",
"name": "Fred",
"created_at": testUtils.MustParseTime("2031-07-23T03:23:23Z"),
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ func TestQueryOneToManyWithParentUpdateAndLastCidAndDocID(t *testing.T) {
testUtils.Request{
Request: `query {
Book (
cid: "bafyreigyxgn2tss7objjzen5s77w6hijpe6wmmz4z3ercpxdcrq7uwnhl4",
cid: "bafyreihylh2iftquu5vukm2myjrfbkjnpr5vonlp5s5oo22bfrhddkju6e",
docID: "bae-5366ba09-54e8-5381-8169-a770aa9282ae"
) {
name
Expand Down
10 changes: 5 additions & 5 deletions tests/integration/query/simple/with_group_average_filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,11 @@ func TestQuerySimpleWithGroupByStringWithRenderedGroupWithFilterAndChildAverageW
}`,
Results: map[string]any{
"Users": []map[string]any{
{
"Name": "Alice",
"_avg": float64(0),
"_group": []map[string]any{},
},
{
"Name": "John",
"_avg": float64(34),
Expand All @@ -298,11 +303,6 @@ func TestQuerySimpleWithGroupByStringWithRenderedGroupWithFilterAndChildAverageW
},
},
},
{
"Name": "Alice",
"_avg": float64(0),
"_group": []map[string]any{},
},
},
},
},
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/query/simple/with_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,10 @@ func TestQuerySimpleWithGroupByDateTime(t *testing.T) {
"CreatedAt": testUtils.MustParseTime("2011-07-23T03:46:56-05:00"),
},
{
"CreatedAt": testUtils.MustParseTime("2013-07-23T03:46:56-05:00"),
"CreatedAt": testUtils.MustParseTime("2012-07-23T03:46:56-05:00"),
},
{
"CreatedAt": testUtils.MustParseTime("2012-07-23T03:46:56-05:00"),
"CreatedAt": testUtils.MustParseTime("2013-07-23T03:46:56-05:00"),
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func areResultsEqual(expected any, actual any) bool {
case []immutable.Option[string]:
return areResultArraysEqual(expectedVal, actual)
case time.Time:
return areResultsEqual(expectedVal.Format(time.RFC3339), actual)
return areResultsEqual(expectedVal.Format(time.RFC3339Nano), actual)
default:
return assert.ObjectsAreEqualValues(expected, actual)
}
Expand Down
Loading