github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/kv/index_iter.go (about)

     1  // Copyright 2015 PingCAP, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package kv
    15  
    16  import (
    17  	"bytes"
    18  	"encoding/binary"
    19  	"io"
    20  
    21  	"github.com/insionng/yougam/libraries/juju/errors"
    22  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/codec"
    23  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/types"
    24  )
    25  
    26  var (
    27  	_ Index         = (*kvIndex)(nil)
    28  	_ IndexIterator = (*indexIter)(nil)
    29  )
    30  
    31  // IndexIterator is the interface for iterator of index data on KV store.
    32  type IndexIterator interface {
    33  	Next() (k []types.Datum, h int64, err error)
    34  	Close()
    35  }
    36  
    37  // Index is the interface for index data on KV store.
    38  type Index interface {
    39  	// Create supports insert into statement.
    40  	Create(rm RetrieverMutator, indexedValues []types.Datum, h int64) error
    41  	// Delete supports delete from statement.
    42  	Delete(m Mutator, indexedValues []types.Datum, h int64) error
    43  	// Drop supports drop table, drop index statements.
    44  	Drop(rm RetrieverMutator) error
    45  	// Exist supports check index exists or not.
    46  	Exist(rm RetrieverMutator, indexedValues []types.Datum, h int64) (bool, int64, error)
    47  	// GenIndexKey generates an index key.
    48  	GenIndexKey(indexedValues []types.Datum, h int64) (key []byte, distinct bool, err error)
    49  	// Seek supports where clause.
    50  	Seek(r Retriever, indexedValues []types.Datum) (iter IndexIterator, hit bool, err error)
    51  	// SeekFirst supports aggregate min and ascend order by.
    52  	SeekFirst(r Retriever) (iter IndexIterator, err error)
    53  }
    54  
    55  func encodeHandle(h int64) []byte {
    56  	buf := &bytes.Buffer{}
    57  	err := binary.Write(buf, binary.BigEndian, h)
    58  	if err != nil {
    59  		panic(err)
    60  	}
    61  	return buf.Bytes()
    62  }
    63  
    64  func decodeHandle(data []byte) (int64, error) {
    65  	var h int64
    66  	buf := bytes.NewBuffer(data)
    67  	err := binary.Read(buf, binary.BigEndian, &h)
    68  	return h, errors.Trace(err)
    69  }
    70  
    71  // indexIter is for KV store index iterator.
    72  type indexIter struct {
    73  	it     Iterator
    74  	idx    *kvIndex
    75  	prefix Key
    76  }
    77  
    78  // Close does the clean up works when KV store index iterator is closed.
    79  func (c *indexIter) Close() {
    80  	if c.it != nil {
    81  		c.it.Close()
    82  		c.it = nil
    83  	}
    84  }
    85  
    86  // Next returns current key and moves iterator to the next step.
    87  func (c *indexIter) Next() (val []types.Datum, h int64, err error) {
    88  	if !c.it.Valid() {
    89  		return nil, 0, errors.Trace(io.EOF)
    90  	}
    91  	if !c.it.Key().HasPrefix(c.prefix) {
    92  		return nil, 0, errors.Trace(io.EOF)
    93  	}
    94  	// get indexedValues
    95  	buf := c.it.Key()[len(c.prefix):]
    96  	vv, err := codec.Decode(buf)
    97  	if err != nil {
    98  		return nil, 0, errors.Trace(err)
    99  	}
   100  	// if index is *not* unique, the handle is in keybuf
   101  	if !c.idx.unique {
   102  		h = vv[len(vv)-1].GetInt64()
   103  		val = vv[0 : len(vv)-1]
   104  	} else {
   105  		// otherwise handle is value
   106  		h, err = decodeHandle(c.it.Value())
   107  		if err != nil {
   108  			return nil, 0, errors.Trace(err)
   109  		}
   110  		val = vv
   111  	}
   112  	// update new iter to next
   113  	err = c.it.Next()
   114  	if err != nil {
   115  		return nil, 0, errors.Trace(err)
   116  	}
   117  	return
   118  }
   119  
   120  // kvIndex is the data structure for index data in the KV store.
   121  type kvIndex struct {
   122  	indexName string
   123  	indexID   int64
   124  	unique    bool
   125  	prefix    Key
   126  }
   127  
   128  // GenIndexPrefix generates the index prefix.
   129  func GenIndexPrefix(indexPrefix Key, indexID int64) Key {
   130  	buf := make([]byte, 0, len(indexPrefix)+8)
   131  	buf = append(buf, indexPrefix...)
   132  	buf = codec.EncodeInt(buf, indexID)
   133  	return buf
   134  }
   135  
   136  // NewKVIndex builds a new kvIndex object.
   137  func NewKVIndex(indexPrefix Key, indexName string, indexID int64, unique bool) Index {
   138  	index := &kvIndex{
   139  		indexName: indexName,
   140  		indexID:   indexID,
   141  		unique:    unique,
   142  		prefix:    GenIndexPrefix(indexPrefix, indexID),
   143  	}
   144  
   145  	return index
   146  }
   147  
   148  // GenIndexKey generates storage key for index values. Returned distinct indicates whether the
   149  // indexed values should be distinct in storage (i.e. whether handle is encoded in the key).
   150  func (c *kvIndex) GenIndexKey(indexedValues []types.Datum, h int64) (key []byte, distinct bool, err error) {
   151  	if c.unique {
   152  		// See: https://dev.mysql.com/doc/refman/5.7/en/create-index.html
   153  		// A UNIQUE index creates a constraint such that all values in the index must be distinct.
   154  		// An error occurs if you try to add a new row with a key value that matches an existing row.
   155  		// For all engines, a UNIQUE index permits multiple NULL values for columns that can contain NULL.
   156  		distinct = true
   157  		for _, cv := range indexedValues {
   158  			if cv.Kind() == types.KindNull {
   159  				distinct = false
   160  				break
   161  			}
   162  		}
   163  	}
   164  
   165  	key = append(key, c.prefix...)
   166  	if distinct {
   167  		key, err = codec.EncodeKey(key, indexedValues...)
   168  	} else {
   169  		key, err = codec.EncodeKey(key, append(indexedValues, types.NewDatum(h))...)
   170  	}
   171  	if err != nil {
   172  		return nil, false, errors.Trace(err)
   173  	}
   174  	return
   175  }
   176  
   177  // Create creates a new entry in the kvIndex data.
   178  // If the index is unique and there is an existing entry with the same key, Create will return ErrKeyExists.
   179  func (c *kvIndex) Create(rm RetrieverMutator, indexedValues []types.Datum, h int64) error {
   180  	key, distinct, err := c.GenIndexKey(indexedValues, h)
   181  	if err != nil {
   182  		return errors.Trace(err)
   183  	}
   184  	if !distinct {
   185  		// TODO: reconsider value
   186  		err = rm.Set(key, []byte("timestamp?"))
   187  		return errors.Trace(err)
   188  	}
   189  
   190  	_, err = rm.Get(key)
   191  	if IsErrNotFound(err) {
   192  		err = rm.Set(key, encodeHandle(h))
   193  		return errors.Trace(err)
   194  	}
   195  
   196  	return errors.Trace(ErrKeyExists)
   197  }
   198  
   199  // Delete removes the entry for handle h and indexdValues from KV index.
   200  func (c *kvIndex) Delete(m Mutator, indexedValues []types.Datum, h int64) error {
   201  	key, _, err := c.GenIndexKey(indexedValues, h)
   202  	if err != nil {
   203  		return errors.Trace(err)
   204  	}
   205  	err = m.Delete(key)
   206  	return errors.Trace(err)
   207  }
   208  
   209  // Drop removes the KV index from store.
   210  func (c *kvIndex) Drop(rm RetrieverMutator) error {
   211  	it, err := rm.Seek(c.prefix)
   212  	if err != nil {
   213  		return errors.Trace(err)
   214  	}
   215  	defer it.Close()
   216  
   217  	// remove all indices
   218  	for it.Valid() {
   219  		if !it.Key().HasPrefix(c.prefix) {
   220  			break
   221  		}
   222  		err := rm.Delete(it.Key())
   223  		if err != nil {
   224  			return errors.Trace(err)
   225  		}
   226  		err = it.Next()
   227  		if err != nil {
   228  			return errors.Trace(err)
   229  		}
   230  	}
   231  	return nil
   232  }
   233  
   234  // Seek searches KV index for the entry with indexedValues.
   235  func (c *kvIndex) Seek(r Retriever, indexedValues []types.Datum) (iter IndexIterator, hit bool, err error) {
   236  	key, _, err := c.GenIndexKey(indexedValues, 0)
   237  	if err != nil {
   238  		return nil, false, errors.Trace(err)
   239  	}
   240  	it, err := r.Seek(key)
   241  	if err != nil {
   242  		return nil, false, errors.Trace(err)
   243  	}
   244  	// check if hit
   245  	hit = false
   246  	if it.Valid() && it.Key().Cmp(key) == 0 {
   247  		hit = true
   248  	}
   249  	return &indexIter{it: it, idx: c, prefix: c.prefix}, hit, nil
   250  }
   251  
   252  // SeekFirst returns an iterator which points to the first entry of the KV index.
   253  func (c *kvIndex) SeekFirst(r Retriever) (iter IndexIterator, err error) {
   254  	it, err := r.Seek(c.prefix)
   255  	if err != nil {
   256  		return nil, errors.Trace(err)
   257  	}
   258  	return &indexIter{it: it, idx: c, prefix: c.prefix}, nil
   259  }
   260  
   261  func (c *kvIndex) Exist(rm RetrieverMutator, indexedValues []types.Datum, h int64) (bool, int64, error) {
   262  	key, distinct, err := c.GenIndexKey(indexedValues, h)
   263  	if err != nil {
   264  		return false, 0, errors.Trace(err)
   265  	}
   266  
   267  	value, err := rm.Get(key)
   268  	if IsErrNotFound(err) {
   269  		return false, 0, nil
   270  	}
   271  	if err != nil {
   272  		return false, 0, errors.Trace(err)
   273  	}
   274  
   275  	// For distinct index, the value of key is handle.
   276  	if distinct {
   277  		handle, err := decodeHandle(value)
   278  		if err != nil {
   279  			return false, 0, errors.Trace(err)
   280  		}
   281  
   282  		if handle != h {
   283  			return true, handle, errors.Trace(ErrKeyExists)
   284  		}
   285  
   286  		return true, handle, nil
   287  	}
   288  
   289  	return true, h, nil
   290  }