* Parse a SQL statement from a Python code string. * * @param code - The Python code string to parse * @returns The parsed SQL statement or null if parsing fails
(code: string)
| 171 | * @returns The parsed SQL statement or null if parsing fails |
| 172 | */ |
| 173 | function parseSQLStatement(code: string): SQLParseInfo | null { |
| 174 | try { |
| 175 | const tree = parsePythonAST(code); |
| 176 | const cursor = tree.cursor(); |
| 177 | |
| 178 | // Trees start with a Script node |
| 179 | if (cursor.name === "Script") { |
| 180 | cursor.next(); |
| 181 | } |
| 182 | const assignStmt = findAssignment(cursor); |
| 183 | if (!assignStmt) { |
| 184 | return null; |
| 185 | } |
| 186 | |
| 187 | // Code after the assignment statement is not allowed |
| 188 | if (code.slice(assignStmt.to).trim().length > 0) { |
| 189 | return null; |
| 190 | } |
| 191 | |
| 192 | let dfName: string | null = null; |
| 193 | let sqlString: string | null = null; |
| 194 | let engine: string | undefined; |
| 195 | let output: boolean | undefined; |
| 196 | let startPosition = 0; |
| 197 | |
| 198 | // Parse the assignment |
| 199 | const assignCursor = assignStmt.cursor(); |
| 200 | assignCursor.firstChild(); // Move to first child of assignment |
| 201 | |
| 202 | // First child should be the variable name |
| 203 | if (assignCursor.name === "VariableName") { |
| 204 | dfName = code.slice(assignCursor.from, assignCursor.to); |
| 205 | } |
| 206 | |
| 207 | if (!dfName) { |
| 208 | return null; |
| 209 | } |
| 210 | |
| 211 | // Move to the expression part (after the =) |
| 212 | // We need to find the value being assigned (after AssignOp) |
| 213 | let foundAssignOp = false; |
| 214 | let rightHandSide: SyntaxNode | null = null; |
| 215 | |
| 216 | while (assignCursor.nextSibling()) { |
| 217 | if (assignCursor.name === "AssignOp") { |
| 218 | foundAssignOp = true; |
| 219 | } else if (foundAssignOp && !rightHandSide) { |
| 220 | // This is the right-hand side of the assignment |
| 221 | rightHandSide = assignCursor.node; |
| 222 | break; |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | if (!rightHandSide) { |
| 227 | return null; |
| 228 | } |
| 229 | |
| 230 | // Check if the right-hand side is wrapped in a conditional or binary expression |
no test coverage detected
searching dependent graphs…