func (t *Table) Index(index string) *Index {
	return t.indexes[Name(index)]
}
Index returns the index object of an index of the table. If the index does
not exist, nil is returned.
package cete
import (
	"bytes"
	"errors"
	"log"
	"os"
	"reflect"
	"runtime/debug"
	"sync"
	"github.com/1lann/badger"
	"github.com/1lann/msgpack"
)
func (d *DB) NewTable(name string, keyCompression ...bool) error {
	if name == "" || len(name) > 125 {
		return ErrBadIdentifier
	}
	useKeyCompression := true
	if len(keyCompression) > 0 {
		useKeyCompression = keyCompression[0]
	}
	d.configMutex.Lock()
	defer d.configMutex.Unlock()
	for _, table := range d.config.Tables {
		if table.TableName == name {
			return ErrAlreadyExists
		}
	}
	kv, err := d.newKV(Name(name))
	if err != nil {
		return err
	}
	d.config.Tables = append(d.config.Tables, tableConfig{
		TableName:         name,
		UseKeyCompression: useKeyCompression,
	})
	if err := d.writeConfig(); err != nil {
		return err
	}
	tb := &Table{
		indexes: make(map[Name]*Index),
		data:    kv,
		db:      d,
	}
	if useKeyCompression {
		tb.compressionLock = new(sync.RWMutex)
		tb.keyToCompressed = make(map[string]string)
		tb.compressedToKey = make(map[string]string)
		tb.nextKey = "0"
	}
	d.tables[Name(name)] = tb
	return nil
}
func (t *Table) Drop() error {
	t.db.configMutex.Lock()
	defer t.db.configMutex.Unlock()
	var tableName Name
	for name, table := range t.db.tables {
		if t == table {
			tableName = name
		}
	}
	if string(tableName) == "" {
		return ErrNotFound
	}
	for i, table := range t.db.config.Tables {
		if table.TableName == string(tableName) {
			t.db.config.Tables = append(t.db.config.Tables[:i],
				t.db.config.Tables[i+1:]...)
			break
		}
	}
	if err := t.db.writeConfig(); err != nil {
		return err
	}
	for _, index := range t.indexes {
		index.index.Close()
	}
	t.data.Close()
	delete(t.db.tables, tableName)
	return os.RemoveAll(t.db.path + "/" + tableName.Hex())
}
func (t *Table) Get(key string, dst interface{}) (uint64, error) {
	var item badger.KVItem
	err := t.data.Get([]byte(key), &item)
	if err != nil {
		return 0, err
	}
	itemValue := getItemValue(&item)
	if itemValue == nil {
		return 0, ErrNotFound
	}
	if dst == nil {
		return item.Counter(), nil
	}
	if t.keyToCompressed != nil {
		return item.Counter(), msgpack.UnmarshalCompressed(t.cToKey,
			itemValue, dst)
	}
	return item.Counter(), msgpack.Unmarshal(itemValue, dst)
}
func (t *Table) Set(key string, value interface{}, counter ...uint64) error {
	var item badger.KVItem
	err := t.data.Get([]byte(key), &item)
	if err != nil {
		return err
	}
	if len(counter) > 0 {
		if item.Counter() != counter[0] {
			return ErrCounterChanged
		}
	}
	var data []byte
	if t.keyToCompressed != nil {
		data, err = msgpack.MarshalCompressed(t.keyToC, value)
	} else {
		data, err = msgpack.Marshal(value)
	}
	if err != nil {
		return err
	}
	if len(counter) > 0 {
		if counter[0] == 0 {
			err = t.data.SetIfAbsent([]byte(key), data, 0)
		} else {
			err = t.data.CompareAndSet([]byte(key), data, counter[0])
		}
	} else {
		err = t.data.Set([]byte(key), data, 0)
	}
	if err == badger.ErrCasMismatch || err == badger.ErrKeyExists {
		return ErrCounterChanged
	}
	if err != nil {
		return err
	}
	t.updateIndex(key, getItemValue(&item), data)
	return nil
}
type diffEntry struct {
	indexName string
	indexKey  []byte
}
func (t *Table) diffIndexes(old, new []byte) ([]diffEntry, []diffEntry) {
	var removals []diffEntry
	var additions []diffEntry
	for indexName, index := range t.indexes {
		oldRawValues, _ := index.indexQuery(old, string(indexName))
		newRawValues, _ := index.indexQuery(new, string(indexName))
		if oldRawValues == nil || len(old) == 0 {
			oldRawValues = []interface{}{}
		}
		if newRawValues == nil || len(new) == 0 {
			newRawValues = []interface{}{}
		}
		oldValues := make([][]byte, len(oldRawValues))
		newValues := make([][]byte, len(newRawValues))
		for i, oldRawValue := range oldRawValues {
			oldValues[i] = valueToBytes(oldRawValue)
		}
		for i, newRawValue := range newRawValues {
			newValues[i] = valueToBytes(newRawValue)
		}
		additions = append(additions, getOneWayDiffs(string(indexName),
			newValues, oldValues)...)
		removals = append(removals, getOneWayDiffs(string(indexName),
			oldValues, newValues)...)
	}
	return additions, removals
}
func getOneWayDiffs(indexName string, a, b [][]byte) []diffEntry {
	var results []diffEntry
	for _, aa := range a {
		found := false
		for _, bb := range b {
			if bytes.Equal(bb, aa) {
				found = true
				break
			}
		}
		if !found {
			results = append(results, diffEntry{indexName, aa})
		}
	}
	return results
}
func (t *Table) updateIndex(key string, old, new []byte) error {
	additions, removals := t.diffIndexes(old, new)
	var lastError error
	for _, removal := range removals {
		err := t.Index(removal.indexName).deleteFromIndex(removal.indexKey, key)
		if err != nil {
			log.Println("cete: error while updating index \""+
				removal.indexName+"\", index likely corrupt:", err)
			lastError = err
		}
	}
	for _, addition := range additions {
		err := t.Index(addition.indexName).addToIndex(addition.indexKey, key)
		if err != nil {
			log.Println("cete: error while updating index \""+
				addition.indexName+"\", index likely corrupt:", err)
			lastError = err
		}
	}
	return lastError
}
func (i *Index) deleteFromIndex(indexKey []byte, key string) error {
	var item badger.KVItem
	for {
		err := i.index.Get(indexKey, &item)
		if err != nil {
			return err
		}
		itemValue := getItemValue(&item)
		if itemValue == nil {
			log.Println("cete: warning: corrupt index detected:", i.name())
			return nil
		}
		var list []string
		err = msgpack.Unmarshal(itemValue, &list)
		if err != nil {
			log.Println("cete: warning: corrupt index detected:", i.name())
			return err
		}
		found := false
		for k, v := range list {
			if v == key {
				found = true
				list = append(list[:k], list[k+1:]...)
				break
			}
		}
		if !found {
			log.Println("cete: warning: corrupt index detected:", i.name())
			return nil
		}
		if len(list) == 0 {
			err = i.index.CompareAndDelete(indexKey, item.Counter())
			if err == badger.ErrCasMismatch {
				continue
			}
			return err
		}
		data, err := msgpack.Marshal(list)
		if err != nil {
			log.Fatal("cete: marshal should never fail: ", err)
		}
		err = i.index.CompareAndSet(indexKey, data, item.Counter())
		if err == badger.ErrCasMismatch {
			continue
		}
		return err
	}
}
func (i *Index) addToIndex(indexKey []byte, key string) error {
	var item badger.KVItem
	for {
		err := i.index.Get(indexKey, &item)
		if err != nil {
			return err
		}
		var list []string
		itemValue := getItemValue(&item)
		if itemValue != nil {
			err = msgpack.Unmarshal(itemValue, &list)
			if err != nil {
				log.Println("cete: warning: corrupt index detected:", i.name())
				return err
			}
		}
		for _, item := range list {
			if item == key {
				return nil
			}
		}
		list = append(list, key)
		data, err := msgpack.Marshal(list)
		if err != nil {
			log.Fatal("cete: marshal should never fail: ", err)
		}
		if itemValue == nil {
			err = i.index.SetIfAbsent(indexKey, data, 0)
			if err == badger.ErrKeyExists {
				continue
			}
		} else {
			err = i.index.CompareAndSet(indexKey, data, item.Counter())
			if err == badger.ErrCasMismatch {
				continue
			}
		}
		return err
	}
}
func (i *Index) name() string {
	for indexName, index := range i.table.indexes {
		if index == i {
			return i.table.name() + "/" + string(indexName)
		}
	}
	return i.table.name() + "/__unknown_index"
}
func (t *Table) Delete(key string, counter ...uint64) error {
	var item badger.KVItem
	err := t.data.Get([]byte(key), &item)
	if err != nil {
		return err
	}
	itemValue := getItemValue(&item)
	if itemValue == nil {
		return nil
	}
	if len(counter) > 0 {
		if item.Counter() != counter[0] {
			return ErrCounterChanged
		}
		err = t.data.CompareAndDelete([]byte(key), counter[0])
	} else {
		err = t.data.Delete([]byte(key))
	}
	if err == badger.ErrCasMismatch {
		return ErrCounterChanged
	}
	if err != nil {
		return err
	}
	t.updateIndex(key, itemValue, nil)
	return nil
}