-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathiterator.go
102 lines (90 loc) · 2.1 KB
/
iterator.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
package anystore
import (
"errors"
"io"
"zombiezen.com/go/sqlite"
"github.com/anyproto/any-store/internal/syncpool"
)
// Iterator represents an iterator over query results.
//
// Example of usage:
//
// for iter.Next() {
// doc, err := iter.Doc()
// if err != nil {
// log.Fatalf("error retrieving document: %v", err)
// }
// fmt.Println("Document:", doc.Value().String())
// }
// if err := iter.Close(); err != nil {
// log.Fatalf("iteration error: %v", err)
// }
type Iterator interface {
// Next advances the iterator to the next document.
// Returns false if there are no more documents.
Next() bool
// Doc returns the current document.
// Returns an error if there is an issue retrieving the document.
Doc() (Doc, error)
// Err returns any error encountered during the lifetime of the iterator,
Err() error
// Close closes the iterator and releases any associated resources.
// Returns an error if there is an issue closing the iterator or any other error encountered during its lifetime.
Close() error
}
type iterator struct {
tx ReadTx
buf *syncpool.DocBuffer
qb *queryBuilder
err error
closed bool
stmt *sqlite.Stmt
}
func (i *iterator) Next() bool {
if i.err != nil {
return false
}
hasRow, stepErr := i.stmt.Step()
if stepErr != nil {
stepErr = replaceInterruptErr(stepErr)
i.err = stepErr
return false
}
return hasRow
}
func (i *iterator) Doc() (Doc, error) {
if i.err != nil && !errors.Is(i.err, io.EOF) {
return nil, i.err
}
i.buf.DocBuf = readBytes(i.stmt, i.buf.DocBuf)
val, err := i.buf.Parser.Parse(i.buf.DocBuf)
if err != nil {
return nil, err
}
return newItem(val)
}
func (i *iterator) Err() error {
if i.err != nil && errors.Is(i.err, io.EOF) {
return nil
}
return i.err
}
func (i *iterator) Close() (err error) {
if i.closed {
return ErrIterClosed
}
i.closed = true
if i.stmt != nil {
err = errors.Join(err, i.stmt.Finalize())
}
if i.tx != nil {
err = errors.Join(err, i.tx.Commit())
}
if i.buf != nil && i.qb != nil {
i.qb.coll.db.syncPool.ReleaseDocBuf(i.buf)
}
if i.qb != nil {
i.qb.Close()
}
return
}