r"""Execute a SQL query and return results. This method executes a SQL query against the configured database and returns the results. For SELECT queries, returns a list of dictionaries where each dictionary represents a row. For write operations (INSERT, UPDATE, DELE
(
self,
query: str,
params: Optional[
Union[
List[Union[str, int, float, bool, None]],
Dict[str, Union[str, int, float, bool, None]],
]
] = None,
)
| 255 | return f'"{escaped}"' |
| 256 | |
| 257 | def execute_query( |
| 258 | self, |
| 259 | query: str, |
| 260 | params: Optional[ |
| 261 | Union[ |
| 262 | List[Union[str, int, float, bool, None]], |
| 263 | Dict[str, Union[str, int, float, bool, None]], |
| 264 | ] |
| 265 | ] = None, |
| 266 | ) -> Union[List[Dict[str, Any]], Dict[str, Any], str]: |
| 267 | r"""Execute a SQL query and return results. |
| 268 | |
| 269 | This method executes a SQL query against the configured database and |
| 270 | returns the results. For SELECT queries, returns a list of dictionaries |
| 271 | where each dictionary represents a row. For write operations (INSERT, |
| 272 | UPDATE, DELETE, etc.), returns a status dictionary with execution info. |
| 273 | |
| 274 | Args: |
| 275 | query (str): The SQL query to execute. |
| 276 | params (Optional[Union[List[Union[str, int, float, bool, None]], |
| 277 | Dict[str, Union[str, int, float, bool, None]]]], optional): |
| 278 | Parameters for parameterized queries. Can be a list for |
| 279 | positional parameters (with ? placeholders) or a dict for |
| 280 | named parameters. Values can be strings, numbers, booleans, |
| 281 | or None. Note: tuples are also accepted at runtime but should |
| 282 | be passed as lists for type compatibility. |
| 283 | (default: :obj:`None`) |
| 284 | |
| 285 | Returns: |
| 286 | Union[List[Dict[str, Any]], Dict[str, Any], str]: |
| 287 | - For SELECT queries: List of dictionaries with column names as |
| 288 | keys and row values as values. |
| 289 | - For write operations (INSERT, UPDATE, DELETE, CREATE, etc.): |
| 290 | A dictionary with 'status', 'message', and optionally |
| 291 | 'rows_affected' keys. |
| 292 | - For errors: An error message string starting with "Error:". |
| 293 | """ |
| 294 | if not query or not query.strip(): |
| 295 | return "Error: Query cannot be empty" |
| 296 | |
| 297 | # Validate query mode (check for write operations in read-only mode) |
| 298 | if self.read_only and self._is_write_query(query): |
| 299 | return ( |
| 300 | "Error: Write operations are not allowed in read-only mode. " |
| 301 | "The query contains write operations (INSERT, UPDATE, DELETE, " |
| 302 | "DROP, CREATE, ALTER, TRUNCATE, etc.). Only SELECT queries " |
| 303 | "are permitted." |
| 304 | ) |
| 305 | |
| 306 | try: |
| 307 | logger.debug(f"Executing query: {query}...") |
| 308 | |
| 309 | cursor = self._connection.cursor() |
| 310 | |
| 311 | # Execute query with or without parameters |
| 312 | if params is not None: |
| 313 | cursor.execute(query, params) |
| 314 | else: |