Exemple #1
0
// Next implements Executor Next interface.
func (e *IndexRangeExec) Next() (*Row, error) {
	if e.iter == nil {
		seekVals := make([]interface{}, len(e.scan.idx.Columns))
		for i := 0; i < len(e.lowVals); i++ {
			var err error
			if e.lowVals[i] == plan.MinNotNullVal {
				seekVals[i] = []byte{}
			} else {
				seekVals[i], err = types.Convert(e.lowVals[i], e.scan.valueTypes[i])
				if err != nil {
					return nil, errors.Trace(err)
				}
			}
		}
		txn, err := e.scan.ctx.GetTxn(false)
		if err != nil {
			return nil, errors.Trace(err)
		}
		e.iter, _, err = e.scan.idx.X.Seek(txn, seekVals)
		if err != nil {
			return nil, types.EOFAsNil(err)
		}
	}

	for {
		if e.finished {
			return nil, nil
		}
		idxKey, h, err := e.iter.Next()
		if err != nil {
			return nil, types.EOFAsNil(err)
		}
		if !e.skipLowCmp {
			var cmp int
			cmp, err = indexCompare(idxKey, e.lowVals)
			if err != nil {
				return nil, errors.Trace(err)
			}
			if cmp < 0 || (cmp == 0 && e.lowExclude) {
				continue
			}
			e.skipLowCmp = true
		}
		cmp, err := indexCompare(idxKey, e.highVals)
		if err != nil {
			return nil, errors.Trace(err)
		}
		if cmp > 0 || (cmp == 0 && e.highExclude) {
			// This span has finished iteration.
			e.finished = true
			continue
		}
		var row *Row
		row, err = e.lookupRow(h)
		if err != nil {
			return nil, errors.Trace(err)
		}
		return row, nil
	}
}
Exemple #2
0
// Do implements plan.Plan Do interface.
func (r *selectIndexDefaultPlan) Do(ctx context.Context, f plan.RowIterFunc) (err error) {
	var x kv.Index
	switch ix := r.x.(type) {
	case *column.IndexedCol:
		x = ix.X
	default:
		panic("should never happen")
	}

	txn, err := ctx.GetTxn(false)
	if err != nil {
		return err
	}
	en, err := x.SeekFirst(txn)
	if err != nil {
		return types.EOFAsNil(err)
	}
	defer en.Close()

	var id int64
	for {
		k, _, err := en.Next()
		if err != nil {
			return types.EOFAsNil(err)
		}

		id++
		if more, err := f(id, k); !more || err != nil {
			return err
		}
	}
}
Exemple #3
0
// Next implements plan.Plan Next interface.
func (r *indexPlan) Next(ctx context.Context) (row *plan.Row, err error) {
	for {
		if r.cursor == len(r.spans) {
			return
		}
		span := r.spans[r.cursor]
		if r.iter == nil {
			seekVal := span.seekVal
			if span.lowVal == minNotNullVal {
				seekVal = []byte{}
			}
			var txn kv.Transaction
			txn, err = ctx.GetTxn(false)
			if err != nil {
				return nil, errors.Trace(err)
			}
			r.iter, _, err = r.idx.Seek(txn, []interface{}{seekVal})
			if err != nil {
				return nil, types.EOFAsNil(err)
			}
		}
		var idxKey []interface{}
		var h int64
		idxKey, h, err = r.iter.Next()
		if err != nil {
			return nil, types.EOFAsNil(err)
		}
		val := idxKey[0]
		if !r.skipLowCmp {
			cmp := indexCompare(val, span.lowVal)
			if cmp < 0 || (cmp == 0 && span.lowExclude) {
				continue
			}
			r.skipLowCmp = true
		}
		cmp := indexCompare(val, span.highVal)
		if cmp > 0 || (cmp == 0 && span.highExclude) {
			// This span has finished iteration.
			// Move to the next span.
			r.iter.Close()
			r.iter = nil
			r.cursor++
			r.skipLowCmp = false
			continue
		}
		row = &plan.Row{}
		row.Data, err = r.src.Row(ctx, h)
		if err != nil {
			return nil, errors.Trace(err)
		}
		rowKey := &plan.RowKeyEntry{
			Tbl: r.src,
			Key: string(r.src.RecordKey(h, nil)),
		}
		row.RowKeys = append(row.RowKeys, rowKey)
		return
	}
}
Exemple #4
0
// Do implements plan.Plan Do interface, all records are added into an
// in-memory array, and sorted in ASC/DESC order.
func (r *OrderByDefaultPlan) Do(ctx context.Context, f plan.RowIterFunc) error {
	t := &orderByTable{Ascs: r.Ascs}

	m := map[interface{}]interface{}{}
	err := r.Src.Do(ctx, func(rid interface{}, in []interface{}) (bool, error) {
		m[expressions.ExprEvalIdentFunc] = func(name string) (interface{}, error) {
			return getIdentValue(name, r.ResultFields, in, field.CheckFieldFlag)
		}

		m[expressions.ExprEvalPositionFunc] = func(position int) (interface{}, error) {
			// position is in [1, len(fields)], so we must decrease 1 to get correct index
			// TODO: check position invalidation
			return in[position-1], nil
		}

		row := &orderByRow{
			Row: in,
			Key: make([]interface{}, 0, len(r.By)),
		}

		for _, by := range r.By {
			// err1 is used for passing `go tool vet --shadow` check.
			val, err1 := by.Eval(ctx, m)
			if err1 != nil {
				return false, err1
			}

			if val != nil {
				var ordered bool
				val, ordered, err1 = types.IsOrderedType(val)
				if err1 != nil {
					return false, err1
				}

				if !ordered {
					return false, errors.Errorf("cannot order by %v (type %T)", val, val)
				}
			}

			row.Key = append(row.Key, val)
		}

		t.Rows = append(t.Rows, row)
		return true, nil
	})
	if err != nil {
		return err
	}

	sort.Sort(t)

	var more bool
	for _, row := range t.Rows {
		if more, err = f(nil, row.Row); !more || err != nil {
			break
		}
	}
	return types.EOFAsNil(err)
}
Exemple #5
0
func (r *indexPlan) doSpan(ctx context.Context, txn kv.Transaction, span *indexSpan, f plan.RowIterFunc) error {
	seekVal := span.lowVal
	if span.lowVal == minNotNullVal {
		seekVal = []byte{}
	}
	it, _, err := r.idx.Seek(txn, []interface{}{seekVal})
	if err != nil {
		return types.EOFAsNil(err)
	}
	defer it.Close()
	var skipLowCompare bool
	for {
		k, h, err := it.Next()
		if err != nil {
			return types.EOFAsNil(err)
		}
		val := k[0]
		if !skipLowCompare {
			if span.lowExclude && indexCompare(span.lowVal, val) == 0 {
				continue
			}
			skipLowCompare = true
		}
		cmp := indexCompare(span.highVal, val)
		if cmp < 0 || (cmp == 0 && span.highExclude) {
			return nil
		}
		data, err := r.src.Row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(h, data); err != nil || !more {
			return err
		}
	}
}
Exemple #6
0
// Do : Distinct plan use an in-memory temp table for storing items that has same
// key, the value in temp table is an array of record handles.
func (r *DistinctDefaultPlan) Do(ctx context.Context, f plan.RowIterFunc) (err error) {
	t, err := memkv.CreateTemp(true)
	if err != nil {
		return
	}

	defer func() {
		if derr := t.Drop(); derr != nil && err == nil {
			err = derr
		}
	}()

	var rows [][]interface{}
	if err = r.Src.Do(ctx, func(id interface{}, in []interface{}) (bool, error) {
		var v []interface{}
		// get distinct key
		key := in[0:r.HiddenFieldOffset]
		v, err = t.Get(key)
		if err != nil {
			return false, err
		}

		if len(v) == 0 {
			// no group for key, save data for this group
			rows = append(rows, in)
			if err := t.Set(key, []interface{}{true}); err != nil {
				return false, err
			}
		}

		return true, nil
	}); err != nil {
		return
	}

	var more bool
	for _, row := range rows {
		if more, err = f(nil, row); !more || err != nil {
			break
		}
	}
	return types.EOFAsNil(err)
}
Exemple #7
0
// Do implements plan.Plan Do interface.
// Table: Subject_Selection
// Subject   Semester   Attendee
// ---------------------------------
// ITB001    1          John
// ITB001    1          Bob
// ITB001    1          Mickey
// ITB001    2          Jenny
// ITB001    2          James
// MKB114    1          John
// MKB114    1          Erica
// refs: http://stackoverflow.com/questions/2421388/using-group-by-on-multiple-columns
func (r *GroupByDefaultPlan) Do(ctx context.Context, f plan.RowIterFunc) (err error) {
	// TODO: now we have to use this to save group key -> row index
	// later we will serialize group by items into a string key and then use a map instead.
	t, err := memkv.CreateTemp(true)
	if err != nil {
		return err
	}

	defer func() {
		if derr := t.Drop(); derr != nil && err == nil {
			err = derr
		}
	}()

	k := make([]interface{}, len(r.By))

	// save output group by result
	var outRows []*groupRow

	err = r.Src.Do(ctx, func(rid interface{}, in []interface{}) (more bool, err error) {
		out := make([]interface{}, len(r.Fields))

		// TODO: later order by will use the same mechanism, so we may use another plan to do this
		m := map[interface{}]interface{}{}
		// must first eval none aggregate fields, because alias group by will use this.
		if err := r.evalNoneAggFields(ctx, out, m, in); err != nil {
			return false, err
		}

		if err := r.evalGroupKey(ctx, k, out, in); err != nil {
			return false, err
		}

		// get row index with k.
		v, err := t.Get(k)
		if err != nil {
			return false, err
		}

		index := 0
		if len(v) == 0 {
			// no group for key, save data for this group
			index = len(outRows)
			outRows = append(outRows, &groupRow{Row: out, Args: m})

			if err := t.Set(k, []interface{}{index}); err != nil {
				return false, err
			}
		} else {
			// we have already saved data in the group by key, use this
			index = v[0].(int)

			// we will use this context args to evaluate aggregate fields.
			m = outRows[index].Args
		}

		// eval aggregate fields
		if err := r.evalAggFields(ctx, out, m, in); err != nil {
			return false, err
		}

		return true, nil
	})

	if err != nil {
		return err
	}

	if len(outRows) == 0 {
		// empty table
		var out []interface{}
		out, err = r.evalEmptyTable(ctx)
		if err != nil || out == nil {
			return err
		}

		_, err = f(nil, out)

		return err
	}

	// we don't consider implicit GROUP BY sorting now.
	// Relying on implicit GROUP BY sorting in MySQL 5.7 is deprecated.
	// To achieve a specific sort order of grouped results,
	// it is preferable to use an explicit ORDER BY clause.
	// GROUP BY sorting is a MySQL extension that may change in a future release
	var more bool
	for _, row := range outRows {
		// eval aggregate done
		if err := r.evalAggDone(ctx, row.Row, row.Args); err != nil {
			return err
		}
		if more, err = f(nil, row.Row); !more || err != nil {
			break
		}
	}

	return types.EOFAsNil(err)
}
Exemple #8
0
func (r *TableDefaultPlan) rangeNext(ctx context.Context) (*plan.Row, error) {
	for {
		if r.cursor == len(r.spans) {
			return nil, nil
		}
		span := r.spans[r.cursor]
		if r.seekKey == nil {
			seekVal := span.seekVal
			var err error
			r.seekKey, err = r.toSeekKey(seekVal)
			if err != nil {
				return nil, errors.Trace(err)
			}
		}
		txn, err := ctx.GetTxn(false)
		if err != nil {
			return nil, errors.Trace(err)
		}
		if r.iter != nil {
			r.iter.Close()
		}
		r.iter, err = txn.Seek(r.seekKey)
		if err != nil {
			return nil, types.EOFAsNil(err)
		}

		if !r.iter.Valid() || !r.iter.Key().HasPrefix(r.T.RecordPrefix()) {
			r.seekKey = nil
			r.cursor++
			r.skipLowCmp = false
			continue
		}
		rowKey := r.iter.Key()
		handle, err := tables.DecodeRecordKeyHandle(rowKey)
		if err != nil {
			return nil, errors.Trace(err)
		}
		r.seekKey, err = r.toSeekKey(handle + 1)
		if err != nil {
			return nil, errors.Trace(err)
		}
		if !r.skipLowCmp {
			cmp := indexCompare(handle, span.lowVal)
			if cmp < 0 || (cmp == 0 && span.lowExclude) {
				continue
			}
			r.skipLowCmp = true
		}
		cmp := indexCompare(handle, span.highVal)
		if cmp > 0 || (cmp == 0 && span.highExclude) {
			// This span has finished iteration.
			// Move to the next span.
			r.seekKey = nil
			r.cursor++
			r.skipLowCmp = false
			continue
		}
		row := &plan.Row{}
		row.Data, err = r.T.Row(ctx, handle)
		if err != nil {
			return nil, errors.Trace(err)
		}
		// Put rowKey to the tail of record row
		rke := &plan.RowKeyEntry{
			Tbl: r.T,
			Key: string(rowKey),
		}
		row.RowKeys = append(row.RowKeys, rke)
		return row, nil
	}
}
Exemple #9
0
// Next implements plan.Plan Next interface.
func (r *indexPlan) Next(ctx context.Context) (*plan.Row, error) {
	for {
		if r.cursor == len(r.spans) {
			return nil, nil
		}
		span := r.spans[r.cursor]
		if r.isPointLookup(span) {
			// Do point lookup on index will prevent prefetch cost.
			row, err := r.pointLookup(ctx, span.seekVal)
			if err != nil {
				return nil, errors.Trace(err)
			}
			r.cursor++
			if row != nil {
				return row, nil
			}
			continue
		}
		if r.iter == nil {
			seekVal := span.seekVal
			if span.lowVal == minNotNullVal {
				seekVal = []byte{}
			}
			var txn kv.Transaction
			txn, err := ctx.GetTxn(false)
			if err != nil {
				return nil, errors.Trace(err)
			}
			r.iter, _, err = r.idx.Seek(txn, []interface{}{seekVal})
			if err != nil {
				return nil, types.EOFAsNil(err)
			}
		}
		idxKey, h, err := r.iter.Next()
		if err != nil {
			return nil, types.EOFAsNil(err)
		}
		val := idxKey[0]
		if !r.skipLowCmp {
			cmp := indexCompare(val, span.lowVal)
			if cmp < 0 || (cmp == 0 && span.lowExclude) {
				continue
			}
			r.skipLowCmp = true
		}
		cmp := indexCompare(val, span.highVal)
		if cmp > 0 || (cmp == 0 && span.highExclude) {
			// This span has finished iteration.
			// Move to the next span.
			r.iter.Close()
			r.iter = nil
			r.cursor++
			r.skipLowCmp = false
			continue
		}
		var row *plan.Row
		row, err = r.lookupRow(ctx, h)
		if err != nil {
			return nil, errors.Trace(err)
		}
		return row, nil
	}
}