func (p *PatternInExprDecorator) Text() string {
	return ""
}
Text implement ast.Node
package plan
import (
	"fmt"
	"io"
	"sort"
	"github.com/nooncall/shazam/parser/ast"
	"github.com/nooncall/shazam/parser/format"
	driver "github.com/nooncall/shazam/parser/tidb-types/parser_driver"
	"github.com/nooncall/shazam/parser/types"
	"github.com/nooncall/shazam/proxy/router"
	"github.com/nooncall/shazam/util"
)
var _ ast.ExprNode = &PatternInExprDecorator{}
type PatternInExprDecorator struct {
	Expr ast.ExprNode
	List []ast.ExprNode
	Not  bool
	tableIndexes  []int
	indexValueMap map[int][]ast.ExprNode  
	rule   router.Rule
	result *RouteResult
}
func NeedCreatePatternInExprDecorator(p *TableAliasStmtInfo, n *ast.PatternInExpr) (router.Rule, bool, bool, error) {
	if n.Sel != nil {
		return nil, false, false, fmt.Errorf("TableName does not support Sel in sharding")
	}
	columnNameExpr, ok := n.Expr.(*ast.ColumnNameExpr)
	if !ok {
		return nil, false, false, nil
	}
	rule, need, isAlias, err := NeedCreateColumnNameExprDecoratorInCondition(p, columnNameExpr)
	if err != nil {
		return nil, false, false, fmt.Errorf("check ColumnName error: %v", err)
	}
	if !need && rule == nil {
		return nil, false, false, nil
	}
	if rule.GetType() == router.GlobalTableRuleType {
		return rule, true, isAlias, nil
	}
	return rule, need, isAlias, nil
}
func CreatePatternInExprDecorator(n *ast.PatternInExpr, rule router.Rule, isAlias bool, result *RouteResult) (*PatternInExprDecorator, error) {
	columnNameExpr := n.Expr.(*ast.ColumnNameExpr)
	columnNameExprDecorator := CreateColumnNameExprDecorator(columnNameExpr, rule, isAlias, result)
	tableIndexes, indexValueMap, err := getPatternInRouteResult(columnNameExpr.Name, n.Not, rule, n.List)
	if err != nil {
		return nil, fmt.Errorf("getPatternInRouteResult error: %v", err)
	}
	ret := &PatternInExprDecorator{
		Expr:          columnNameExprDecorator,
		List:          n.List,
		Not:           n.Not,
		rule:          rule,
		result:        result,
		tableIndexes:  tableIndexes,
		indexValueMap: indexValueMap,
	}
	return ret, nil
}
func getPatternInRouteResult(n *ast.ColumnName, isNotIn bool, rule router.Rule, values []ast.ExprNode) ([]int, map[int][]ast.ExprNode, error) {
	if rule.GetType() == router.GlobalTableRuleType {
		indexes := rule.GetSubTableIndexes()
		valueMap := getBroadcastValueMap(indexes, values)
		return indexes, valueMap, nil
	}
	if err := checkValueType(values); err != nil {
		return nil, nil, fmt.Errorf("check value error: %v", err)
	}
	_, _, column := getColumnInfoFromColumnName(n)
	if isNotIn {
		indexes := rule.GetSubTableIndexes()
		valueMap := getBroadcastValueMap(indexes, values)
		return indexes, valueMap, nil
	}
	if rule.GetShardingColumn() != column {
		indexes := rule.GetSubTableIndexes()
		valueMap := getBroadcastValueMap(indexes, values)
		return indexes, valueMap, nil
	}
	var indexes []int
	valueMap := make(map[int][]ast.ExprNode)
	for _, vi := range values {
		v, _ := vi.(*driver.ValueExpr)
		value, err := util.GetValueExprResult(v)
		if err != nil {
			return nil, nil, err
		}
		idx, err := rule.FindTableIndex(value)
		if err != nil {
			return nil, nil, err
		}
		if _, ok := valueMap[idx]; !ok {
			indexes = append(indexes, idx)
		}
		valueMap[idx] = append(valueMap[idx], vi)
	}
	sort.Ints(indexes)
	return indexes, valueMap, nil
}
func checkValueType(values []ast.ExprNode) error {
	for i, v := range values {
		if _, ok := v.(*driver.ValueExpr); !ok {
			return fmt.Errorf("value is not ValueExpr, index: %d, type: %T", i, v)
		}
	}
	return nil
}
func getBroadcastValueMap(subTableIndexes []int, nodes []ast.ExprNode) map[int][]ast.ExprNode {
	ret := make(map[int][]ast.ExprNode)
	for _, idx := range subTableIndexes {
		ret[idx] = append(ret[idx], nodes...)
	}
	return ret
}
func (p *PatternInExprDecorator) GetCurrentRouteResult() []int {
	return p.tableIndexes
}
func (p *PatternInExprDecorator) Restore(ctx *format.RestoreCtx) error {
	tableIndex, err := p.result.GetCurrentTableIndex()
	if err != nil {
		return err
	}
	if err := p.Expr.Restore(ctx); err != nil {
		return fmt.Errorf("an error occurred while restore PatternInExpr.Expr: %v", err)
	}
	if p.Not {
		ctx.WriteKeyWord(" NOT IN ")
	} else {
		ctx.WriteKeyWord(" IN ")
	}
	ctx.WritePlain("(")
	for i, expr := range p.indexValueMap[tableIndex] {
		if i != 0 {
			ctx.WritePlain(",")
		}
		if err := expr.Restore(ctx); err != nil {
			return fmt.Errorf("an error occurred while restore PatternInExpr.List[%d], err: %v", i, err)
		}
	}
	ctx.WritePlain(")")
	return nil
}
func (p *PatternInExprDecorator) Accept(v ast.Visitor) (node ast.Node, ok bool) {
	return p, ok
}