lmdbscan

package
Version: v1.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 20, 2021 License: BSD-3-Clause Imports: 2 Imported by: 0

Documentation

Overview

Package lmdbscan provides a wrapper for lmdb.Cursor to simplify iteration.

Index

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

func New(txn *lmdb.Txn, dbi lmdb.DBI) *Scanner

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

func (s *Scanner) Cursor() *lmdb.Cursor

Cursor returns the lmdb.Cursor underlying s. Cursor returns nil if s is closed.

func (*Scanner) Del

func (s *Scanner) Del(flags uint) error

Del will delete the key at the current cursor location.

Del is deprecated. Instead use s.Cursor().Del(flags).

func (*Scanner) Err

func (s *Scanner) Err() error

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) Key

func (s *Scanner) Key() []byte

Key returns the key read during the last call to Scan.

func (*Scanner) Scan

func (s *Scanner) Scan() bool

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

func (s *Scanner) Set(k, v []byte, opset uint) bool

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

func (s *Scanner) SetNext(k, v []byte, opset, opnext uint) bool

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:

func (*Scanner) Val

func (s *Scanner) Val() []byte

Val returns the value read during the last call to Scan.

Source Files

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
t or T : Toggle theme light dark auto
y or Y : Canonical URL