forked from cayleygraph/cayley
-
Notifications
You must be signed in to change notification settings - Fork 0
/
limit.go
135 lines (113 loc) · 3.01 KB
/
limit.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package iterator
import (
"github.com/cayleygraph/cayley/graph"
)
// Limit iterator will stop iterating if certain a number of values were encountered.
// Zero and negative limit values means no limit.
type Limit struct {
uid uint64
limit int64
count int64
primaryIt graph.Iterator
}
func NewLimit(primaryIt graph.Iterator, limit int64) *Limit {
return &Limit{
uid: NextUID(),
limit: limit,
primaryIt: primaryIt,
}
}
func (it *Limit) UID() uint64 {
return it.uid
}
// Reset resets the internal iterators and the iterator itself.
func (it *Limit) Reset() {
it.count = 0
it.primaryIt.Reset()
}
func (it *Limit) Tagger() *graph.Tagger {
return it.primaryIt.Tagger()
}
func (it *Limit) TagResults(dst map[string]graph.Value) {
it.primaryIt.TagResults(dst)
}
func (it *Limit) Clone() graph.Iterator {
return NewLimit(it.primaryIt.Clone(), it.limit)
}
// SubIterators returns a slice of the sub iterators.
func (it *Limit) SubIterators() []graph.Iterator {
return []graph.Iterator{it.primaryIt}
}
// Next advances the Limit iterator. It will stop iteration if limit was reached.
func (it *Limit) Next() bool {
graph.NextLogIn(it)
if it.limit > 0 && it.count >= it.limit {
return graph.NextLogOut(it, false)
}
if it.primaryIt.Next() {
it.count++
return graph.NextLogOut(it, true)
}
return graph.NextLogOut(it, false)
}
func (it *Limit) Err() error {
return it.primaryIt.Err()
}
func (it *Limit) Result() graph.Value {
return it.primaryIt.Result()
}
func (it *Limit) Contains(val graph.Value) bool {
return it.primaryIt.Contains(val) // FIXME(dennwc): limit is ignored in this case
}
// NextPath checks whether there is another path. Will call primary iterator
// if limit is not reached yet.
func (it *Limit) NextPath() bool {
if it.limit > 0 && it.count >= it.limit {
return false
}
if it.primaryIt.NextPath() {
it.count++
return true
}
return false
}
// Close closes the primary and all iterators. It closes all subiterators
// it can, but returns the first error it encounters.
func (it *Limit) Close() error {
return it.primaryIt.Close()
}
func (it *Limit) Type() graph.Type { return graph.Limit }
func (it *Limit) Optimize() (graph.Iterator, bool) {
optimizedPrimaryIt, optimized := it.primaryIt.Optimize()
if it.limit <= 0 { // no limit
return optimizedPrimaryIt, true
}
it.primaryIt = optimizedPrimaryIt
return it, optimized
}
func (it *Limit) Stats() graph.IteratorStats {
primaryStats := it.primaryIt.Stats()
if it.limit > 0 && primaryStats.Size > it.limit {
primaryStats.Size = it.limit
}
return primaryStats
}
func (it *Limit) Size() (int64, bool) {
primarySize, exact := it.primaryIt.Size()
if it.limit > 0 && primarySize > it.limit {
primarySize = it.limit
}
return primarySize, exact
}
func (it *Limit) Describe() graph.Description {
subIts := []graph.Description{
it.primaryIt.Describe(),
}
return graph.Description{
UID: it.UID(),
Type: it.Type(),
Tags: it.Tagger().Tags(),
Iterators: subIts,
}
}
var _ graph.Iterator = &Limit{}