SplitSQL splits the input into multiple SQL statements using the omni Doris splitter, then converts each Segment into a base.Statement with the position fields bytebase expects. Positions are computed in a single O(n) pass over the input.
(statement string)
| 19 | // |
| 20 | // Positions are computed in a single O(n) pass over the input. |
| 21 | func SplitSQL(statement string) ([]base.Statement, error) { |
| 22 | segs := parser.Split(statement) |
| 23 | if len(segs) == 0 { |
| 24 | return nil, nil |
| 25 | } |
| 26 | |
| 27 | type pos struct{ line, col int } |
| 28 | positions := make(map[int]pos, len(segs)*3) |
| 29 | for _, seg := range segs { |
| 30 | positions[seg.ByteStart] = pos{} |
| 31 | positions[seg.ByteEnd] = pos{} |
| 32 | // Also collect position immediately past the trailing ';' for End column. |
| 33 | if seg.ByteEnd < len(statement) && statement[seg.ByteEnd] == ';' { |
| 34 | positions[seg.ByteEnd+1] = pos{} |
| 35 | } |
| 36 | } |
| 37 | |
| 38 | line, col := 1, 1 |
| 39 | for i := 0; i <= len(statement); { |
| 40 | if _, need := positions[i]; need { |
| 41 | positions[i] = pos{line, col} |
| 42 | } |
| 43 | if i == len(statement) { |
| 44 | break |
| 45 | } |
| 46 | r, size := utf8.DecodeRuneInString(statement[i:]) |
| 47 | if r == '\n' { |
| 48 | line++ |
| 49 | col = 1 |
| 50 | } else { |
| 51 | col++ |
| 52 | } |
| 53 | i += size |
| 54 | } |
| 55 | |
| 56 | stmts := make([]base.Statement, 0, len(segs)) |
| 57 | for _, seg := range segs { |
| 58 | // bytebase historically returns Text including the trailing ';' delimiter |
| 59 | // (when present). omni's Segment.Text excludes it, so we re-attach when |
| 60 | // the byte after ByteEnd is ';'. |
| 61 | text := seg.Text |
| 62 | end := seg.ByteEnd |
| 63 | if end < len(statement) && statement[end] == ';' { |
| 64 | text = statement[seg.ByteStart : end+1] |
| 65 | end++ |
| 66 | } |
| 67 | sp := positions[seg.ByteStart] |
| 68 | ep, ok := positions[end] |
| 69 | if !ok { |
| 70 | ep = positions[seg.ByteEnd] |
| 71 | } |
| 72 | stmts = append(stmts, base.Statement{ |
| 73 | Text: text, |
| 74 | Empty: seg.Empty(), |
| 75 | Start: &storepb.Position{ |
| 76 | Line: int32(sp.line), |
| 77 | Column: int32(sp.col), |
| 78 | }, |
no outgoing calls
no test coverage detected