validateQuery validates the SQL statement for the SQL editor, which only permits read-only queries. It returns (allReadOnly, allReturnData, error): - allReadOnly: every statement can run in read-only mode; - allReturnData: every statement returns data; - error: a syntax error if a stateme
(statement string)
| 33 | // other_command.explain as read-only and data-returning without inspecting the |
| 34 | // inner statement; we preserve that via a lexical EXPLAIN check. |
| 35 | func validateQuery(statement string) (bool, bool, error) { |
| 36 | // Split into top-level statements with the omni splitter so EXPLAIN (which |
| 37 | // omni cannot parse) can be classified per-segment before parsing. |
| 38 | stmts, err := SplitSQL(statement) |
| 39 | if err != nil { |
| 40 | return false, false, err |
| 41 | } |
| 42 | |
| 43 | returnsData := true |
| 44 | for _, stmt := range stmts { |
| 45 | if stmt.Empty || strings.TrimSpace(stmt.Text) == "" { |
| 46 | continue |
| 47 | } |
| 48 | |
| 49 | file, perr := parser.Parse(stmt.Text) |
| 50 | if perr != nil { |
| 51 | return false, false, perr |
| 52 | } |
| 53 | if file == nil || len(file.Stmts) == 0 { |
| 54 | // A segment that parses to no statement (e.g. comment-only) is neither |
| 55 | // read-only nor a write; treat it as a no-op like the legacy walker did. |
| 56 | continue |
| 57 | } |
| 58 | |
| 59 | readOnly, isSet := classifyForEditor(getQueryType(file.Stmts[0]), file.Stmts[0]) |
| 60 | if !readOnly { |
| 61 | return false, false, nil |
| 62 | } |
| 63 | if isSet { |
| 64 | returnsData = false |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | return true, returnsData, nil |
| 69 | } |
| 70 | |
| 71 | // classifyForEditor maps a statement's base.QueryType (plus its node, to single |
| 72 | // out SET) onto the SQL-editor read-only decision, mirroring the legacy |