Skip to content

Commit

Permalink
feat: Remove filter depth limit (#777)
Browse files Browse the repository at this point in the history
* Remove deprecated test file

It is dependent on package internals and function signatures upon which it relies upon will soon be modified and deleted

* Add enumerable.concat

* Add enumerable.select

* Add enumerable.tryGetFirst

* Refactor schema intergration tests

Should further improve dev-ex when adding and maintaining schema integration tests.

* Make mapping.Children slice of pointers

Original struct setup starts to cause issues when the items in the slice need to be mutated

* Remove depth restriction in filter clause
  • Loading branch information
AndrewSisley authored Sep 8, 2022
1 parent 5448e25 commit b9116bc
Show file tree
Hide file tree
Showing 12 changed files with 870 additions and 1,300 deletions.
16 changes: 10 additions & 6 deletions core/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ type DocumentMapping struct {
//
// Indexes correspond exactly to field indexes, however entries may be default
// if the field is unmappable (e.g. integer fields).
ChildMappings []DocumentMapping
ChildMappings []*DocumentMapping
}

// NewDocumentMapping instantiates a new DocumentMapping instance.
Expand All @@ -111,7 +111,7 @@ func (source *DocumentMapping) CloneWithoutRender() *DocumentMapping {
result := DocumentMapping{
IndexesByName: make(map[string][]int, len(source.IndexesByName)),
nextIndex: source.nextIndex,
ChildMappings: make([]DocumentMapping, len(source.ChildMappings)),
ChildMappings: make([]*DocumentMapping, len(source.ChildMappings)),
}

for externalName, sourceIndexes := range source.IndexesByName {
Expand All @@ -121,7 +121,7 @@ func (source *DocumentMapping) CloneWithoutRender() *DocumentMapping {
}

for i, childMapping := range source.ChildMappings {
result.ChildMappings[i] = *childMapping.CloneWithoutRender()
result.ChildMappings[i] = childMapping.CloneWithoutRender()
}

return &result
Expand Down Expand Up @@ -210,10 +210,10 @@ func (mapping *DocumentMapping) Add(index int, name string) {
//
// If the index is greater than the ChildMappings length the collection will
// grow.
func (m *DocumentMapping) SetChildAt(index int, childMapping DocumentMapping) {
var newMappings []DocumentMapping
func (m *DocumentMapping) SetChildAt(index int, childMapping *DocumentMapping) {
var newMappings []*DocumentMapping
if index >= len(m.ChildMappings)-1 {
newMappings = make([]DocumentMapping, index+1)
newMappings = make([]*DocumentMapping, index+1)
copy(newMappings, m.ChildMappings)
} else {
newMappings = m.ChildMappings
Expand All @@ -238,6 +238,10 @@ func (mapping *DocumentMapping) TryToFindNameFromIndex(targetIndex int) (string,

// Try to find the name of this index in the ChildMappings.
for _, childMapping := range mapping.ChildMappings {
if childMapping == nil {
continue
}

name, found := childMapping.TryToFindNameFromIndex(targetIndex)
if found {
return name, true
Expand Down
56 changes: 56 additions & 0 deletions core/enumerable/concat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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()
}
}
12 changes: 12 additions & 0 deletions core/enumerable/enumerable.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,15 @@ func OnEach[T any](source Enumerable[T], action func()) error {
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
}
55 changes: 55 additions & 0 deletions core/enumerable/select.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// 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()
}
Loading

0 comments on commit b9116bc

Please sign in to comment.