Format parses and re-formats a SQL string.
(sql string)
| 122 | |
| 123 | // Format parses and re-formats a SQL string. |
| 124 | func (f *Formatter) Format(sql string) (string, error) { |
| 125 | if strings.TrimSpace(sql) == "" { |
| 126 | return "", nil |
| 127 | } |
| 128 | |
| 129 | tkz := tokenizer.GetTokenizer() |
| 130 | defer tokenizer.PutTokenizer(tkz) |
| 131 | |
| 132 | tokens, err := tkz.Tokenize([]byte(sql)) |
| 133 | if err != nil { |
| 134 | return "", fmt.Errorf("tokenization failed: %w", err) |
| 135 | } |
| 136 | |
| 137 | if len(tokens) == 0 { |
| 138 | return "", nil |
| 139 | } |
| 140 | |
| 141 | // Capture comments from tokenizer before parsing |
| 142 | comments := tkz.Comments |
| 143 | |
| 144 | p := parser.GetParser() |
| 145 | defer parser.PutParser(p) |
| 146 | parsedAST, err := p.ParseFromModelTokens(tokens) |
| 147 | if err != nil { |
| 148 | return "", fmt.Errorf("parsing failed: %w", err) |
| 149 | } |
| 150 | defer ast.ReleaseAST(parsedAST) |
| 151 | |
| 152 | // Attach captured comments to AST |
| 153 | if len(comments) > 0 { |
| 154 | parsedAST.Comments = make([]models.Comment, len(comments)) |
| 155 | copy(parsedAST.Comments, comments) |
| 156 | } |
| 157 | |
| 158 | // Build format options and delegate to the visitor-based renderer. |
| 159 | style := ast.ReadableStyle() |
| 160 | if f.opts.Compact { |
| 161 | style = ast.CompactStyle() |
| 162 | } |
| 163 | if f.opts.IndentSize > 0 { |
| 164 | style.IndentWidth = f.opts.IndentSize |
| 165 | } |
| 166 | if f.opts.Uppercase { |
| 167 | style.KeywordCase = ast.KeywordUpper |
| 168 | } |
| 169 | style.Dialect = f.opts.Dialect |
| 170 | |
| 171 | return FormatAST(parsedAST, style), nil |
| 172 | } |
| 173 | |
| 174 | // FormatString is a convenience function that formats SQL with default options. |
| 175 | func FormatString(sql string) (string, error) { |