func NewDefault(provider sql.DatabaseProvider) *Analyzer {
	return NewBuilder(provider).Build()
}
NewDefault creates a default Analyzer instance with all default Rules and configuration.
To add custom rules, the easiest way is use the Builder.
package analyzer
import (
	"fmt"
	"os"
	"reflect"
	"strings"
	opentracing "github.com/opentracing/opentracing-go"
	"github.com/pmezard/go-difflib/difflib"
	"github.com/sirupsen/logrus"
	"gopkg.in/src-d/go-errors.v1"
	"github.com/dolthub/go-mysql-server/sql"
)
const debugAnalyzerKey = "DEBUG_ANALYZER"
const maxAnalysisIterations = 8
var ErrMaxAnalysisIters = errors.NewKind("exceeded max analysis iterations (%d)")
var ErrInAnalysis = errors.NewKind("error in analysis: %s")
var ErrInvalidNodeType = errors.NewKind("%s: invalid node of type: %T")
type Builder struct {
	preAnalyzeRules     []Rule
	postAnalyzeRules    []Rule
	preValidationRules  []Rule
	postValidationRules []Rule
	onceBeforeRules     []Rule
	defaultRules        []Rule
	onceAfterRules      []Rule
	validationRules     []Rule
	afterAllRules       []Rule
	provider            sql.DatabaseProvider
	debug               bool
	parallelism         int
}
func NewBuilder(pro sql.DatabaseProvider) *Builder {
	return &Builder{
		provider:        pro,
		onceBeforeRules: OnceBeforeDefault,
		defaultRules:    DefaultRules,
		onceAfterRules:  OnceAfterDefault,
		validationRules: DefaultValidationRules,
		afterAllRules:   OnceAfterAll,
	}
}
func (ab *Builder) WithDebug() *Builder {
	ab.debug = true
	return ab
}
func (ab *Builder) WithParallelism(parallelism int) *Builder {
	ab.parallelism = parallelism
	return ab
}
func (ab *Builder) AddPreAnalyzeRule(name string, fn RuleFunc) *Builder {
	ab.preAnalyzeRules = append(ab.preAnalyzeRules, Rule{name, fn})
	return ab
}
func (ab *Builder) AddPostAnalyzeRule(name string, fn RuleFunc) *Builder {
	ab.postAnalyzeRules = append(ab.postAnalyzeRules, Rule{name, fn})
	return ab
}
func (ab *Builder) AddPreValidationRule(name string, fn RuleFunc) *Builder {
	ab.preValidationRules = append(ab.preValidationRules, Rule{name, fn})
	return ab
}
func (ab *Builder) AddPostValidationRule(name string, fn RuleFunc) *Builder {
	ab.postValidationRules = append(ab.postValidationRules, Rule{name, fn})
	return ab
}
func duplicateRulesWithout(rules []Rule, excludedRuleName string) []Rule {
	newRules := make([]Rule, 0, len(rules))
	for _, rule := range rules {
		if rule.Name != excludedRuleName {
			newRules = append(newRules, rule)
		}
	}
	return newRules
}
func (ab *Builder) RemoveOnceBeforeRule(name string) *Builder {
	ab.onceBeforeRules = duplicateRulesWithout(ab.onceBeforeRules, name)
	return ab
}
func (ab *Builder) RemoveDefaultRule(name string) *Builder {
	ab.defaultRules = duplicateRulesWithout(ab.defaultRules, name)
	return ab
}
func (ab *Builder) RemoveOnceAfterRule(name string) *Builder {
	ab.onceAfterRules = duplicateRulesWithout(ab.onceAfterRules, name)
	return ab
}
func (ab *Builder) RemoveValidationRule(name string) *Builder {
	ab.validationRules = duplicateRulesWithout(ab.validationRules, name)
	return ab
}
func (ab *Builder) RemoveAfterAllRule(name string) *Builder {
	ab.afterAllRules = duplicateRulesWithout(ab.afterAllRules, name)
	return ab
}
var log = logrus.New()
func init() {
	log.SetFormatter(simpleLogFormatter{})
}
type simpleLogFormatter struct{}
func (s simpleLogFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	lvl := ""
	switch entry.Level {
	case logrus.PanicLevel:
		lvl = "PANIC"
	case logrus.FatalLevel:
		lvl = "FATAL"
	case logrus.ErrorLevel:
		lvl = "ERROR"
	case logrus.WarnLevel:
		lvl = "WARN"
	case logrus.InfoLevel:
		lvl = "INFO"
	case logrus.DebugLevel:
		lvl = "DEBUG"
	case logrus.TraceLevel:
		lvl = "TRACE"
	}
	msg := fmt.Sprintf("%s: %s\n", lvl, entry.Message)
	return ([]byte)(msg), nil
}
func (ab *Builder) Build() *Analyzer {
	_, debug := os.LookupEnv(debugAnalyzerKey)
	var batches = []*Batch{
		{
			Desc:       "pre-analyzer",
			Iterations: maxAnalysisIterations,
			Rules:      ab.preAnalyzeRules,
		},
		{
			Desc:       "once-before",
			Iterations: 1,
			Rules:      ab.onceBeforeRules,
		},
		{
			Desc:       "default-rules",
			Iterations: maxAnalysisIterations,
			Rules:      ab.defaultRules,
		},
		{
			Desc:       "once-after",
			Iterations: 1,
			Rules:      ab.onceAfterRules,
		},
		{
			Desc:       "post-analyzer",
			Iterations: maxAnalysisIterations,
			Rules:      ab.postAnalyzeRules,
		},
		{
			Desc:       "pre-validation",
			Iterations: 1,
			Rules:      ab.preValidationRules,
		},
		{
			Desc:       "validation",
			Iterations: 1,
			Rules:      ab.validationRules,
		},
		{
			Desc:       "post-validation",
			Iterations: 1,
			Rules:      ab.postValidationRules,
		},
		{
			Desc:       "after-all",
			Iterations: 1,
			Rules:      ab.afterAllRules,
		},
	}
	return &Analyzer{
		Debug:          debug || ab.debug,
		contextStack:   make([]string, 0),
		Batches:        batches,
		Catalog:        NewCatalog(ab.provider),
		Parallelism:    ab.parallelism,
		ProcedureCache: NewProcedureCache(),
	}
}
type Analyzer struct {
	Debug bool
	Verbose bool
	contextStack []string
	Parallelism  int
	Batches []*Batch
	Catalog sql.Catalog
	ProcedureCache *ProcedureCache
}