func (t *ProcessIndexableTable) PartitionRows(ctx *sql.Context, p sql.Partition) (sql.RowIter, error) {
	iter, err := t.DriverIndexableTable.PartitionRows(ctx, p)
	if err != nil {
		return nil, err
	}
	partitionName := partitionName(p)
	if t.OnPartitionStart != nil {
		t.OnPartitionStart(partitionName)
	}
	var onDone NotifyFunc
	if t.OnPartitionDone != nil {
		onDone = func() {
			t.OnPartitionDone(partitionName)
		}
	}
	var onNext NotifyFunc
	if t.OnRowNext != nil {
		onNext = func() {
			t.OnRowNext(partitionName)
		}
	}
	return &trackedRowIter{iter: iter, onNext: onNext, onDone: onDone}, nil
}
PartitionRows implements the sql.Table interface.
package plan
import (
	"fmt"
	"github.com/dolthub/go-mysql-server/sql"
)
type QueryProcess struct {
	UnaryNode
	Notify NotifyFunc
}
type NotifyFunc func()
func NewQueryProcess(node sql.Node, notify NotifyFunc) *QueryProcess {
	return &QueryProcess{UnaryNode{Child: node}, notify}
}
func (p *QueryProcess) WithChildren(children ...sql.Node) (sql.Node, error) {
	if len(children) != 1 {
		return nil, sql.ErrInvalidChildrenNumber.New(p, len(children), 1)
	}
	return NewQueryProcess(children[0], p.Notify), nil
}
func (p *QueryProcess) RowIter(ctx *sql.Context, row sql.Row) (sql.RowIter, error) {
	iter, err := p.Child.RowIter(ctx, row)
	if err != nil {
		return nil, err
	}
	qType := getQueryType(p.Child)
	return &trackedRowIter{
		node:               p.Child,
		iter:               iter,
		onDone:             p.Notify,
		queryType:          qType,
		shouldSetFoundRows: qType == queryTypeSelect && p.shouldSetFoundRows(),
	}, nil
}
func getQueryType(child sql.Node) queryType {
	var queryType queryType = queryTypeSelect
	Inspect(child, func(node sql.Node) bool {
		if IsNoRowNode(node) {
			queryType = queryTypeDdl
			return false
		}
		switch node.(type) {
		case *Signal:
			queryType = queryTypeDdl
			return false
		case nil:
			return false
		case *TriggerExecutor, *InsertInto, *Update, *DeleteFrom, *LoadData:
			queryType = queryTypeUpdate
			return false
		}
		return true
	})
	return queryType
}
func (p *QueryProcess) String() string { return p.Child.String() }
func (p *QueryProcess) DebugString() string {
	tp := sql.NewTreePrinter()
	_ = tp.WriteNode("QueryProcess")
	_ = tp.WriteChildren(sql.DebugString(p.Child))
	return tp.String()
}
func (p *QueryProcess) shouldSetFoundRows() bool {
	var limit *Limit
	Inspect(p.Child, func(n sql.Node) bool {
		switch n := n.(type) {
		case *StartTransaction:
			return true
		case *Limit:
			limit = n
			return false
		default:
			return false
		}
	})
	if limit == nil {
		return true
	}
	return !limit.CalcFoundRows
}
type ProcessIndexableTable struct {
	sql.DriverIndexableTable
	OnPartitionDone  NamedNotifyFunc
	OnPartitionStart NamedNotifyFunc
	OnRowNext        NamedNotifyFunc
}
func (t *ProcessIndexableTable) DebugString() string {
	tp := sql.NewTreePrinter()
	_ = tp.WriteNode("ProcessIndexableTable")
	_ = tp.WriteChildren(sql.DebugString(t.Underlying()))
	return tp.String()
}
func NewProcessIndexableTable(t sql.DriverIndexableTable, onPartitionDone, onPartitionStart, OnRowNext NamedNotifyFunc) *ProcessIndexableTable {
	return &ProcessIndexableTable{t, onPartitionDone, onPartitionStart, OnRowNext}
}
func (t *ProcessIndexableTable) Underlying() sql.Table {
	return t.DriverIndexableTable
}
func (t *ProcessIndexableTable) IndexKeyValues(
	ctx *sql.Context,
	columns []string,
) (sql.PartitionIndexKeyValueIter, error) {
	iter, err := t.DriverIndexableTable.IndexKeyValues(ctx, columns)
	if err != nil {
		return nil, err
	}
	return &trackedPartitionIndexKeyValueIter{iter, t.OnPartitionDone, t.OnPartitionStart, t.OnRowNext}, nil
}