| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982 |
- // Copyright (c) 2014 ql Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package ql
- import (
- "fmt"
- "strings"
- )
- type storage interface {
- Acid() bool
- BeginTransaction() error
- Close() error
- Commit() error
- Create(data ...interface{}) (h int64, err error)
- CreateIndex(unique bool) (handle int64, x btreeIndex, err error)
- CreateTemp(asc bool) (bt temp, err error)
- Delete(h int64, blobCols ...*col) error //LATER split the nil blobCols case
- ID() (id int64, err error)
- Name() string
- OpenIndex(unique bool, handle int64) (btreeIndex, error) // Never called on the memory backend.
- Read(dst []interface{}, h int64, cols ...*col) (data []interface{}, err error)
- ResetID() (err error)
- Rollback() error
- Update(h int64, data ...interface{}) error
- UpdateRow(h int64, blobCols []*col, data ...interface{}) error
- Verify() (allocs int64, err error)
- }
- type btreeIterator interface {
- Next() (k, v []interface{}, err error)
- }
- type temp interface {
- BeginTransaction() error
- Create(data ...interface{}) (h int64, err error)
- Drop() (err error)
- Get(k []interface{}) (v []interface{}, err error)
- Read(dst []interface{}, h int64, cols ...*col) (data []interface{}, err error)
- SeekFirst() (e btreeIterator, err error)
- Set(k, v []interface{}) (err error)
- }
- type indexIterator interface {
- Next() (k []interface{}, h int64, err error)
- Prev() (k []interface{}, h int64, err error)
- }
- type btreeIndex interface {
- Clear() error // supports truncate table statement
- Create(indexedValues []interface{}, h int64) error // supports insert into statement
- Delete(indexedValues []interface{}, h int64) error // supports delete from statement
- Drop() error // supports drop table, drop index statements
- Seek(indexedValues []interface{}) (iter indexIterator, hit bool, err error) // supports where clause
- SeekFirst() (iter indexIterator, err error) // supports aggregate min / ascending order by
- SeekLast() (iter indexIterator, err error) // supports aggregate max / descending order by
- }
- type indexedCol struct { // Column name or id() index.
- name string
- unique bool
- x btreeIndex
- xroot int64
- }
- type index2 struct { // Expression list index.
- unique bool
- x btreeIndex
- xroot int64
- sources []string
- exprList []expression
- }
- func (x *index2) eval(ctx *execCtx, cols []*col, id int64, r []interface{}) ([]interface{}, error) {
- f, isFile := ctx.db.store.(*file)
- vlist := make([]interface{}, len(x.exprList))
- m := map[interface{}]interface{}{"$id": id}
- for _, col := range cols {
- ci := col.index
- v := interface{}(nil)
- if ci < len(r) {
- v = r[ci]
- }
- if b, ok := v.([]byte); ok && isFile {
- var err error
- if v, err = expand1(chunk{f: f, b: b}, nil); err != nil {
- return nil, err
- }
- }
- m[col.name] = v
- }
- for i, e := range x.exprList {
- v, err := e.eval(ctx, m)
- if err != nil {
- return nil, err
- }
- if ok, typ := isBlobType(v); ok {
- return nil, fmt.Errorf("value of a complex index cannot be of blob-like type: %v", typ)
- }
- vlist[i] = v
- }
- return vlist, nil
- }
- type indexKey struct {
- value []interface{}
- h int64
- }
- // storage fields
- // 0: next int64
- // 1: scols string
- // 2: hhead int64
- // 3: name string
- // 4: indices string - optional
- // 5: hxroots int64 - optional
- type table struct {
- cols []*col // logical
- cols0 []*col // physical
- h int64 //
- head int64 // head of the single linked record list
- hhead int64 // handle of the head of the single linked record list
- hxroots int64
- indices []*indexedCol
- indices2 map[string]*index2
- name string
- next int64 // single linked table list
- store storage
- tnext *table
- tprev *table
- xroots []interface{}
- constraints []*constraint
- defaults []expression
- }
- func (t *table) hasIndices() bool { return len(t.indices) != 0 || len(t.indices2) != 0 }
- func (t *table) constraintsAndDefaults(ctx *execCtx) error {
- if isSystemName[t.name] {
- return nil
- }
- _, ok := ctx.db.root.tables["__Column2"]
- if !ok {
- return nil
- }
- cols := t.cols
- constraints := make([]*constraint, len(cols))
- defaults := make([]expression, len(cols))
- arg := []interface{}{t.name}
- rs, err := selectColumn2.l[0].exec(&execCtx{db: ctx.db, arg: arg})
- if err != nil {
- return err
- }
- var rows [][]interface{}
- ok = false
- if err := rs.(recordset).do(
- &execCtx{db: ctx.db, arg: arg},
- func(id interface{}, data []interface{}) (more bool, err error) {
- rows = append(rows, data)
- return true, nil
- },
- ); err != nil {
- return err
- }
- for _, row := range rows {
- nm := row[0].(string)
- nonNull := row[1].(bool)
- cexpr := row[2].(string)
- dexpr := row[3].(string)
- for i, c := range cols {
- if c.name == nm {
- var co *constraint
- if nonNull || cexpr != "" {
- co = &constraint{}
- constraints[i] = co
- if cexpr != "" {
- if co.expr, err = ctx.db.str2expr(cexpr); err != nil {
- return fmt.Errorf("constraint %q: %v", cexpr, err)
- }
- }
- t.constraints = constraints
- }
- if dexpr != "" {
- if defaults[i], err = ctx.db.str2expr(dexpr); err != nil {
- return fmt.Errorf("constraint %q: %v", dexpr, err)
- }
- t.defaults = defaults
- }
- }
- }
- }
- return nil
- }
- func (t *table) checkConstraintsAndDefaults(ctx *execCtx, row []interface{}, m map[interface{}]interface{}) error {
- cols := t.cols
- if len(t.defaults) != 0 {
- // 1.
- for _, c := range cols {
- m[c.name] = row[c.index]
- }
- // 2.
- for i, c := range cols {
- val := row[c.index]
- expr := t.defaults[i]
- if val != nil || expr == nil {
- continue
- }
- dval, err := expr.eval(ctx, m)
- if err != nil {
- return err
- }
- row[c.index] = dval
- if err = typeCheck(row, []*col{c}); err != nil {
- return err
- }
- }
- }
- if len(t.constraints) != 0 {
- // 3.
- for _, c := range cols {
- m[c.name] = row[c.index]
- }
- // 4.
- for i, c := range cols {
- constraint := t.constraints[i]
- if constraint == nil {
- continue
- }
- val := row[c.index]
- expr := constraint.expr
- if expr == nil { // Constraint: NOT NULL
- if val == nil {
- return fmt.Errorf("column %s: constraint violation: NOT NULL", c.name)
- }
- continue
- }
- // Constraint is an expression
- cval, err := expr.eval(ctx, m)
- if err != nil {
- return err
- }
- if cval == nil {
- return fmt.Errorf("column %s: constraint violation: %s", c.name, expr)
- }
- bval, ok := cval.(bool)
- if !ok {
- return fmt.Errorf("column %s: non bool constraint expression: %s", c.name, expr)
- }
- if !bval {
- return fmt.Errorf("column %s: constraint violation: %s", c.name, expr)
- }
- }
- }
- return nil
- }
- func (t *table) clone() *table {
- r := &table{}
- *r = *t
- r.constraints = append([]*constraint(nil), t.constraints...)
- r.defaults = append([]expression(nil), t.defaults...)
- r.indices2 = nil
- if n := len(t.indices2); n != 0 {
- r.indices2 = make(map[string]*index2, n)
- for k, v := range t.indices2 {
- r.indices2[k] = v
- }
- }
- r.cols = make([]*col, len(t.cols))
- for i, v := range t.cols {
- c := &col{}
- *c = *v
- r.cols[i] = c
- }
- r.cols0 = make([]*col, len(t.cols0))
- for i, v := range t.cols0 {
- c := &col{}
- *c = *v
- r.cols0[i] = c
- }
- r.indices = make([]*indexedCol, len(t.indices))
- for i, v := range t.indices {
- if v != nil {
- c := &indexedCol{}
- *c = *v
- r.indices[i] = c
- }
- }
- r.xroots = make([]interface{}, len(t.xroots))
- copy(r.xroots, t.xroots)
- r.tnext, r.tprev = nil, nil
- return r
- }
- func (t *table) findIndexByColName(name string) (*col, *indexedCol) {
- for i, v := range t.indices {
- if v == nil {
- continue
- }
- if i == 0 {
- if name == "id()" {
- return idCol, v
- }
- continue
- }
- if c := t.cols[i-1]; c.name == name {
- return c, v
- }
- }
- return nil, nil
- }
- func (t *table) findIndexByName(name string) interface{} {
- for _, v := range t.indices {
- if v != nil && v.name == name {
- return v
- }
- }
- for k, v := range t.indices2 {
- if k == name {
- return v
- }
- }
- return nil
- }
- func (t *table) load() (err error) {
- data, err := t.store.Read(nil, t.h)
- if err != nil {
- return
- }
- var hasIndices bool
- switch n := len(data); n {
- case 4:
- case 6:
- hasIndices = true
- default:
- return fmt.Errorf("corrupted DB: table data len %d", n)
- }
- var ok bool
- if t.next, ok = data[0].(int64); !ok {
- return fmt.Errorf("corrupted DB: table data[0] of type %T", data[0])
- }
- scols, ok := data[1].(string)
- if !ok {
- return fmt.Errorf("corrupted DB: table data[1] of type %T", data[1])
- }
- if t.hhead, ok = data[2].(int64); !ok {
- return fmt.Errorf("corrupted DB: table data[2] of type %T", data[2])
- }
- if t.name, ok = data[3].(string); !ok {
- return fmt.Errorf("corrupted DB: table data[3] of type %T", data[3])
- }
- var head []interface{}
- if head, err = t.store.Read(nil, t.hhead); err != nil {
- return err
- }
- if len(head) != 1 {
- return fmt.Errorf("corrupted DB: table head data len %d", len(head))
- }
- if t.head, ok = head[0].(int64); !ok {
- return fmt.Errorf("corrupted DB: table head data[0] of type %T", head[0])
- }
- a := strings.Split(scols, "|")
- t.cols0 = make([]*col, len(a))
- for i, v := range a {
- if len(v) < 1 {
- return fmt.Errorf("corrupted DB: field info %q", v)
- }
- col := &col{name: v[1:], typ: int(v[0]), index: i}
- t.cols0[i] = col
- if col.name != "" {
- t.cols = append(t.cols, col)
- }
- }
- if !hasIndices {
- return
- }
- if t.hxroots, ok = data[5].(int64); !ok {
- return fmt.Errorf("corrupted DB: table data[5] of type %T", data[5])
- }
- xroots, err := t.store.Read(nil, t.hxroots)
- if err != nil {
- return err
- }
- if g, e := len(xroots), len(t.cols0)+1; g != e {
- return fmt.Errorf("corrupted DB: got %d index roots, expected %d", g, e)
- }
- indices, ok := data[4].(string)
- if !ok {
- return fmt.Errorf("corrupted DB: table data[4] of type %T", data[4])
- }
- a = strings.Split(indices, "|")
- if g, e := len(a), len(t.cols0)+1; g != e {
- return fmt.Errorf("corrupted DB: got %d index definitions, expected %d", g, e)
- }
- t.indices = make([]*indexedCol, len(a))
- for i, v := range a {
- if v == "" {
- continue
- }
- if len(v) < 2 {
- return fmt.Errorf("corrupted DB: invalid index definition %q", v)
- }
- nm := v[1:]
- h, ok := xroots[i].(int64)
- if !ok {
- return fmt.Errorf("corrupted DB: table index root of type %T", xroots[i])
- }
- if h == 0 {
- return fmt.Errorf("corrupted DB: missing root for index %s", nm)
- }
- unique := v[0] == 'u'
- x, err := t.store.OpenIndex(unique, h)
- if err != nil {
- return err
- }
- t.indices[i] = &indexedCol{nm, unique, x, h}
- }
- t.xroots = xroots
- return
- }
- func newTable(store storage, name string, next int64, cols []*col, tprev, tnext *table) (t *table, err error) {
- hhead, err := store.Create(int64(0))
- if err != nil {
- return
- }
- scols := cols2meta(cols)
- h, err := store.Create(next, scols, hhead, name)
- if err != nil {
- return
- }
- t = &table{
- cols0: cols,
- h: h,
- hhead: hhead,
- name: name,
- next: next,
- store: store,
- tnext: tnext,
- tprev: tprev,
- }
- return t.updateCols(), nil
- }
- func (t *table) blobCols() (r []*col) {
- for _, c := range t.cols0 {
- switch c.typ {
- case qBlob, qBigInt, qBigRat, qTime, qDuration:
- r = append(r, c)
- }
- }
- return
- }
- func (t *table) truncate() (err error) {
- h := t.head
- var rec []interface{}
- blobCols := t.blobCols()
- for h != 0 {
- rec, err := t.store.Read(rec, h)
- if err != nil {
- return err
- }
- nh := rec[0].(int64)
- if err = t.store.Delete(h, blobCols...); err != nil { //LATER remove double read for len(blobCols) != 0
- return err
- }
- h = nh
- }
- if err = t.store.Update(t.hhead, 0); err != nil {
- return
- }
- for _, v := range t.indices {
- if v == nil {
- continue
- }
- if err := v.x.Clear(); err != nil {
- return err
- }
- }
- for _, ix := range t.indices2 {
- if err := ix.x.Clear(); err != nil {
- return err
- }
- }
- t.head = 0
- return t.updated()
- }
- func (t *table) addIndex0(unique bool, indexName string, colIndex int) (int64, btreeIndex, error) {
- switch len(t.indices) {
- case 0:
- indices := make([]*indexedCol, len(t.cols0)+1)
- h, x, err := t.store.CreateIndex(unique)
- if err != nil {
- return -1, nil, err
- }
- indices[colIndex+1] = &indexedCol{indexName, unique, x, h}
- xroots := make([]interface{}, len(indices))
- xroots[colIndex+1] = h
- hx, err := t.store.Create(xroots...)
- if err != nil {
- return -1, nil, err
- }
- t.hxroots, t.xroots, t.indices = hx, xroots, indices
- return h, x, t.updated()
- default:
- ex := t.indices[colIndex+1]
- if ex != nil && ex.name != "" {
- colName := "id()"
- if colIndex >= 0 {
- colName = t.cols0[colIndex].name
- }
- return -1, nil, fmt.Errorf("column %s already has an index: %s", colName, ex.name)
- }
- h, x, err := t.store.CreateIndex(unique)
- if err != nil {
- return -1, nil, err
- }
- t.xroots[colIndex+1] = h
- if err := t.store.Update(t.hxroots, t.xroots...); err != nil {
- return -1, nil, err
- }
- t.indices[colIndex+1] = &indexedCol{indexName, unique, x, h}
- return h, x, t.updated()
- }
- }
- func (t *table) addIndex(unique bool, indexName string, colIndex int) (int64, error) {
- hx, x, err := t.addIndex0(unique, indexName, colIndex)
- if err != nil {
- return -1, err
- }
- // Must fill the new index.
- ncols := len(t.cols0)
- h, store := t.head, t.store
- for h != 0 {
- rec, err := store.Read(nil, h, t.cols...)
- if err != nil {
- return -1, err
- }
- if n := ncols + 2 - len(rec); n > 0 {
- rec = append(rec, make([]interface{}, n)...)
- }
- if err = x.Create([]interface{}{rec[colIndex+2]}, h); err != nil {
- return -1, err
- }
- h = rec[0].(int64)
- }
- return hx, nil
- }
- func (t *table) addIndex2(execCtx *execCtx, unique bool, indexName string, exprList []expression) (int64, error) {
- if _, ok := t.indices2[indexName]; ok {
- panic("internal error 009")
- }
- hx, x, err := t.store.CreateIndex(unique)
- if err != nil {
- return -1, err
- }
- var a []string
- for _, v := range exprList {
- a = append(a, v.String())
- }
- x2 := &index2{unique, x, hx, a, exprList}
- if t.indices2 == nil {
- t.indices2 = map[string]*index2{}
- }
- t.indices2[indexName] = x2
- // Must fill the new index.
- m := map[interface{}]interface{}{}
- h, store := t.head, t.store
- for h != 0 {
- rec, err := store.Read(nil, h, t.cols...)
- if err != nil {
- return -1, err
- }
- for _, col := range t.cols {
- ci := col.index
- v := interface{}(nil)
- if ci < len(rec) {
- v = rec[ci+2]
- }
- m[col.name] = v
- }
- id := rec[1].(int64)
- vlist, err := x2.eval(execCtx, t.cols, id, rec[2:])
- if err != nil {
- return -1, err
- }
- if err := x2.x.Create(vlist, h); err != nil {
- return -1, err
- }
- h = rec[0].(int64)
- }
- return hx, nil
- }
- func (t *table) dropIndex(xIndex int) error {
- t.xroots[xIndex] = 0
- if err := t.indices[xIndex].x.Drop(); err != nil {
- return err
- }
- t.indices[xIndex] = nil
- return t.updated()
- }
- func (t *table) updated() (err error) {
- switch {
- case len(t.indices) != 0:
- a := []string{}
- for _, v := range t.indices {
- if v == nil {
- a = append(a, "")
- continue
- }
- s := "n"
- if v.unique {
- s = "u"
- }
- a = append(a, s+v.name)
- }
- return t.store.Update(t.h, t.next, cols2meta(t.updateCols().cols0), t.hhead, t.name, strings.Join(a, "|"), t.hxroots)
- default:
- return t.store.Update(t.h, t.next, cols2meta(t.updateCols().cols0), t.hhead, t.name)
- }
- }
- // storage fields
- // 0: next record handle int64
- // 1: record id int64
- // 2...: data row
- func (t *table) addRecord(execCtx *execCtx, r []interface{}) (id int64, err error) {
- if id, err = t.store.ID(); err != nil {
- return
- }
- r = append([]interface{}{t.head, id}, r...)
- h, err := t.store.Create(r...)
- if err != nil {
- return
- }
- for i, v := range t.indices {
- if v == nil {
- continue
- }
- if err = v.x.Create([]interface{}{r[i+1]}, h); err != nil {
- return
- }
- }
- for _, ix := range t.indices2 {
- vlist, err := ix.eval(execCtx, t.cols, id, r[2:])
- if err != nil {
- return -1, err
- }
- if err := ix.x.Create(vlist, h); err != nil {
- return -1, err
- }
- }
- if err = t.store.Update(t.hhead, h); err != nil {
- return
- }
- t.head = h
- return
- }
- func (t *table) fieldNames() []string {
- r := make([]string, len(t.cols))
- for i, v := range t.cols {
- r[i] = v.name
- }
- return r
- }
- func (t *table) updateCols() *table {
- t.cols = t.cols[:0]
- for i, c := range t.cols0 {
- if c.name != "" {
- c.index = i
- t.cols = append(t.cols, c)
- }
- }
- return t
- }
- func (t *table) row0(ctx *execCtx, h int64) ([]interface{}, error) {
- rec, err := ctx.db.store.Read(nil, h, t.cols...)
- if err != nil {
- return nil, err
- }
- if d := len(t.cols) - (len(rec) - 2); d > 0 {
- rec = append(rec, make([]interface{}, d)...)
- }
- return rec, nil
- }
- func (t *table) row(ctx *execCtx, h int64) (int64, []interface{}, error) {
- rec, err := t.row0(ctx, h)
- if err != nil {
- return -1, nil, err
- }
- return rec[1].(int64), rec[2:], nil
- }
- // storage fields
- // 0: handle of first table in DB int64
- type root struct {
- head int64 // Single linked table list
- lastInsertID int64
- parent *root
- //rowsAffected int64 //LATER implement
- store storage
- tables map[string]*table
- thead *table
- }
- func newRoot(store storage) (r *root, err error) {
- data, err := store.Read(nil, 1)
- if err != nil {
- return
- }
- switch len(data) {
- case 0: // new empty DB, create empty table list
- if err = store.BeginTransaction(); err != nil {
- return
- }
- if err = store.Update(1, int64(0)); err != nil {
- store.Rollback()
- return
- }
- if err = store.Commit(); err != nil {
- return
- }
- return &root{
- store: store,
- tables: map[string]*table{},
- }, nil
- case 1: // existing DB, load tables
- if len(data) != 1 {
- return nil, fmt.Errorf("corrupted DB: root is an %d-scalar", len(data))
- }
- p, ok := data[0].(int64)
- if !ok {
- return nil, fmt.Errorf("corrupted DB: root head has type %T", data[0])
- }
- r := &root{
- head: p,
- store: store,
- tables: map[string]*table{},
- }
- var tprev *table
- for p != 0 {
- t := &table{
- h: p,
- store: store,
- tprev: tprev,
- }
- if r.thead == nil {
- r.thead = t
- }
- if tprev != nil {
- tprev.tnext = t
- }
- tprev = t
- if err = t.load(); err != nil {
- return nil, err
- }
- if r.tables[t.name] != nil { // duplicate
- return nil, fmt.Errorf("corrupted DB: duplicate table metadata for table %s", t.name)
- }
- r.tables[t.name] = t
- p = t.next
- }
- return r, nil
- default:
- return nil, errIncompatibleDBFormat
- }
- }
- func (r *root) findIndexByName(name string) (*table, interface{}) {
- for _, t := range r.tables {
- if i := t.findIndexByName(name); i != nil {
- return t, i
- }
- }
- return nil, nil
- }
- func (r *root) updated() (err error) {
- return r.store.Update(1, r.head)
- }
- func (r *root) createTable(name string, cols []*col) (t *table, err error) {
- if _, ok := r.tables[name]; ok {
- panic("internal error 065")
- }
- if t, err = newTable(r.store, name, r.head, cols, nil, r.thead); err != nil {
- return nil, err
- }
- if err = r.store.Update(1, t.h); err != nil {
- return nil, err
- }
- if p := r.thead; p != nil {
- p.tprev = t
- }
- r.tables[name], r.head, r.thead = t, t.h, t
- return
- }
- func (r *root) dropTable(t *table) (err error) {
- defer func() {
- if err != nil {
- return
- }
- delete(r.tables, t.name)
- }()
- if err = t.truncate(); err != nil {
- return
- }
- if err = t.store.Delete(t.hhead); err != nil {
- return
- }
- if err = t.store.Delete(t.h); err != nil {
- return
- }
- for _, v := range t.indices {
- if v != nil && v.x != nil {
- if err = v.x.Drop(); err != nil {
- return
- }
- }
- }
- for _, v := range t.indices2 {
- if err = v.x.Drop(); err != nil {
- return
- }
- }
- if h := t.hxroots; h != 0 {
- if err = t.store.Delete(h); err != nil {
- return
- }
- }
- switch {
- case t.tprev == nil && t.tnext == nil:
- r.head = 0
- r.thead = nil
- err = r.updated()
- return errSet(&err, r.store.ResetID())
- case t.tprev == nil && t.tnext != nil:
- next := t.tnext
- next.tprev = nil
- r.head = next.h
- r.thead = next
- if err = r.updated(); err != nil {
- return
- }
- return next.updated()
- case t.tprev != nil && t.tnext == nil: // last in list
- prev := t.tprev
- prev.next = 0
- prev.tnext = nil
- return prev.updated()
- default: //case t.tprev != nil && t.tnext != nil:
- prev, next := t.tprev, t.tnext
- prev.next = next.h
- prev.tnext = next
- next.tprev = prev
- if err = prev.updated(); err != nil {
- return
- }
- return next.updated()
- }
- }
|