walkNode recursively walks a node and its children
(node *pg_query.Node, fn func(*pg_query.Node) bool)
| 74 | // final query. When populated, the normal deparse result should be ignored. |
| 75 | Statements []string |
| 76 | |
| 77 | // CleanupStatements contains statements to execute after obtaining the cursor |
| 78 | // for the final query but before streaming results. Typically DROP TEMP TABLE |
| 79 | // and COMMIT statements. Execute these with best-effort (ignore errors). |
| 80 | CleanupStatements []string |
| 81 | } |
| 82 | |
| 83 | // Transform defines the interface for SQL transformations. |
| 84 | // Each transform modifies the AST in place and can set result metadata. |
| 85 | type Transform interface { |
| 86 | // Name returns the transform identifier for logging/debugging |
| 87 | Name() string |
| 88 | |
| 89 | // Transform modifies the AST in place. |
| 90 | // Returns true if any changes were made. |
| 91 | // The result parameter can be used to set metadata like IsNoOp. |
| 92 | Transform(tree *pg_query.ParseResult, result *Result) (changed bool, err error) |
| 93 | } |
| 94 | |
| 95 | // WalkFunc walks all nodes in a ParseResult and calls fn for each. |
| 96 | // If fn returns false, walking stops. |
| 97 | func WalkFunc(tree *pg_query.ParseResult, fn func(node *pg_query.Node) bool) { |
| 98 | for _, stmt := range tree.Stmts { |
| 99 | if stmt.Stmt != nil { |
| 100 | walkNode(stmt.Stmt, fn) |
| 101 | } |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | // walkNode recursively walks a node and its children |
| 106 | func walkNode(node *pg_query.Node, fn func(*pg_query.Node) bool) bool { |
| 107 | if node == nil { |
| 108 | return true |
| 109 | } |
| 110 | |
| 111 | if !fn(node) { |
| 112 | return false |
| 113 | } |
| 114 | |
| 115 | // Walk children based on node type |
| 116 | // pg_query uses a union type, so we need to check each possibility |
| 117 | switch n := node.Node.(type) { |
| 118 | case *pg_query.Node_SelectStmt: |
| 119 | if n.SelectStmt != nil { |
| 120 | walkSelectStmt(n.SelectStmt, fn) |
| 121 | } |
| 122 | case *pg_query.Node_InsertStmt: |
| 123 | if n.InsertStmt != nil { |
| 124 | walkInsertStmt(n.InsertStmt, fn) |
| 125 | } |
| 126 | case *pg_query.Node_UpdateStmt: |
| 127 | if n.UpdateStmt != nil { |
| 128 | walkUpdateStmt(n.UpdateStmt, fn) |
| 129 | } |
| 130 | case *pg_query.Node_DeleteStmt: |
| 131 | if n.DeleteStmt != nil { |
| 132 | walkDeleteStmt(n.DeleteStmt, fn) |
| 133 | } |
no test coverage detected