Skip to content

Commit f0f94ee

Browse files
authored
chore: remove addSubIterator and make iterators less mutable (#2898)
1 parent 0b407f0 commit f0f94ee

14 files changed

+122
-224
lines changed

pkg/query/build_tree.go

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,15 @@ func (b *iteratorBuilder) buildIteratorFromRelation(r *schema.Relation, withSubR
142142
}
143143
return NewAliasIterator(r.Name(), baseIt), nil
144144
}
145-
union := NewUnionIterator()
145+
subIts := make([]Iterator, 0, len(r.BaseRelations()))
146146
for _, br := range r.BaseRelations() {
147147
it, err := b.buildBaseDatastoreIterator(br, withSubRelations)
148148
if err != nil {
149149
return nil, err
150150
}
151-
union.addSubIterator(it)
151+
subIts = append(subIts, it)
152152
}
153+
union := NewUnionIterator(subIts...)
153154
return NewAliasIterator(r.Name(), union), nil
154155
}
155156

@@ -180,26 +181,26 @@ func (b *iteratorBuilder) buildIteratorFromOperation(p *schema.Permission, op sc
180181
return b.buildIteratorFromSchemaInternal(p.Parent().Name(), perm.RelationName(), true)
181182

182183
case *schema.UnionOperation:
183-
union := NewUnionIterator()
184+
subIts := make([]Iterator, 0, len(perm.Children()))
184185
for _, op := range perm.Children() {
185186
it, err := b.buildIteratorFromOperation(p, op)
186187
if err != nil {
187188
return nil, err
188189
}
189-
union.addSubIterator(it)
190+
subIts = append(subIts, it)
190191
}
191-
return union, nil
192+
return NewUnionIterator(subIts...), nil
192193

193194
case *schema.IntersectionOperation:
194-
inter := NewIntersectionIterator()
195+
subIts := make([]Iterator, 0, len(perm.Children()))
195196
for _, op := range perm.Children() {
196197
it, err := b.buildIteratorFromOperation(p, op)
197198
if err != nil {
198199
return nil, err
199200
}
200-
inter.addSubIterator(it)
201+
subIts = append(subIts, it)
201202
}
202-
return inter, nil
203+
return NewIntersectionIterator(subIts...), nil
203204

204205
case *schema.ExclusionOperation:
205206
mainIt, err := b.buildIteratorFromOperation(p, perm.Left())
@@ -290,7 +291,7 @@ func (b *iteratorBuilder) buildBaseDatastoreIterator(br *schema.BaseRelation, wi
290291

291292
// buildArrowIterators creates a union of arrow iterators for the given relation and right-hand side
292293
func (b *iteratorBuilder) buildArrowIterators(rel *schema.Relation, rightSide string) (Iterator, error) {
293-
union := NewUnionIterator()
294+
subIts := make([]Iterator, 0, len(rel.BaseRelations()))
294295
hasMultipleBaseRelations := len(rel.BaseRelations()) > 1
295296
var lastNotFoundError error
296297

@@ -306,7 +307,7 @@ func (b *iteratorBuilder) buildArrowIterators(rel *schema.Relation, rightSide st
306307
// applies to some of them. If there's only one base relation, we should error.
307308
if errors.As(err, &RelationNotFoundError{}) {
308309
if hasMultipleBaseRelations {
309-
union.addSubIterator(NewEmptyFixedIterator())
310+
subIts = append(subIts, NewFixedIterator())
310311
continue
311312
}
312313
lastNotFoundError = err
@@ -317,28 +318,28 @@ func (b *iteratorBuilder) buildArrowIterators(rel *schema.Relation, rightSide st
317318
// Use NewSchemaArrow only for BaseRelations without subrelations.
318319
// BaseRelations with subrelations (like folder#parent) should use regular arrows
319320
// because they need strict subrelation matching.
320-
var arrow *ArrowIterator
321+
var arrow Iterator
321322
if br.Subrelation() != "" && br.Subrelation() != tuple.Ellipsis {
322323
// Has a specific subrelation: use regular arrow (no ellipsis queries)
323324
arrow = NewArrowIterator(left, right)
324325
} else {
325326
// No subrelation or ellipsis: use schema arrow (with ellipsis queries)
326327
arrow = NewSchemaArrow(left, right)
327328
}
328-
union.addSubIterator(arrow)
329+
subIts = append(subIts, arrow)
329330
}
330331

331332
// If we have no sub-iterators and only have a not-found error, return that error
332-
if len(union.Subiterators()) == 0 && lastNotFoundError != nil {
333+
if len(subIts) == 0 && lastNotFoundError != nil {
333334
return nil, lastNotFoundError
334335
}
335336

336-
return union, nil
337+
return NewUnionIterator(subIts...), nil
337338
}
338339

339340
// buildIntersectionArrowIterators creates a union of intersection arrow iterators for the given relation and right-hand side
340341
func (b *iteratorBuilder) buildIntersectionArrowIterators(rel *schema.Relation, rightSide string) (Iterator, error) {
341-
union := NewUnionIterator()
342+
subIts := make([]Iterator, 0, len(rel.BaseRelations()))
342343
hasMultipleBaseRelations := len(rel.BaseRelations()) > 1
343344
var lastNotFoundError error
344345

@@ -354,7 +355,7 @@ func (b *iteratorBuilder) buildIntersectionArrowIterators(rel *schema.Relation,
354355
// applies to some of them. If there's only one base relation, we should error.
355356
if errors.As(err, &RelationNotFoundError{}) {
356357
if hasMultipleBaseRelations {
357-
union.addSubIterator(NewEmptyFixedIterator())
358+
subIts = append(subIts, NewFixedIterator())
358359
continue
359360
}
360361
lastNotFoundError = err
@@ -363,15 +364,15 @@ func (b *iteratorBuilder) buildIntersectionArrowIterators(rel *schema.Relation,
363364
return nil, err
364365
}
365366
intersectionArrow := NewIntersectionArrowIterator(left, right)
366-
union.addSubIterator(intersectionArrow)
367+
subIts = append(subIts, intersectionArrow)
367368
}
368369

369370
// If we have no sub-iterators and only have a not-found error, return that error
370-
if len(union.Subiterators()) == 0 && lastNotFoundError != nil {
371+
if len(subIts) == 0 && lastNotFoundError != nil {
371372
return nil, lastNotFoundError
372373
}
373374

374-
return union, nil
375+
return NewUnionIterator(subIts...), nil
375376
}
376377

377378
func functionTypeString(ft schema.FunctionType) string {

pkg/query/exclusion_test.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -396,9 +396,10 @@ func TestExclusionWithComplexIteratorTypes(t *testing.T) {
396396
t.Run("Exclusion with Union as Main Set", func(t *testing.T) {
397397
t.Parallel()
398398
// Create union iterator as main set
399-
union := NewUnionIterator()
400-
union.addSubIterator(NewFixedIterator(path1, path2))
401-
union.addSubIterator(NewFixedIterator(path3))
399+
union := NewUnionIterator(
400+
NewFixedIterator(path1, path2),
401+
NewFixedIterator(path3),
402+
)
402403

403404
excludedSet := NewFixedIterator(path2) // Exclude path2
404405

@@ -430,9 +431,10 @@ func TestExclusionWithComplexIteratorTypes(t *testing.T) {
430431
mainSet := NewFixedIterator(path1, path2, path3, path4)
431432

432433
// Create union iterator as excluded set
433-
union := NewUnionIterator()
434-
union.addSubIterator(NewFixedIterator(path2))
435-
union.addSubIterator(NewFixedIterator(path4))
434+
union := NewUnionIterator(
435+
NewFixedIterator(path2),
436+
NewFixedIterator(path4),
437+
)
436438

437439
exclusion := NewExclusionIterator(mainSet, union)
438440

pkg/query/intersection.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,16 @@ type IntersectionIterator struct {
1515

1616
var _ Iterator = &IntersectionIterator{}
1717

18-
func NewIntersectionIterator(subiterators ...Iterator) *IntersectionIterator {
18+
func NewIntersectionIterator(subiterators ...Iterator) Iterator {
1919
if len(subiterators) == 0 {
20-
return &IntersectionIterator{
21-
id: uuid.NewString(),
22-
}
20+
return NewFixedIterator() // Return empty FixedIterator instead of empty Intersection
2321
}
2422
return &IntersectionIterator{
2523
id: uuid.NewString(),
2624
subIts: subiterators,
2725
}
2826
}
2927

30-
func (i *IntersectionIterator) addSubIterator(subIt Iterator) {
31-
i.subIts = append(i.subIts, subIt)
32-
}
33-
3428
func (i *IntersectionIterator) CheckImpl(ctx *Context, resources []Object, subject ObjectAndRelation) (PathSeq, error) {
3529
validResources := resources
3630

0 commit comments

Comments
 (0)