package sql import ( "bufio" "bytes" "io" ) type stack struct { c []rune } func newStack() *stack { return &stack{ c: make([]rune, 0), } } func (s *stack) push(r rune) { s.c = append(s.c, r) } func (s *stack) pop() rune { if len(s.c) == 0 { return rune(0) } c := s.c[len(s.c)-1] s.c = s.c[:len(s.c)-1] return c } func (s *stack) peek() rune { if len(s.c) == 0 { return rune(0) } c := s.c[len(s.c)-1] return c } func (s *stack) empty() bool { return len(s.c) == 0 } // Scanner represents a SQL statement scanner. type Scanner struct { r *bufio.Reader c *stack } // NewScanner returns a new instance of Scanner. func NewScanner(r io.Reader) *Scanner { return &Scanner{ r: bufio.NewReader(r), c: newStack(), } } // read reads the next rune from the bufferred reader. // Returns the rune(0) if an error occurs (or io.EOF is returned). func (s *Scanner) read() rune { ch, _, err := s.r.ReadRune() if err != nil { return eof } return ch } // Scan returns the next SQL statement. func (s *Scanner) Scan() string { var buf bytes.Buffer seekSemi := true for { ch := s.read() if ch == eof { break } // Store the character. _, _ = buf.WriteRune(ch) if ch == '\'' || ch == '"' { if s.c.empty() { // add to stack seekSemi = false } else if s.c.peek() != ch { s.c.push(ch) seekSemi = false } else { s.c.pop() if s.c.empty() { seekSemi = true } } } else if ch == ';' && seekSemi { break } } return buf.String() } // eof represents a marker rune for the end of the reader. var eof = rune(0)