Execute a query in a read-only transaction. The query is wrapped in a read-only transaction to ensure no data modifications can occur. Args: conn: Database connection query: SQL query to execute Returns: Dictionary with 'columns' and 'rows' keys R
(conn, query: str)
| 236 | |
| 237 | |
| 238 | def _execute_readonly_query(conn, query: str) -> dict: |
| 239 | """ |
| 240 | Execute a query in a read-only transaction. |
| 241 | |
| 242 | The query is wrapped in a read-only transaction to ensure |
| 243 | no data modifications can occur. |
| 244 | |
| 245 | Args: |
| 246 | conn: Database connection |
| 247 | query: SQL query to execute |
| 248 | |
| 249 | Returns: |
| 250 | Dictionary with 'columns' and 'rows' keys |
| 251 | |
| 252 | Raises: |
| 253 | DatabaseToolError: If query execution fails |
| 254 | """ |
| 255 | # Set the transaction to read-only, execute, then rollback. |
| 256 | # This ensures even if the query tries to modify data, it will fail. |
| 257 | try: |
| 258 | # First, set the transaction to read-only mode |
| 259 | status, result = conn.execute_void( |
| 260 | "BEGIN TRANSACTION READ ONLY" |
| 261 | ) |
| 262 | if not status: |
| 263 | raise DatabaseToolError( |
| 264 | f"Failed to start read-only transaction: {result}", |
| 265 | code="TRANSACTION_ERROR" |
| 266 | ) |
| 267 | |
| 268 | try: |
| 269 | # Execute the actual query |
| 270 | status, result = conn.execute_2darray(query) |
| 271 | |
| 272 | if not status: |
| 273 | raise DatabaseToolError( |
| 274 | f"Query execution failed: {result}", |
| 275 | code="QUERY_ERROR" |
| 276 | ) |
| 277 | |
| 278 | # Format the result |
| 279 | columns = [] |
| 280 | rows = [] |
| 281 | |
| 282 | if result and 'columns' in result: |
| 283 | columns = [col['name'] for col in result['columns']] |
| 284 | |
| 285 | if result and 'rows' in result: |
| 286 | rows = result['rows'] |
| 287 | |
| 288 | return { |
| 289 | 'columns': columns, |
| 290 | 'rows': rows, |
| 291 | 'row_count': len(rows) |
| 292 | } |
| 293 | |
| 294 | finally: |
| 295 | # Always rollback - we're read-only anyway |
no test coverage detected