github.com/scraniel/migrate@v0.0.0-20230320185700-339088f36cee/database/multistmt/parse.go (about) 1 // Package multistmt provides methods for parsing multi-statement database migrations 2 package multistmt 3 4 import ( 5 "bufio" 6 "bytes" 7 "io" 8 ) 9 10 // StartBufSize is the default starting size of the buffer used to scan and parse multi-statement migrations 11 var StartBufSize = 4096 12 13 // Handler handles a single migration parsed from a multi-statement migration. 14 // It's given the single migration to handle and returns whether or not further statements 15 // from the multi-statement migration should be parsed and handled. 16 type Handler func(migration []byte) bool 17 18 func splitWithDelimiter(delimiter []byte) func(d []byte, atEOF bool) (int, []byte, error) { 19 return func(d []byte, atEOF bool) (int, []byte, error) { 20 // SplitFunc inspired by bufio.ScanLines() implementation 21 if atEOF { 22 if len(d) == 0 { 23 return 0, nil, nil 24 } 25 return len(d), d, nil 26 } 27 if i := bytes.Index(d, delimiter); i >= 0 { 28 return i + len(delimiter), d[:i+len(delimiter)], nil 29 } 30 return 0, nil, nil 31 } 32 } 33 34 // Parse parses the given multi-statement migration 35 func Parse(reader io.Reader, delimiter []byte, maxMigrationSize int, h Handler) error { 36 scanner := bufio.NewScanner(reader) 37 scanner.Buffer(make([]byte, 0, StartBufSize), maxMigrationSize) 38 scanner.Split(splitWithDelimiter(delimiter)) 39 for scanner.Scan() { 40 cont := h(scanner.Bytes()) 41 if !cont { 42 break 43 } 44 } 45 return scanner.Err() 46 }