func (t *fileTemp) Set(k, v []interface{}) (err error) { if err = expand(k); err != nil { return } if err = expand(v); err != nil { return } infer(k, &t.colsK) infer(v, &t.colsV) if err = t.flatten(k); err != nil { return } bk, err := lldb.EncodeScalars(k...) if err != nil { return } if err = t.flatten(v); err != nil { return } bv, err := lldb.EncodeScalars(v...) if err != nil { return } return t.t.Set(bk, bv) }
func (x *fileIndex) Delete(indexedValues []interface{}, h int64) error { for i, indexedValue := range indexedValues { chunk, ok := indexedValue.(chunk) if ok { indexedValues[i] = chunk.b } } t := x.t var k []byte var err error switch { case !x.unique: k, err = lldb.EncodeScalars(append(indexedValues, h)...) case isIndexNull(indexedValues): // unique, NULL k, err = lldb.EncodeScalars(nil, h) default: // unique, non NULL k, err = lldb.EncodeScalars(append(indexedValues, int64(0))...) } if err != nil { return err } return t.Delete(k) }
// The []byte version of the key in the BTree shares chunks, if any, with // the value stored in the record. func (x *fileIndex) Create(indexedValues []interface{}, h int64) error { for i, indexedValue := range indexedValues { chunk, ok := indexedValue.(chunk) if ok { indexedValues[i] = chunk.b } } t := x.t switch { case !x.unique: k, err := lldb.EncodeScalars(append(indexedValues, h)...) if err != nil { return err } return t.Set(k, gbZeroInt64) case isIndexNull(indexedValues): // unique, NULL k, err := lldb.EncodeScalars(nil, h) if err != nil { return err } return t.Set(k, gbZeroInt64) default: // unique, non NULL k, err := lldb.EncodeScalars(append(indexedValues, int64(0))...) if err != nil { return err } v, err := lldb.EncodeScalars(h) if err != nil { return err } _, _, err = t.Put(nil, k, func(key, old []byte) (new []byte, write bool, err error) { if old == nil { return v, true, nil } return nil, false, fmt.Errorf("(file-018) cannot insert into unique index: duplicate value(s): %v", indexedValues) }) return err } }
func (s *file) Update(h int64, data ...interface{}) (err error) { b, err := lldb.EncodeScalars(data...) if err != nil { return } defer s.lock()() return s.a.Realloc(h, b) }
func (s *file) Create(data ...interface{}) (h int64, err error) { if err = expand(data); err != nil { return } if err = s.flatten(data); err != nil { return } b, err := lldb.EncodeScalars(data...) if err != nil { return } defer s.lock()() return s.a.Alloc(b) }
func (x *fileIndex) Seek(indexedValues []interface{}) (indexIterator, bool, error) { data := append(indexedValues, 0) if err := x.flatten(data); err != nil { return nil, false, err } k, err := lldb.EncodeScalars(data...) if err != nil { return nil, false, err } en, hit, err := x.t.Seek(k) if err != nil { return nil, false, err } return &fileIndexIterator{x.f, en, x.unique}, hit, nil }
func (t *fileTemp) Get(k []interface{}) (v []interface{}, err error) { if err = expand(k); err != nil { return } if err = t.flatten(k); err != nil { return nil, err } bk, err := lldb.EncodeScalars(k...) if err != nil { return } bv, err := t.t.Get(nil, bk) if err != nil { return } return lldb.DecodeScalars(bv) }
// []interface{}{qltype, ...}->[]interface{}{lldb scalar type, ...} func (x *fileIndex) flatten(data []interface{}) (err error) { for i, v := range data { tag := 0 var b []byte switch xx := v.(type) { case []byte: tag = qBlob b = xx case *big.Int: tag = qBigInt b, err = x.codec.encode(xx) case *big.Rat: tag = qBigRat b, err = x.codec.encode(xx) case time.Time: tag = qTime b, err = x.codec.encode(xx) case time.Duration: tag = qDuration b, err = x.codec.encode(xx) default: continue } if err != nil { return } var buf []byte if buf, err = lldb.EncodeScalars([]interface{}{tag, b}...); err != nil { return } data[i] = buf } return }
func init() { var err error if gbZeroInt64, err = lldb.EncodeScalars(int64(0)); err != nil { panic(err) } }
// []interface{}{qltype, ...}->[]interface{}{lldb scalar type, ...} // + long blobs are (pre)written to a chain of chunks. func (s *file) flatten(data []interface{}) (err error) { for i, v := range data { tag := 0 var b []byte switch x := v.(type) { case []byte: tag = qBlob b = x case *big.Int: tag = qBigInt b, err = s.codec.encode(x) case *big.Rat: tag = qBigRat b, err = s.codec.encode(x) case time.Time: tag = qTime b, err = s.codec.encode(x) case time.Duration: tag = qDuration b, err = s.codec.encode(x) default: continue } if err != nil { return } const chunk = 1 << 16 chunks := 0 var next int64 var buf []byte for rem := len(b); rem > shortBlob; { n := mathutil.Min(rem, chunk) part := b[rem-n:] b = b[:rem-n] rem -= n switch next { case 0: // last chunk buf, err = lldb.EncodeScalars([]interface{}{part}...) default: // middle chunk buf, err = lldb.EncodeScalars([]interface{}{next, part}...) } if err != nil { return } s.mu.Lock() h, err := s.a.Alloc(buf) s.mu.Unlock() if err != nil { return err } next = h chunks++ } switch next { case 0: // single chunk buf, err = lldb.EncodeScalars([]interface{}{tag, b}...) default: // multi chunks buf, err = lldb.EncodeScalars([]interface{}{tag, next, b}...) } if err != nil { return } data[i] = buf } return }