func (stmt *Statement) isCreateWithBegin() bool {
	return stmt.Type == StatementTypeCreate &&
		(stmt.ObjectType == tengo.ObjectTypeProc || stmt.ObjectType == tengo.ObjectTypeFunc) &&
		strings.Contains(strings.ToLower(stmt.Text), "begin")
}
isCreateWithBegin is useful for identifying multi-line statements that may
have been mis-parsed (for example, due to lack of DELIMITER commands)
package fs
import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"regexp"
	"strings"
	"unicode"
	"unicode/utf8"
	"github.com/alecthomas/participle"
	"github.com/alecthomas/participle/lexer"
	"github.com/skeema/tengo"
)
type StatementType int
const (
	StatementTypeUnknown StatementType = iota
	StatementTypeNoop                   
	StatementTypeCommand                
	StatementTypeCreate
	StatementTypeAlter  
)
type Statement struct {
	File            string
	LineNo          int
	CharNo          int
	Text            string  
	DefaultDatabase string  
	Type            StatementType
	ObjectType      tengo.ObjectType
	ObjectName      string
	ObjectQualifier string
	FromFile        *TokenizedSQLFile
	delimiter       string
}
func (stmt *Statement) Location() string {
	if stmt.File == "" && stmt.LineNo == 0 && stmt.CharNo == 0 {
		return ""
	}
	if stmt.File == "" {
		return fmt.Sprintf("unknown:%d:%d", stmt.LineNo, stmt.CharNo)
	}
	return fmt.Sprintf("%s:%d:%d", stmt.File, stmt.LineNo, stmt.CharNo)
}
func (stmt *Statement) ObjectKey() tengo.ObjectKey {
	return tengo.ObjectKey{
		Type: stmt.ObjectType,
		Name: stmt.ObjectName,
	}
}
func (stmt *Statement) Schema() string {
	if stmt.ObjectQualifier != "" {
		return stmt.ObjectQualifier
	}
	return stmt.DefaultDatabase
}
func (stmt *Statement) Body() string {
	body, _ := stmt.SplitTextBody()
	if stmt.ObjectQualifier != "" {
		pattern := fmt.Sprintf("(?is)^(.*?create.+?%s.*?)(`%s`|%s)([\\s\\p{Zs}]*\\.[\\s\\p{Zs}]*)", string(stmt.ObjectType), stmt.ObjectQualifier, stmt.ObjectQualifier)
		re := regexp.MustCompile(pattern)
		body = re.ReplaceAllString(body, "$1")
	}
	return body
}
func (stmt *Statement) SplitTextBody() (body string, suffix string) {
	body = strings.TrimRight(stmt.Text, "\n\r\t ")
	body = strings.TrimSuffix(body, stmt.delimiter)
	body = strings.TrimRight(body, "\n\r\t ")
	return body, stmt.Text[len(body):]
}
func (stmt *Statement) Remove() {
	for i, comp := range stmt.FromFile.Statements {
		if stmt == comp {
			copy(stmt.FromFile.Statements[i:], stmt.FromFile.Statements[i+1:])
			stmt.FromFile.Statements[len(stmt.FromFile.Statements)-1] = nil
			stmt.FromFile.Statements = stmt.FromFile.Statements[:len(stmt.FromFile.Statements)-1]
			return
		}
	}
	panic(fmt.Errorf("Statement previously at %s not actually found in file", stmt.Location()))
}