SplitSQL splits the input into multiple SQL statements using the omni Snowflake splitter, then converts each Segment into a base.Statement with the position fields bytebase expects. Positions are computed in a single O(n) pass via the shared base.ByteOffsetPositionMapper (segment offsets are queried
(statement string)
| 17 | // shared base.ByteOffsetPositionMapper (segment offsets are queried in |
| 18 | // increasing order). |
| 19 | func SplitSQL(statement string) ([]base.Statement, error) { |
| 20 | segs := parser.Split(statement) |
| 21 | if len(segs) == 0 { |
| 22 | return nil, nil |
| 23 | } |
| 24 | |
| 25 | mapper := base.NewByteOffsetPositionMapper(statement) |
| 26 | stmts := make([]base.Statement, 0, len(segs)) |
| 27 | for _, seg := range segs { |
| 28 | // bytebase historically returns Text including the trailing ';' delimiter |
| 29 | // (when present). omni's Segment.Text excludes it, so we re-attach when |
| 30 | // the byte after ByteEnd is ';'. |
| 31 | text := seg.Text |
| 32 | end := seg.ByteEnd |
| 33 | if end < len(statement) && statement[end] == ';' { |
| 34 | text = statement[seg.ByteStart : end+1] |
| 35 | end++ |
| 36 | } |
| 37 | stmts = append(stmts, base.Statement{ |
| 38 | Text: text, |
| 39 | Empty: seg.Empty(), |
| 40 | Start: mapper.Position(seg.ByteStart), |
| 41 | End: mapper.Position(end), |
| 42 | Range: &storepb.Range{ |
| 43 | Start: int32(seg.ByteStart), |
| 44 | End: int32(end), |
| 45 | }, |
| 46 | }) |
| 47 | } |
| 48 | return stmts, nil |
| 49 | } |