Split the given sql script into individual statements. The base case is to simply split on semicolons, as these naturally terminate a statement. However, more complex cases like pl/pgsql can have semicolons within a statement. For these cases, we provide the explicit annotations 'StatementBegin' a
(r io.ReadSeeker)
| 108 | // 'StatementBegin' and 'StatementEnd' to allow the script to |
| 109 | // tell us to ignore semicolons. |
| 110 | func ParseMigration(r io.ReadSeeker) (*ParsedMigration, error) { |
| 111 | p := &ParsedMigration{} |
| 112 | |
| 113 | _, err := r.Seek(0, 0) |
| 114 | if err != nil { |
| 115 | return nil, err |
| 116 | } |
| 117 | |
| 118 | var buf bytes.Buffer |
| 119 | scanner := bufio.NewScanner(r) |
| 120 | scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024) |
| 121 | |
| 122 | statementEnded := false |
| 123 | ignoreSemicolons := false |
| 124 | currentDirection := directionNone |
| 125 | |
| 126 | for scanner.Scan() { |
| 127 | line := scanner.Text() |
| 128 | // ignore comment except beginning with '-- +' |
| 129 | if strings.HasPrefix(line, "-- ") && !strings.HasPrefix(line, "-- +") { |
| 130 | continue |
| 131 | } |
| 132 | |
| 133 | // handle any migrate-specific commands |
| 134 | if strings.HasPrefix(line, sqlCmdPrefix) { |
| 135 | cmd, err := parseCommand(line) |
| 136 | if err != nil { |
| 137 | return nil, err |
| 138 | } |
| 139 | |
| 140 | switch cmd.Command { |
| 141 | case "Up": |
| 142 | if len(strings.TrimSpace(buf.String())) > 0 { |
| 143 | return nil, errNoTerminator() |
| 144 | } |
| 145 | currentDirection = directionUp |
| 146 | if cmd.HasOption(optionNoTransaction) { |
| 147 | p.DisableTransactionUp = true |
| 148 | } |
| 149 | |
| 150 | case "Down": |
| 151 | if len(strings.TrimSpace(buf.String())) > 0 { |
| 152 | return nil, errNoTerminator() |
| 153 | } |
| 154 | currentDirection = directionDown |
| 155 | if cmd.HasOption(optionNoTransaction) { |
| 156 | p.DisableTransactionDown = true |
| 157 | } |
| 158 | |
| 159 | case "StatementBegin": |
| 160 | if currentDirection != directionNone { |
| 161 | ignoreSemicolons = true |
| 162 | } |
| 163 | |
| 164 | case "StatementEnd": |
| 165 | if currentDirection != directionNone { |
| 166 | statementEnded = ignoreSemicolons |
| 167 | ignoreSemicolons = false |
searching dependent graphs…