package ql

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/cznic/b"
	"github.com/cznic/strutil"
)

const (
	_               = iota
	indexEq         
	indexFalse      
	indexGe         
	indexGt         
	indexIsNotNull  
	indexIsNull     
	indexIntervalCC 
	indexIntervalCO 
	indexIntervalOC 
	indexIntervalOO 
	indexLe         
	indexLt         
	indexNe         
	indexTrue       
)

var (
	_ plan = (*crossJoinDefaultPlan)(nil)
	_ plan = (*distinctDefaultPlan)(nil)
	_ plan = (*explainDefaultPlan)(nil)
	_ plan = (*filterDefaultPlan)(nil)
	_ plan = (*fullJoinDefaultPlan)(nil)
	_ plan = (*groupByDefaultPlan)(nil)
	_ plan = (*indexPlan)(nil)
	_ plan = (*leftJoinDefaultPlan)(nil)
	_ plan = (*limitDefaultPlan)(nil)
	_ plan = (*nullPlan)(nil)
	_ plan = (*offsetDefaultPlan)(nil)
	_ plan = (*orderByDefaultPlan)(nil)
	_ plan = (*rightJoinDefaultPlan)(nil)
	_ plan = (*selectFieldsDefaultPlan)(nil)
	_ plan = (*selectFieldsGroupPlan)(nil)
	_ plan = (*selectIndexDefaultPlan)(nil)
	_ plan = (*selectDummyPlan)(nil)
	_ plan = (*sysColumnDefaultPlan)(nil)
	_ plan = (*sysIndexDefaultPlan)(nil)
	_ plan = (*sysTableDefaultPlan)(nil)
	_ plan = (*tableDefaultPlan)(nil)
	_ plan = (*tableNilPlan)(nil)
)

type plan interface {
	do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error
	explain(w strutil.Formatter)
	fieldNames() []string
	filter(expr expression) (p plan, indicesSought []string, err error)
	hasID() bool
}

func isTableOrIndex(p plan) bool {
	switch p.(type) {
	case
		*indexPlan,
		*sysColumnDefaultPlan,
		*sysIndexDefaultPlan,
		*sysTableDefaultPlan,
		*tableDefaultPlan:
		return true
	default:
		return false
	}
}

type indexPlan struct {
	src   *table
	cname string
	xname string
	x     btreeIndex
	kind  int         
	lval  interface{} 
	hval  interface{}
}

func (r *indexPlan) doGe(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {

	t := r.src
	it, _, err := r.x.Seek([]interface{}{r.lval})
	if err != nil {
		return noEOF(err)
	}

	for {
		_, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doGt(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {

	t := r.src
	it, _, err := r.x.Seek([]interface{}{r.lval})
	if err != nil {
		return noEOF(err)
	}

	var ok bool
	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if !ok {
			val, err := expand1(k[0], nil)
			if err != nil {
				return err
			}

			if collate1(val, r.lval) == 0 {
				continue
			}

			ok = true
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doInterval00(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {

	t := r.src
	it, _, err := r.x.Seek([]interface{}{r.lval})
	if err != nil {
		return noEOF(err)
	}

	var ok bool
	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if !ok {
			val, err := expand1(k[0], nil)
			if err != nil {
				return err
			}

			if collate1(val, r.lval) == 0 {
				continue
			}

			ok = true
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.hval) == 0 {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doIntervalOC(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {

	t := r.src
	it, _, err := r.x.Seek([]interface{}{r.lval})
	if err != nil {
		return noEOF(err)
	}

	var ok bool
	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if !ok {
			val, err := expand1(k[0], nil)
			if err != nil {
				return err
			}

			if collate1(val, r.lval) == 0 {
				continue
			}

			ok = true
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.hval) > 0 {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doIntervalCC(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {

	t := r.src
	it, _, err := r.x.Seek([]interface{}{r.lval})
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.hval) > 0 {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doIntervalCO(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {

	t := r.src
	it, _, err := r.x.Seek([]interface{}{r.lval})
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.hval) >= 0 {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doLe(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {

	t := r.src
	it, err := r.x.SeekFirst()
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if k == nil || k[0] == nil {
			continue
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.hval) > 0 {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doLt(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {

	t := r.src
	it, err := r.x.SeekFirst()
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if k == nil || k[0] == nil {
			continue
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.hval) >= 0 {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doEq(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {

	t := r.src
	it, _, err := r.x.Seek([]interface{}{r.lval})
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.lval) != 0 {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doNe(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {

	t := r.src
	it, err := r.x.SeekFirst()
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if k == nil || k[0] == nil {
			continue
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.hval) == 0 {
			continue
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doIsNull(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {

	t := r.src
	it, err := r.x.SeekFirst()
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if k != nil && k[0] != nil {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doIsNotNull(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {

	t := r.src
	it, _, err := r.x.Seek([]interface{}{false}) 
	if err != nil {
		return noEOF(err)
	}

	for {
		_, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doFalse(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	t := r.src
	it, _, err := r.x.Seek([]interface{}{false})
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		b, ok := k[0].(bool)
		if !ok || b {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doTrue(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	t := r.src
	it, _, err := r.x.Seek([]interface{}{true})
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if _, ok := k[0].(bool); !ok {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) do(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	switch r.kind {
	case indexEq:
		return r.doEq(ctx, f)
	case indexGe:
		return r.doGe(ctx, f)
	case indexGt:
		return r.doGt(ctx, f)
	case indexLe:
		return r.doLe(ctx, f)
	case indexLt:
		return r.doLt(ctx, f)
	case indexNe:
		return r.doNe(ctx, f)
	case indexIsNull:
		return r.doIsNull(ctx, f)
	case indexIsNotNull:
		return r.doIsNotNull(ctx, f)
	case indexFalse:
		return r.doFalse(ctx, f)
	case indexTrue:
		return r.doTrue(ctx, f)
	case indexIntervalOO:
		return r.doInterval00(ctx, f)
	case indexIntervalCC:
		return r.doIntervalCC(ctx, f)
	case indexIntervalOC:
		return r.doIntervalOC(ctx, f)
	case indexIntervalCO:
		return r.doIntervalCO(ctx, f)
	default:

		panic("internal error 068")
	}
}

func (r *indexPlan) explain(w strutil.Formatter) {
	s := ""
	if r.kind == indexFalse {
		s = "!"
	}
	w.Format("┌Iterate all rows of table %q using index %q where %s%s", r.src.name, r.xname, s, r.cname)
	switch r.kind {
	case indexEq:
		w.Format(" == %v", value{r.lval})
	case indexGe:
		w.Format(" >= %v", value{r.lval})
	case indexGt:
		w.Format(" > %v", value{r.lval})
	case indexLe:
		w.Format(" <= %v", value{r.hval})
	case indexLt:
		w.Format(" < %v", value{r.hval})
	case indexNe:
		w.Format(" != %v", value{r.lval})
	case indexIsNull:
		w.Format(" IS NULL")
	case indexIsNotNull:
		w.Format(" IS NOT NULL")
	case indexFalse, indexTrue:

	case indexIntervalOO:
		w.Format(" > %v && %s < %v", value{r.lval}, r.cname, value{r.hval})
	case indexIntervalCC:
		w.Format(" >= %v && %s <= %v", value{r.lval}, r.cname, value{r.hval})
	case indexIntervalCO:
		w.Format(" >= %v && %s < %v", value{r.lval}, r.cname, value{r.hval})
	case indexIntervalOC:
		w.Format(" > %v && %s <= %v", value{r.lval}, r.cname, value{r.hval})
	default:

		panic("internal error 053")
	}
	w.Format("\n└Output field names %v\n", qnames(r.fieldNames()))
}

func (r *indexPlan) fieldNames() []string { return r.src.fieldNames() }

func (r *indexPlan) filterEq(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(r.lval, val) == 0 {
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case ge:
		if collate1(r.lval, val) >= 0 {
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case '>':
		if collate1(r.lval, val) > 0 {
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case le:
		if collate1(r.lval, val) <= 0 {
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case '<':
		if collate1(r.lval, val) < 0 {
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case neq:
		if collate1(r.lval, val) != 0 {
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	}
	return nil, nil, nil
}

func (r *indexPlan) filterGe(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(r.lval, val) <= 0 {
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case ge:
		if collate1(r.lval, val) < 0 {
			r.lval = val
		}
		return r, nil, nil
	case '>':
		if collate1(r.lval, val) <= 0 {
			r.lval = val
			r.kind = indexGt
		}
		return r, nil, nil
	case le:
		switch c := collate1(r.lval, val); {
		case c < 0:
			r.hval = val
			r.kind = indexIntervalCC
			return r, nil, nil
		case c == 0:
			r.kind = indexEq
			return r, nil, nil
		default: 
			return &nullPlan{r.fieldNames()}, nil, nil
		}
	case '<':
		if collate1(r.lval, val) < 0 {
			r.hval = val
			r.kind = indexIntervalCO
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case neq:
		switch c := collate1(r.lval, val); {
		case c < 0:

		case c == 0:
			r.kind = indexGt
			return r, nil, nil
		default: 
			return r, nil, nil
		}
	}
	return nil, nil, nil
}

func (r *indexPlan) filterGt(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(r.lval, val) < 0 {
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case ge:
		if collate1(r.lval, val) < 0 {
			r.lval = val
			r.kind = indexGe
		}
		return r, nil, nil
	case '>':
		if collate1(r.lval, val) < 0 {
			r.lval = val
		}
		return r, nil, nil
	case le:
		if collate1(r.lval, val) < 0 {
			r.hval = val
			r.kind = indexIntervalOC
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case '<':
		if collate1(r.lval, val) < 0 {
			r.hval = val
			r.kind = indexIntervalOO
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case neq:
		if collate1(r.lval, val) >= 0 {
			return r, nil, nil
		}
	}
	return nil, nil, nil
}

func (r *indexPlan) filterLe(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(r.hval, val) >= 0 {
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case ge:
		switch c := collate1(r.hval, val); {
		case c < 0:
			return &nullPlan{r.fieldNames()}, nil, nil
		case c == 0:
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		default: 
			r.lval = val
			r.kind = indexIntervalCC
			return r, nil, nil
		}
	case '>':
		if collate1(r.hval, val) > 0 {
			r.lval = val
			r.kind = indexIntervalOC
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case le:
		if collate1(r.hval, val) > 0 {
			r.hval = val
		}
		return r, nil, nil
	case '<':
		if collate1(r.hval, val) >= 0 {
			r.hval = val
			r.kind = indexLt
		}
		return r, nil, nil
	case neq:
		switch c := collate1(r.hval, val); {
		case c < 0:
			return r, nil, nil
		case c == 0:
			r.kind = indexLt
			return r, nil, nil
		default: 

		}
	}
	return nil, nil, nil
}

func (r *indexPlan) filterLt(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(r.hval, val) > 0 {
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case ge:
		if collate1(r.hval, val) > 0 {
			r.lval = val
			r.kind = indexIntervalCO
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case '>':
		if collate1(r.hval, val) > 0 {
			r.lval = val
			r.kind = indexIntervalOO
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case le:
		if collate1(r.hval, val) > 0 {
			r.hval = val
			r.kind = indexLe
		}
		return r, nil, nil
	case '<':
		if collate1(r.hval, val) > 0 {
			r.hval = val
		}
		return r, nil, nil
	case neq:
		if collate1(r.hval, val) > 0 {
			return nil, nil, nil
		}

		return r, nil, nil
	}
	return nil, nil, nil
}

func (r *indexPlan) filterCC(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(val, r.lval) < 0 || collate1(val, r.hval) > 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		r.lval = val
		r.kind = indexEq
		return r, nil, nil
	case ge:
		if collate1(val, r.lval) <= 0 {
			return r, nil, nil
		}

		switch c := collate1(val, r.hval); {
		case c < 0:
			r.lval = val
			return r, nil, nil
		case c == 0:
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		default:
			return &nullPlan{r.fieldNames()}, nil, nil
		}
	case '>':
		switch c := collate1(val, r.lval); {
		case c < 0:
			return r, nil, nil
		case c == 0:
			r.kind = indexIntervalOC
			return r, nil, nil
		default:
			if collate1(val, r.hval) < 0 {
				r.lval = val
				r.kind = indexIntervalOC
				return r, nil, nil
			}

			return &nullPlan{r.fieldNames()}, nil, nil
		}
	case le:
		switch c := collate1(val, r.lval); {
		case c < 0:
			return &nullPlan{r.fieldNames()}, nil, nil
		case c == 0:
			r.kind = indexEq
			return r, nil, nil
		default:
			if collate1(val, r.hval) < 0 {
				r.hval = val
			}
			return r, nil, nil
		}
	case '<':
		if collate1(val, r.lval) <= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		if collate1(val, r.hval) <= 0 {
			r.hval = val
			r.kind = indexIntervalCO
		}
		return r, nil, nil
	case neq:
		switch c := collate1(val, r.lval); {
		case c < 0:
			return r, nil, nil
		case c == 0:
			r.kind = indexIntervalOC
			return r, nil, nil
		default:
			switch c := collate1(val, r.hval); {
			case c == 0:
				r.kind = indexIntervalCO
				return r, nil, nil
			case c > 0:
				return r, nil, nil
			default:
				return nil, nil, nil
			}
		}
	}
	return nil, nil, nil
}

func (r *indexPlan) filterOC(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(val, r.lval) <= 0 || collate1(val, r.hval) > 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		r.lval = val
		r.kind = indexEq
		return r, nil, nil
	case ge:
		if collate1(val, r.lval) <= 0 {
			return r, nil, nil
		}

		switch c := collate1(val, r.hval); {
		case c < 0:
			r.lval = val
			r.kind = indexIntervalCC
			return r, nil, nil
		case c == 0:
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		default:
			return &nullPlan{r.fieldNames()}, nil, nil
		}
	case '>':
		if collate1(val, r.lval) <= 0 {
			return r, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.lval = val
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case le:
		if collate1(val, r.lval) <= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.hval = val
		}
		return r, nil, nil
	case '<':
		if collate1(val, r.lval) <= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		switch c := collate1(val, r.hval); {
		case c < 0:
			r.hval = val
			r.kind = indexIntervalOO
		case c == 0:
			r.kind = indexIntervalOO
		}
		return r, nil, nil
	case neq:
		if collate1(val, r.lval) <= 0 {
			return r, nil, nil
		}

		switch c := collate1(val, r.hval); {
		case c < 0:
			return nil, nil, nil
		case c == 0:
			r.kind = indexIntervalOO
			return r, nil, nil
		default:
			return r, nil, nil
		}
	}
	return nil, nil, nil
}

func (r *indexPlan) filterOO(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(val, r.lval) <= 0 || collate1(val, r.hval) >= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		r.lval = val
		r.kind = indexEq
		return r, nil, nil
	case ge:
		if collate1(val, r.lval) <= 0 {
			return r, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.lval = val
			r.kind = indexIntervalCO
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case '>':
		if collate1(val, r.lval) <= 0 {
			return r, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.lval = val
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case le:
		if collate1(val, r.lval) <= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.hval = val
			r.kind = indexIntervalOC
		}
		return r, nil, nil
	case '<':
		if collate1(val, r.lval) <= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.hval = val
		}
		return r, nil, nil
	case neq:
		if collate1(val, r.lval) <= 0 || collate1(val, r.hval) >= 0 {
			return r, nil, nil
		}

		return nil, nil, nil
	}
	return nil, nil, nil
}

func (r *indexPlan) filterCO(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(val, r.lval) < 0 || collate1(val, r.hval) >= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		r.lval = val
		r.kind = indexEq
		return r, nil, nil
	case ge:
		if collate1(val, r.lval) <= 0 {
			return r, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.lval = val
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case '>':
		switch c := collate1(val, r.lval); {
		case c < 0:
			return r, nil, nil
		case c == 0:
			r.kind = indexIntervalOO
			return r, nil, nil
		default:
			if collate1(val, r.hval) < 0 {
				r.lval = val
				r.kind = indexIntervalOO
				return r, nil, nil
			}

			return &nullPlan{r.fieldNames()}, nil, nil
		}
	case le:
		switch c := collate1(val, r.lval); {
		case c < 0:
			return &nullPlan{r.fieldNames()}, nil, nil
		case c == 0:
			r.kind = indexEq
			return r, nil, nil
		default:
			if collate1(val, r.hval) < 0 {
				r.hval = val
				r.kind = indexIntervalCC
			}
			return r, nil, nil
		}
	case '<':
		if collate1(val, r.lval) <= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.hval = val
		}
		return r, nil, nil
	case neq:
		switch c := collate1(val, r.lval); {
		case c < 0:
			return r, nil, nil
		case c == 0:
			r.kind = indexIntervalOO
			return r, nil, nil
		default:
			if collate1(val, r.hval) < 0 {
				return nil, nil, nil
			}

			return r, nil, nil
		}
	}
	return nil, nil, nil
}

func (r *indexPlan) filterNe(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(val, r.lval) != 0 {
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case ge:
		switch c := collate1(val, r.lval); {
		case c < 0:
			return nil, nil, nil 
		case c == 0:
			r.kind = indexGt
			return r, nil, nil
		default:
			r.lval = val
			r.kind = indexGe
			return r, nil, nil
		}
	case '>':
		if collate1(val, r.lval) < 0 {
			return nil, nil, nil 
		}

		r.lval = val
		r.kind = indexGt
		return r, nil, nil
	case le:
		switch c := collate1(val, r.lval); {
		case c < 0:
			r.hval = val
			r.kind = indexLe
			return r, nil, nil
		case c == 0:
			r.kind = indexLt
			return r, nil, nil
		default:
			return nil, nil, nil 
		}
	case '<':
		if collate1(val, r.lval) <= 0 {
			r.hval = val
			r.kind = indexLt
			return r, nil, nil
		}

		return nil, nil, nil 
	case neq:
		if collate1(val, r.lval) == 0 {
			return r, nil, nil
		}

		return nil, nil, nil
	}
	return nil, nil, nil
}

func (r *indexPlan) filter(expr expression) (plan, []string, error) {
	switch x := expr.(type) {
	case *binaryOperation:
		ok, cname, val, err := x.isIdentRelOpVal()
		if err != nil {
			return nil, nil, err
		}

		if !ok || r.cname != cname {
			break
		}

		if val, err = typeCheck1(val, findCol(r.src.cols, cname)); err != nil {
			return nil, nil, err
		}

		switch r.kind {
		case indexEq: 
			return r.filterEq(x.op, val)
		case indexGe: 
			return r.filterGe(x.op, val)
		case indexGt: 
			return r.filterGt(x.op, val)
		case indexIntervalCC: 
			return r.filterCC(x.op, val)
		case indexIntervalCO: 
			return r.filterCO(x.op, val)
		case indexIntervalOC: 
			return r.filterOC(x.op, val)
		case indexIntervalOO: 
			return r.filterOO(x.op, val)
		case indexLe: 
			return r.filterLe(x.op, val)
		case indexLt: 
			return r.filterLt(x.op, val)
		case indexNe: 
			return r.filterNe(x.op, val)
		}
	case *ident:
		cname := x.s
		if r.cname != cname {
			break
		}

		switch r.kind {
		case indexFalse: 
			return &nullPlan{r.fieldNames()}, nil, nil
		case indexTrue: 
			return r, nil, nil
		}
	case *unaryOperation:
		if x.op != '!' {
			break
		}

		operand, ok := x.v.(*ident)
		if !ok {
			break
		}

		cname := operand.s
		if r.cname != cname {
			break
		}

		switch r.kind {
		case indexFalse: 
			return r, nil, nil
		case indexTrue: 
			return &nullPlan{r.fieldNames()}, nil, nil
		}
	}

	return nil, nil, nil
}

func (r *indexPlan) hasID() bool { return true }

type explainDefaultPlan struct {
	s stmt
}

func (r *explainDefaultPlan) hasID() bool { return false }

func (r *explainDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error {
	var buf bytes.Buffer
	switch x := r.s.(type) {
	default:
		w := strutil.IndentFormatter(&buf, "│   ")
		x.explain(ctx, w)
	}

	a := bytes.Split(buf.Bytes(), []byte{'\n'})
	for _, v := range a[:len(a)-1] {
		if more, err := f(nil, []interface{}{string(v)}); !more || err != nil {
			return err
		}
	}
	return nil
}

func (r *explainDefaultPlan) explain(w strutil.Formatter) {}

func (r *explainDefaultPlan) fieldNames() []string {
	return []string{""}
}

func (r *explainDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

type filterDefaultPlan struct {
	plan
	expr expression
	is   []string
}

func (r *filterDefaultPlan) hasID() bool { return r.plan.hasID() }

func (r *filterDefaultPlan) explain(w strutil.Formatter) {
	r.plan.explain(w)
	w.Format("┌Filter on %v\n", r.expr)
	if len(r.is) != 0 {
		w.Format("│Possibly useful indices\n")
		m := map[string]bool{}
		for _, v := range r.is {
			if !m[v] {
				m[v] = true
				n := ""
				for _, r := range v {
					if r >= '0' && r <= '9' || r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' || r == '_' {
						n += string(r)
						continue
					}

					n += "_"
				}
				for strings.Contains(n, "__") {
					n = strings.Replace(n, "__", "_", -1)
				}
				for strings.HasSuffix(n, "_") {
					n = n[:len(n)-1]
				}
				w.Format("│CREATE INDEX x%s ON %s;\n", n, v)
			}
		}
	}
	w.Format("└Output field names %v\n", qnames(r.plan.fieldNames()))
}

func (r *filterDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
	m := map[interface{}]interface{}{}
	fields := r.plan.fieldNames()
	return r.plan.do(ctx, func(rid interface{}, data []interface{}) (bool, error) {
		for i, v := range fields {
			m[v] = data[i]
		}
		m["$id"] = rid
		val, err := r.expr.eval(ctx, m)
		if err != nil {
			return false, err
		}

		if val == nil {
			return true, nil
		}

		x, ok := val.(bool)
		if !ok {
			return false, fmt.Errorf("invalid boolean expression %s (value of type %T)", val, val)
		}

		if !x {
			return true, nil
		}

		return f(rid, data)
	})
}

type crossJoinDefaultPlan struct {
	rsets  []plan
	names  []string
	fields []string
}

func (r *crossJoinDefaultPlan) hasID() bool { return false }

func (r *crossJoinDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Compute Cartesian product of%i\n")
	for i, v := range r.rsets {
		sel := !isTableOrIndex(v)
		if sel {
			w.Format("┌Iterate all rows of virtual table %q%i\n", r.names[i])
		}
		v.explain(w)
		if sel {
			w.Format("%u└Output field names %v\n", qnames(v.fieldNames()))
		}
	}
	w.Format("%u└Output field names %v\n", qnames(r.fields))
}

func (r *crossJoinDefaultPlan) filter(expr expression) (plan, []string, error) {
	var is []string
	for i, v := range r.names {
		e2, err := expr.clone(nil, v)
		if err != nil {
			return nil, nil, err
		}

		p2, is2, err := r.rsets[i].filter(e2)
		is = append(is, is2...)
		if err != nil {
			return nil, nil, err
		}

		if p2 != nil {
			r.rsets[i] = p2
			return r, is, nil
		}
	}
	return nil, is, nil
}

func (r *crossJoinDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error {
	if len(r.rsets) == 1 {
		return r.rsets[0].do(ctx, f)
	}

	ids := map[string]interface{}{}
	var g func([]interface{}, []plan, int) error
	g = func(prefix []interface{}, rsets []plan, x int) (err error) {
		return rsets[0].do(ctx, func(id interface{}, in []interface{}) (bool, error) {
			ids[r.names[x]] = id
			if len(rsets) > 1 {
				return true, g(append(prefix, in...), rsets[1:], x+1)
			}

			return f(ids, append(prefix, in...))
		})
	}
	return g(nil, r.rsets, 0)
}

func (r *crossJoinDefaultPlan) fieldNames() []string { return r.fields }

type distinctDefaultPlan struct {
	src    plan
	fields []string
}

func (r *distinctDefaultPlan) hasID() bool { return false }

func (r *distinctDefaultPlan) explain(w strutil.Formatter) {
	r.src.explain(w)
	w.Format("┌Compute distinct rows\n└Output field names %v\n", r.fields)
}

func (r *distinctDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *distinctDefaultPlan) fieldNames() []string { return r.fields }

func (r *distinctDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
	t, err := ctx.db.store.CreateTemp(true)
	if err != nil {
		return
	}

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

	if err = r.src.do(ctx, func(id interface{}, in []interface{}) (bool, error) {
		if err = t.Set(in, nil); err != nil {
			return false, err
		}

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

	var data []interface{}
	more := true
	it, err := t.SeekFirst()
	for more && err == nil {
		data, _, err = it.Next()
		if err != nil {
			break
		}

		more, err = f(nil, data)
	}
	return noEOF(err)
}

type groupByDefaultPlan struct {
	colNames []string
	src      plan
	fields   []string
}

func (r *groupByDefaultPlan) hasID() bool { return false }

func (r *groupByDefaultPlan) explain(w strutil.Formatter) {
	r.src.explain(w)
	switch {
	case len(r.colNames) == 0: 
		w.Format("┌Group by distinct rows")
	default:
		w.Format("┌Group by")
		for _, v := range r.colNames {
			w.Format(" %s,", v)
		}
	}
	w.Format("\n└Output field names %v\n", qnames(r.fields))
}

func (r *groupByDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *groupByDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
	t, err := ctx.db.store.CreateTemp(true)
	if err != nil {
		return
	}

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

	var gcols []*col
	var cols []*col
	m := map[string]int{}
	for i, v := range r.src.fieldNames() {
		m[v] = i
	}
	for _, c := range r.colNames {
		i, ok := m[c]
		if !ok {
			return fmt.Errorf("unknown field %s", c)
		}

		gcols = append(gcols, &col{name: c, index: i})
	}
	k := make([]interface{}, len(r.colNames)) 
	if err = r.src.do(ctx, func(rid interface{}, in []interface{}) (more bool, err error) {
		infer(in, &cols)
		for i, c := range gcols {
			k[i] = in[c.index]
		}
		h0, err := t.Get(k)
		if err != nil {
			return false, err
		}

		var h int64
		if len(h0) != 0 {
			h, _ = h0[0].(int64)
		}
		nh, err := t.Create(append([]interface{}{h, nil}, in...)...)
		if err != nil {
			return false, err
		}

		for i, c := range gcols {
			k[i] = in[c.index]
		}
		err = t.Set(k, []interface{}{nh})
		if err != nil {
			return false, err
		}

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

	for i, v := range r.src.fieldNames()[:len(cols)] {
		cols[i].name = v
		cols[i].index = i
	}
	if more, err := f(nil, []interface{}{t, cols}); !more || err != nil {
		return err
	}

	it, err := t.SeekFirst()
	more := true
	var data []interface{}
	for more && err == nil {
		if _, data, err = it.Next(); err != nil {
			break
		}

		more, err = f(nil, data)
	}
	return noEOF(err)
}

func (r *groupByDefaultPlan) fieldNames() []string { return r.fields }

type selectIndexDefaultPlan struct {
	nm string
	x  interface{}
}

func (r *selectIndexDefaultPlan) hasID() bool { return false }

func (r *selectIndexDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Iterate all values of index %q\n└Output field names N/A\n", r.nm)
}

func (r *selectIndexDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *selectIndexDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
	var x btreeIndex
	switch ix := r.x.(type) {
	case *indexedCol:
		x = ix.x
	case *index2:
		x = ix.x
	default:
		panic("internal error 007")
	}

	en, err := x.SeekFirst()
	if err != nil {
		return noEOF(err)
	}

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

		id++
		if more, err := f(id, k); !more || err != nil {
			return err
		}
	}
}

func (r *selectIndexDefaultPlan) fieldNames() []string {
	return []string{r.nm}
}

type limitDefaultPlan struct {
	expr   expression
	src    plan
	fields []string
}

func (r *limitDefaultPlan) hasID() bool { return r.src.hasID() }

func (r *limitDefaultPlan) explain(w strutil.Formatter) {
	r.src.explain(w)
	w.Format("┌Pass first %v records\n└Output field names %v\n", r.expr, r.fields)
}

func (r *limitDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *limitDefaultPlan) fieldNames() []string { return r.fields }

func (r *limitDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) (err error) {
	m := map[interface{}]interface{}{}
	var eval bool
	var lim uint64
	return r.src.do(ctx, func(rid interface{}, in []interface{}) (more bool, err error) {
		if !eval {
			for i, fld := range r.fields {
				if fld != "" {
					m[fld] = in[i]
				}
			}
			m["$id"] = rid
			val, err := r.expr.eval(ctx, m)
			if err != nil {
				return false, err
			}

			if val == nil {
				return true, nil
			}

			if lim, err = limOffExpr(val); err != nil {
				return false, err
			}

			eval = true
		}
		switch lim {
		case 0:
			return false, nil
		default:
			lim--
			return f(rid, in)
		}
	})
}

type offsetDefaultPlan struct {
	expr   expression
	src    plan
	fields []string
}

func (r *offsetDefaultPlan) hasID() bool { return r.src.hasID() }

func (r *offsetDefaultPlan) explain(w strutil.Formatter) {
	r.src.explain(w)
	w.Format("┌Skip first %v records\n└Output field names %v\n", r.expr, qnames(r.fields))
}

func (r *offsetDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *offsetDefaultPlan) fieldNames() []string { return r.fields }

func (r *offsetDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error {
	m := map[interface{}]interface{}{}
	var eval bool
	var off uint64
	return r.src.do(ctx, func(rid interface{}, in []interface{}) (bool, error) {
		if !eval {
			for i, fld := range r.fields {
				if fld != "" {
					m[fld] = in[i]
				}
			}
			m["$id"] = rid
			val, err := r.expr.eval(ctx, m)
			if err != nil {
				return false, err
			}

			if val == nil {
				return true, nil
			}

			if off, err = limOffExpr(val); err != nil {
				return false, err
			}

			eval = true
		}
		if off > 0 {
			off--
			return true, nil
		}

		return f(rid, in)
	})
}

type orderByDefaultPlan struct {
	asc    bool
	by     []expression
	src    plan
	fields []string
}

func (r *orderByDefaultPlan) hasID() bool { return r.src.hasID() }

func (r *orderByDefaultPlan) explain(w strutil.Formatter) {
	r.src.explain(w)
	w.Format("┌Order%s by", map[bool]string{false: " descending"}[r.asc])
	for _, v := range r.by {
		w.Format(" %s,", v)
	}
	w.Format("\n└Output field names %v\n", qnames(r.fields))
}

func (r *orderByDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *orderByDefaultPlan) fieldNames() []string { return r.fields }

func (r *orderByDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
	t, err := ctx.db.store.CreateTemp(r.asc)
	if err != nil {
		return
	}

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

	m := map[interface{}]interface{}{}
	flds := r.fields
	k := make([]interface{}, len(r.by)+1)
	id := int64(-1)
	if err = r.src.do(ctx, func(rid interface{}, in []interface{}) (bool, error) {
		id++
		for i, fld := range flds {
			if fld != "" {
				m[fld] = in[i]
			}
		}
		m["$id"] = rid
		for i, expr := range r.by {
			val, err := expr.eval(ctx, m)
			if err != nil {
				return false, err
			}

			if val != nil {
				val, ordered, err := isOrderedType(val)
				if err != nil {
					return false, err
				}

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

				}
			}

			k[i] = val
		}
		k[len(r.by)] = id
		if err = t.Set(k, in); err != nil {
			return false, err
		}

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

	it, err := t.SeekFirst()
	if err != nil {
		return noEOF(err)
	}

	var data []interface{}
	more := true
	for more && err == nil {
		if _, data, err = it.Next(); err != nil {
			break
		}

		more, err = f(nil, data)
	}
	return noEOF(err)
}

type selectFieldsDefaultPlan struct {
	flds   []*fld
	src    plan
	fields []string
}

func (r *selectFieldsDefaultPlan) hasID() bool { return r.src.hasID() }

func (r *selectFieldsDefaultPlan) explain(w strutil.Formatter) {

	r.src.explain(w)
	w.Format("┌Evaluate")
	for _, v := range r.flds {
		w.Format(" %s as %s,", v.expr, fmt.Sprintf("%q", v.name))
	}
	w.Format("\n└Output field names %v\n", qnames(r.fields))
}

func (r *selectFieldsDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *selectFieldsDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error {
	fields := r.src.fieldNames()
	m := map[interface{}]interface{}{}
	return r.src.do(ctx, func(rid interface{}, in []interface{}) (bool, error) {
		for i, nm := range fields {
			if nm != "" {
				m[nm] = in[i]
			}
		}
		m["$id"] = rid
		out := make([]interface{}, len(r.flds))
		for i, fld := range r.flds {
			var err error
			if out[i], err = fld.expr.eval(ctx, m); err != nil {
				return false, err
			}
		}
		return f(rid, out)
	})
}

func (r *selectFieldsDefaultPlan) fieldNames() []string { return r.fields }

type selectFieldsGroupPlan struct {
	flds   []*fld
	src    *groupByDefaultPlan
	fields []string
}

func (r *selectFieldsGroupPlan) hasID() bool { return false }

func (r *selectFieldsGroupPlan) explain(w strutil.Formatter) {

	r.src.explain(w)
	w.Format("┌Evaluate")
	for _, v := range r.flds {
		w.Format(" %s as %s,", v.expr, fmt.Sprintf("%q", v.name))
	}
	w.Format("\n└Output field names %v\n", qnames(r.fields))
}

func (r *selectFieldsGroupPlan) fieldNames() []string { return r.fields }

func (r *selectFieldsGroupPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *selectFieldsGroupPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error {
	var t temp
	var cols []*col
	var err error
	out := make([]interface{}, len(r.flds))
	ok := false
	rows := false
	if err = r.src.do(ctx, func(rid interface{}, in []interface{}) (bool, error) {
		if ok {
			h := in[0].(int64)
			m := map[interface{}]interface{}{}
			for h != 0 {
				in, err = t.Read(nil, h, cols...)
				if err != nil {
					return false, err
				}

				rec := in[2:]
				for i, c := range cols {
					if nm := c.name; nm != "" {
						m[nm] = rec[i]
					}
				}
				m["$id"] = rid
				for _, fld := range r.flds {
					if _, err = fld.expr.eval(ctx, m); err != nil {
						return false, err
					}
				}

				h = in[0].(int64)
			}
			m["$agg"] = true
			for i, fld := range r.flds {
				if out[i], err = fld.expr.eval(ctx, m); err != nil {
					return false, err
				}
			}
			rows = true
			return f(nil, out)
		}

		ok = true
		t = in[0].(temp)
		cols = in[1].([]*col)
		if len(r.flds) == 0 { 
			r.flds = make([]*fld, len(cols))
			for i, v := range cols {
				r.flds[i] = &fld{expr: &ident{v.name}, name: v.name}
			}
			out = make([]interface{}, len(r.flds))
		}
		return true, nil
	}); err != nil {
		return err
	}

	if rows {
		return nil
	}

	m := map[interface{}]interface{}{"$agg0": true} 
	for i, fld := range r.flds {
		if out[i], err = fld.expr.eval(ctx, m); err != nil {
			return err
		}
	}
	_, err = f(nil, out)

	return err
}

type sysColumnDefaultPlan struct{}

func (r *sysColumnDefaultPlan) hasID() bool { return false }

func (r *sysColumnDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Iterate all rows of table \"__Column\"\n└Output field names %v\n", qnames(r.fieldNames()))
}

func (r *sysColumnDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *sysColumnDefaultPlan) fieldNames() []string {
	return []string{"TableName", "Ordinal", "Name", "Type"}
}

func (r *sysColumnDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error {
	rec := make([]interface{}, 4)
	di, err := ctx.db.info()
	if err != nil {
		return err
	}

	var id int64
	for _, ti := range di.Tables {
		rec[0] = ti.Name
		var ix int64
		for _, ci := range ti.Columns {
			ix++
			rec[1] = ix
			rec[2] = ci.Name
			rec[3] = ci.Type.String()
			id++
			if more, err := f(id, rec); !more || err != nil {
				return err
			}
		}
	}
	return nil
}

type sysIndexDefaultPlan struct{}

func (r *sysIndexDefaultPlan) hasID() bool { return false }

func (r *sysIndexDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Iterate all rows of table \"__Index\"\n└Output field names %v\n", qnames(r.fieldNames()))
}

func (r *sysIndexDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *sysIndexDefaultPlan) fieldNames() []string {
	return []string{"TableName", "ColumnName", "Name", "IsUnique"}
}

func (r *sysIndexDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error {
	rec := make([]interface{}, 4)
	di, err := ctx.db.info()
	if err != nil {
		return err
	}

	var id int64
	for _, xi := range di.Indices {
		rec[0] = xi.Table
		rec[1] = xi.Column
		rec[2] = xi.Name
		rec[3] = xi.Unique
		id++
		if more, err := f(id, rec); !more || err != nil {
			return err
		}
	}
	return nil
}

type sysTableDefaultPlan struct{}

func (r *sysTableDefaultPlan) hasID() bool { return false }

func (r *sysTableDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Iterate all rows of table \"__Table\"\n└Output field names %v\n", qnames(r.fieldNames()))
}

func (r *sysTableDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *sysTableDefaultPlan) fieldNames() []string { return []string{"Name", "Schema"} }

func (r *sysTableDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error {
	rec := make([]interface{}, 2)
	di, err := ctx.db.info()
	if err != nil {
		return err
	}

	var id int64
	for _, ti := range di.Tables {
		rec[0] = ti.Name
		a := []string{}
		for _, ci := range ti.Columns {
			s := ""
			if ci.NotNull {
				s += " NOT NULL"
			}
			if c := ci.Constraint; c != "" {
				s += " " + c
			}
			if d := ci.Default; d != "" {
				s += " DEFAULT " + d
			}
			a = append(a, fmt.Sprintf("%s %s%s", ci.Name, ci.Type, s))
		}
		rec[1] = fmt.Sprintf("CREATE TABLE %s (%s);", ti.Name, strings.Join(a, ", "))
		id++
		if more, err := f(id, rec); !more || err != nil {
			return err
		}
	}
	return nil
}

type tableNilPlan struct {
	t *table
}

func (r *tableNilPlan) hasID() bool { return true }

func (r *tableNilPlan) explain(w strutil.Formatter) {
	w.Format("┌Iterate all rows of table %q\n└Output field names %v\n", r.t.name, qnames(r.fieldNames()))
}

func (r *tableNilPlan) fieldNames() []string { return []string{} }

func (r *tableNilPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *tableNilPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
	t := r.t
	h := t.head
	cols := t.cols
	for h > 0 {
		rec, err := t.store.Read(nil, h, cols...) 
		if err != nil {
			return err
		}

		if m, err := f(rec[1], nil); !m || err != nil {
			return err
		}

		h = rec[0].(int64) 
	}
	return nil
}

type tableDefaultPlan struct {
	t      *table
	fields []string
}

func (r *tableDefaultPlan) hasID() bool { return true }

func (r *tableDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Iterate all rows of table %q\n└Output field names %v\n", r.t.name, qnames(r.fields))
}

func (r *tableDefaultPlan) filterBinOp(x *binaryOperation) (plan, []string, error) {
	ok, cn, rval, err := x.isIdentRelOpVal()
	if err != nil {
		return nil, nil, err
	}

	if !ok {
		return nil, nil, nil
	}

	t := r.t
	c, ix := t.findIndexByColName(cn)
	if ix == nil { 
		return nil, []string{fmt.Sprintf("%s(%s)", t.name, cn)}, nil
	}

	if rval, err = typeCheck1(rval, c); err != nil {
		return nil, nil, err
	}

	switch x.op {
	case eq:
		return &indexPlan{t, cn, ix.name, ix.x, indexEq, rval, rval}, nil, nil
	case '<':
		return &indexPlan{t, cn, ix.name, ix.x, indexLt, nil, rval}, nil, nil
	case le:
		return &indexPlan{t, cn, ix.name, ix.x, indexLe, nil, rval}, nil, nil
	case ge:
		return &indexPlan{t, cn, ix.name, ix.x, indexGe, rval, nil}, nil, nil
	case '>':
		return &indexPlan{t, cn, ix.name, ix.x, indexGt, rval, nil}, nil, nil
	case neq:
		return &indexPlan{t, cn, ix.name, ix.x, indexNe, rval, rval}, nil, nil
	default:
		panic("internal error 069")
	}
}

func (r *tableDefaultPlan) filterIdent(x *ident, trueValue bool) (plan, []string, error) {
	cn := x.s
	t := r.t
	for _, v := range t.cols {
		if v.name != cn {
			continue
		}

		if v.typ != qBool {
			return nil, nil, nil
		}

		xi := v.index + 1 
		if xi >= len(t.indices) {
			return nil, nil, nil
		}

		ix := t.indices[xi]
		if ix == nil { 
			return nil, []string{fmt.Sprintf("%s(%s)", t.name, cn)}, nil
		}

		kind := indexFalse
		if trueValue {
			kind = indexTrue
		}
		return &indexPlan{t, cn, ix.name, ix.x, kind, nil, nil}, nil, nil
	}
	return nil, nil, nil
}

func (r *tableDefaultPlan) filterIsNull(x *isNull) (plan, []string, error) {
	ok, cn := isColumnExpression(x.expr)
	if !ok {
		return nil, nil, nil
	}

	t := r.t
	_, ix := t.findIndexByColName(cn)
	if ix == nil { 
		return nil, []string{fmt.Sprintf("%s(%s)", t.name, cn)}, nil
	}

	switch {
	case x.not:
		return &indexPlan{t, cn, ix.name, ix.x, indexIsNotNull, nil, nil}, nil, nil
	default:
		return &indexPlan{t, cn, ix.name, ix.x, indexIsNull, nil, nil}, nil, nil
	}
}

func (r *tableDefaultPlan) filter(expr expression) (plan, []string, error) {
	cols := mentionedColumns(expr)
	for _, v := range r.fields {
		delete(cols, v)
	}
	for k := range cols {
		return nil, nil, fmt.Errorf("unknown field %s", k)
	}

	var is []string

	switch x := expr.(type) {
	case *binaryOperation:
		return r.filterBinOp(x)
	case *ident:
		return r.filterIdent(x, true)
	case *isNull:
		return r.filterIsNull(x)
	case *unaryOperation:
		if x.op != '!' {
			break
		}

		if operand, ok := x.v.(*ident); ok {
			return r.filterIdent(operand, false)
		}
	default:

		return nil, is, nil 
	}

	return nil, is, nil
}

func (r *tableDefaultPlan) do(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) (err error) {
	t := r.t
	cols := t.cols
	h := t.head
	for h > 0 {
		rec, err := t.row0(ctx, h)
		if err != nil {
			return err
		}

		h = rec[0].(int64)
		id := rec[1].(int64)
		for i, c := range cols {
			rec[i] = rec[c.index+2]
		}
		if m, err := f(id, rec[:len(cols)]); !m || err != nil {
			return err
		}
	}
	return nil
}

func (r *tableDefaultPlan) fieldNames() []string { return r.fields }

type nullPlan struct {
	fields []string
}

func (r *nullPlan) hasID() bool { return false }

func (r *nullPlan) fieldNames() []string { return r.fields }

func (r *nullPlan) explain(w strutil.Formatter) {
	w.Format("┌Iterate no rows\n└Output field names %v\n", qnames(r.fields))
}

func (r *nullPlan) do(*execCtx, func(interface{}, []interface{}) (bool, error)) error {
	return nil
}

func (r *nullPlan) filter(expr expression) (plan, []string, error) {
	return r, nil, nil
}

type leftJoinDefaultPlan struct {
	on     expression
	rsets  []plan
	names  []string
	right  int
	fields []string
}

func (r *leftJoinDefaultPlan) hasID() bool { return false }

func (r *leftJoinDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Compute Cartesian product of%i\n")
	for i, v := range r.rsets {
		sel := !isTableOrIndex(v)
		if sel {
			w.Format("┌Iterate all rows of virtual table %q%i\n", r.names[i])
		}
		v.explain(w)
		if sel {
			w.Format("%u└Output field names %v\n", qnames(v.fieldNames()))
		}
	}
	w.Format("Extend the product with all NULL rows of %q when no match for %v%u\n", r.names[len(r.names)-1], r.on)
	w.Format("└Output field names %v\n", qnames(r.fields))
}

func (r *leftJoinDefaultPlan) filter(expr expression) (plan, []string, error) {
	var is []string
	for i, v := range r.names {
		e2, err := expr.clone(nil, v)
		if err != nil {
			return nil, nil, err
		}

		p2, is2, err := r.rsets[i].filter(e2)
		is = append(is, is2...)
		if err != nil {
			return nil, nil, err
		}

		if p2 != nil {
			r.rsets[i] = p2
			return r, is, nil
		}
	}
	return nil, is, nil
}

type rightJoinDefaultPlan struct {
	leftJoinDefaultPlan
}

func (r *rightJoinDefaultPlan) hasID() bool { return false }

func (r *rightJoinDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Compute Cartesian product of%i\n")
	for i, v := range r.rsets {
		sel := !isTableOrIndex(v)
		if sel {
			w.Format("┌Iterate all rows of virtual table %q%i\n", r.names[i])
		}
		v.explain(w)
		if sel {
			w.Format("%u└Output field names %v\n", qnames(v.fieldNames()))
		}
	}
	w.Format("Extend the product with all NULL rows of all but %q when no match for %v%u\n", r.names[len(r.names)-1], r.on)
	w.Format("└Output field names %v\n", qnames(r.fields))
}

func (r *rightJoinDefaultPlan) filter(expr expression) (plan, []string, error) {
	var is []string
	for i, v := range r.names {
		e2, err := expr.clone(nil, v)
		if err != nil {
			return nil, nil, err
		}

		p2, is2, err := r.rsets[i].filter(e2)
		is = append(is, is2...)
		if err != nil {
			return nil, nil, err
		}

		if p2 != nil {
			r.rsets[i] = p2
			return r, is, nil
		}
	}
	return nil, is, nil
}

type fullJoinDefaultPlan struct {
	leftJoinDefaultPlan
}

func (r *fullJoinDefaultPlan) hasID() bool { return false }

func (r *fullJoinDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Compute Cartesian product of%i\n")
	for i, v := range r.rsets {
		sel := !isTableOrIndex(v)
		if sel {
			w.Format("┌Iterate all rows of virtual table %q%i\n", r.names[i])
		}
		v.explain(w)
		if sel {
			w.Format("%u└Output field names %v\n", qnames(v.fieldNames()))
		}
	}
	w.Format("Extend the product with all NULL rows of %q when no match for %v\n", r.names[len(r.names)-1], r.on)
	w.Format("Extend the product with all NULL rows of all but %q when no match for %v%u\n", r.names[len(r.names)-1], r.on)
	w.Format("└Output field names %v\n", qnames(r.fields))
}

func (r *fullJoinDefaultPlan) filter(expr expression) (plan, []string, error) {
	var is []string
	for i, v := range r.names {
		e2, err := expr.clone(nil, v)
		if err != nil {
			return nil, nil, err
		}

		p2, is2, err := r.rsets[i].filter(e2)
		is = append(is, is2...)
		if err != nil {
			return nil, nil, err
		}

		if p2 != nil {
			r.rsets[i] = p2
			return r, is, nil
		}
	}
	return nil, is, nil
}

func (r *leftJoinDefaultPlan) fieldNames() []string { return r.fields }

func (r *leftJoinDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error {
	m := map[interface{}]interface{}{}
	ids := map[string]interface{}{}
	var g func([]interface{}, []plan, int) error
	var match bool
	g = func(prefix []interface{}, rsets []plan, x int) (err error) {
		return rsets[0].do(ctx, func(id interface{}, in []interface{}) (bool, error) {
			ids[r.names[x]] = id
			row := append(prefix, in...)
			if len(rsets) > 1 {
				if len(rsets) == 2 {
					match = false
				}
				if err = g(row, rsets[1:], x+1); err != nil {
					return false, err
				}

				if len(rsets) != 2 || match {
					return true, nil
				}

				ids[r.names[x+1]] = nil
				return f(ids, append(row, make([]interface{}, r.right)...))
			}

			for i, fld := range r.fields {
				if fld != "" {
					m[fld] = row[i]
				}
			}

			val, err := r.on.eval(ctx, m)
			if err != nil {
				return false, err
			}

			if val == nil {
				return true, nil
			}

			x, ok := val.(bool)
			if !ok {
				return false, fmt.Errorf("invalid ON expression %s (value of type %T)", val, val)
			}

			if !x {
				return true, nil
			}

			match = true
			return f(ids, row)
		})
	}
	return g(nil, r.rsets, 0)
}

func (r *rightJoinDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error {
	right := r.right
	left := len(r.fields) - right
	n := len(r.rsets)
	m := map[interface{}]interface{}{}
	ids := map[string]interface{}{}
	var g func([]interface{}, []plan, int) error
	var match bool
	nf := len(r.fields)
	fields := append(append([]string(nil), r.fields[nf-right:]...), r.fields[:nf-right]...)
	g = func(prefix []interface{}, rsets []plan, x int) (err error) {
		return rsets[0].do(ctx, func(id interface{}, in []interface{}) (bool, error) {
			ids[r.names[x]] = id
			row := append(prefix, in...)
			if len(rsets) > 1 {
				if len(rsets) == n {
					match = false
				}
				if err = g(row, rsets[1:], x+1); err != nil {
					return false, err
				}

				if len(rsets) != n || match {
					return true, nil
				}

				for i := 0; i < n-1; i++ {
					ids[r.names[i]] = nil
				}

				return f(ids, append(make([]interface{}, left), row[:right]...))
			}

			for i, fld := range fields {
				if fld != "" {
					m[fld] = row[i]
				}
			}

			val, err := r.on.eval(ctx, m)
			if err != nil {
				return false, err
			}

			if val == nil {
				return true, nil
			}

			x, ok := val.(bool)
			if !ok {
				return false, fmt.Errorf("invalid ON expression %s (value of type %T)", val, val)
			}

			if !x {
				return true, nil
			}

			match = true

			return f(ids, append(append([]interface{}(nil), row[right:]...), row[:right]...))
		})
	}
	return g(nil, append([]plan{r.rsets[n-1]}, r.rsets[:n-1]...), 0)
}

func (r *fullJoinDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error {
	b3 := b.TreeNew(func(a, b interface{}) int {
		x := a.(int64)
		y := b.(int64)
		if x < y {
			return -1
		}

		if x == y {
			return 0
		}

		return 1
	})
	m := map[interface{}]interface{}{}
	ids := map[string]interface{}{}
	var g func([]interface{}, []plan, int) error
	var match bool
	var rid int64
	firstR := true
	g = func(prefix []interface{}, rsets []plan, x int) (err error) {
		return rsets[0].do(ctx, func(id interface{}, in []interface{}) (bool, error) {
			ids[r.names[x]] = id
			row := append(prefix, in...)
			if len(rsets) > 1 {
				if len(rsets) == 2 {
					match = false
					rid = 0
				}
				if err = g(row, rsets[1:], x+1); err != nil {
					return false, err
				}

				if len(rsets) == 2 {
					firstR = false
				}
				if len(rsets) != 2 || match {
					return true, nil
				}

				ids[r.names[x+1]] = nil
				return f(ids, append(row, make([]interface{}, r.right)...))
			}

			rid++
			if firstR {
				b3.Set(rid, in)
			}
			for i, fld := range r.fields {
				if fld != "" {
					m[fld] = row[i]
				}
			}

			val, err := r.on.eval(ctx, m)
			if err != nil {
				return false, err
			}

			if val == nil {
				return true, nil
			}

			x, ok := val.(bool)
			if !ok {
				return false, fmt.Errorf("invalid ON expression %s (value of type %T)", val, val)
			}

			if !x {
				return true, nil
			}

			match = true
			b3.Delete(rid)
			return f(ids, row)
		})
	}
	if err := g(nil, r.rsets, 0); err != nil {
		return err
	}

	it, err := b3.SeekFirst()
	if err != nil {
		return noEOF(err)
	}

	pref := make([]interface{}, len(r.fields)-r.right)
	for {
		_, v, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		more, err := f(nil, append(pref, v.([]interface{})...))
		if err != nil || !more {
			return err
		}
	}
}

type selectDummyPlan struct {
	flds []*fld
}

func (r *selectDummyPlan) hasID() bool { return true }

func (r *selectDummyPlan) explain(w strutil.Formatter) {
	w.Format("┌Selects values from dummy table\n└Output field names %v\n", qnames(r.fieldNames()))
}

func (r *selectDummyPlan) fieldNames() []string { return make([]string, len(r.flds)) }

func (r *selectDummyPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *selectDummyPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
	m := map[interface{}]interface{}{}
	data := []interface{}{}
	for _, v := range r.flds {
		rst, err := v.expr.eval(ctx, m)
		if err != nil {
			return err
		}
		data = append(data, rst)
	}
	_, err = f(nil, data)
	return
}
// Copyright 2015 The 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 (
	"bytes"
	"fmt"
	"strings"

	"github.com/cznic/b"
	"github.com/cznic/strutil"
)

const (
	_               = iota
	indexEq         // [L]
	indexFalse      // [false]
	indexGe         // [L, ...)
	indexGt         // (L, ...)
	indexIsNotNull  // (NULL, ...)
	indexIsNull     // [NULL]
	indexIntervalCC // [L, H]
	indexIntervalCO // [L, H)
	indexIntervalOC // (L, H]
	indexIntervalOO // (L, H)
	indexLe         // (..., H]
	indexLt         // (..., H)
	indexNe         // (L)
	indexTrue       // [true]
)

// Note: All plans must have a pointer receiver. Enables planA == planB operation.
var (
	_ plan = (*crossJoinDefaultPlan)(nil)
	_ plan = (*distinctDefaultPlan)(nil)
	_ plan = (*explainDefaultPlan)(nil)
	_ plan = (*filterDefaultPlan)(nil)
	_ plan = (*fullJoinDefaultPlan)(nil)
	_ plan = (*groupByDefaultPlan)(nil)
	_ plan = (*indexPlan)(nil)
	_ plan = (*leftJoinDefaultPlan)(nil)
	_ plan = (*limitDefaultPlan)(nil)
	_ plan = (*nullPlan)(nil)
	_ plan = (*offsetDefaultPlan)(nil)
	_ plan = (*orderByDefaultPlan)(nil)
	_ plan = (*rightJoinDefaultPlan)(nil)
	_ plan = (*selectFieldsDefaultPlan)(nil)
	_ plan = (*selectFieldsGroupPlan)(nil)
	_ plan = (*selectIndexDefaultPlan)(nil)
	_ plan = (*selectDummyPlan)(nil)
	_ plan = (*sysColumnDefaultPlan)(nil)
	_ plan = (*sysIndexDefaultPlan)(nil)
	_ plan = (*sysTableDefaultPlan)(nil)
	_ plan = (*tableDefaultPlan)(nil)
	_ plan = (*tableNilPlan)(nil)
)

type plan interface {
	do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error
	explain(w strutil.Formatter)
	fieldNames() []string
	filter(expr expression) (p plan, indicesSought []string, err error)
	hasID() bool
}

func isTableOrIndex(p plan) bool {
	switch p.(type) {
	case
		*indexPlan,
		*sysColumnDefaultPlan,
		*sysIndexDefaultPlan,
		*sysTableDefaultPlan,
		*tableDefaultPlan:
		return true
	default:
		return false
	}
}

// Invariants
// - All interval plans produce rows in ascending index value collating order.
// - L <= H
type indexPlan struct {
	src   *table
	cname string
	xname string
	x     btreeIndex
	kind  int         // See interval* consts.
	lval  interface{} // L, H: Ordered and comparable (lldb perspective).
	hval  interface{}
}

func (r *indexPlan) doGe(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	// nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ...
	// ---  ---  ---  ---  ---  +  +  +++  +++  +++
	t := r.src
	it, _, err := r.x.Seek([]interface{}{r.lval})
	if err != nil {
		return noEOF(err)
	}

	for {
		_, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doGt(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	// nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ...
	// ---  ---  ---  ---  ---  -  -  +++  +++  +++
	t := r.src
	it, _, err := r.x.Seek([]interface{}{r.lval})
	if err != nil {
		return noEOF(err)
	}

	var ok bool
	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if !ok {
			val, err := expand1(k[0], nil)
			if err != nil {
				return err
			}

			if collate1(val, r.lval) == 0 {
				continue
			}

			ok = true
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doInterval00(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	// nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ..., H-1, H-1, H, H, H+1, H+1, ...
	// ---  ---  ---  ---  ---  -  -  +++  +++  +++  +++  +++  -  -  ---  ---  ---
	t := r.src
	it, _, err := r.x.Seek([]interface{}{r.lval})
	if err != nil {
		return noEOF(err)
	}

	var ok bool
	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if !ok {
			val, err := expand1(k[0], nil)
			if err != nil {
				return err
			}

			if collate1(val, r.lval) == 0 {
				continue
			}

			ok = true
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.hval) == 0 {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doIntervalOC(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	// nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ..., H-1, H-1, H, H, H+1, H+1, ...
	// ---  ---  ---  ---  ---  -  -  +++  +++  +++  +++  +++  +  +  ---  ---  ---
	t := r.src
	it, _, err := r.x.Seek([]interface{}{r.lval})
	if err != nil {
		return noEOF(err)
	}

	var ok bool
	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if !ok {
			val, err := expand1(k[0], nil)
			if err != nil {
				return err
			}

			if collate1(val, r.lval) == 0 {
				continue
			}

			ok = true
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.hval) > 0 {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doIntervalCC(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	// nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ..., H-1, H-1, H, H, H+1, H+1, ...
	// ---  ---  ---  ---  ---  +  +  +++  +++  +++  +++  +++  +  +  ---  ---  ---
	t := r.src
	it, _, err := r.x.Seek([]interface{}{r.lval})
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.hval) > 0 {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doIntervalCO(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	// nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ..., H-1, H-1, H, H, H+1, H+1, ...
	// ---  ---  ---  ---  ---  +  +  +++  +++  +++  +++  +++  -  -  ---  ---  ---
	t := r.src
	it, _, err := r.x.Seek([]interface{}{r.lval})
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.hval) >= 0 {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doLe(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	// nil, nil, ..., H-1, H-1, H, H, H+1, H+1, ...
	// ---  ---  +++  +++  +++  +  +  ---  ---
	t := r.src
	it, err := r.x.SeekFirst()
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if k == nil || k[0] == nil {
			continue
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.hval) > 0 {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doLt(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	// nil, nil, ..., H-1, H-1, H, H, H+1, H+1, ...
	// ---  ---  +++  +++  +++  -  -  ---  ---
	t := r.src
	it, err := r.x.SeekFirst()
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if k == nil || k[0] == nil {
			continue
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.hval) >= 0 {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doEq(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	// nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ...
	// ---  ---  ---  ---  ---  +  +  ---  ---  ---
	t := r.src
	it, _, err := r.x.Seek([]interface{}{r.lval})
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.lval) != 0 {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doNe(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	// nil, nil, ..., L-1, L-1, L, L, L+1, L+1, ...
	// ---  ---  +++  +++  +++  -  -  +++  +++  +++
	t := r.src
	it, err := r.x.SeekFirst()
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if k == nil || k[0] == nil {
			continue
		}

		val, err := expand1(k[0], nil)
		if err != nil {
			return err
		}

		if collate1(val, r.hval) == 0 {
			continue
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doIsNull(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	// nil, nil, ...
	// +++  +++  ---
	t := r.src
	it, err := r.x.SeekFirst()
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if k != nil && k[0] != nil {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doIsNotNull(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	// nil, nil, ...
	// ---  ---  +++
	t := r.src
	it, _, err := r.x.Seek([]interface{}{false}) // lldb collates false right after NULL.
	if err != nil {
		return noEOF(err)
	}

	for {
		_, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doFalse(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	t := r.src
	it, _, err := r.x.Seek([]interface{}{false})
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		b, ok := k[0].(bool)
		if !ok || b {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) doTrue(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	t := r.src
	it, _, err := r.x.Seek([]interface{}{true})
	if err != nil {
		return noEOF(err)
	}

	for {
		k, h, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		if _, ok := k[0].(bool); !ok {
			return nil
		}

		id, data, err := t.row(ctx, h)
		if err != nil {
			return err
		}

		if more, err := f(id, data); err != nil || !more {
			return err
		}
	}
}

func (r *indexPlan) do(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) error {
	switch r.kind {
	case indexEq:
		return r.doEq(ctx, f)
	case indexGe:
		return r.doGe(ctx, f)
	case indexGt:
		return r.doGt(ctx, f)
	case indexLe:
		return r.doLe(ctx, f)
	case indexLt:
		return r.doLt(ctx, f)
	case indexNe:
		return r.doNe(ctx, f)
	case indexIsNull:
		return r.doIsNull(ctx, f)
	case indexIsNotNull:
		return r.doIsNotNull(ctx, f)
	case indexFalse:
		return r.doFalse(ctx, f)
	case indexTrue:
		return r.doTrue(ctx, f)
	case indexIntervalOO:
		return r.doInterval00(ctx, f)
	case indexIntervalCC:
		return r.doIntervalCC(ctx, f)
	case indexIntervalOC:
		return r.doIntervalOC(ctx, f)
	case indexIntervalCO:
		return r.doIntervalCO(ctx, f)
	default:
		//dbg("", r.kind)
		panic("internal error 068")
	}
}

func (r *indexPlan) explain(w strutil.Formatter) {
	s := ""
	if r.kind == indexFalse {
		s = "!"
	}
	w.Format("┌Iterate all rows of table %q using index %q where %s%s", r.src.name, r.xname, s, r.cname)
	switch r.kind {
	case indexEq:
		w.Format(" == %v", value{r.lval})
	case indexGe:
		w.Format(" >= %v", value{r.lval})
	case indexGt:
		w.Format(" > %v", value{r.lval})
	case indexLe:
		w.Format(" <= %v", value{r.hval})
	case indexLt:
		w.Format(" < %v", value{r.hval})
	case indexNe:
		w.Format(" != %v", value{r.lval})
	case indexIsNull:
		w.Format(" IS NULL")
	case indexIsNotNull:
		w.Format(" IS NOT NULL")
	case indexFalse, indexTrue:
		// nop
	case indexIntervalOO:
		w.Format(" > %v && %s < %v", value{r.lval}, r.cname, value{r.hval})
	case indexIntervalCC:
		w.Format(" >= %v && %s <= %v", value{r.lval}, r.cname, value{r.hval})
	case indexIntervalCO:
		w.Format(" >= %v && %s < %v", value{r.lval}, r.cname, value{r.hval})
	case indexIntervalOC:
		w.Format(" > %v && %s <= %v", value{r.lval}, r.cname, value{r.hval})
	default:
		//dbg("", r.kind)
		panic("internal error 053")
	}
	w.Format("\n└Output field names %v\n", qnames(r.fieldNames()))
}

func (r *indexPlan) fieldNames() []string { return r.src.fieldNames() }

func (r *indexPlan) filterEq(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(r.lval, val) == 0 {
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case ge:
		if collate1(r.lval, val) >= 0 {
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case '>':
		if collate1(r.lval, val) > 0 {
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case le:
		if collate1(r.lval, val) <= 0 {
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case '<':
		if collate1(r.lval, val) < 0 {
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case neq:
		if collate1(r.lval, val) != 0 {
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	}
	return nil, nil, nil
}

func (r *indexPlan) filterGe(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(r.lval, val) <= 0 {
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case ge:
		if collate1(r.lval, val) < 0 {
			r.lval = val
		}
		return r, nil, nil
	case '>':
		if collate1(r.lval, val) <= 0 {
			r.lval = val
			r.kind = indexGt
		}
		return r, nil, nil
	case le:
		switch c := collate1(r.lval, val); {
		case c < 0:
			r.hval = val
			r.kind = indexIntervalCC
			return r, nil, nil
		case c == 0:
			r.kind = indexEq
			return r, nil, nil
		default: // c > 0
			return &nullPlan{r.fieldNames()}, nil, nil
		}
	case '<':
		if collate1(r.lval, val) < 0 {
			r.hval = val
			r.kind = indexIntervalCO
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case neq:
		switch c := collate1(r.lval, val); {
		case c < 0:
			//MAYBE ORed intervals
		case c == 0:
			r.kind = indexGt
			return r, nil, nil
		default: // c > 0
			return r, nil, nil
		}
	}
	return nil, nil, nil
}

func (r *indexPlan) filterGt(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(r.lval, val) < 0 {
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case ge:
		if collate1(r.lval, val) < 0 {
			r.lval = val
			r.kind = indexGe
		}
		return r, nil, nil
	case '>':
		if collate1(r.lval, val) < 0 {
			r.lval = val
		}
		return r, nil, nil
	case le:
		if collate1(r.lval, val) < 0 {
			r.hval = val
			r.kind = indexIntervalOC
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case '<':
		if collate1(r.lval, val) < 0 {
			r.hval = val
			r.kind = indexIntervalOO
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case neq:
		if collate1(r.lval, val) >= 0 {
			return r, nil, nil
		}
	}
	return nil, nil, nil
}

func (r *indexPlan) filterLe(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(r.hval, val) >= 0 {
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case ge:
		switch c := collate1(r.hval, val); {
		case c < 0:
			return &nullPlan{r.fieldNames()}, nil, nil
		case c == 0:
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		default: // c > 0
			r.lval = val
			r.kind = indexIntervalCC
			return r, nil, nil
		}
	case '>':
		if collate1(r.hval, val) > 0 {
			r.lval = val
			r.kind = indexIntervalOC
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case le:
		if collate1(r.hval, val) > 0 {
			r.hval = val
		}
		return r, nil, nil
	case '<':
		if collate1(r.hval, val) >= 0 {
			r.hval = val
			r.kind = indexLt
		}
		return r, nil, nil
	case neq:
		switch c := collate1(r.hval, val); {
		case c < 0:
			return r, nil, nil
		case c == 0:
			r.kind = indexLt
			return r, nil, nil
		default: // c > 0
			//bop
		}
	}
	return nil, nil, nil
}

func (r *indexPlan) filterLt(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(r.hval, val) > 0 {
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case ge:
		if collate1(r.hval, val) > 0 {
			r.lval = val
			r.kind = indexIntervalCO
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case '>':
		if collate1(r.hval, val) > 0 {
			r.lval = val
			r.kind = indexIntervalOO
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case le:
		if collate1(r.hval, val) > 0 {
			r.hval = val
			r.kind = indexLe
		}
		return r, nil, nil
	case '<':
		if collate1(r.hval, val) > 0 {
			r.hval = val
		}
		return r, nil, nil
	case neq:
		if collate1(r.hval, val) > 0 {
			return nil, nil, nil
		}

		return r, nil, nil
	}
	return nil, nil, nil
}

func (r *indexPlan) filterCC(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(val, r.lval) < 0 || collate1(val, r.hval) > 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		r.lval = val
		r.kind = indexEq
		return r, nil, nil
	case ge:
		if collate1(val, r.lval) <= 0 {
			return r, nil, nil
		}

		switch c := collate1(val, r.hval); {
		case c < 0:
			r.lval = val
			return r, nil, nil
		case c == 0:
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		default:
			return &nullPlan{r.fieldNames()}, nil, nil
		}
	case '>':
		switch c := collate1(val, r.lval); {
		case c < 0:
			return r, nil, nil
		case c == 0:
			r.kind = indexIntervalOC
			return r, nil, nil
		default:
			if collate1(val, r.hval) < 0 {
				r.lval = val
				r.kind = indexIntervalOC
				return r, nil, nil
			}

			return &nullPlan{r.fieldNames()}, nil, nil
		}
	case le:
		switch c := collate1(val, r.lval); {
		case c < 0:
			return &nullPlan{r.fieldNames()}, nil, nil
		case c == 0:
			r.kind = indexEq
			return r, nil, nil
		default:
			if collate1(val, r.hval) < 0 {
				r.hval = val
			}
			return r, nil, nil
		}
	case '<':
		if collate1(val, r.lval) <= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		if collate1(val, r.hval) <= 0 {
			r.hval = val
			r.kind = indexIntervalCO
		}
		return r, nil, nil
	case neq:
		switch c := collate1(val, r.lval); {
		case c < 0:
			return r, nil, nil
		case c == 0:
			r.kind = indexIntervalOC
			return r, nil, nil
		default:
			switch c := collate1(val, r.hval); {
			case c == 0:
				r.kind = indexIntervalCO
				return r, nil, nil
			case c > 0:
				return r, nil, nil
			default:
				return nil, nil, nil
			}
		}
	}
	return nil, nil, nil
}

func (r *indexPlan) filterOC(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(val, r.lval) <= 0 || collate1(val, r.hval) > 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		r.lval = val
		r.kind = indexEq
		return r, nil, nil
	case ge:
		if collate1(val, r.lval) <= 0 {
			return r, nil, nil
		}

		switch c := collate1(val, r.hval); {
		case c < 0:
			r.lval = val
			r.kind = indexIntervalCC
			return r, nil, nil
		case c == 0:
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		default:
			return &nullPlan{r.fieldNames()}, nil, nil
		}
	case '>':
		if collate1(val, r.lval) <= 0 {
			return r, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.lval = val
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case le:
		if collate1(val, r.lval) <= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.hval = val
		}
		return r, nil, nil
	case '<':
		if collate1(val, r.lval) <= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		switch c := collate1(val, r.hval); {
		case c < 0:
			r.hval = val
			r.kind = indexIntervalOO
		case c == 0:
			r.kind = indexIntervalOO
		}
		return r, nil, nil
	case neq:
		if collate1(val, r.lval) <= 0 {
			return r, nil, nil
		}

		switch c := collate1(val, r.hval); {
		case c < 0:
			return nil, nil, nil
		case c == 0:
			r.kind = indexIntervalOO
			return r, nil, nil
		default:
			return r, nil, nil
		}
	}
	return nil, nil, nil
}

func (r *indexPlan) filterOO(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(val, r.lval) <= 0 || collate1(val, r.hval) >= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		r.lval = val
		r.kind = indexEq
		return r, nil, nil
	case ge:
		if collate1(val, r.lval) <= 0 {
			return r, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.lval = val
			r.kind = indexIntervalCO
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case '>':
		if collate1(val, r.lval) <= 0 {
			return r, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.lval = val
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case le:
		if collate1(val, r.lval) <= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.hval = val
			r.kind = indexIntervalOC
		}
		return r, nil, nil
	case '<':
		if collate1(val, r.lval) <= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.hval = val
		}
		return r, nil, nil
	case neq:
		if collate1(val, r.lval) <= 0 || collate1(val, r.hval) >= 0 {
			return r, nil, nil
		}

		return nil, nil, nil
	}
	return nil, nil, nil
}

func (r *indexPlan) filterCO(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(val, r.lval) < 0 || collate1(val, r.hval) >= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		r.lval = val
		r.kind = indexEq
		return r, nil, nil
	case ge:
		if collate1(val, r.lval) <= 0 {
			return r, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.lval = val
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case '>':
		switch c := collate1(val, r.lval); {
		case c < 0:
			return r, nil, nil
		case c == 0:
			r.kind = indexIntervalOO
			return r, nil, nil
		default:
			if collate1(val, r.hval) < 0 {
				r.lval = val
				r.kind = indexIntervalOO
				return r, nil, nil
			}

			return &nullPlan{r.fieldNames()}, nil, nil
		}
	case le:
		switch c := collate1(val, r.lval); {
		case c < 0:
			return &nullPlan{r.fieldNames()}, nil, nil
		case c == 0:
			r.kind = indexEq
			return r, nil, nil
		default:
			if collate1(val, r.hval) < 0 {
				r.hval = val
				r.kind = indexIntervalCC
			}
			return r, nil, nil
		}
	case '<':
		if collate1(val, r.lval) <= 0 {
			return &nullPlan{r.fieldNames()}, nil, nil
		}

		if collate1(val, r.hval) < 0 {
			r.hval = val
		}
		return r, nil, nil
	case neq:
		switch c := collate1(val, r.lval); {
		case c < 0:
			return r, nil, nil
		case c == 0:
			r.kind = indexIntervalOO
			return r, nil, nil
		default:
			if collate1(val, r.hval) < 0 {
				return nil, nil, nil
			}

			return r, nil, nil
		}
	}
	return nil, nil, nil
}

func (r *indexPlan) filterNe(binOp2 int, val interface{}) (plan, []string, error) {
	switch binOp2 {
	case eq:
		if collate1(val, r.lval) != 0 {
			r.lval = val
			r.kind = indexEq
			return r, nil, nil
		}

		return &nullPlan{r.fieldNames()}, nil, nil
	case ge:
		switch c := collate1(val, r.lval); {
		case c < 0:
			return nil, nil, nil //TODO
		case c == 0:
			r.kind = indexGt
			return r, nil, nil
		default:
			r.lval = val
			r.kind = indexGe
			return r, nil, nil
		}
	case '>':
		if collate1(val, r.lval) < 0 {
			return nil, nil, nil //TODO
		}

		r.lval = val
		r.kind = indexGt
		return r, nil, nil
	case le:
		switch c := collate1(val, r.lval); {
		case c < 0:
			r.hval = val
			r.kind = indexLe
			return r, nil, nil
		case c == 0:
			r.kind = indexLt
			return r, nil, nil
		default:
			return nil, nil, nil //TODO
		}
	case '<':
		if collate1(val, r.lval) <= 0 {
			r.hval = val
			r.kind = indexLt
			return r, nil, nil
		}

		return nil, nil, nil //TODO
	case neq:
		if collate1(val, r.lval) == 0 {
			return r, nil, nil
		}

		return nil, nil, nil
	}
	return nil, nil, nil
}

func (r *indexPlan) filter(expr expression) (plan, []string, error) {
	switch x := expr.(type) {
	case *binaryOperation:
		ok, cname, val, err := x.isIdentRelOpVal()
		if err != nil {
			return nil, nil, err
		}

		if !ok || r.cname != cname {
			break
		}

		if val, err = typeCheck1(val, findCol(r.src.cols, cname)); err != nil {
			return nil, nil, err
		}

		switch r.kind {
		case indexEq: // [L]
			return r.filterEq(x.op, val)
		case indexGe: // [L, ...)
			return r.filterGe(x.op, val)
		case indexGt: // (L, ...)
			return r.filterGt(x.op, val)
		case indexIntervalCC: // [L, H]
			return r.filterCC(x.op, val)
		case indexIntervalCO: // [L, H)
			return r.filterCO(x.op, val)
		case indexIntervalOC: // (L, H]
			return r.filterOC(x.op, val)
		case indexIntervalOO: // (L, H)
			return r.filterOO(x.op, val)
		case indexLe: // (..., H]
			return r.filterLe(x.op, val)
		case indexLt: // (..., H)
			return r.filterLt(x.op, val)
		case indexNe: // (L)
			return r.filterNe(x.op, val)
		}
	case *ident:
		cname := x.s
		if r.cname != cname {
			break
		}

		switch r.kind {
		case indexFalse: // [false]
			return &nullPlan{r.fieldNames()}, nil, nil
		case indexTrue: // [true]
			return r, nil, nil
		}
	case *unaryOperation:
		if x.op != '!' {
			break
		}

		operand, ok := x.v.(*ident)
		if !ok {
			break
		}

		cname := operand.s
		if r.cname != cname {
			break
		}

		switch r.kind {
		case indexFalse: // [false]
			return r, nil, nil
		case indexTrue: // [true]
			return &nullPlan{r.fieldNames()}, nil, nil
		}
	}

	return nil, nil, nil
}

func (r *indexPlan) hasID() bool { return true }

type explainDefaultPlan struct {
	s stmt
}

func (r *explainDefaultPlan) hasID() bool { return false }

func (r *explainDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error {
	var buf bytes.Buffer
	switch x := r.s.(type) {
	default:
		w := strutil.IndentFormatter(&buf, "│   ")
		x.explain(ctx, w)
	}

	a := bytes.Split(buf.Bytes(), []byte{'\n'})
	for _, v := range a[:len(a)-1] {
		if more, err := f(nil, []interface{}{string(v)}); !more || err != nil {
			return err
		}
	}
	return nil
}

func (r *explainDefaultPlan) explain(w strutil.Formatter) {}

func (r *explainDefaultPlan) fieldNames() []string {
	return []string{""}
}

func (r *explainDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

type filterDefaultPlan struct {
	plan
	expr expression
	is   []string
}

func (r *filterDefaultPlan) hasID() bool { return r.plan.hasID() }

func (r *filterDefaultPlan) explain(w strutil.Formatter) {
	r.plan.explain(w)
	w.Format("┌Filter on %v\n", r.expr)
	if len(r.is) != 0 {
		w.Format("│Possibly useful indices\n")
		m := map[string]bool{}
		for _, v := range r.is {
			if !m[v] {
				m[v] = true
				n := ""
				for _, r := range v {
					if r >= '0' && r <= '9' || r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' || r == '_' {
						n += string(r)
						continue
					}

					n += "_"
				}
				for strings.Contains(n, "__") {
					n = strings.Replace(n, "__", "_", -1)
				}
				for strings.HasSuffix(n, "_") {
					n = n[:len(n)-1]
				}
				w.Format("│CREATE INDEX x%s ON %s;\n", n, v)
			}
		}
	}
	w.Format("└Output field names %v\n", qnames(r.plan.fieldNames()))
}

func (r *filterDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
	m := map[interface{}]interface{}{}
	fields := r.plan.fieldNames()
	return r.plan.do(ctx, func(rid interface{}, data []interface{}) (bool, error) {
		for i, v := range fields {
			m[v] = data[i]
		}
		m["$id"] = rid
		val, err := r.expr.eval(ctx, m)
		if err != nil {
			return false, err
		}

		if val == nil {
			return true, nil
		}

		x, ok := val.(bool)
		if !ok {
			return false, fmt.Errorf("invalid boolean expression %s (value of type %T)", val, val)
		}

		if !x {
			return true, nil
		}

		return f(rid, data)
	})
}

type crossJoinDefaultPlan struct {
	rsets  []plan
	names  []string
	fields []string
}

func (r *crossJoinDefaultPlan) hasID() bool { return false }

func (r *crossJoinDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Compute Cartesian product of%i\n")
	for i, v := range r.rsets {
		sel := !isTableOrIndex(v)
		if sel {
			w.Format("┌Iterate all rows of virtual table %q%i\n", r.names[i])
		}
		v.explain(w)
		if sel {
			w.Format("%u└Output field names %v\n", qnames(v.fieldNames()))
		}
	}
	w.Format("%u└Output field names %v\n", qnames(r.fields))
}

func (r *crossJoinDefaultPlan) filter(expr expression) (plan, []string, error) {
	var is []string
	for i, v := range r.names {
		e2, err := expr.clone(nil, v)
		if err != nil {
			return nil, nil, err
		}

		p2, is2, err := r.rsets[i].filter(e2)
		is = append(is, is2...)
		if err != nil {
			return nil, nil, err
		}

		if p2 != nil {
			r.rsets[i] = p2
			return r, is, nil
		}
	}
	return nil, is, nil
}

func (r *crossJoinDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error {
	if len(r.rsets) == 1 {
		return r.rsets[0].do(ctx, f)
	}

	ids := map[string]interface{}{}
	var g func([]interface{}, []plan, int) error
	g = func(prefix []interface{}, rsets []plan, x int) (err error) {
		return rsets[0].do(ctx, func(id interface{}, in []interface{}) (bool, error) {
			ids[r.names[x]] = id
			if len(rsets) > 1 {
				return true, g(append(prefix, in...), rsets[1:], x+1)
			}

			return f(ids, append(prefix, in...))
		})
	}
	return g(nil, r.rsets, 0)
}

func (r *crossJoinDefaultPlan) fieldNames() []string { return r.fields }

type distinctDefaultPlan struct {
	src    plan
	fields []string
}

func (r *distinctDefaultPlan) hasID() bool { return false }

func (r *distinctDefaultPlan) explain(w strutil.Formatter) {
	r.src.explain(w)
	w.Format("┌Compute distinct rows\n└Output field names %v\n", r.fields)
}

func (r *distinctDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *distinctDefaultPlan) fieldNames() []string { return r.fields }

func (r *distinctDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
	t, err := ctx.db.store.CreateTemp(true)
	if err != nil {
		return
	}

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

	if err = r.src.do(ctx, func(id interface{}, in []interface{}) (bool, error) {
		if err = t.Set(in, nil); err != nil {
			return false, err
		}

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

	var data []interface{}
	more := true
	it, err := t.SeekFirst()
	for more && err == nil {
		data, _, err = it.Next()
		if err != nil {
			break
		}

		more, err = f(nil, data)
	}
	return noEOF(err)
}

type groupByDefaultPlan struct {
	colNames []string
	src      plan
	fields   []string
}

func (r *groupByDefaultPlan) hasID() bool { return false }

func (r *groupByDefaultPlan) explain(w strutil.Formatter) {
	r.src.explain(w)
	switch {
	case len(r.colNames) == 0: //TODO this case should not exist for this plan, should become tableDefaultPlan
		w.Format("┌Group by distinct rows")
	default:
		w.Format("┌Group by")
		for _, v := range r.colNames {
			w.Format(" %s,", v)
		}
	}
	w.Format("\n└Output field names %v\n", qnames(r.fields))
}

func (r *groupByDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *groupByDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
	t, err := ctx.db.store.CreateTemp(true)
	if err != nil {
		return
	}

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

	var gcols []*col
	var cols []*col
	m := map[string]int{}
	for i, v := range r.src.fieldNames() {
		m[v] = i
	}
	for _, c := range r.colNames {
		i, ok := m[c]
		if !ok {
			return fmt.Errorf("unknown field %s", c)
		}

		gcols = append(gcols, &col{name: c, index: i})
	}
	k := make([]interface{}, len(r.colNames)) //TODO optimize when len(r.cols) == 0, should become tableDefaultPlan
	if err = r.src.do(ctx, func(rid interface{}, in []interface{}) (more bool, err error) {
		infer(in, &cols)
		for i, c := range gcols {
			k[i] = in[c.index]
		}
		h0, err := t.Get(k)
		if err != nil {
			return false, err
		}

		var h int64
		if len(h0) != 0 {
			h, _ = h0[0].(int64)
		}
		nh, err := t.Create(append([]interface{}{h, nil}, in...)...)
		if err != nil {
			return false, err
		}

		for i, c := range gcols {
			k[i] = in[c.index]
		}
		err = t.Set(k, []interface{}{nh})
		if err != nil {
			return false, err
		}

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

	for i, v := range r.src.fieldNames()[:len(cols)] {
		cols[i].name = v
		cols[i].index = i
	}
	if more, err := f(nil, []interface{}{t, cols}); !more || err != nil {
		return err
	}

	it, err := t.SeekFirst()
	more := true
	var data []interface{}
	for more && err == nil {
		if _, data, err = it.Next(); err != nil {
			break
		}

		more, err = f(nil, data)
	}
	return noEOF(err)
}

func (r *groupByDefaultPlan) fieldNames() []string { return r.fields }

type selectIndexDefaultPlan struct {
	nm string
	x  interface{}
}

func (r *selectIndexDefaultPlan) hasID() bool { return false }

func (r *selectIndexDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Iterate all values of index %q\n└Output field names N/A\n", r.nm)
}

func (r *selectIndexDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *selectIndexDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
	var x btreeIndex
	switch ix := r.x.(type) {
	case *indexedCol:
		x = ix.x
	case *index2:
		x = ix.x
	default:
		panic("internal error 007")
	}

	en, err := x.SeekFirst()
	if err != nil {
		return noEOF(err)
	}

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

		id++
		if more, err := f(id, k); !more || err != nil {
			return err
		}
	}
}

func (r *selectIndexDefaultPlan) fieldNames() []string {
	return []string{r.nm}
}

type limitDefaultPlan struct {
	expr   expression
	src    plan
	fields []string
}

func (r *limitDefaultPlan) hasID() bool { return r.src.hasID() }

func (r *limitDefaultPlan) explain(w strutil.Formatter) {
	r.src.explain(w)
	w.Format("┌Pass first %v records\n└Output field names %v\n", r.expr, r.fields)
}

func (r *limitDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *limitDefaultPlan) fieldNames() []string { return r.fields }

func (r *limitDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) (err error) {
	m := map[interface{}]interface{}{}
	var eval bool
	var lim uint64
	return r.src.do(ctx, func(rid interface{}, in []interface{}) (more bool, err error) {
		if !eval {
			for i, fld := range r.fields {
				if fld != "" {
					m[fld] = in[i]
				}
			}
			m["$id"] = rid
			val, err := r.expr.eval(ctx, m)
			if err != nil {
				return false, err
			}

			if val == nil {
				return true, nil
			}

			if lim, err = limOffExpr(val); err != nil {
				return false, err
			}

			eval = true
		}
		switch lim {
		case 0:
			return false, nil
		default:
			lim--
			return f(rid, in)
		}
	})
}

type offsetDefaultPlan struct {
	expr   expression
	src    plan
	fields []string
}

func (r *offsetDefaultPlan) hasID() bool { return r.src.hasID() }

func (r *offsetDefaultPlan) explain(w strutil.Formatter) {
	r.src.explain(w)
	w.Format("┌Skip first %v records\n└Output field names %v\n", r.expr, qnames(r.fields))
}

func (r *offsetDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *offsetDefaultPlan) fieldNames() []string { return r.fields }

func (r *offsetDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error {
	m := map[interface{}]interface{}{}
	var eval bool
	var off uint64
	return r.src.do(ctx, func(rid interface{}, in []interface{}) (bool, error) {
		if !eval {
			for i, fld := range r.fields {
				if fld != "" {
					m[fld] = in[i]
				}
			}
			m["$id"] = rid
			val, err := r.expr.eval(ctx, m)
			if err != nil {
				return false, err
			}

			if val == nil {
				return true, nil
			}

			if off, err = limOffExpr(val); err != nil {
				return false, err
			}

			eval = true
		}
		if off > 0 {
			off--
			return true, nil
		}

		return f(rid, in)
	})
}

type orderByDefaultPlan struct {
	asc    bool
	by     []expression
	src    plan
	fields []string
}

func (r *orderByDefaultPlan) hasID() bool { return r.src.hasID() }

func (r *orderByDefaultPlan) explain(w strutil.Formatter) {
	r.src.explain(w)
	w.Format("┌Order%s by", map[bool]string{false: " descending"}[r.asc])
	for _, v := range r.by {
		w.Format(" %s,", v)
	}
	w.Format("\n└Output field names %v\n", qnames(r.fields))
}

func (r *orderByDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *orderByDefaultPlan) fieldNames() []string { return r.fields }

func (r *orderByDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
	t, err := ctx.db.store.CreateTemp(r.asc)
	if err != nil {
		return
	}

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

	m := map[interface{}]interface{}{}
	flds := r.fields
	k := make([]interface{}, len(r.by)+1)
	id := int64(-1)
	if err = r.src.do(ctx, func(rid interface{}, in []interface{}) (bool, error) {
		id++
		for i, fld := range flds {
			if fld != "" {
				m[fld] = in[i]
			}
		}
		m["$id"] = rid
		for i, expr := range r.by {
			val, err := expr.eval(ctx, m)
			if err != nil {
				return false, err
			}

			if val != nil {
				val, ordered, err := isOrderedType(val)
				if err != nil {
					return false, err
				}

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

				}
			}

			k[i] = val
		}
		k[len(r.by)] = id
		if err = t.Set(k, in); err != nil {
			return false, err
		}

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

	it, err := t.SeekFirst()
	if err != nil {
		return noEOF(err)
	}

	var data []interface{}
	more := true
	for more && err == nil {
		if _, data, err = it.Next(); err != nil {
			break
		}

		more, err = f(nil, data)
	}
	return noEOF(err)
}

type selectFieldsDefaultPlan struct {
	flds   []*fld
	src    plan
	fields []string
}

func (r *selectFieldsDefaultPlan) hasID() bool { return r.src.hasID() }

func (r *selectFieldsDefaultPlan) explain(w strutil.Formatter) {
	//TODO check for non existing fields
	r.src.explain(w)
	w.Format("┌Evaluate")
	for _, v := range r.flds {
		w.Format(" %s as %s,", v.expr, fmt.Sprintf("%q", v.name))
	}
	w.Format("\n└Output field names %v\n", qnames(r.fields))
}

func (r *selectFieldsDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *selectFieldsDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error {
	fields := r.src.fieldNames()
	m := map[interface{}]interface{}{}
	return r.src.do(ctx, func(rid interface{}, in []interface{}) (bool, error) {
		for i, nm := range fields {
			if nm != "" {
				m[nm] = in[i]
			}
		}
		m["$id"] = rid
		out := make([]interface{}, len(r.flds))
		for i, fld := range r.flds {
			var err error
			if out[i], err = fld.expr.eval(ctx, m); err != nil {
				return false, err
			}
		}
		return f(rid, out)
	})
}

func (r *selectFieldsDefaultPlan) fieldNames() []string { return r.fields }

type selectFieldsGroupPlan struct {
	flds   []*fld
	src    *groupByDefaultPlan
	fields []string
}

func (r *selectFieldsGroupPlan) hasID() bool { return false }

func (r *selectFieldsGroupPlan) explain(w strutil.Formatter) {
	//TODO check for non existing fields
	r.src.explain(w)
	w.Format("┌Evaluate")
	for _, v := range r.flds {
		w.Format(" %s as %s,", v.expr, fmt.Sprintf("%q", v.name))
	}
	w.Format("\n└Output field names %v\n", qnames(r.fields))
}

func (r *selectFieldsGroupPlan) fieldNames() []string { return r.fields }

func (r *selectFieldsGroupPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *selectFieldsGroupPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error {
	var t temp
	var cols []*col
	var err error
	out := make([]interface{}, len(r.flds))
	ok := false
	rows := false
	if err = r.src.do(ctx, func(rid interface{}, in []interface{}) (bool, error) {
		if ok {
			h := in[0].(int64)
			m := map[interface{}]interface{}{}
			for h != 0 {
				in, err = t.Read(nil, h, cols...)
				if err != nil {
					return false, err
				}

				rec := in[2:]
				for i, c := range cols {
					if nm := c.name; nm != "" {
						m[nm] = rec[i]
					}
				}
				m["$id"] = rid
				for _, fld := range r.flds {
					if _, err = fld.expr.eval(ctx, m); err != nil {
						return false, err
					}
				}

				h = in[0].(int64)
			}
			m["$agg"] = true
			for i, fld := range r.flds {
				if out[i], err = fld.expr.eval(ctx, m); err != nil {
					return false, err
				}
			}
			rows = true
			return f(nil, out)
		}

		ok = true
		t = in[0].(temp)
		cols = in[1].([]*col)
		if len(r.flds) == 0 { // SELECT *
			r.flds = make([]*fld, len(cols))
			for i, v := range cols {
				r.flds[i] = &fld{expr: &ident{v.name}, name: v.name}
			}
			out = make([]interface{}, len(r.flds))
		}
		return true, nil
	}); err != nil {
		return err
	}

	if rows {
		return nil
	}

	m := map[interface{}]interface{}{"$agg0": true} // aggregate empty record set
	for i, fld := range r.flds {
		if out[i], err = fld.expr.eval(ctx, m); err != nil {
			return err
		}
	}
	_, err = f(nil, out)

	return err
}

type sysColumnDefaultPlan struct{}

func (r *sysColumnDefaultPlan) hasID() bool { return false }

func (r *sysColumnDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Iterate all rows of table \"__Column\"\n└Output field names %v\n", qnames(r.fieldNames()))
}

func (r *sysColumnDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *sysColumnDefaultPlan) fieldNames() []string {
	return []string{"TableName", "Ordinal", "Name", "Type"}
}

func (r *sysColumnDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error {
	rec := make([]interface{}, 4)
	di, err := ctx.db.info()
	if err != nil {
		return err
	}

	var id int64
	for _, ti := range di.Tables {
		rec[0] = ti.Name
		var ix int64
		for _, ci := range ti.Columns {
			ix++
			rec[1] = ix
			rec[2] = ci.Name
			rec[3] = ci.Type.String()
			id++
			if more, err := f(id, rec); !more || err != nil {
				return err
			}
		}
	}
	return nil
}

type sysIndexDefaultPlan struct{}

func (r *sysIndexDefaultPlan) hasID() bool { return false }

func (r *sysIndexDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Iterate all rows of table \"__Index\"\n└Output field names %v\n", qnames(r.fieldNames()))
}

func (r *sysIndexDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *sysIndexDefaultPlan) fieldNames() []string {
	return []string{"TableName", "ColumnName", "Name", "IsUnique"}
}

func (r *sysIndexDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error {
	rec := make([]interface{}, 4)
	di, err := ctx.db.info()
	if err != nil {
		return err
	}

	var id int64
	for _, xi := range di.Indices {
		rec[0] = xi.Table
		rec[1] = xi.Column
		rec[2] = xi.Name
		rec[3] = xi.Unique
		id++
		if more, err := f(id, rec); !more || err != nil {
			return err
		}
	}
	return nil
}

type sysTableDefaultPlan struct{}

func (r *sysTableDefaultPlan) hasID() bool { return false }

func (r *sysTableDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Iterate all rows of table \"__Table\"\n└Output field names %v\n", qnames(r.fieldNames()))
}

func (r *sysTableDefaultPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *sysTableDefaultPlan) fieldNames() []string { return []string{"Name", "Schema"} }

func (r *sysTableDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) error {
	rec := make([]interface{}, 2)
	di, err := ctx.db.info()
	if err != nil {
		return err
	}

	var id int64
	for _, ti := range di.Tables {
		rec[0] = ti.Name
		a := []string{}
		for _, ci := range ti.Columns {
			s := ""
			if ci.NotNull {
				s += " NOT NULL"
			}
			if c := ci.Constraint; c != "" {
				s += " " + c
			}
			if d := ci.Default; d != "" {
				s += " DEFAULT " + d
			}
			a = append(a, fmt.Sprintf("%s %s%s", ci.Name, ci.Type, s))
		}
		rec[1] = fmt.Sprintf("CREATE TABLE %s (%s);", ti.Name, strings.Join(a, ", "))
		id++
		if more, err := f(id, rec); !more || err != nil {
			return err
		}
	}
	return nil
}

type tableNilPlan struct {
	t *table
}

func (r *tableNilPlan) hasID() bool { return true }

func (r *tableNilPlan) explain(w strutil.Formatter) {
	w.Format("┌Iterate all rows of table %q\n└Output field names %v\n", r.t.name, qnames(r.fieldNames()))
}

func (r *tableNilPlan) fieldNames() []string { return []string{} }

func (r *tableNilPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *tableNilPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
	t := r.t
	h := t.head
	cols := t.cols
	for h > 0 {
		rec, err := t.store.Read(nil, h, cols...) // 0:next, 1:id, 2...: data
		if err != nil {
			return err
		}

		if m, err := f(rec[1], nil); !m || err != nil {
			return err
		}

		h = rec[0].(int64) // next
	}
	return nil
}

type tableDefaultPlan struct {
	t      *table
	fields []string
}

func (r *tableDefaultPlan) hasID() bool { return true }

func (r *tableDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Iterate all rows of table %q\n└Output field names %v\n", r.t.name, qnames(r.fields))
}

func (r *tableDefaultPlan) filterBinOp(x *binaryOperation) (plan, []string, error) {
	ok, cn, rval, err := x.isIdentRelOpVal()
	if err != nil {
		return nil, nil, err
	}

	if !ok {
		return nil, nil, nil
	}

	t := r.t
	c, ix := t.findIndexByColName(cn)
	if ix == nil { // Column cn has no index.
		return nil, []string{fmt.Sprintf("%s(%s)", t.name, cn)}, nil
	}

	if rval, err = typeCheck1(rval, c); err != nil {
		return nil, nil, err
	}

	switch x.op {
	case eq:
		return &indexPlan{t, cn, ix.name, ix.x, indexEq, rval, rval}, nil, nil
	case '<':
		return &indexPlan{t, cn, ix.name, ix.x, indexLt, nil, rval}, nil, nil
	case le:
		return &indexPlan{t, cn, ix.name, ix.x, indexLe, nil, rval}, nil, nil
	case ge:
		return &indexPlan{t, cn, ix.name, ix.x, indexGe, rval, nil}, nil, nil
	case '>':
		return &indexPlan{t, cn, ix.name, ix.x, indexGt, rval, nil}, nil, nil
	case neq:
		return &indexPlan{t, cn, ix.name, ix.x, indexNe, rval, rval}, nil, nil
	default:
		panic("internal error 069")
	}
}

func (r *tableDefaultPlan) filterIdent(x *ident, trueValue bool) (plan, []string, error) {
	cn := x.s
	t := r.t
	for _, v := range t.cols {
		if v.name != cn {
			continue
		}

		if v.typ != qBool {
			return nil, nil, nil
		}

		xi := v.index + 1 // 0: id()
		if xi >= len(t.indices) {
			return nil, nil, nil
		}

		ix := t.indices[xi]
		if ix == nil { // Column cn has no index.
			return nil, []string{fmt.Sprintf("%s(%s)", t.name, cn)}, nil
		}

		kind := indexFalse
		if trueValue {
			kind = indexTrue
		}
		return &indexPlan{t, cn, ix.name, ix.x, kind, nil, nil}, nil, nil
	}
	return nil, nil, nil
}

func (r *tableDefaultPlan) filterIsNull(x *isNull) (plan, []string, error) {
	ok, cn := isColumnExpression(x.expr)
	if !ok {
		return nil, nil, nil
	}

	t := r.t
	_, ix := t.findIndexByColName(cn)
	if ix == nil { // Column cn has no index.
		return nil, []string{fmt.Sprintf("%s(%s)", t.name, cn)}, nil
	}

	switch {
	case x.not:
		return &indexPlan{t, cn, ix.name, ix.x, indexIsNotNull, nil, nil}, nil, nil
	default:
		return &indexPlan{t, cn, ix.name, ix.x, indexIsNull, nil, nil}, nil, nil
	}
}

func (r *tableDefaultPlan) filter(expr expression) (plan, []string, error) {
	cols := mentionedColumns(expr)
	for _, v := range r.fields {
		delete(cols, v)
	}
	for k := range cols {
		return nil, nil, fmt.Errorf("unknown field %s", k)
	}

	var is []string

	//TODO var sexpr string
	//TODO for _, ix := range t.indices2 {
	//TODO 	if len(ix.exprList) != 1 {
	//TODO 		continue
	//TODO 	}

	//TODO 	if sexpr == "" {
	//TODO 		sexpr = expr.String()
	//TODO 	}
	//TODO 	if ix.sources[0] != sexpr {
	//TODO 		continue
	//TODO 	}

	//TODO }

	switch x := expr.(type) {
	case *binaryOperation:
		return r.filterBinOp(x)
	case *ident:
		return r.filterIdent(x, true)
	case *isNull:
		return r.filterIsNull(x)
	case *unaryOperation:
		if x.op != '!' {
			break
		}

		if operand, ok := x.v.(*ident); ok {
			return r.filterIdent(operand, false)
		}
	default:
		//dbg("", expr)
		return nil, is, nil //TODO
	}

	return nil, is, nil
}

func (r *tableDefaultPlan) do(ctx *execCtx, f func(interface{}, []interface{}) (bool, error)) (err error) {
	t := r.t
	cols := t.cols
	h := t.head
	for h > 0 {
		rec, err := t.row0(ctx, h)
		if err != nil {
			return err
		}

		h = rec[0].(int64)
		id := rec[1].(int64)
		for i, c := range cols {
			rec[i] = rec[c.index+2]
		}
		if m, err := f(id, rec[:len(cols)]); !m || err != nil {
			return err
		}
	}
	return nil
}

func (r *tableDefaultPlan) fieldNames() []string { return r.fields }

type nullPlan struct {
	fields []string
}

func (r *nullPlan) hasID() bool { return false }

func (r *nullPlan) fieldNames() []string { return r.fields }

func (r *nullPlan) explain(w strutil.Formatter) {
	w.Format("┌Iterate no rows\n└Output field names %v\n", qnames(r.fields))
}

func (r *nullPlan) do(*execCtx, func(interface{}, []interface{}) (bool, error)) error {
	return nil
}

func (r *nullPlan) filter(expr expression) (plan, []string, error) {
	return r, nil, nil
}

type leftJoinDefaultPlan struct {
	on     expression
	rsets  []plan
	names  []string
	right  int
	fields []string
}

func (r *leftJoinDefaultPlan) hasID() bool { return false }

func (r *leftJoinDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Compute Cartesian product of%i\n")
	for i, v := range r.rsets {
		sel := !isTableOrIndex(v)
		if sel {
			w.Format("┌Iterate all rows of virtual table %q%i\n", r.names[i])
		}
		v.explain(w)
		if sel {
			w.Format("%u└Output field names %v\n", qnames(v.fieldNames()))
		}
	}
	w.Format("Extend the product with all NULL rows of %q when no match for %v%u\n", r.names[len(r.names)-1], r.on)
	w.Format("└Output field names %v\n", qnames(r.fields))
}

func (r *leftJoinDefaultPlan) filter(expr expression) (plan, []string, error) {
	var is []string
	for i, v := range r.names {
		e2, err := expr.clone(nil, v)
		if err != nil {
			return nil, nil, err
		}

		p2, is2, err := r.rsets[i].filter(e2)
		is = append(is, is2...)
		if err != nil {
			return nil, nil, err
		}

		if p2 != nil {
			r.rsets[i] = p2
			return r, is, nil
		}
	}
	return nil, is, nil
}

type rightJoinDefaultPlan struct {
	leftJoinDefaultPlan
}

func (r *rightJoinDefaultPlan) hasID() bool { return false }

func (r *rightJoinDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Compute Cartesian product of%i\n")
	for i, v := range r.rsets {
		sel := !isTableOrIndex(v)
		if sel {
			w.Format("┌Iterate all rows of virtual table %q%i\n", r.names[i])
		}
		v.explain(w)
		if sel {
			w.Format("%u└Output field names %v\n", qnames(v.fieldNames()))
		}
	}
	w.Format("Extend the product with all NULL rows of all but %q when no match for %v%u\n", r.names[len(r.names)-1], r.on)
	w.Format("└Output field names %v\n", qnames(r.fields))
}

func (r *rightJoinDefaultPlan) filter(expr expression) (plan, []string, error) {
	var is []string
	for i, v := range r.names {
		e2, err := expr.clone(nil, v)
		if err != nil {
			return nil, nil, err
		}

		p2, is2, err := r.rsets[i].filter(e2)
		is = append(is, is2...)
		if err != nil {
			return nil, nil, err
		}

		if p2 != nil {
			r.rsets[i] = p2
			return r, is, nil
		}
	}
	return nil, is, nil
}

type fullJoinDefaultPlan struct {
	leftJoinDefaultPlan
}

func (r *fullJoinDefaultPlan) hasID() bool { return false }

func (r *fullJoinDefaultPlan) explain(w strutil.Formatter) {
	w.Format("┌Compute Cartesian product of%i\n")
	for i, v := range r.rsets {
		sel := !isTableOrIndex(v)
		if sel {
			w.Format("┌Iterate all rows of virtual table %q%i\n", r.names[i])
		}
		v.explain(w)
		if sel {
			w.Format("%u└Output field names %v\n", qnames(v.fieldNames()))
		}
	}
	w.Format("Extend the product with all NULL rows of %q when no match for %v\n", r.names[len(r.names)-1], r.on)
	w.Format("Extend the product with all NULL rows of all but %q when no match for %v%u\n", r.names[len(r.names)-1], r.on)
	w.Format("└Output field names %v\n", qnames(r.fields))
}

func (r *fullJoinDefaultPlan) filter(expr expression) (plan, []string, error) {
	var is []string
	for i, v := range r.names {
		e2, err := expr.clone(nil, v)
		if err != nil {
			return nil, nil, err
		}

		p2, is2, err := r.rsets[i].filter(e2)
		is = append(is, is2...)
		if err != nil {
			return nil, nil, err
		}

		if p2 != nil {
			r.rsets[i] = p2
			return r, is, nil
		}
	}
	return nil, is, nil
}

func (r *leftJoinDefaultPlan) fieldNames() []string { return r.fields }

func (r *leftJoinDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error {
	m := map[interface{}]interface{}{}
	ids := map[string]interface{}{}
	var g func([]interface{}, []plan, int) error
	var match bool
	g = func(prefix []interface{}, rsets []plan, x int) (err error) {
		return rsets[0].do(ctx, func(id interface{}, in []interface{}) (bool, error) {
			ids[r.names[x]] = id
			row := append(prefix, in...)
			if len(rsets) > 1 {
				if len(rsets) == 2 {
					match = false
				}
				if err = g(row, rsets[1:], x+1); err != nil {
					return false, err
				}

				if len(rsets) != 2 || match {
					return true, nil
				}

				ids[r.names[x+1]] = nil
				return f(ids, append(row, make([]interface{}, r.right)...))
			}

			for i, fld := range r.fields {
				if fld != "" {
					m[fld] = row[i]
				}
			}

			val, err := r.on.eval(ctx, m)
			if err != nil {
				return false, err
			}

			if val == nil {
				return true, nil
			}

			x, ok := val.(bool)
			if !ok {
				return false, fmt.Errorf("invalid ON expression %s (value of type %T)", val, val)
			}

			if !x {
				return true, nil
			}

			match = true
			return f(ids, row)
		})
	}
	return g(nil, r.rsets, 0)
}

func (r *rightJoinDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error {
	right := r.right
	left := len(r.fields) - right
	n := len(r.rsets)
	m := map[interface{}]interface{}{}
	ids := map[string]interface{}{}
	var g func([]interface{}, []plan, int) error
	var match bool
	nf := len(r.fields)
	fields := append(append([]string(nil), r.fields[nf-right:]...), r.fields[:nf-right]...)
	g = func(prefix []interface{}, rsets []plan, x int) (err error) {
		return rsets[0].do(ctx, func(id interface{}, in []interface{}) (bool, error) {
			ids[r.names[x]] = id
			row := append(prefix, in...)
			if len(rsets) > 1 {
				if len(rsets) == n {
					match = false
				}
				if err = g(row, rsets[1:], x+1); err != nil {
					return false, err
				}

				if len(rsets) != n || match {
					return true, nil
				}

				for i := 0; i < n-1; i++ {
					ids[r.names[i]] = nil
				}

				// rigth, left -> left, right
				return f(ids, append(make([]interface{}, left), row[:right]...))
			}

			for i, fld := range fields {
				if fld != "" {
					m[fld] = row[i]
				}
			}

			val, err := r.on.eval(ctx, m)
			if err != nil {
				return false, err
			}

			if val == nil {
				return true, nil
			}

			x, ok := val.(bool)
			if !ok {
				return false, fmt.Errorf("invalid ON expression %s (value of type %T)", val, val)
			}

			if !x {
				return true, nil
			}

			match = true
			// rigth, left -> left, right
			return f(ids, append(append([]interface{}(nil), row[right:]...), row[:right]...))
		})
	}
	return g(nil, append([]plan{r.rsets[n-1]}, r.rsets[:n-1]...), 0)
}

func (r *fullJoinDefaultPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (more bool, err error)) error {
	b3 := b.TreeNew(func(a, b interface{}) int {
		x := a.(int64)
		y := b.(int64)
		if x < y {
			return -1
		}

		if x == y {
			return 0
		}

		return 1
	})
	m := map[interface{}]interface{}{}
	ids := map[string]interface{}{}
	var g func([]interface{}, []plan, int) error
	var match bool
	var rid int64
	firstR := true
	g = func(prefix []interface{}, rsets []plan, x int) (err error) {
		return rsets[0].do(ctx, func(id interface{}, in []interface{}) (bool, error) {
			ids[r.names[x]] = id
			row := append(prefix, in...)
			if len(rsets) > 1 {
				if len(rsets) == 2 {
					match = false
					rid = 0
				}
				if err = g(row, rsets[1:], x+1); err != nil {
					return false, err
				}

				if len(rsets) == 2 {
					firstR = false
				}
				if len(rsets) != 2 || match {
					return true, nil
				}

				ids[r.names[x+1]] = nil
				return f(ids, append(row, make([]interface{}, r.right)...))
			}

			rid++
			if firstR {
				b3.Set(rid, in)
			}
			for i, fld := range r.fields {
				if fld != "" {
					m[fld] = row[i]
				}
			}

			val, err := r.on.eval(ctx, m)
			if err != nil {
				return false, err
			}

			if val == nil {
				return true, nil
			}

			x, ok := val.(bool)
			if !ok {
				return false, fmt.Errorf("invalid ON expression %s (value of type %T)", val, val)
			}

			if !x {
				return true, nil
			}

			match = true
			b3.Delete(rid)
			return f(ids, row)
		})
	}
	if err := g(nil, r.rsets, 0); err != nil {
		return err
	}

	it, err := b3.SeekFirst()
	if err != nil {
		return noEOF(err)
	}

	pref := make([]interface{}, len(r.fields)-r.right)
	for {
		_, v, err := it.Next()
		if err != nil {
			return noEOF(err)
		}

		more, err := f(nil, append(pref, v.([]interface{})...))
		if err != nil || !more {
			return err
		}
	}
}

type selectDummyPlan struct {
	flds []*fld
}

func (r *selectDummyPlan) hasID() bool { return true }

func (r *selectDummyPlan) explain(w strutil.Formatter) {
	w.Format("┌Selects values from dummy table\n└Output field names %v\n", qnames(r.fieldNames()))
}

func (r *selectDummyPlan) fieldNames() []string { return make([]string, len(r.flds)) }

func (r *selectDummyPlan) filter(expr expression) (plan, []string, error) {
	return nil, nil, nil
}

func (r *selectDummyPlan) do(ctx *execCtx, f func(id interface{}, data []interface{}) (bool, error)) (err error) {
	m := map[interface{}]interface{}{}
	data := []interface{}{}
	for _, v := range r.flds {
		rst, err := v.expr.eval(ctx, m)
		if err != nil {
			return err
		}
		data = append(data, rst)
	}
	_, err = f(nil, data)
	return
}
