func (j *LeftJoin) WithChildren(children ...sql.Node) (sql.Node, error) {
	if len(children) != 2 {
		return nil, sql.ErrInvalidChildrenNumber.New(j, len(children), 1)
	}
	nj := *j
	nj.BinaryNode = BinaryNode{children[0], children[1]}
	return &nj, nil
}
WithChildren implements the Node interface.
package plan
import (
	"io"
	"os"
	"reflect"
	"strings"
	opentracing "github.com/opentracing/opentracing-go"
	"github.com/dolthub/go-mysql-server/sql"
)
const (
	inMemoryJoinKey        = "INMEMORY_JOINS"
	inMemoryJoinSessionVar = "inmemory_joins"
)
var useInMemoryJoins = shouldUseMemoryJoinsByEnv()
func shouldUseMemoryJoinsByEnv() bool {
	v := strings.TrimSpace(strings.ToLower(os.Getenv(inMemoryJoinKey)))
	return v == "on" || v == "1"
}
type JoinNode interface {
	sql.Node
	Left() sql.Node
	Right() sql.Node
	JoinCond() sql.Expression
	JoinType() JoinType
	Comment() string
	WithScopeLen(int) JoinNode
	WithMultipassMode() JoinNode
}
type joinStruct struct {
	BinaryNode
	Cond       sql.Expression
	CommentStr string
	ScopeLen   int
	JoinMode   joinMode
}
func (j joinStruct) Expressions() []sql.Expression {
	return []sql.Expression{j.Cond}
}
func (j joinStruct) JoinCond() sql.Expression {
	return j.Cond
}
func (j joinStruct) Comment() string {
	return j.CommentStr
}
type InnerJoin struct {
	joinStruct
}
var _ JoinNode = (*InnerJoin)(nil)
var _ sql.CommentedNode = (*InnerJoin)(nil)
func (j *InnerJoin) JoinType() JoinType {
	return JoinTypeInner
}
func NewInnerJoin(left, right sql.Node, cond sql.Expression) *InnerJoin {
	return &InnerJoin{
		joinStruct{
			BinaryNode: BinaryNode{
				left:  left,
				right: right,
			},
			Cond: cond,
		},
	}
}
func (j *InnerJoin) Schema() sql.Schema {
	return append(j.left.Schema(), j.right.Schema()...)
}
func (j *InnerJoin) Resolved() bool {
	return j.left.Resolved() && j.right.Resolved() && j.Cond.Resolved()
}
func (j *InnerJoin) RowIter(ctx *sql.Context, row sql.Row) (sql.RowIter, error) {
	return joinRowIter(ctx, JoinTypeInner, j.left, j.right, j.Cond, row, j.ScopeLen, j.JoinMode)
}
func (j *InnerJoin) WithChildren(children ...sql.Node) (sql.Node, error) {
	if len(children) != 2 {
		return nil, sql.ErrInvalidChildrenNumber.New(j, len(children), 2)
	}
	nj := *j
	nj.BinaryNode = BinaryNode{children[0], children[1]}
	return &nj, nil
}
func (j *InnerJoin) WithScopeLen(i int) JoinNode {
	nj := *j
	nj.ScopeLen = i
	return &nj
}
func (j InnerJoin) WithMultipassMode() JoinNode {
	j.JoinMode = multipassMode
	return &j
}
func (j *InnerJoin) WithExpressions(exprs ...sql.Expression) (sql.Node, error) {
	if len(exprs) != 1 {
		return nil, sql.ErrInvalidChildrenNumber.New(j, len(exprs), 1)
	}
	nj := *j
	nj.Cond = exprs[0]
	return &nj, nil
}
func (j *InnerJoin) WithComment(comment string) sql.Node {
	nj := *j
	nj.CommentStr = comment
	return &nj
}
func (j *InnerJoin) String() string {
	pr := sql.NewTreePrinter()
	_ = pr.WriteNode("InnerJoin%s", j.Cond)
	_ = pr.WriteChildren(j.left.String(), j.right.String())
	return pr.String()
}
func (j *InnerJoin) DebugString() string {
	pr := sql.NewTreePrinter()
	_ = pr.WriteNode("InnerJoin%s, comment=%s", sql.DebugString(j.Cond), j.Comment())
	_ = pr.WriteChildren(sql.DebugString(j.left), sql.DebugString(j.right))
	return pr.String()
}
type LeftJoin struct {
	joinStruct
}
var _ JoinNode = (*LeftJoin)(nil)
var _ sql.CommentedNode = (*LeftJoin)(nil)
func (j *LeftJoin) JoinType() JoinType {
	return JoinTypeLeft
}
func NewLeftJoin(left, right sql.Node, cond sql.Expression) *LeftJoin {
	return &LeftJoin{
		joinStruct{
			BinaryNode: BinaryNode{
				left:  left,
				right: right,
			},
			Cond: cond,
		},
	}
}
func (j *LeftJoin) Schema() sql.Schema {
	return append(j.left.Schema(), makeNullable(j.right.Schema())...)
}
func (j *LeftJoin) Resolved() bool {
	return j.left.Resolved() && j.right.Resolved() && j.Cond.Resolved()
}
func (j *LeftJoin) RowIter(ctx *sql.Context, row sql.Row) (sql.RowIter, error) {
	return joinRowIter(ctx, JoinTypeLeft, j.left, j.right, j.Cond, row, j.ScopeLen, j.JoinMode)
}