From 54e8b6b4352a3118c18749f25adf58657c86979c Mon Sep 17 00:00:00 2001 From: Fred Carle Date: Wed, 23 Nov 2022 16:37:01 -0500 Subject: [PATCH] change to external immubable package --- api/http/handlerfuncs.go | 3 +- api/http/server.go | 12 +- client/db.go | 2 +- client/request/aggregate.go | 2 +- client/request/commit.go | 18 +-- client/request/field.go | 4 +- client/request/mutation.go | 6 +- client/request/select.go | 17 +-- client/request/subscription.go | 8 +- connor/eq.go | 11 +- core/doc.go | 7 +- core/parser.go | 4 +- db/collection_update.go | 8 +- db/db.go | 7 +- db/fetcher/dag.go | 6 +- db/fetcher/encoded_doc.go | 18 +-- db/subscriptions.go | 4 +- events/db_update.go | 7 +- go.mod | 1 + go.sum | 2 + immutables/doc.go | 14 --- immutables/enumerable/concat.go | 56 --------- immutables/enumerable/enumerable.go | 115 ------------------ immutables/enumerable/select.go | 55 --------- immutables/enumerable/skip.go | 48 -------- immutables/enumerable/sort.go | 86 ------------- immutables/enumerable/take.go | 43 ------- immutables/enumerable/where.go | 48 -------- immutables/option.go | 46 ------- merkle/crdt/factory_test.go | 15 +-- planner/count.go | 13 +- planner/mapper/commitSelect.go | 10 +- planner/mapper/mapper.go | 23 ++-- planner/mapper/select.go | 5 +- planner/mapper/targetable.go | 5 +- planner/select.go | 6 +- planner/sum.go | 15 +-- query/graphql/parser.go | 11 +- query/graphql/parser/commit.go | 22 ++-- query/graphql/parser/filter.go | 50 ++++---- query/graphql/parser/mutation.go | 6 +- query/graphql/parser/query.go | 40 +++--- .../inline_array/update/simple_test.go | 51 ++++---- .../query/inline_array/simple_test.go | 49 ++++---- 44 files changed, 242 insertions(+), 737 deletions(-) delete mode 100644 immutables/doc.go delete mode 100644 immutables/enumerable/concat.go delete mode 100644 immutables/enumerable/enumerable.go delete mode 100644 immutables/enumerable/select.go delete mode 100644 immutables/enumerable/skip.go delete mode 100644 immutables/enumerable/sort.go delete mode 100644 immutables/enumerable/take.go delete mode 100644 immutables/enumerable/where.go delete mode 100644 immutables/option.go diff --git a/api/http/handlerfuncs.go b/api/http/handlerfuncs.go index e12fc59153..ab6b9a85ad 100644 --- a/api/http/handlerfuncs.go +++ b/api/http/handlerfuncs.go @@ -25,7 +25,6 @@ import ( "github.com/multiformats/go-multihash" "github.com/pkg/errors" - "github.com/sourcenetwork/defradb/client" corecrdt "github.com/sourcenetwork/defradb/core/crdt" "github.com/sourcenetwork/defradb/events" ) @@ -266,7 +265,7 @@ func peerIDHandler(rw http.ResponseWriter, req *http.Request) { ) } -func subscriptionHandler(pub *events.Publisher[client.UpdateEvent], rw http.ResponseWriter, req *http.Request) { +func subscriptionHandler(pub *events.Publisher[events.Update], rw http.ResponseWriter, req *http.Request) { flusher, ok := rw.(http.Flusher) if !ok { handleErr(req.Context(), rw, errors.New("streaming unsupported"), http.StatusInternalServerError) diff --git a/api/http/server.go b/api/http/server.go index 1f4239d44a..52fa35ed3b 100644 --- a/api/http/server.go +++ b/api/http/server.go @@ -19,11 +19,11 @@ import ( "path" "strings" + "github.com/sourcenetwork/immutable" "golang.org/x/crypto/acme/autocert" "github.com/sourcenetwork/defradb/client" "github.com/sourcenetwork/defradb/errors" - "github.com/sourcenetwork/defradb/immutables" "github.com/sourcenetwork/defradb/logging" ) @@ -56,7 +56,7 @@ type serverOptions struct { // ID of the server node. peerID string // when the value is present, the server will run with tls - tls immutables.Option[tlsOptions] + tls immutable.Option[tlsOptions] // root directory for the node config. rootDir string } @@ -133,7 +133,7 @@ func WithAddress(addr string) func(*Server) { if ip == nil { tlsOpt := s.options.tls.Value() tlsOpt.domain = addr - s.options.tls = immutables.Some(tlsOpt) + s.options.tls = immutable.Some(tlsOpt) } } } @@ -143,7 +143,7 @@ func WithCAEmail(email string) func(*Server) { return func(s *Server) { tlsOpt := s.options.tls.Value() tlsOpt.email = email - s.options.tls = immutables.Some(tlsOpt) + s.options.tls = immutable.Some(tlsOpt) } } @@ -164,7 +164,7 @@ func WithSelfSignedCert(pubKey, privKey string) func(*Server) { tlsOpt := s.options.tls.Value() tlsOpt.pubKey = pubKey tlsOpt.privKey = privKey - s.options.tls = immutables.Some(tlsOpt) + s.options.tls = immutable.Some(tlsOpt) } } @@ -172,7 +172,7 @@ func WithTLSPort(port int) func(*Server) { return func(s *Server) { tlsOpt := s.options.tls.Value() tlsOpt.port = fmt.Sprintf(":%d", port) - s.options.tls = immutables.Some(tlsOpt) + s.options.tls = immutable.Some(tlsOpt) } } diff --git a/client/db.go b/client/db.go index 8fd9357294..356652d99d 100644 --- a/client/db.go +++ b/client/db.go @@ -48,5 +48,5 @@ type GQLResult struct { type QueryResult struct { GQL GQLResult - Pub *events.Publisher[UpdateEvent] + Pub *events.Publisher[events.Update] } diff --git a/client/request/aggregate.go b/client/request/aggregate.go index 6607afd7ce..902134b258 100644 --- a/client/request/aggregate.go +++ b/client/request/aggregate.go @@ -10,7 +10,7 @@ package request -import "github.com/sourcenetwork/defradb/immutables" +import immutables "github.com/sourcenetwork/immutable" type Aggregate struct { Field diff --git a/client/request/commit.go b/client/request/commit.go index e0290c8044..d8da5e8c43 100644 --- a/client/request/commit.go +++ b/client/request/commit.go @@ -10,7 +10,7 @@ package request -import "github.com/sourcenetwork/defradb/immutables" +import "github.com/sourcenetwork/immutable" var ( _ Selection = (*CommitSelect)(nil) @@ -19,15 +19,15 @@ var ( type CommitSelect struct { Field - DocKey immutables.Option[string] - FieldName immutables.Option[string] - Cid immutables.Option[string] - Depth immutables.Option[uint64] + DocKey immutable.Option[string] + FieldName immutable.Option[string] + Cid immutable.Option[string] + Depth immutable.Option[uint64] - Limit immutables.Option[uint64] - Offset immutables.Option[uint64] - OrderBy immutables.Option[OrderBy] - GroupBy immutables.Option[GroupBy] + Limit immutable.Option[uint64] + Offset immutable.Option[uint64] + OrderBy immutable.Option[OrderBy] + GroupBy immutable.Option[GroupBy] Fields []Selection } diff --git a/client/request/field.go b/client/request/field.go index 3d67decb77..578074671b 100644 --- a/client/request/field.go +++ b/client/request/field.go @@ -10,10 +10,10 @@ package request -import "github.com/sourcenetwork/defradb/immutables" +import "github.com/sourcenetwork/immutable" // Field implements Selection type Field struct { Name string - Alias immutables.Option[string] + Alias immutable.Option[string] } diff --git a/client/request/mutation.go b/client/request/mutation.go index 943eefa366..6767f22871 100644 --- a/client/request/mutation.go +++ b/client/request/mutation.go @@ -10,7 +10,7 @@ package request -import "github.com/sourcenetwork/defradb/immutables" +import "github.com/sourcenetwork/immutable" type MutationType int @@ -35,8 +35,8 @@ type Mutation struct { // if this mutation is on an object. Collection string - IDs immutables.Option[[]string] - Filter immutables.Option[Filter] + IDs immutable.Option[[]string] + Filter immutable.Option[Filter] Data string Fields []Selection diff --git a/client/request/select.go b/client/request/select.go index dd85eef71e..9898dbc83b 100644 --- a/client/request/select.go +++ b/client/request/select.go @@ -11,8 +11,9 @@ package request import ( + "github.com/sourcenetwork/immutable" + "github.com/sourcenetwork/defradb/client" - "github.com/sourcenetwork/defradb/immutables" ) type SelectionType int @@ -29,17 +30,17 @@ const ( type Select struct { Field - DocKeys immutables.Option[[]string] - CID immutables.Option[string] + DocKeys immutable.Option[[]string] + CID immutable.Option[string] // Root is the top level query parsed type Root SelectionType - Limit immutables.Option[uint64] - Offset immutables.Option[uint64] - OrderBy immutables.Option[OrderBy] - GroupBy immutables.Option[GroupBy] - Filter immutables.Option[Filter] + Limit immutable.Option[uint64] + Offset immutable.Option[uint64] + OrderBy immutable.Option[OrderBy] + GroupBy immutable.Option[GroupBy] + Filter immutable.Option[Filter] Fields []Selection } diff --git a/client/request/subscription.go b/client/request/subscription.go index bdc2afbdc9..d8361b3896 100644 --- a/client/request/subscription.go +++ b/client/request/subscription.go @@ -11,7 +11,7 @@ package request import ( - "github.com/sourcenetwork/defradb/client" + "github.com/sourcenetwork/immutable" ) // ObjectSubscription is a field on the SubscriptionType @@ -23,7 +23,7 @@ type ObjectSubscription struct { // Collection is the target collection name Collection string - Filter client.Option[Filter] + Filter immutable.Option[Filter] Fields []Selection } @@ -36,8 +36,8 @@ func (m ObjectSubscription) ToSelect(docKey, cid string) *Select { Name: m.Collection, Alias: m.Alias, }, - DocKeys: client.Some([]string{docKey}), - CID: client.Some(cid), + DocKeys: immutable.Some([]string{docKey}), + CID: immutable.Some(cid), Fields: m.Fields, Filter: m.Filter, } diff --git a/connor/eq.go b/connor/eq.go index d02944add9..f28824de1d 100644 --- a/connor/eq.go +++ b/connor/eq.go @@ -4,10 +4,11 @@ import ( "reflect" "time" + "github.com/sourcenetwork/immutable" + "github.com/sourcenetwork/defradb/connor/numbers" ctime "github.com/sourcenetwork/defradb/connor/time" "github.com/sourcenetwork/defradb/core" - "github.com/sourcenetwork/defradb/immutables" ) // eq is an operator which performs object equality @@ -27,25 +28,25 @@ func eq(condition, data any) (bool, error) { } return false, nil - case immutables.Option[bool]: + case immutable.Option[bool]: if !arr.HasValue() { return condition == nil, nil } data = arr.Value() - case immutables.Option[int64]: + case immutable.Option[int64]: if !arr.HasValue() { return condition == nil, nil } data = arr.Value() - case immutables.Option[float64]: + case immutable.Option[float64]: if !arr.HasValue() { return condition == nil, nil } data = arr.Value() - case immutables.Option[string]: + case immutable.Option[string]: if !arr.HasValue() { return condition == nil, nil } diff --git a/core/doc.go b/core/doc.go index 12ef172ae4..f1c31592e4 100644 --- a/core/doc.go +++ b/core/doc.go @@ -14,8 +14,9 @@ Package core provides commonly shared interfaces and building blocks. package core import ( + "github.com/sourcenetwork/immutable" + "github.com/sourcenetwork/defradb/client/request" - "github.com/sourcenetwork/defradb/immutables" ) const DocKeyFieldIndex int = 0 @@ -86,7 +87,7 @@ type mappingTypeInfo struct { type DocumentMapping struct { // The type information for the object, if provided. - typeInfo immutables.Option[mappingTypeInfo] + typeInfo immutable.Option[mappingTypeInfo] // The set of fields that should be rendered. // @@ -230,7 +231,7 @@ func (mapping *DocumentMapping) Add(index int, name string) { func (mapping *DocumentMapping) SetTypeName(typeName string) { index := mapping.GetNextIndex() mapping.Add(index, request.TypeNameFieldName) - mapping.typeInfo = immutables.Some(mappingTypeInfo{ + mapping.typeInfo = immutable.Some(mappingTypeInfo{ Index: index, Name: typeName, }) diff --git a/core/parser.go b/core/parser.go index bf895d5ce7..fd04db1db1 100644 --- a/core/parser.go +++ b/core/parser.go @@ -13,6 +13,8 @@ package core import ( "context" + "github.com/sourcenetwork/immutable" + "github.com/sourcenetwork/defradb/client" "github.com/sourcenetwork/defradb/client/request" ) @@ -40,7 +42,7 @@ type Parser interface { Parse(request string) (*request.Request, []error) // NewFilterFromString creates a new filter from a string. - NewFilterFromString(collectionType string, body string) (client.Option[request.Filter], error) + NewFilterFromString(collectionType string, body string) (immutable.Option[request.Filter], error) // Adds the given schema to this parser's model. AddSchema(ctx context.Context, schema string) error diff --git a/db/collection_update.go b/db/collection_update.go index 8d49a597c3..20c556c503 100644 --- a/db/collection_update.go +++ b/db/collection_update.go @@ -15,6 +15,7 @@ import ( "strings" cbor "github.com/fxamacker/cbor/v2" + "github.com/sourcenetwork/immutable" "github.com/valyala/fastjson" "github.com/sourcenetwork/defradb/client" @@ -23,7 +24,6 @@ import ( "github.com/sourcenetwork/defradb/datastore" "github.com/sourcenetwork/defradb/errors" "github.com/sourcenetwork/defradb/events" - "github.com/sourcenetwork/defradb/immutables" "github.com/sourcenetwork/defradb/planner" ) @@ -594,7 +594,7 @@ func (c *collection) makeSelectionQuery( txn datastore.Txn, filter any, ) (planner.Query, error) { - var f immutables.Option[request.Filter] + var f immutable.Option[request.Filter] var err error switch fval := filter.(type) { case string: @@ -606,7 +606,7 @@ func (c *collection) makeSelectionQuery( if err != nil { return nil, err } - case immutables.Option[request.Filter]: + case immutable.Option[request.Filter]: f = fval default: return nil, errors.New("invalid filter") @@ -631,7 +631,7 @@ func (c *collection) makeSelectionQuery( }) } -func (c *collection) makeSelectLocal(filter immutables.Option[request.Filter]) (*request.Select, error) { +func (c *collection) makeSelectLocal(filter immutable.Option[request.Filter]) (*request.Select, error) { slct := &request.Select{ Field: request.Field{ Name: c.Name(), diff --git a/db/db.go b/db/db.go index 29497ca0f3..d3fddb6641 100644 --- a/db/db.go +++ b/db/db.go @@ -19,16 +19,15 @@ import ( "sync" ds "github.com/ipfs/go-datastore" - "github.com/ipfs/go-datastore/query" dsq "github.com/ipfs/go-datastore/query" blockstore "github.com/ipfs/go-ipfs-blockstore" + "github.com/sourcenetwork/immutable" "github.com/sourcenetwork/defradb/client" "github.com/sourcenetwork/defradb/core" "github.com/sourcenetwork/defradb/datastore" "github.com/sourcenetwork/defradb/errors" "github.com/sourcenetwork/defradb/events" - "github.com/sourcenetwork/defradb/immutables" "github.com/sourcenetwork/defradb/logging" "github.com/sourcenetwork/defradb/merkle/crdt" "github.com/sourcenetwork/defradb/query/graphql" @@ -75,7 +74,7 @@ const updateEventBufferSize = 100 func WithUpdateEvents() Option { return func(db *db) { db.events = events.Events{ - Updates: immutables.Some(events.New[events.Update](0, updateEventBufferSize)), + Updates: immutable.Some(events.New[events.Update](0, updateEventBufferSize)), } } } @@ -197,7 +196,7 @@ func (db *db) Close(ctx context.Context) { } func printStore(ctx context.Context, store datastore.DSReaderWriter) error { - q := query.Query{ + q := dsq.Query{ Prefix: "", KeysOnly: false, Orders: []dsq.Order{dsq.OrderByKey{}}, diff --git a/db/fetcher/dag.go b/db/fetcher/dag.go index e8b39a9682..53cfd1452f 100644 --- a/db/fetcher/dag.go +++ b/db/fetcher/dag.go @@ -17,17 +17,17 @@ import ( "github.com/ipfs/go-cid" dsq "github.com/ipfs/go-datastore/query" + "github.com/sourcenetwork/immutable" "github.com/sourcenetwork/defradb/core" "github.com/sourcenetwork/defradb/datastore" - "github.com/sourcenetwork/defradb/immutables" ) // HeadFetcher is a utility to incrementally fetch all the MerkleCRDT // heads of a given doc/field type HeadFetcher struct { spans core.Spans - fieldId immutables.Option[string] + fieldId immutable.Option[string] kvIter dsq.Results } @@ -36,7 +36,7 @@ func (hf *HeadFetcher) Start( ctx context.Context, txn datastore.Txn, spans core.Spans, - fieldId immutables.Option[string], + fieldId immutable.Option[string], ) error { if len(spans.Value) == 0 { spans = core.NewSpans( diff --git a/db/fetcher/encoded_doc.go b/db/fetcher/encoded_doc.go index 54aede3f29..c75ce3ac53 100644 --- a/db/fetcher/encoded_doc.go +++ b/db/fetcher/encoded_doc.go @@ -14,11 +14,11 @@ import ( "fmt" "github.com/fxamacker/cbor/v2" + "github.com/sourcenetwork/immutable" "github.com/sourcenetwork/defradb/client" "github.com/sourcenetwork/defradb/core" "github.com/sourcenetwork/defradb/errors" - "github.com/sourcenetwork/defradb/immutables" ) type EPTuple []encProperty @@ -140,11 +140,11 @@ func (e encProperty) Decode() (client.CType, any, error) { return ctype, val, nil } -func convertNillableArray[T any](items []any) ([]immutables.Option[T], error) { - resultArray := make([]immutables.Option[T], len(items)) +func convertNillableArray[T any](items []any) ([]immutable.Option[T], error) { + resultArray := make([]immutable.Option[T], len(items)) for i, untypedValue := range items { if untypedValue == nil { - resultArray[i] = immutables.None[T]() + resultArray[i] = immutable.None[T]() continue } value, ok := untypedValue.(T) @@ -156,7 +156,7 @@ func convertNillableArray[T any](items []any) ([]immutables.Option[T], error) { *new(T), )) } - resultArray[i] = immutables.Some(value) + resultArray[i] = immutable.Some(value) } return resultArray, nil } @@ -164,18 +164,18 @@ func convertNillableArray[T any](items []any) ([]immutables.Option[T], error) { func convertNillableArrayWithConverter[TOut any]( items []any, converter func(in any) (TOut, error), -) ([]immutables.Option[TOut], error) { - resultArray := make([]immutables.Option[TOut], len(items)) +) ([]immutable.Option[TOut], error) { + resultArray := make([]immutable.Option[TOut], len(items)) for i, untypedValue := range items { if untypedValue == nil { - resultArray[i] = immutables.None[TOut]() + resultArray[i] = immutable.None[TOut]() continue } value, err := converter(untypedValue) if err != nil { return nil, err } - resultArray[i] = immutables.Some(value) + resultArray[i] = immutable.Some(value) } return resultArray, nil } diff --git a/db/subscriptions.go b/db/subscriptions.go index 5012fcc911..c555638cb9 100644 --- a/db/subscriptions.go +++ b/db/subscriptions.go @@ -20,7 +20,7 @@ import ( ) func (db *db) checkForClientSubsciptions(r *request.Request) ( - *events.Publisher[client.UpdateEvent], + *events.Publisher[events.Update], *request.ObjectSubscription, error, ) { @@ -46,7 +46,7 @@ func (db *db) checkForClientSubsciptions(r *request.Request) ( func (db *db) handleSubscription( ctx context.Context, - pub *events.Publisher[client.UpdateEvent], + pub *events.Publisher[events.Update], r *request.ObjectSubscription, ) { for evt := range pub.Event() { diff --git a/events/db_update.go b/events/db_update.go index 79de5f1efd..0ae2e9f059 100644 --- a/events/db_update.go +++ b/events/db_update.go @@ -13,13 +13,12 @@ package events import ( "github.com/ipfs/go-cid" ipld "github.com/ipfs/go-ipld-format" - - "github.com/sourcenetwork/defradb/immutables" + "github.com/sourcenetwork/immutable" ) -type UpdateChannel = immutables.Option[Channel[Update]] +type UpdateChannel = immutable.Option[Channel[Update]] -var EmptyUpdateChannel = immutables.None[Channel[Update]]() +var EmptyUpdateChannel = immutable.None[Channel[Update]]() // UpdateEvent represents a new DAG node added to the // append-only MerkleCRDT Clock graph of a diff --git a/go.mod b/go.mod index cf12aae3a9..f563760554 100644 --- a/go.mod +++ b/go.mod @@ -38,6 +38,7 @@ require ( github.com/multiformats/go-varint v0.0.6 github.com/pkg/errors v0.9.1 github.com/satori/go.uuid v1.2.0 + github.com/sourcenetwork/immutable v0.2.1 github.com/spf13/cobra v1.4.0 github.com/spf13/viper v1.11.0 github.com/stretchr/testify v1.8.0 diff --git a/go.sum b/go.sum index bca9742317..066098508e 100644 --- a/go.sum +++ b/go.sum @@ -1223,6 +1223,8 @@ github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:Udh github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/sourcenetwork/graphql-go v0.7.10-0.20221119101706-0f80a1725ab7 h1:9v7Ld9hS60HAcw/ID/yierzEjtAwkenr/5i6rGSmiXI= github.com/sourcenetwork/graphql-go v0.7.10-0.20221119101706-0f80a1725ab7/go.mod h1:3Ty9EMes+aoxl8xS0CsuCGQZ4JEsOlC5yqQDLOKoBRw= +github.com/sourcenetwork/immutable v0.2.1 h1:0SAnoiGm1XQG+xiG4gK4nmLFqTMRnQ5Y1N4WHL7vQtE= +github.com/sourcenetwork/immutable v0.2.1/go.mod h1:4jpxObkIQw8pvlIRm4ndZqf3pH9ZjYEw/UYI6GZDJww= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= diff --git a/immutables/doc.go b/immutables/doc.go deleted file mode 100644 index 281004b187..0000000000 --- a/immutables/doc.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2022 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 immutables provides immutable types. -*/ -package immutables diff --git a/immutables/enumerable/concat.go b/immutables/enumerable/concat.go deleted file mode 100644 index 309c6019dd..0000000000 --- a/immutables/enumerable/concat.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2022 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 enumerable - -type enumerableConcat[T any] struct { - sources []Enumerable[T] - currentSourceIndex int -} - -// Concat takes zero to many source `Ènumerable`s and stacks them on top -// of each other, resulting in one enumerable that will iterate through all -// the values in all of the given sources. -func Concat[T any](sources ...Enumerable[T]) Enumerable[T] { - return &enumerableConcat[T]{ - sources: sources, - currentSourceIndex: 0, - } -} - -func (s *enumerableConcat[T]) Next() (bool, error) { - for { - if s.currentSourceIndex >= len(s.sources) { - return false, nil - } - - currentSource := s.sources[s.currentSourceIndex] - hasValue, err := currentSource.Next() - if err != nil { - return false, nil - } - if hasValue { - return true, nil - } - - s.currentSourceIndex += 1 - } -} - -func (s *enumerableConcat[T]) Value() T { - return s.sources[s.currentSourceIndex].Value() -} - -func (s *enumerableConcat[T]) Reset() { - s.currentSourceIndex = 0 - for _, source := range s.sources { - source.Reset() - } -} diff --git a/immutables/enumerable/enumerable.go b/immutables/enumerable/enumerable.go deleted file mode 100644 index 065e93f5ed..0000000000 --- a/immutables/enumerable/enumerable.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2022 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 enumerable - -// Enumerable represents a set of elements that can be iterated through -// multiple times. -// -// The enumerable may be a composite of multiple actions that will be lazily -// executed upon iteration, allowing the enumerable to be constructed out of a -// complex set of instructions that can be evaluated in a single iteration of the -// underlying set. -type Enumerable[T any] interface { - // Next attempts to evaluate the next item in the enumeration - allowing its - // exposure via the `Value()` function. - // - // It will return false if it has reached the end of the enumerable, and/or an - // error if one was generated during evaluation. - Next() (bool, error) - - // Value returns the current item in the enumeration. It does not progress the - // enumeration, and should be a simple getter. - // - // If the previous Next call did not return true, or Next has never been called - // the behaviour and return value of this function is undefined. - Value() T - - // Reset resets the enumerable, allowing for re-iteration. - Reset() -} - -type enumerableSlice[T any] struct { - source []T - currentIndex int - maxIndex int -} - -// New creates an `Enumerable` from the given slice. -func New[T any](source []T) Enumerable[T] { - return &enumerableSlice[T]{ - source: source, - currentIndex: -1, - maxIndex: len(source) - 1, - } -} - -func (s *enumerableSlice[T]) Next() (bool, error) { - if s.currentIndex == s.maxIndex { - return false, nil - } - s.currentIndex += 1 - return true, nil -} - -func (s *enumerableSlice[T]) Value() T { - return s.source[s.currentIndex] -} - -func (s *enumerableSlice[T]) Reset() { - s.currentIndex = -1 -} - -// ForEach iterates over the given source `Enumerable` performing the given -// action on each item. It resets the source `Enumerable` on completion. -func ForEach[T any](source Enumerable[T], action func(item T)) error { - for { - hasNext, err := source.Next() - if err != nil { - return err - } - if !hasNext { - break - } - item := source.Value() - action(item) - } - source.Reset() - return nil -} - -// OnEach iterates over the given source `Enumerable` performing the given -// action for each item yielded. It resets the source `Enumerable` on completion. -func OnEach[T any](source Enumerable[T], action func()) error { - for { - hasNext, err := source.Next() - if err != nil { - return err - } - if !hasNext { - break - } - action() - } - source.Reset() - return nil -} - -// TryGetFirst returns the first element yielded from the given source along with true. -// If no items are yielded by the source, then false with be returned. Any errors generated -// during enumeration will be yielded instead of a value. -func TryGetFirst[T any](source Enumerable[T]) (T, bool, error) { - hasNext, err := source.Next() - if err != nil || !hasNext { - var defaultV T - return defaultV, false, err - } - return source.Value(), true, nil -} diff --git a/immutables/enumerable/select.go b/immutables/enumerable/select.go deleted file mode 100644 index a946887ee1..0000000000 --- a/immutables/enumerable/select.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2022 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 enumerable - -type enumerableSelect[TSource any, TResult any] struct { - source Enumerable[TSource] - selector func(TSource) (TResult, error) - currentValue TResult -} - -// Select creates a new `Enumerable` that iterates through each item -// yielded by the given source and then yields the value returned by -// the given selector. -func Select[TSource any, TResult any]( - source Enumerable[TSource], - selector func(TSource) (TResult, error), -) Enumerable[TResult] { - return &enumerableSelect[TSource, TResult]{ - source: source, - selector: selector, - } -} - -func (s *enumerableSelect[TSource, TResult]) Next() (bool, error) { - hasNext, err := s.source.Next() - if !hasNext || err != nil { - return hasNext, err - } - - value := s.source.Value() - // We do this here to keep the work (and errors) in the `Next` call - result, err := s.selector(value) - if err != nil { - return false, nil - } - - s.currentValue = result - return true, nil -} - -func (s *enumerableSelect[TSource, TResult]) Value() TResult { - return s.currentValue -} - -func (s *enumerableSelect[TSource, TResult]) Reset() { - s.source.Reset() -} diff --git a/immutables/enumerable/skip.go b/immutables/enumerable/skip.go deleted file mode 100644 index 2ad62d3af0..0000000000 --- a/immutables/enumerable/skip.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2022 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 enumerable - -type enumerableSkip[T any] struct { - source Enumerable[T] - offset uint64 - count uint64 -} - -// Skip creates an `Enumerable` from the given `Enumerable` and offset. The returned -// `Enumerable` will skip through items until the number of items yielded from source -// excedes the give offset. -func Skip[T any](source Enumerable[T], offset uint64) Enumerable[T] { - return &enumerableSkip[T]{ - source: source, - offset: offset, - } -} - -func (s *enumerableSkip[T]) Next() (bool, error) { - for s.count < s.offset { - s.count += 1 - hasNext, err := s.source.Next() - if !hasNext || err != nil { - return hasNext, err - } - } - s.count += 1 - return s.source.Next() -} - -func (s *enumerableSkip[T]) Value() T { - return s.source.Value() -} - -func (s *enumerableSkip[T]) Reset() { - s.count = 0 - s.source.Reset() -} diff --git a/immutables/enumerable/sort.go b/immutables/enumerable/sort.go deleted file mode 100644 index c3428127d6..0000000000 --- a/immutables/enumerable/sort.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2022 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 enumerable - -import "sort" - -type enumerableSort[T any] struct { - source Enumerable[T] - less func(T, T) bool - capacity int - result Enumerable[T] -} - -// Sort creates an `Enumerable` from the given `Enumerable`, using the given -// less function to determine as to whether an item is less than the other in -// in terms of order. -// -// The returned `Enumerable` will enumerate the entire source -// enumerable on the first `Next` call, but will not enumerate it again unless -// reset. -func Sort[T any](source Enumerable[T], less func(T, T) bool, capacity int) Enumerable[T] { - return &enumerableSort[T]{ - source: source, - less: less, - capacity: capacity, - } -} - -func (s *enumerableSort[T]) Next() (bool, error) { - if s.result == nil { - result := make([]T, 0, s.capacity) - // Declaring an anonymous function costs, so we do it here outside of the loop - // even though it is slightly less intuitive - f := func(i int) bool { - return !s.less(result[i], s.source.Value()) - } - - for i := 0; i <= s.capacity; i++ { - hasNext, err := s.source.Next() - if err != nil { - return false, err - } - if !hasNext { - break - } - - previousLength := len(result) - indexOfFirstGreaterValue := sort.Search(previousLength, f) - value := s.source.Value() - result = append(result, value) - if indexOfFirstGreaterValue == previousLength { - // Value is the greatest, and belongs at the end - continue - } - // Shift all items to the right of the first element of greater value by - // one place. This call should not allocate. - copy(result[indexOfFirstGreaterValue+1:], result[indexOfFirstGreaterValue:]) - result[indexOfFirstGreaterValue] = value - } - - // Use the enumerableSlice for convienience - s.result = New(result) - } - - return s.result.Next() -} - -func (s *enumerableSort[T]) Value() T { - return s.result.Value() -} - -func (s *enumerableSort[T]) Reset() { - // s.result should be cleared, not reset, as Reset should - // enable the re-enumeration of the entire enumeration chain, - // not just the last step. - s.result = nil - s.source.Reset() -} diff --git a/immutables/enumerable/take.go b/immutables/enumerable/take.go deleted file mode 100644 index d9fdb51380..0000000000 --- a/immutables/enumerable/take.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2022 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 enumerable - -type enumerableTake[T any] struct { - source Enumerable[T] - limit uint64 - count uint64 -} - -// Take creates an `Enumerable` from the given `Enumerable` and limit. The returned -// `Enumerable` will restrict the maximum number of items yielded to the given limit. -func Take[T any](source Enumerable[T], limit uint64) Enumerable[T] { - return &enumerableTake[T]{ - source: source, - limit: limit, - } -} - -func (s *enumerableTake[T]) Next() (bool, error) { - if s.count == s.limit { - return false, nil - } - s.count += 1 - return s.source.Next() -} - -func (s *enumerableTake[T]) Value() T { - return s.source.Value() -} - -func (s *enumerableTake[T]) Reset() { - s.count = 0 - s.source.Reset() -} diff --git a/immutables/enumerable/where.go b/immutables/enumerable/where.go deleted file mode 100644 index 43b523153e..0000000000 --- a/immutables/enumerable/where.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2022 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 enumerable - -type enumerableWhere[T any] struct { - source Enumerable[T] - predicate func(T) (bool, error) -} - -// Where creates an `Enumerable` from the given `Enumerable` and predicate. Items in the -// source `Enumerable` must return true when passed into the predicate in order to be yielded -// from the returned `Enumerable`. -func Where[T any](source Enumerable[T], predicate func(T) (bool, error)) Enumerable[T] { - return &enumerableWhere[T]{ - source: source, - predicate: predicate, - } -} - -func (s *enumerableWhere[T]) Next() (bool, error) { - for { - hasNext, err := s.source.Next() - if !hasNext || err != nil { - return hasNext, err - } - - value := s.source.Value() - if passes, err := s.predicate(value); passes || err != nil { - return passes, err - } - } -} - -func (s *enumerableWhere[T]) Value() T { - return s.source.Value() -} - -func (s *enumerableWhere[T]) Reset() { - s.source.Reset() -} diff --git a/immutables/option.go b/immutables/option.go deleted file mode 100644 index 8d5fa29f39..0000000000 --- a/immutables/option.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2022 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 immutables - -// Option represents an item that may or may not have a value. -type Option[T any] struct { - // If HasValue is true, this Option contains a value, if - // it is false it contains no value. - hasValue bool - - // The Value of this Option. Should be ignored if HasValue is false. - value T -} - -// Some returns an `Option` of type `T` with the given value. -func Some[T any](value T) Option[T] { - return Option[T]{ - hasValue: true, - value: value, - } -} - -// Some returns an `Option` of type `T` with no value. -func None[T any]() Option[T] { - return Option[T]{} -} - -// HasValue returns a boolean indicating whether or not this optino contains a value. If -// it returns true, this Option contains a value, if it is false it contains no value. -func (o Option[T]) HasValue() bool { - return o.hasValue -} - -// Value returns the Value of this Option. Value returned is invalid HasValue() is false -// and should be ignored. -func (o Option[T]) Value() T { - return o.value -} diff --git a/merkle/crdt/factory_test.go b/merkle/crdt/factory_test.go index 0cadfdb1bb..6445f2de8c 100644 --- a/merkle/crdt/factory_test.go +++ b/merkle/crdt/factory_test.go @@ -20,6 +20,7 @@ import ( "github.com/sourcenetwork/defradb/client" "github.com/sourcenetwork/defradb/core" "github.com/sourcenetwork/defradb/datastore" + "github.com/sourcenetwork/defradb/events" ) func newStores() datastore.MultiStore { @@ -127,7 +128,7 @@ func TestFactoryInstanceMissing(t *testing.T) { m := newStores() f := NewFactory(m) - _, err := f.Instance("", client.EmptyUpdateChannel, client.LWW_REGISTER, core.MustNewDataStoreKey("/1/0/MyKey")) + _, err := f.Instance("", events.EmptyUpdateChannel, client.LWW_REGISTER, core.MustNewDataStoreKey("/1/0/MyKey")) assert.Equal(t, err, ErrFactoryTypeNoExist) } @@ -137,7 +138,7 @@ func TestBlankFactoryInstanceWithLWWRegister(t *testing.T) { f1.Register(client.LWW_REGISTER, &lwwFactoryFn) f := f1.WithStores(m) - crdt, err := f.Instance("", client.EmptyUpdateChannel, client.LWW_REGISTER, core.MustNewDataStoreKey("/1/0/MyKey")) + crdt, err := f.Instance("", events.EmptyUpdateChannel, client.LWW_REGISTER, core.MustNewDataStoreKey("/1/0/MyKey")) assert.NoError(t, err) _, ok := crdt.(*MerkleLWWRegister) @@ -150,7 +151,7 @@ func TestBlankFactoryInstanceWithCompositeRegister(t *testing.T) { f1.Register(client.COMPOSITE, &compFactoryFn) f := f1.WithStores(m) - crdt, err := f.Instance("", client.EmptyUpdateChannel, client.COMPOSITE, core.MustNewDataStoreKey("/1/0/MyKey")) + crdt, err := f.Instance("", events.EmptyUpdateChannel, client.COMPOSITE, core.MustNewDataStoreKey("/1/0/MyKey")) assert.NoError(t, err) _, ok := crdt.(*MerkleCompositeDAG) @@ -162,7 +163,7 @@ func TestFullFactoryInstanceLWWRegister(t *testing.T) { f := NewFactory(m) f.Register(client.LWW_REGISTER, &lwwFactoryFn) - crdt, err := f.Instance("", client.EmptyUpdateChannel, client.LWW_REGISTER, core.MustNewDataStoreKey("/1/0/MyKey")) + crdt, err := f.Instance("", events.EmptyUpdateChannel, client.LWW_REGISTER, core.MustNewDataStoreKey("/1/0/MyKey")) assert.NoError(t, err) _, ok := crdt.(*MerkleLWWRegister) @@ -174,7 +175,7 @@ func TestFullFactoryInstanceCompositeRegister(t *testing.T) { f := NewFactory(m) f.Register(client.COMPOSITE, &compFactoryFn) - crdt, err := f.Instance("", client.EmptyUpdateChannel, client.COMPOSITE, core.MustNewDataStoreKey("/1/0/MyKey")) + crdt, err := f.Instance("", events.EmptyUpdateChannel, client.COMPOSITE, core.MustNewDataStoreKey("/1/0/MyKey")) assert.NoError(t, err) _, ok := crdt.(*MerkleCompositeDAG) @@ -185,7 +186,7 @@ func TestLWWRegisterFactoryFn(t *testing.T) { ctx := context.Background() m := newStores() f := NewFactory(m) // here factory is only needed to satisfy datastore.MultiStore interface - crdt := lwwFactoryFn(f, "", client.EmptyUpdateChannel)(core.MustNewDataStoreKey("/1/0/MyKey")) + crdt := lwwFactoryFn(f, "", events.EmptyUpdateChannel)(core.MustNewDataStoreKey("/1/0/MyKey")) lwwreg, ok := crdt.(*MerkleLWWRegister) assert.True(t, ok) @@ -198,7 +199,7 @@ func TestCompositeRegisterFactoryFn(t *testing.T) { ctx := context.Background() m := newStores() f := NewFactory(m) // here factory is only needed to satisfy datastore.MultiStore interface - crdt := compFactoryFn(f, "", client.EmptyUpdateChannel)(core.MustNewDataStoreKey("/1/0/MyKey")) + crdt := compFactoryFn(f, "", events.EmptyUpdateChannel)(core.MustNewDataStoreKey("/1/0/MyKey")) merkleReg, ok := crdt.(*MerkleCompositeDAG) assert.True(t, ok) diff --git a/planner/count.go b/planner/count.go index 3a1df0d58a..cf3acd3c38 100644 --- a/planner/count.go +++ b/planner/count.go @@ -17,9 +17,10 @@ package planner import ( "reflect" + "github.com/sourcenetwork/immutable" + "github.com/sourcenetwork/immutable/enumerable" + "github.com/sourcenetwork/defradb/core" - "github.com/sourcenetwork/defradb/immutables" - "github.com/sourcenetwork/defradb/immutables/enumerable" "github.com/sourcenetwork/defradb/planner/mapper" ) @@ -112,25 +113,25 @@ func (n *countNode) Next() (bool, error) { case []bool: arrayCount, err = countItems(array, source.Filter, source.Limit) - case []immutables.Option[bool]: + case []immutable.Option[bool]: arrayCount, err = countItems(array, source.Filter, source.Limit) case []int64: arrayCount, err = countItems(array, source.Filter, source.Limit) - case []immutables.Option[int64]: + case []immutable.Option[int64]: arrayCount, err = countItems(array, source.Filter, source.Limit) case []float64: arrayCount, err = countItems(array, source.Filter, source.Limit) - case []immutables.Option[float64]: + case []immutable.Option[float64]: arrayCount, err = countItems(array, source.Filter, source.Limit) case []string: arrayCount, err = countItems(array, source.Filter, source.Limit) - case []immutables.Option[string]: + case []immutable.Option[string]: arrayCount, err = countItems(array, source.Filter, source.Limit) } if err != nil { diff --git a/planner/mapper/commitSelect.go b/planner/mapper/commitSelect.go index 13cb5efad6..c4190eb272 100644 --- a/planner/mapper/commitSelect.go +++ b/planner/mapper/commitSelect.go @@ -10,7 +10,7 @@ package mapper -import "github.com/sourcenetwork/defradb/immutables" +import "github.com/sourcenetwork/immutable" // CommitSelect represents a commit request from a consumer. // @@ -20,16 +20,16 @@ type CommitSelect struct { Select // The key of the target document for which to get commits for. - DocKey immutables.Option[string] + DocKey immutable.Option[string] // The field for which commits have been requested. - FieldName immutables.Option[string] + FieldName immutable.Option[string] // The maximum depth to yield results for. - Depth immutables.Option[uint64] + Depth immutable.Option[uint64] // The parent Cid for which commit information has been requested. - Cid immutables.Option[string] + Cid immutable.Option[string] } func (s *CommitSelect) CloneTo(index int) Requestable { diff --git a/planner/mapper/mapper.go b/planner/mapper/mapper.go index f096e00a01..ee5e6c9ab1 100644 --- a/planner/mapper/mapper.go +++ b/planner/mapper/mapper.go @@ -16,14 +16,15 @@ import ( "reflect" "strings" + "github.com/sourcenetwork/immutable" + "github.com/sourcenetwork/immutable/enumerable" + "github.com/sourcenetwork/defradb/client" "github.com/sourcenetwork/defradb/client/request" "github.com/sourcenetwork/defradb/connor" "github.com/sourcenetwork/defradb/core" "github.com/sourcenetwork/defradb/datastore" "github.com/sourcenetwork/defradb/errors" - "github.com/sourcenetwork/defradb/immutables" - "github.com/sourcenetwork/defradb/immutables/enumerable" ) // ToSelect converts the given [parser.Select] into a [Select]. @@ -108,7 +109,7 @@ func toSelect( func resolveOrderDependencies( descriptionsRepo *DescriptionsRepo, descName string, - source immutables.Option[request.OrderBy], + source immutable.Option[request.OrderBy], mapping *core.DocumentMapping, existingFields *[]Requestable, ) error { @@ -629,7 +630,7 @@ func getTopLevelInfo( func resolveFilterDependencies( descriptionsRepo *DescriptionsRepo, parentCollectionName string, - source immutables.Option[request.Filter], + source immutable.Option[request.Filter], mapping *core.DocumentMapping, existingFields []Requestable, ) ([]Requestable, error) { @@ -832,7 +833,7 @@ func toField(index int, parsed *request.Select) Field { // ToFilter converts the given `source` request filter to a Filter using the given mapping. // // Any requestables identified by name will be converted to being identified by index instead. -func ToFilter(source immutables.Option[request.Filter], mapping *core.DocumentMapping) *Filter { +func ToFilter(source immutable.Option[request.Filter], mapping *core.DocumentMapping) *Filter { if !source.HasValue() { return nil } @@ -918,7 +919,7 @@ func toFilterMap( } } -func toLimit(limit immutables.Option[uint64], offset immutables.Option[uint64]) *Limit { +func toLimit(limit immutable.Option[uint64], offset immutable.Option[uint64]) *Limit { var limitValue uint64 var offsetValue uint64 if !limit.HasValue() && !offset.HasValue() { @@ -939,7 +940,7 @@ func toLimit(limit immutables.Option[uint64], offset immutables.Option[uint64]) } } -func toGroupBy(source immutables.Option[request.GroupBy], mapping *core.DocumentMapping) *GroupBy { +func toGroupBy(source immutable.Option[request.GroupBy], mapping *core.DocumentMapping) *GroupBy { if !source.HasValue() { return nil } @@ -963,7 +964,7 @@ func toGroupBy(source immutables.Option[request.GroupBy], mapping *core.Document } } -func toOrderBy(source immutables.Option[request.OrderBy], mapping *core.DocumentMapping) *OrderBy { +func toOrderBy(source immutable.Option[request.OrderBy], mapping *core.DocumentMapping) *OrderBy { if !source.HasValue() { return nil } @@ -1158,14 +1159,14 @@ type aggregateRequestTarget struct { childExternalName string // The aggregate filter specified by the consumer for this target. Optional. - filter immutables.Option[request.Filter] + filter immutable.Option[request.Filter] // The aggregate limit-offset specified by the consumer for this target. Optional. limit *Limit // The order in which items should be aggregated. Affects results when used with // limit. Optional. - order immutables.Option[request.OrderBy] + order immutable.Option[request.OrderBy] } // Returns the source of the aggregate as requested by the consumer @@ -1274,7 +1275,7 @@ func tryGetTarget( // to the given Select. func appendNotNilFilter(field *aggregateRequestTarget, childField string) { if !field.filter.HasValue() || field.filter.Value().Conditions == nil { - field.filter = immutables.Some( + field.filter = immutable.Some( request.Filter{ Conditions: map[string]any{}, }, diff --git a/planner/mapper/select.go b/planner/mapper/select.go index 8961a0fb7b..2696c0ca82 100644 --- a/planner/mapper/select.go +++ b/planner/mapper/select.go @@ -11,8 +11,9 @@ package mapper import ( + "github.com/sourcenetwork/immutable" + "github.com/sourcenetwork/defradb/core" - "github.com/sourcenetwork/defradb/immutables" ) // Select represents a request to return data from Defra. @@ -27,7 +28,7 @@ type Select struct { core.DocumentMapping // A commit identifier that can be specified to request data at a given time. - Cid immutables.Option[string] + Cid immutable.Option[string] // The name of the collection that this Select selects data from. CollectionName string diff --git a/planner/mapper/targetable.go b/planner/mapper/targetable.go index ff27de7de7..e5ba30600e 100644 --- a/planner/mapper/targetable.go +++ b/planner/mapper/targetable.go @@ -11,9 +11,10 @@ package mapper import ( + "github.com/sourcenetwork/immutable" + "github.com/sourcenetwork/defradb/connor" "github.com/sourcenetwork/defradb/core" - "github.com/sourcenetwork/defradb/immutables" ) var ( @@ -132,7 +133,7 @@ type Targetable struct { // A optional collection of docKeys that can be specified to restrict results // to belonging to this set. - DocKeys immutables.Option[[]string] + DocKeys immutable.Option[[]string] // An optional filter, that can be specified to restrict results to documents // that satisfies all of its conditions. diff --git a/planner/select.go b/planner/select.go index c87218748d..02ba59ea88 100644 --- a/planner/select.go +++ b/planner/select.go @@ -12,13 +12,13 @@ package planner import ( cid "github.com/ipfs/go-cid" + "github.com/sourcenetwork/immutable" "github.com/sourcenetwork/defradb/client/request" "github.com/sourcenetwork/defradb/core" "github.com/sourcenetwork/defradb/db/base" "github.com/sourcenetwork/defradb/db/fetcher" "github.com/sourcenetwork/defradb/errors" - "github.com/sourcenetwork/defradb/immutables" "github.com/sourcenetwork/defradb/planner/mapper" ) @@ -116,7 +116,7 @@ type selectNode struct { // are defined in the subtype scan node. filter *mapper.Filter - docKeys immutables.Option[[]string] + docKeys immutable.Option[[]string] parsed *mapper.Select groupSelects []*mapper.Select @@ -293,7 +293,7 @@ func (n *selectNode) initFields(parsed *mapper.Select) ([]aggregateNode, error) // of that Target version we are querying. // So instead of a LatestCommit subquery, we need // a OneCommit subquery, with the supplied parameters. - commitSlct.DocKey = immutables.Some(parsed.DocKeys.Value()[0]) // @todo check length + commitSlct.DocKey = immutable.Some(parsed.DocKeys.Value()[0]) // @todo check length commitSlct.Cid = parsed.Cid } diff --git a/planner/sum.go b/planner/sum.go index eb88536d82..8e1e4a5a32 100644 --- a/planner/sum.go +++ b/planner/sum.go @@ -13,12 +13,13 @@ package planner import ( "fmt" + "github.com/sourcenetwork/immutable" + "github.com/sourcenetwork/immutable/enumerable" + "github.com/sourcenetwork/defradb/client" "github.com/sourcenetwork/defradb/client/request" "github.com/sourcenetwork/defradb/core" "github.com/sourcenetwork/defradb/errors" - "github.com/sourcenetwork/defradb/immutables" - "github.com/sourcenetwork/defradb/immutables/enumerable" "github.com/sourcenetwork/defradb/planner/mapper" ) @@ -230,12 +231,12 @@ func (n *sumNode) Next() (bool, error) { }, ) - case []immutables.Option[int64]: + case []immutable.Option[int64]: collectionSum, err = sumItems( childCollection, &source, lessO[int64], - func(childItem immutables.Option[int64]) float64 { + func(childItem immutable.Option[int64]) float64 { if !childItem.HasValue() { return 0 } @@ -253,12 +254,12 @@ func (n *sumNode) Next() (bool, error) { }, ) - case []immutables.Option[float64]: + case []immutable.Option[float64]: collectionSum, err = sumItems( childCollection, &source, lessO[float64], - func(childItem immutables.Option[float64]) float64 { + func(childItem immutable.Option[float64]) float64 { if !childItem.HasValue() { return 0 } @@ -341,7 +342,7 @@ func lessN[T number](a T, b T) bool { return a < b } -func lessO[T number](a immutables.Option[T], b immutables.Option[T]) bool { +func lessO[T number](a immutable.Option[T], b immutable.Option[T]) bool { if !a.HasValue() { return true } diff --git a/query/graphql/parser.go b/query/graphql/parser.go index 24e42e517f..c94fc6693d 100644 --- a/query/graphql/parser.go +++ b/query/graphql/parser.go @@ -14,15 +14,16 @@ import ( "context" "strings" + gql "github.com/graphql-go/graphql" + gqlp "github.com/graphql-go/graphql/language/parser" + "github.com/graphql-go/graphql/language/source" + "github.com/sourcenetwork/immutable" + "github.com/sourcenetwork/defradb/client" "github.com/sourcenetwork/defradb/client/request" "github.com/sourcenetwork/defradb/core" defrap "github.com/sourcenetwork/defradb/query/graphql/parser" "github.com/sourcenetwork/defradb/query/graphql/schema" - - gql "github.com/graphql-go/graphql" - gqlp "github.com/graphql-go/graphql/language/parser" - "github.com/graphql-go/graphql/language/source" ) var _ core.Parser = (*parser)(nil) @@ -102,6 +103,6 @@ func (p *parser) AddSchema(ctx context.Context, schema string) error { return err } -func (p *parser) NewFilterFromString(collectionType string, body string) (client.Option[request.Filter], error) { +func (p *parser) NewFilterFromString(collectionType string, body string) (immutable.Option[request.Filter], error) { return defrap.NewFilterFromString(*p.schemaManager.Schema(), collectionType, body) } diff --git a/query/graphql/parser/commit.go b/query/graphql/parser/commit.go index 6ce81fe2c8..85e23092d0 100644 --- a/query/graphql/parser/commit.go +++ b/query/graphql/parser/commit.go @@ -15,10 +15,10 @@ import ( gql "github.com/graphql-go/graphql" "github.com/graphql-go/graphql/language/ast" + "github.com/sourcenetwork/immutable" "github.com/sourcenetwork/defradb/client/request" "github.com/sourcenetwork/defradb/core" - "github.com/sourcenetwork/defradb/immutables" ) func parseCommitSelect(schema gql.Schema, parent *gql.Object, field *ast.Field) (*request.CommitSelect, error) { @@ -33,20 +33,20 @@ func parseCommitSelect(schema gql.Schema, parent *gql.Object, field *ast.Field) prop := argument.Name.Value if prop == request.DocKey { raw := argument.Value.(*ast.StringValue) - commit.DocKey = immutables.Some(raw.Value) + commit.DocKey = immutable.Some(raw.Value) } else if prop == request.Cid { raw := argument.Value.(*ast.StringValue) - commit.Cid = immutables.Some(raw.Value) + commit.Cid = immutable.Some(raw.Value) } else if prop == request.FieldName { raw := argument.Value.(*ast.StringValue) - commit.FieldName = immutables.Some(raw.Value) + commit.FieldName = immutable.Some(raw.Value) } else if prop == request.OrderClause { obj := argument.Value.(*ast.ObjectValue) cond, err := ParseConditionsInOrder(obj) if err != nil { return nil, err } - commit.OrderBy = immutables.Some( + commit.OrderBy = immutable.Some( request.OrderBy{ Conditions: cond, }, @@ -57,21 +57,21 @@ func parseCommitSelect(schema gql.Schema, parent *gql.Object, field *ast.Field) if err != nil { return nil, err } - commit.Limit = immutables.Some(limit) + commit.Limit = immutable.Some(limit) } else if prop == request.OffsetClause { val := argument.Value.(*ast.IntValue) offset, err := strconv.ParseUint(val.Value, 10, 64) if err != nil { return nil, err } - commit.Offset = immutables.Some(offset) + commit.Offset = immutable.Some(offset) } else if prop == request.DepthClause { raw := argument.Value.(*ast.IntValue) depth, err := strconv.ParseUint(raw.Value, 10, 64) if err != nil { return nil, err } - commit.Depth = immutables.Some(depth) + commit.Depth = immutable.Some(depth) } else if prop == request.GroupByClause { obj := argument.Value.(*ast.ListValue) fields := []string{} @@ -79,7 +79,7 @@ func parseCommitSelect(schema gql.Schema, parent *gql.Object, field *ast.Field) fields = append(fields, v.GetValue().(string)) } - commit.GroupBy = immutables.Some( + commit.GroupBy = immutable.Some( request.GroupBy{ Fields: fields, }, @@ -92,11 +92,11 @@ func parseCommitSelect(schema gql.Schema, parent *gql.Object, field *ast.Field) // Depth is not exposed as an input parameter for latestCommits, // so we can blindly set it here without worrying about existing // values - commit.Depth = immutables.Some(uint64(1)) + commit.Depth = immutable.Some(uint64(1)) if !commit.FieldName.HasValue() { // latest commits defaults to composite commits only at the moment - commit.FieldName = immutables.Some(core.COMPOSITE_NAMESPACE) + commit.FieldName = immutable.Some(core.COMPOSITE_NAMESPACE) } } diff --git a/query/graphql/parser/filter.go b/query/graphql/parser/filter.go index 4d4e0c724f..9b421de203 100644 --- a/query/graphql/parser/filter.go +++ b/query/graphql/parser/filter.go @@ -14,45 +14,55 @@ import ( "strconv" "strings" + gql "github.com/graphql-go/graphql" "github.com/graphql-go/graphql/language/ast" gqlp "github.com/graphql-go/graphql/language/parser" gqls "github.com/graphql-go/graphql/language/source" + "github.com/sourcenetwork/immutable" "github.com/sourcenetwork/defradb/client/request" "github.com/sourcenetwork/defradb/errors" - "github.com/sourcenetwork/defradb/immutables" ) // type condition // NewFilter parses the given GraphQL ObjectValue AST type // and extracts all the filter conditions into a usable map. -func NewFilter(stmt *ast.ObjectValue) (immutables.Option[request.Filter], error) { - conditions, err := ParseConditions(stmt) +func NewFilter(stmt *ast.ObjectValue, inputType gql.Input) (immutable.Option[request.Filter], error) { + conditions, err := ParseConditions(stmt, inputType) if err != nil { - return immutables.None[request.Filter](), err + return immutable.None[request.Filter](), err } - return immutables.Some(request.Filter{ + return immutable.Some(request.Filter{ Conditions: conditions, }), nil } // NewFilterFromString creates a new filter from a string. -func NewFilterFromString(body string) (immutables.Option[request.Filter], error) { +func NewFilterFromString( + schema gql.Schema, + collectionType string, + body string, +) (immutable.Option[request.Filter], error) { if !strings.HasPrefix(body, "{") { body = "{" + body + "}" } src := gqls.NewSource(&gqls.Source{Body: []byte(body)}) p, err := gqlp.MakeParser(src, gqlp.ParseOptions{}) if err != nil { - return immutables.None[request.Filter](), err + return immutable.None[request.Filter](), err } obj, err := gqlp.ParseObject(p, false) if err != nil { - return immutables.None[request.Filter](), err + return immutable.None[request.Filter](), err } - return NewFilter(obj) + parentFieldType := gql.GetFieldDef(schema, schema.QueryType(), collectionType) + filterType, ok := getArgumentType(parentFieldType, request.FilterClause) + if !ok { + return immutable.None[request.Filter](), errors.New("couldn't find filter argument type") + } + return NewFilter(obj, filterType) } type parseFn func(*ast.ObjectValue) (any, error) @@ -119,8 +129,8 @@ func parseConditionsInOrder(stmt *ast.ObjectValue) (any, error) { // parseConditions loops over the stmt ObjectValue fields, and extracts // all the relevant name/value pairs. -func ParseConditions(stmt *ast.ObjectValue) (map[string]any, error) { - cond, err := parseConditions(stmt) +func ParseConditions(stmt *ast.ObjectValue, inputType gql.Input) (map[string]any, error) { + cond, err := parseConditions(stmt, inputType) if err != nil { return nil, err } @@ -131,20 +141,12 @@ func ParseConditions(stmt *ast.ObjectValue) (map[string]any, error) { return nil, errors.New("failed to parse statement") } -func parseConditions(stmt *ast.ObjectValue) (any, error) { - conditions := make(map[string]any) - if stmt == nil { - return conditions, nil - } - for _, field := range stmt.Fields { - name := field.Name.Value - val, err := parseVal(field.Value, parseConditions) - if err != nil { - return nil, err - } - conditions[name] = val +func parseConditions(stmt *ast.ObjectValue, inputArg gql.Input) (any, error) { + val := gql.ValueFromAST(stmt, inputArg, nil) + if val == nil { + return nil, errors.New("couldn't parse conditions value from AST") } - return conditions, nil + return val, nil } // parseVal handles all the various input types, and extracts their diff --git a/query/graphql/parser/mutation.go b/query/graphql/parser/mutation.go index dd444e1b4e..3db13e6cc9 100644 --- a/query/graphql/parser/mutation.go +++ b/query/graphql/parser/mutation.go @@ -15,10 +15,10 @@ import ( gql "github.com/graphql-go/graphql" "github.com/graphql-go/graphql/language/ast" + "github.com/sourcenetwork/immutable" "github.com/sourcenetwork/defradb/client/request" "github.com/sourcenetwork/defradb/errors" - "github.com/sourcenetwork/defradb/immutables" ) var ( @@ -125,7 +125,7 @@ func parseMutation(schema gql.Schema, parent *gql.Object, field *ast.Field) (*re mut.Filter = filter } else if prop == request.Id { raw := argument.Value.(*ast.StringValue) - mut.IDs = immutables.Some([]string{raw.Value}) + mut.IDs = immutable.Some([]string{raw.Value}) } else if prop == request.Ids { raw := argument.Value.(*ast.ListValue) ids := make([]string, len(raw.Values)) @@ -136,7 +136,7 @@ func parseMutation(schema gql.Schema, parent *gql.Object, field *ast.Field) (*re } ids[i] = id.Value } - mut.IDs = immutables.Some(ids) + mut.IDs = immutable.Some(ids) } } diff --git a/query/graphql/parser/query.go b/query/graphql/parser/query.go index 0d4e28918f..78cbe4278e 100644 --- a/query/graphql/parser/query.go +++ b/query/graphql/parser/query.go @@ -15,10 +15,10 @@ import ( gql "github.com/graphql-go/graphql" "github.com/graphql-go/graphql/language/ast" + "github.com/sourcenetwork/immutable" "github.com/sourcenetwork/defradb/client/request" "github.com/sourcenetwork/defradb/errors" - "github.com/sourcenetwork/defradb/immutables" ) // ParseQuery parses a root ast.Document, and returns a @@ -189,38 +189,38 @@ func parseSelect( slct.Filter = filter } else if prop == request.DocKey { // parse single dockey query field val := astValue.(*ast.StringValue) - slct.DocKeys = immutables.Some([]string{val.Value}) + slct.DocKeys = immutable.Some([]string{val.Value}) } else if prop == request.DocKeys { docKeyValues := astValue.(*ast.ListValue).Values docKeys := make([]string, len(docKeyValues)) for i, value := range docKeyValues { docKeys[i] = value.(*ast.StringValue).Value } - slct.DocKeys = immutables.Some(docKeys) + slct.DocKeys = immutable.Some(docKeys) } else if prop == request.Cid { // parse single CID query field val := astValue.(*ast.StringValue) - slct.CID = immutables.Some(val.Value) + slct.CID = immutable.Some(val.Value) } else if prop == request.LimitClause { // parse limit/offset val := astValue.(*ast.IntValue) limit, err := strconv.ParseUint(val.Value, 10, 64) if err != nil { return nil, err } - slct.Limit = immutables.Some(limit) + slct.Limit = immutable.Some(limit) } else if prop == request.OffsetClause { // parse limit/offset val := astValue.(*ast.IntValue) offset, err := strconv.ParseUint(val.Value, 10, 64) if err != nil { return nil, err } - slct.Offset = immutables.Some(offset) + slct.Offset = immutable.Some(offset) } else if prop == request.OrderClause { // parse order by obj := astValue.(*ast.ObjectValue) cond, err := ParseConditionsInOrder(obj) if err != nil { return nil, err } - slct.OrderBy = immutables.Some( + slct.OrderBy = immutable.Some( request.OrderBy{ Conditions: cond, }, @@ -232,7 +232,7 @@ func parseSelect( fields = append(fields, v.GetValue().(string)) } - slct.GroupBy = immutables.Some( + slct.GroupBy = immutable.Some( request.GroupBy{ Fields: fields, }, @@ -259,11 +259,11 @@ func parseSelect( return slct, err } -func getFieldAlias(field *ast.Field) immutables.Option[string] { +func getFieldAlias(field *ast.Field) immutable.Option[string] { if field.Alias == nil { - return immutables.None[string]() + return immutable.None[string]() } - return immutables.Some(field.Alias.Value) + return immutable.Some(field.Alias.Value) } func parseSelectFields( @@ -324,10 +324,10 @@ func parseAggregate(schema gql.Schema, parent *gql.Object, field *ast.Field, ind case []*ast.ObjectField: hostName := argument.Name.Value var childName string - var filter immutables.Option[request.Filter] - var limit immutables.Option[uint64] - var offset immutables.Option[uint64] - var order immutables.Option[request.OrderBy] + var filter immutable.Option[request.Filter] + var limit immutable.Option[uint64] + var offset immutable.Option[uint64] + var order immutable.Option[request.OrderBy] fieldArg, hasFieldArg := tryGet(argumentValue, request.FieldName) if hasFieldArg { @@ -368,7 +368,7 @@ func parseAggregate(schema gql.Schema, parent *gql.Object, field *ast.Field, ind if err != nil { return nil, err } - limit = immutables.Some(limitValue) + limit = immutable.Some(limitValue) } offsetArg, hasOffsetArg := tryGet(argumentValue, request.OffsetClause) @@ -377,7 +377,7 @@ func parseAggregate(schema gql.Schema, parent *gql.Object, field *ast.Field, ind if err != nil { return nil, err } - offset = immutables.Some(offsetValue) + offset = immutable.Some(offsetValue) } orderArg, hasOrderArg := tryGet(argumentValue, request.OrderClause) @@ -388,7 +388,7 @@ func parseAggregate(schema gql.Schema, parent *gql.Object, field *ast.Field, ind orderDirectionString := orderArgValue.Value orderDirection := request.OrderDirection(orderDirectionString) - order = immutables.Some( + order = immutable.Some( request.OrderBy{ Conditions: []request.OrderCondition{ { @@ -408,7 +408,7 @@ func parseAggregate(schema gql.Schema, parent *gql.Object, field *ast.Field, ind return nil, err } - order = immutables.Some( + order = immutable.Some( request.OrderBy{ Conditions: orderConditions, }, @@ -418,7 +418,7 @@ func parseAggregate(schema gql.Schema, parent *gql.Object, field *ast.Field, ind targets[i] = &request.AggregateTarget{ HostName: hostName, - ChildName: immutables.Some(childName), + ChildName: immutable.Some(childName), Filter: filter, Limit: limit, Offset: offset, diff --git a/tests/integration/mutation/inline_array/update/simple_test.go b/tests/integration/mutation/inline_array/update/simple_test.go index f99df77348..370919187c 100644 --- a/tests/integration/mutation/inline_array/update/simple_test.go +++ b/tests/integration/mutation/inline_array/update/simple_test.go @@ -13,7 +13,8 @@ package update import ( "testing" - "github.com/sourcenetwork/defradb/immutables" + "github.com/sourcenetwork/immutable" + testUtils "github.com/sourcenetwork/defradb/tests/integration" inlineArray "github.com/sourcenetwork/defradb/tests/integration/mutation/inline_array" ) @@ -162,12 +163,12 @@ func TestMutationInlineArrayWithNillableBooleans(t *testing.T) { Results: []map[string]any{ { "Name": "John", - "IndexLikesDislikes": []immutables.Option[bool]{ - immutables.Some(true), - immutables.Some(true), - immutables.Some(false), - immutables.Some(true), - immutables.None[bool](), + "IndexLikesDislikes": []immutable.Option[bool]{ + immutable.Some(true), + immutable.Some(true), + immutable.Some(false), + immutable.Some(true), + immutable.None[bool](), }, }, }, @@ -343,12 +344,12 @@ func TestMutationInlineArrayWithNillableInts(t *testing.T) { Results: []map[string]any{ { "Name": "John", - "TestScores": []immutables.Option[int64]{ - immutables.None[int64](), - immutables.Some[int64](2), - immutables.Some[int64](3), - immutables.None[int64](), - immutables.Some[int64](8), + "TestScores": []immutable.Option[int64]{ + immutable.None[int64](), + immutable.Some[int64](2), + immutable.Some[int64](3), + immutable.None[int64](), + immutable.Some[int64](8), }, }, }, @@ -501,11 +502,11 @@ func TestMutationInlineArrayWithNillableFloats(t *testing.T) { Results: []map[string]any{ { "Name": "John", - "PageRatings": []immutables.Option[float64]{ - immutables.Some(3.1425), - immutables.Some(-0.00000000001), - immutables.None[float64](), - immutables.Some[float64](10), + "PageRatings": []immutable.Option[float64]{ + immutable.Some(3.1425), + immutable.Some(-0.00000000001), + immutable.None[float64](), + immutable.Some[float64](10), }, }, }, @@ -665,13 +666,13 @@ func TestMutationInlineArrayWithNillableStrings(t *testing.T) { Results: []map[string]any{ { "Name": "John", - "PageHeaders": []immutables.Option[string]{ - immutables.Some(""), - immutables.Some("the previous"), - immutables.None[string](), - immutables.Some("empty string"), - immutables.Some("blank string"), - immutables.Some("hitchi"), + "PageHeaders": []immutable.Option[string]{ + immutable.Some(""), + immutable.Some("the previous"), + immutable.None[string](), + immutable.Some("empty string"), + immutable.Some("blank string"), + immutable.Some("hitchi"), }, }, }, diff --git a/tests/integration/query/inline_array/simple_test.go b/tests/integration/query/inline_array/simple_test.go index 9a516634ed..619c7ad364 100644 --- a/tests/integration/query/inline_array/simple_test.go +++ b/tests/integration/query/inline_array/simple_test.go @@ -13,7 +13,8 @@ package inline_array import ( "testing" - "github.com/sourcenetwork/defradb/immutables" + "github.com/sourcenetwork/immutable" + testUtils "github.com/sourcenetwork/defradb/tests/integration" ) @@ -76,7 +77,7 @@ func TestQueryInlineArrayWithBooleans(t *testing.T) { Docs: map[int][]string{ 0: { `{ - "Name": "John", + "Name": "John", "LikedIndexes": [true, true, false, true] }`, }, @@ -115,11 +116,11 @@ func TestQueryInlineArrayWithNillableBooleans(t *testing.T) { Results: []map[string]any{ { "Name": "John", - "IndexLikesDislikes": []immutables.Option[bool]{ - immutables.Some(true), - immutables.Some(true), - immutables.Some(false), - immutables.None[bool](), + "IndexLikesDislikes": []immutable.Option[bool]{ + immutable.Some(true), + immutable.Some(true), + immutable.Some(false), + immutable.None[bool](), }, }, }, @@ -294,12 +295,12 @@ func TestQueryInlineArrayWithNillableInts(t *testing.T) { Results: []map[string]any{ { "Name": "John", - "TestScores": []immutables.Option[int64]{ - immutables.Some[int64](-1), - immutables.None[int64](), - immutables.Some[int64](-1), - immutables.Some[int64](2), - immutables.Some[int64](0), + "TestScores": []immutable.Option[int64]{ + immutable.Some[int64](-1), + immutable.None[int64](), + immutable.Some[int64](-1), + immutable.Some[int64](2), + immutable.Some[int64](0), }, }, }, @@ -406,11 +407,11 @@ func TestQueryInlineArrayWithNillableFloats(t *testing.T) { Results: []map[string]any{ { "Name": "John", - "PageRatings": []immutables.Option[float64]{ - immutables.Some(3.1425), - immutables.None[float64](), - immutables.Some(-0.00000000001), - immutables.Some[float64](10), + "PageRatings": []immutable.Option[float64]{ + immutable.Some(3.1425), + immutable.None[float64](), + immutable.Some(-0.00000000001), + immutable.Some[float64](10), }, }, }, @@ -517,12 +518,12 @@ func TestQueryInlineArrayWithNillableString(t *testing.T) { Results: []map[string]any{ { "Name": "John", - "PageHeaders": []immutables.Option[string]{ - immutables.Some(""), - immutables.Some("the previous"), - immutables.Some("the first"), - immutables.Some("empty string"), - immutables.None[string](), + "PageHeaders": []immutable.Option[string]{ + immutable.Some(""), + immutable.Some("the previous"), + immutable.Some("the first"), + immutable.Some("empty string"), + immutable.None[string](), }, }, },