Documentation ¶
Overview ¶
Package lmdbscan provides a wrapper for lmdb.Cursor to simplify iteration.
Index ¶
- type Scanner
- func (s *Scanner) Close()
- func (s *Scanner) Cursor() *lmdb.Cursor
- func (s *Scanner) Del(flags uint) error
- func (s *Scanner) Err() error
- func (s *Scanner) Key() []byte
- func (s *Scanner) Scan() bool
- func (s *Scanner) Set(k, v []byte, opset uint) bool
- func (s *Scanner) SetNext(k, v []byte, opset, opnext uint) bool
- func (s *Scanner) Val() []byte
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Scanner ¶
type Scanner struct {
// contains filtered or unexported fields
}
Scanner is a low level construct for scanning databases inside a transaction.
Example ¶
This example demonstrates basic usage of a Scanner to scan a database. It is important to always call scanner.Err() which will returned any unexpected error which interrupted scanner.Scan().
package main import ( "log" "github.com/PowerDNS/lmdb-go/lmdb" "github.com/PowerDNS/lmdb-go/lmdbscan" ) var env *lmdb.Env var dbi lmdb.DBI func main() { err := env.View(func(txn *lmdb.Txn) (err error) { scanner := lmdbscan.New(txn, dbi) defer scanner.Close() for scanner.Scan() { log.Printf("k=%q v=%q", scanner.Key(), scanner.Val()) } return scanner.Err() }) if err != nil { panic(err) } }
Output:
func New ¶
New allocates and intializes a Scanner for dbi within txn. When the Scanner returned by New is no longer needed its Close method must be called.
func (*Scanner) Close ¶
func (s *Scanner) Close()
Close closes the cursor underlying s and clears its ows internal structures. Close does not attempt to terminate the enclosing transaction.
Scan must not be called after Close.
func (*Scanner) Cursor ¶
Cursor returns the lmdb.Cursor underlying s. Cursor returns nil if s is closed.
func (*Scanner) Del ¶
Del will delete the key at the current cursor location.
Del is deprecated. Instead use s.Cursor().Del(flags).
func (*Scanner) Err ¶
Err returns a non-nil error if and only if the previous call to s.Scan() resulted in an error other than lmdb.ErrNotFound.
func (*Scanner) Scan ¶
Scan gets successive key-value pairs using the underlying cursor. Scan returns false when key-value pairs are exhausted or another error is encountered.
func (*Scanner) Set ¶
Set moves the cursor with s.Cursor().Get(k, v, opset), and sets s.Key(), s.Val(), and s.Err() accordingly. The cursor will not move in the next call to Scan.
Example ¶
This example demonstrates scanning a key range in a database. Set is used to move the cursor's starting position to the desired prefix.
package main import ( "bytes" "log" "github.com/PowerDNS/lmdb-go/lmdb" "github.com/PowerDNS/lmdb-go/lmdbscan" ) var env *lmdb.Env var dbi lmdb.DBI func main() { keyprefix := []byte("users:") err := env.View(func(txn *lmdb.Txn) (err error) { scanner := lmdbscan.New(txn, dbi) defer scanner.Close() scanner.Set(keyprefix, nil, lmdb.SetRange) for scanner.Scan() { if !bytes.HasPrefix(scanner.Key(), keyprefix) { break } log.Printf("k=%q v=%q", scanner.Key(), scanner.Val()) } return scanner.Err() }) if err != nil { panic(err) } }
Output:
func (*Scanner) SetNext ¶
SetNext moves the cursor like s.Set(k, v, opset) for the next call to s.Scan(). Subsequent calls to s.Scan() move the cursor as c.Get(nil, nil, opnext)
Example ¶
This example demonstrates scanning all values for a key in a root database with the lmdb.DupSort flag set. SetNext is used instead of Set to configure Cursor the to return ErrNotFound (EOF) after all duplicate keys have been iterated.
package main import ( "log" "github.com/PowerDNS/lmdb-go/lmdb" "github.com/PowerDNS/lmdb-go/lmdbscan" ) var env *lmdb.Env var dbi lmdb.DBI func main() { key := []byte("userphone:123") err := env.View(func(txn *lmdb.Txn) (err error) { scanner := lmdbscan.New(txn, dbi) defer scanner.Close() scanner.SetNext(key, nil, lmdb.GetBothRange, lmdb.NextDup) for scanner.Scan() { log.Printf("k=%q v=%q", scanner.Key(), scanner.Val()) } return scanner.Err() }) if err != nil { panic(err) } }
Output:
Example (GetMultiple) ¶
This advanced example demonstrates batch scanning of values for duplicate keys in a database with the lmdb.DupFixed and lmdb.DupSort flags set. The outer loop scans unique keys and the inner loop scans duplicate values. The GetMultiple op requires an additional check following its use to determine if no duplicates exist in the database.
package main import ( "log" "github.com/PowerDNS/lmdb-go/lmdb" "github.com/PowerDNS/lmdb-go/lmdbscan" ) var env *lmdb.Env var dbi lmdb.DBI func main() { err := env.View(func(txn *lmdb.Txn) (err error) { scanner := lmdbscan.New(txn, dbi) defer scanner.Close() for scanner.Set(nil, nil, lmdb.NextNoDup) { key := scanner.Key() valFirst := scanner.Val() var vals [][]byte if !scanner.SetNext(nil, nil, lmdb.GetMultiple, lmdb.NextMultiple) { // only one value exists for the key, and it has been scanned. vals = append(vals, valFirst) } for scanner.Scan() { // this loop is only entered if multiple values exist for key. multi := lmdb.WrapMulti(scanner.Val(), len(valFirst)) vals = append(vals, multi.Vals()...) } log.Printf("k=%q v=%q", key, vals) if scanner.Err() != nil { break } } return scanner.Err() }) if err != nil { panic(err) } }
Output:
Example (NextNoDup) ¶
This example demonstrates scanning all values for duplicate keys in a database with the lmdb.DupSort flag set. Two loops are used to iterate over unique keys and their values respectively. The example exploits the return value from SetNext as the termination condition for the first loop.
package main import ( "log" "github.com/PowerDNS/lmdb-go/lmdb" "github.com/PowerDNS/lmdb-go/lmdbscan" ) var env *lmdb.Env var dbi lmdb.DBI func main() { err := env.View(func(txn *lmdb.Txn) (err error) { scanner := lmdbscan.New(txn, dbi) defer scanner.Close() for scanner.SetNext(nil, nil, lmdb.NextNoDup, lmdb.NextDup) { key := scanner.Key() var vals [][]byte for scanner.Scan() { vals = append(vals, scanner.Val()) } log.Printf("k=%q v=%q", key, vals) if scanner.Err() != nil { break } } return scanner.Err() }) if err != nil { panic(err) } }
Output: