clone
This commit is contained in:
14
vendor/github.com/asdine/storm/v3/index/errors.go
generated
vendored
Normal file
14
vendor/github.com/asdine/storm/v3/index/errors.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
package index
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
// ErrNotFound is returned when the specified record is not saved in the bucket.
|
||||
ErrNotFound = errors.New("not found")
|
||||
|
||||
// ErrAlreadyExists is returned uses when trying to set an existing value on a field that has a unique index.
|
||||
ErrAlreadyExists = errors.New("already exists")
|
||||
|
||||
// ErrNilParam is returned when the specified param is expected to be not nil.
|
||||
ErrNilParam = errors.New("param must not be nil")
|
||||
)
|
14
vendor/github.com/asdine/storm/v3/index/indexes.go
generated
vendored
Normal file
14
vendor/github.com/asdine/storm/v3/index/indexes.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// Package index contains Index engines used to store values and their corresponding IDs
|
||||
package index
|
||||
|
||||
// Index interface
|
||||
type Index interface {
|
||||
Add(value []byte, targetID []byte) error
|
||||
Remove(value []byte) error
|
||||
RemoveID(id []byte) error
|
||||
Get(value []byte) []byte
|
||||
All(value []byte, opts *Options) ([][]byte, error)
|
||||
AllRecords(opts *Options) ([][]byte, error)
|
||||
Range(min []byte, max []byte, opts *Options) ([][]byte, error)
|
||||
Prefix(prefix []byte, opts *Options) ([][]byte, error)
|
||||
}
|
283
vendor/github.com/asdine/storm/v3/index/list.go
generated
vendored
Normal file
283
vendor/github.com/asdine/storm/v3/index/list.go
generated
vendored
Normal file
@ -0,0 +1,283 @@
|
||||
package index
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/asdine/storm/v3/internal"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
// NewListIndex loads a ListIndex
|
||||
func NewListIndex(parent *bolt.Bucket, indexName []byte) (*ListIndex, error) {
|
||||
var err error
|
||||
b := parent.Bucket(indexName)
|
||||
if b == nil {
|
||||
if !parent.Writable() {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
b, err = parent.CreateBucket(indexName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
ids, err := NewUniqueIndex(b, []byte("storm__ids"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ListIndex{
|
||||
IndexBucket: b,
|
||||
Parent: parent,
|
||||
IDs: ids,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListIndex is an index that references values and the corresponding IDs.
|
||||
type ListIndex struct {
|
||||
Parent *bolt.Bucket
|
||||
IndexBucket *bolt.Bucket
|
||||
IDs *UniqueIndex
|
||||
}
|
||||
|
||||
// Add a value to the list index
|
||||
func (idx *ListIndex) Add(newValue []byte, targetID []byte) error {
|
||||
if newValue == nil || len(newValue) == 0 {
|
||||
return ErrNilParam
|
||||
}
|
||||
if targetID == nil || len(targetID) == 0 {
|
||||
return ErrNilParam
|
||||
}
|
||||
|
||||
key := idx.IDs.Get(targetID)
|
||||
if key != nil {
|
||||
err := idx.IndexBucket.Delete(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = idx.IDs.Remove(targetID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key = key[:0]
|
||||
}
|
||||
|
||||
key = append(key, newValue...)
|
||||
key = append(key, '_')
|
||||
key = append(key, '_')
|
||||
key = append(key, targetID...)
|
||||
|
||||
err := idx.IDs.Add(targetID, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return idx.IndexBucket.Put(key, targetID)
|
||||
}
|
||||
|
||||
// Remove a value from the unique index
|
||||
func (idx *ListIndex) Remove(value []byte) error {
|
||||
var err error
|
||||
var keys [][]byte
|
||||
|
||||
c := idx.IndexBucket.Cursor()
|
||||
prefix := generatePrefix(value)
|
||||
|
||||
for k, _ := c.Seek(prefix); bytes.HasPrefix(k, prefix); k, _ = c.Next() {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
for _, k := range keys {
|
||||
err = idx.IndexBucket.Delete(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return idx.IDs.RemoveID(value)
|
||||
}
|
||||
|
||||
// RemoveID removes an ID from the list index
|
||||
func (idx *ListIndex) RemoveID(targetID []byte) error {
|
||||
value := idx.IDs.Get(targetID)
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := idx.IndexBucket.Delete(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return idx.IDs.Remove(targetID)
|
||||
}
|
||||
|
||||
// Get the first ID corresponding to the given value
|
||||
func (idx *ListIndex) Get(value []byte) []byte {
|
||||
c := idx.IndexBucket.Cursor()
|
||||
prefix := generatePrefix(value)
|
||||
|
||||
for k, id := c.Seek(prefix); bytes.HasPrefix(k, prefix); k, id = c.Next() {
|
||||
return id
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// All the IDs corresponding to the given value
|
||||
func (idx *ListIndex) All(value []byte, opts *Options) ([][]byte, error) {
|
||||
var list [][]byte
|
||||
c := idx.IndexBucket.Cursor()
|
||||
cur := internal.Cursor{C: c, Reverse: opts != nil && opts.Reverse}
|
||||
|
||||
prefix := generatePrefix(value)
|
||||
|
||||
k, id := c.Seek(prefix)
|
||||
if cur.Reverse {
|
||||
var count int
|
||||
kc := k
|
||||
idc := id
|
||||
for ; kc != nil && bytes.HasPrefix(kc, prefix); kc, idc = c.Next() {
|
||||
count++
|
||||
k, id = kc, idc
|
||||
}
|
||||
if kc != nil {
|
||||
k, id = c.Prev()
|
||||
}
|
||||
list = make([][]byte, 0, count)
|
||||
}
|
||||
|
||||
for ; bytes.HasPrefix(k, prefix); k, id = cur.Next() {
|
||||
if opts != nil && opts.Skip > 0 {
|
||||
opts.Skip--
|
||||
continue
|
||||
}
|
||||
|
||||
if opts != nil && opts.Limit == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if opts != nil && opts.Limit > 0 {
|
||||
opts.Limit--
|
||||
}
|
||||
|
||||
list = append(list, id)
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// AllRecords returns all the IDs of this index
|
||||
func (idx *ListIndex) AllRecords(opts *Options) ([][]byte, error) {
|
||||
var list [][]byte
|
||||
|
||||
c := internal.Cursor{C: idx.IndexBucket.Cursor(), Reverse: opts != nil && opts.Reverse}
|
||||
|
||||
for k, id := c.First(); k != nil; k, id = c.Next() {
|
||||
if id == nil || bytes.Equal(k, []byte("storm__ids")) {
|
||||
continue
|
||||
}
|
||||
|
||||
if opts != nil && opts.Skip > 0 {
|
||||
opts.Skip--
|
||||
continue
|
||||
}
|
||||
|
||||
if opts != nil && opts.Limit == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if opts != nil && opts.Limit > 0 {
|
||||
opts.Limit--
|
||||
}
|
||||
|
||||
list = append(list, id)
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// Range returns the ids corresponding to the given range of values
|
||||
func (idx *ListIndex) Range(min []byte, max []byte, opts *Options) ([][]byte, error) {
|
||||
var list [][]byte
|
||||
|
||||
c := internal.RangeCursor{
|
||||
C: idx.IndexBucket.Cursor(),
|
||||
Reverse: opts != nil && opts.Reverse,
|
||||
Min: min,
|
||||
Max: max,
|
||||
CompareFn: func(val, limit []byte) int {
|
||||
pos := bytes.LastIndex(val, []byte("__"))
|
||||
return bytes.Compare(val[:pos], limit)
|
||||
},
|
||||
}
|
||||
|
||||
for k, id := c.First(); c.Continue(k); k, id = c.Next() {
|
||||
if id == nil || bytes.Equal(k, []byte("storm__ids")) {
|
||||
continue
|
||||
}
|
||||
|
||||
if opts != nil && opts.Skip > 0 {
|
||||
opts.Skip--
|
||||
continue
|
||||
}
|
||||
|
||||
if opts != nil && opts.Limit == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if opts != nil && opts.Limit > 0 {
|
||||
opts.Limit--
|
||||
}
|
||||
|
||||
list = append(list, id)
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// Prefix returns the ids whose values have the given prefix.
|
||||
func (idx *ListIndex) Prefix(prefix []byte, opts *Options) ([][]byte, error) {
|
||||
var list [][]byte
|
||||
|
||||
c := internal.PrefixCursor{
|
||||
C: idx.IndexBucket.Cursor(),
|
||||
Reverse: opts != nil && opts.Reverse,
|
||||
Prefix: prefix,
|
||||
}
|
||||
|
||||
for k, id := c.First(); k != nil && c.Continue(k); k, id = c.Next() {
|
||||
if id == nil || bytes.Equal(k, []byte("storm__ids")) {
|
||||
continue
|
||||
}
|
||||
|
||||
if opts != nil && opts.Skip > 0 {
|
||||
opts.Skip--
|
||||
continue
|
||||
}
|
||||
|
||||
if opts != nil && opts.Limit == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if opts != nil && opts.Limit > 0 {
|
||||
opts.Limit--
|
||||
}
|
||||
|
||||
list = append(list, id)
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func generatePrefix(value []byte) []byte {
|
||||
prefix := make([]byte, len(value)+2)
|
||||
var i int
|
||||
for i = range value {
|
||||
prefix[i] = value[i]
|
||||
}
|
||||
prefix[i+1] = '_'
|
||||
prefix[i+2] = '_'
|
||||
return prefix
|
||||
}
|
15
vendor/github.com/asdine/storm/v3/index/options.go
generated
vendored
Normal file
15
vendor/github.com/asdine/storm/v3/index/options.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
package index
|
||||
|
||||
// NewOptions creates initialized Options
|
||||
func NewOptions() *Options {
|
||||
return &Options{
|
||||
Limit: -1,
|
||||
}
|
||||
}
|
||||
|
||||
// Options are used to customize queries
|
||||
type Options struct {
|
||||
Limit int
|
||||
Skip int
|
||||
Reverse bool
|
||||
}
|
183
vendor/github.com/asdine/storm/v3/index/unique.go
generated
vendored
Normal file
183
vendor/github.com/asdine/storm/v3/index/unique.go
generated
vendored
Normal file
@ -0,0 +1,183 @@
|
||||
package index
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/asdine/storm/v3/internal"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
// NewUniqueIndex loads a UniqueIndex
|
||||
func NewUniqueIndex(parent *bolt.Bucket, indexName []byte) (*UniqueIndex, error) {
|
||||
var err error
|
||||
b := parent.Bucket(indexName)
|
||||
if b == nil {
|
||||
if !parent.Writable() {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
b, err = parent.CreateBucket(indexName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &UniqueIndex{
|
||||
IndexBucket: b,
|
||||
Parent: parent,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UniqueIndex is an index that references unique values and the corresponding ID.
|
||||
type UniqueIndex struct {
|
||||
Parent *bolt.Bucket
|
||||
IndexBucket *bolt.Bucket
|
||||
}
|
||||
|
||||
// Add a value to the unique index
|
||||
func (idx *UniqueIndex) Add(value []byte, targetID []byte) error {
|
||||
if value == nil || len(value) == 0 {
|
||||
return ErrNilParam
|
||||
}
|
||||
if targetID == nil || len(targetID) == 0 {
|
||||
return ErrNilParam
|
||||
}
|
||||
|
||||
exists := idx.IndexBucket.Get(value)
|
||||
if exists != nil {
|
||||
if bytes.Equal(exists, targetID) {
|
||||
return nil
|
||||
}
|
||||
return ErrAlreadyExists
|
||||
}
|
||||
|
||||
return idx.IndexBucket.Put(value, targetID)
|
||||
}
|
||||
|
||||
// Remove a value from the unique index
|
||||
func (idx *UniqueIndex) Remove(value []byte) error {
|
||||
return idx.IndexBucket.Delete(value)
|
||||
}
|
||||
|
||||
// RemoveID removes an ID from the unique index
|
||||
func (idx *UniqueIndex) RemoveID(id []byte) error {
|
||||
c := idx.IndexBucket.Cursor()
|
||||
|
||||
for val, ident := c.First(); val != nil; val, ident = c.Next() {
|
||||
if bytes.Equal(ident, id) {
|
||||
return idx.Remove(val)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get the id corresponding to the given value
|
||||
func (idx *UniqueIndex) Get(value []byte) []byte {
|
||||
return idx.IndexBucket.Get(value)
|
||||
}
|
||||
|
||||
// All returns all the ids corresponding to the given value
|
||||
func (idx *UniqueIndex) All(value []byte, opts *Options) ([][]byte, error) {
|
||||
id := idx.IndexBucket.Get(value)
|
||||
if id != nil {
|
||||
return [][]byte{id}, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// AllRecords returns all the IDs of this index
|
||||
func (idx *UniqueIndex) AllRecords(opts *Options) ([][]byte, error) {
|
||||
var list [][]byte
|
||||
|
||||
c := internal.Cursor{C: idx.IndexBucket.Cursor(), Reverse: opts != nil && opts.Reverse}
|
||||
|
||||
for val, ident := c.First(); val != nil; val, ident = c.Next() {
|
||||
if opts != nil && opts.Skip > 0 {
|
||||
opts.Skip--
|
||||
continue
|
||||
}
|
||||
|
||||
if opts != nil && opts.Limit == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if opts != nil && opts.Limit > 0 {
|
||||
opts.Limit--
|
||||
}
|
||||
|
||||
list = append(list, ident)
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// Range returns the ids corresponding to the given range of values
|
||||
func (idx *UniqueIndex) Range(min []byte, max []byte, opts *Options) ([][]byte, error) {
|
||||
var list [][]byte
|
||||
|
||||
c := internal.RangeCursor{
|
||||
C: idx.IndexBucket.Cursor(),
|
||||
Reverse: opts != nil && opts.Reverse,
|
||||
Min: min,
|
||||
Max: max,
|
||||
CompareFn: func(val, limit []byte) int {
|
||||
return bytes.Compare(val, limit)
|
||||
},
|
||||
}
|
||||
|
||||
for val, ident := c.First(); val != nil && c.Continue(val); val, ident = c.Next() {
|
||||
if opts != nil && opts.Skip > 0 {
|
||||
opts.Skip--
|
||||
continue
|
||||
}
|
||||
|
||||
if opts != nil && opts.Limit == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if opts != nil && opts.Limit > 0 {
|
||||
opts.Limit--
|
||||
}
|
||||
|
||||
list = append(list, ident)
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// Prefix returns the ids whose values have the given prefix.
|
||||
func (idx *UniqueIndex) Prefix(prefix []byte, opts *Options) ([][]byte, error) {
|
||||
var list [][]byte
|
||||
|
||||
c := internal.PrefixCursor{
|
||||
C: idx.IndexBucket.Cursor(),
|
||||
Reverse: opts != nil && opts.Reverse,
|
||||
Prefix: prefix,
|
||||
}
|
||||
|
||||
for val, ident := c.First(); val != nil && c.Continue(val); val, ident = c.Next() {
|
||||
if opts != nil && opts.Skip > 0 {
|
||||
opts.Skip--
|
||||
continue
|
||||
}
|
||||
|
||||
if opts != nil && opts.Limit == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if opts != nil && opts.Limit > 0 {
|
||||
opts.Limit--
|
||||
}
|
||||
|
||||
list = append(list, ident)
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// first returns the first ID of this index
|
||||
func (idx *UniqueIndex) first() []byte {
|
||||
c := idx.IndexBucket.Cursor()
|
||||
|
||||
for val, ident := c.First(); val != nil; val, ident = c.Next() {
|
||||
return ident
|
||||
}
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user