Cat Feeder  1.0.0
The Cat feeder project
Loading...
Searching...
No Matches
sql_connections.py
Go to the documentation of this file.
1r"""
2# +==== BEGIN CatFeeder =================+
3# LOGO:
4# ..............(..../\
5# ...............)..(.')
6# ..............(../..)
7# ...............\‍(__)|
8# Inspired by Joan Stark
9# source https://www.asciiart.eu/
10# animals/cats
11# /STOP
12# PROJECT: CatFeeder
13# FILE: sql_connections.py
14# CREATION DATE: 11-10-2025
15# LAST Modified: 14:52:3 19-12-2025
16# DESCRIPTION:
17# This is the backend server in charge of making the actual website work.
18# /STOP
19# COPYRIGHT: (c) Cat Feeder
20# PURPOSE: File in charge of containing the class that will manage the sql connections.
21# // AR
22# +==== END CatFeeder =================+
23"""
24
25
26from typing import Union, Any, List, Optional
27from threading import RLock
28
29import mysql
30import mysql.connector
31import mysql.connector.cursor
32from display_tty import Disp, initialise_logger
33
34from . import sql_constants as SCONST
35from ..utils import constants as CONST
36
37
39 """
40 Async connection manager for SQL using `mysql`.
41
42 Provides a small, async-friendly facade around an
43 :class:`mysql.Pool` instance. Access is serialized using an
44
45 Attributes:
46 disp (Disp): Logger instance for debugging and error reporting.
47 error (int): Numeric error code.
48 success (int): Numeric success code.
49 debug (bool): Debug mode flag.
50 url (str): Host or URL string.
51 port (int): Port number.
52 username (str): Username for the database.
53 password (str): Password for the database.
54 db_name (str): Name of the database to connect to.
55 pool_parameters (dict): Configuration for the connection pool.
56 pool (Optional[mysql.connector.pooling.MySQLConnectionPool]): Connection pool instance.
57 """
58
59 # Initialise the logger globally in the class.
60 disp: Disp = initialise_logger(__qualname__, False)
61
63 self,
64 url: str,
65 port: int,
66 username: str,
67 password: str,
68 db_name: str,
69 success: int = 0,
70 error: int = 84,
71 debug: bool = False,
72 ) -> None:
73 """
74 Initialize the connection manager instance.
75
76 Args:
77 url (str): Host or URL string.
78 port (int): Port number.
79 username (str): Username for the database.
80 password (str): Password for the database.
81 db_name (str): Name of the database to connect to.
82 success (int, optional): Success return code. Defaults to 0.
83 error (int, optional): Error return code. Defaults to 84.
84 debug (bool, optional): Enable debug logging. Defaults to False.
85 """
86 # ------------------------ The logging function ------------------------
87 self.disp.update_disp_debug(debug)
88 self.disp.log_debug("Initialising...")
89 # -------------------------- Inherited values --------------------------
90 self.error: int = error
91 self.debug: bool = debug
92 self.success: int = success
93 self.url: str = url
94 self.port: int = port
95 self.username: str = username
96 self.password: str = password
97 self.db_name: str = db_name
98 # ------------------------ thread lock tracker ------------------------
99 self._lock: RLock = RLock()
100 # -------------------------- Pool parameters --------------------------
102 "pool_name": CONST.DATABASE_POOL_NAME,
103 "pool_size": CONST.DATABASE_MAX_POOL_CONNECTIONS,
104 "pool_reset_session": CONST.DATABASE_RESET_POOL_NODE_CONNECTION,
105 "user": self.username,
106 "password": self.password,
107 "host": self.url,
108 "port": self.port,
109 "database": self.db_name,
110 "collation": CONST.DATABASE_COLLATION,
111 "connection_timeout": CONST.DATABASE_CONNECTION_TIMEOUT,
112 "allow_local_infile": CONST.DATABASE_LOCAL_INFILE,
113 "init_command": CONST.DATABASE_INIT_COMMAND,
114 "option_files": CONST.DATABASE_DEFAULT_FILE, # type error
115 "autocommit": CONST.DATABASE_AUTOCOMMIT,
116 "ssl_disabled": not CONST.DATABASE_SSL,
117 "ssl_key": CONST.DATABASE_SSL_KEY,
118 "ssl_cert": CONST.DATABASE_SSL_CERT,
119 "ssl_ca": CONST.DATABASE_SSL_CA,
120 "ssl_cipher": CONST.DATABASE_SSL_CIPHER,
121 "ssl_verify_cert": CONST.DATABASE_SSL_VERIFY_CERT
122 }
123 # ---------------- variables containing the connection ----------------
124 self.poolpool: Union[
125 None,
126 mysql.connector.pooling.MySQLConnectionPool
127 ] = None
128 self.disp.log_debug("Initialised")
129
130 def show_connection_info(self, func_name: str = "show_connection_info") -> None:
131 """
132 Log connection metadata for debugging.
133
134 This method does not perform any I/O; it only logs the configured
135 connection information (database filename, host/url, and port) via the
136 project's logging helper.
137
138 Args:
139 func_name (str): Optional title used in the logger.
140 """
141 msg = "\n"
142 for key, value in self.pool_parameters.items():
143 msg += f"{key} = '{value}': Type: {type(value)}\n"
144 self.disp.log_debug(msg, func_name)
145
146 def is_connected(self) -> bool:
147 """Check if there is an active connection to the database.
148
149 Returns:
150 bool: The state of the connection.
151 """
152 try:
153 self.run_and_fetch_all("SELECT 1")
154 return True
155 except RuntimeError:
156 return False
157
158 def initialise_pool(self) -> int:
159 """
160 Initialize a connection pool for the database.
161
162 Raises:
163 RuntimeError: If the pool initialization fails.
164
165 Returns:
166 int: `self.success` if the function succeeds, otherwise raises an error.
167 """
168 title = "initialise_pool"
169 self.disp.log_debug("Initialising the connection pool.", title)
170 try:
171 self.pool_parameters = {
172 "pool_name": CONST.DATABASE_POOL_NAME,
173 "pool_size": CONST.DATABASE_MAX_POOL_CONNECTIONS,
174 "pool_reset_session": CONST.DATABASE_RESET_POOL_NODE_CONNECTION,
175 "user": self.username,
176 "password": self.password,
177 "host": self.url,
178 "port": self.port,
179 "database": self.db_name,
180 "collation": CONST.DATABASE_COLLATION,
181 "connection_timeout": CONST.DATABASE_CONNECTION_TIMEOUT,
182 "allow_local_infile": CONST.DATABASE_LOCAL_INFILE,
183 "init_command": CONST.DATABASE_INIT_COMMAND,
184 "option_files": CONST.DATABASE_DEFAULT_FILE, # type error
185 "autocommit": CONST.DATABASE_AUTOCOMMIT,
186 "ssl_ca": CONST.DATABASE_SSL_CA,
187 "ssl_cert": CONST.DATABASE_SSL_CERT,
188 "ssl_key": CONST.DATABASE_SSL_KEY,
189 "ssl_verify_cert": False,
190 "ssl_verify_identity": False,
191 "allow_local_infile_in_path": None
192 }
193
194 for i in SCONST.UNWANTED_ARGUMENTS:
195 if i in self.pool_parameters and self.pool_parameters[i] is None:
196 self.disp.log_debug(
197 f"Removed '{i}' from the pool parameters.", title
198 )
199 self.pool_parameters.pop(i)
200
201 self.show_connection_info(title)
202 self.poolpool = mysql.connector.pooling.MySQLConnectionPool(
203 **self.pool_parameters
204 )
205 return self.success
206 except mysql.connector.errors.ProgrammingError as pe:
207 msg = "ProgrammingError: The pool could not be initialized."
208 msg += f"Original error: {str(pe)}"
209 self.disp.log_critical(msg, title)
210 raise RuntimeError(msg) from pe
211 except mysql.connector.errors.IntegrityError as ie:
212 msg = "IntegrityError: Integrity issue while initializing the pool."
213 msg += f" Original error: {str(ie)}"
214 self.disp.log_critical(msg, title)
215 raise RuntimeError(msg) from ie
216 except mysql.connector.errors.OperationalError as oe:
217 msg = "OperationalError: Operational error occurred during pool initialization."
218 msg += f" Original error: {str(oe)}"
219 self.disp.log_critical(msg, title)
220 raise RuntimeError(msg) from oe
221 except mysql.connector.Error as e:
222 msg = "MySQL Error: An unexpected error occurred during pool initialization."
223 msg += f"Original error: {str(e)}"
224 self.disp.log_critical(msg, title)
225 raise RuntimeError(msg) from e
226
227 def get_connection(self) -> mysql.connector.pooling.PooledMySQLConnection:
228 """
229 Retrieve a connection from the pool.
230
231 Returns:
232 mysql.connector.pooling.PooledMySQLConnection: A pooled connection instance.
233
234 Raises:
235 RuntimeError: If the connection pool is not initialized or an error occurs.
236 """
237 title = "get_connection"
238 if self.poolpool is None:
239 raise RuntimeError("Connection pool is not initialized.")
240 try:
241 self.disp.log_debug("Getting an sql connection", title)
242 return self.poolpool.get_connection()
243 except mysql.connector.errors.OperationalError as oe:
244 msg = "OperationalError: Could not retrieve a connection from the pool."
245 msg += f" Original error: {str(oe)}"
246 self.disp.log_critical(msg, title)
247 raise RuntimeError(msg) from oe
248 except mysql.connector.Error as e:
249 msg = "MySQL Error: An unexpected error occurred while getting the connection."
250 msg += f" Original error: {str(e)}"
251 self.disp.log_critical(msg, title)
252 raise RuntimeError(msg) from e
253
254 def get_cursor(self, connection: mysql.connector.pooling.PooledMySQLConnection) -> mysql.connector.cursor.MySQLCursor:
255 """
256 Retrieve a cursor from the given connection.
257
258 Args:
259 connection (mysql.connector.pooling.PooledMySQLConnection): The active connection.
260
261 Returns:
262 mysql.connector.cursor.MySQLCursor: The cursor object.
263
264 Raises:
265 RuntimeError: If the connection is not active.
266 """
267 if not self.is_connection_active(connection):
268 raise RuntimeError("Cannot get cursor, connection is not active.")
269 return connection.cursor()
270
271 def close_cursor(self, cursor: mysql.connector.cursor.MySQLCursor) -> int:
272 """
273 Close the given cursor.
274
275 Args:
276 cursor (mysql.connector.cursor.MySQLCursor): The cursor to close.
277
278 Returns:
279 int: `self.success` if the cursor is closed successfully, otherwise `self.error`.
280 """
281 title = "close_cursor"
282 self.disp.log_debug("Closing cursor, if it is open.", title)
283 if self.is_cursor_active(cursor):
284 self.disp.log_debug("Closing cursor", title)
285 if cursor.close():
286 return self.success
287 return self.error
288 self.disp.log_error(
289 "The cursor did not have an active connection.", title
290 )
291 return self.error
292
293 def return_connection(self, connection: mysql.connector.pooling.PooledMySQLConnection) -> int:
294 """
295 Return a connection to the pool by closing it.
296
297 Args:
298 connection (mysql.connector.pooling.PooledMySQLConnection): The connection to close.
299
300 Returns:
301 int: `self.success` if the connection is closed successfully, otherwise `self.error`.
302 """
303 title = "return_connection"
304 self.disp.log_debug("Closing a database connection.", title)
305 if self.is_connection_active(connection):
306 self.disp.log_debug("Connection has been closed.", title)
307 connection.close()
308 return self.success
309 self.disp.log_error(
310 "Connection was not open in the first place.", title
311 )
312 return self.error
313
314 def destroy_pool(self) -> int:
315 """
316 Destroy the connection pool.
317
318 Returns:
319 int: `self.success` if the pool is destroyed successfully, otherwise `self.error`.
320 """
321 title = "destroy_pool"
322 self.disp.log_debug("Destroying pool, if it exists.", title)
323 if self.poolpool is not None:
324 self.disp.log_debug("Destroying pool.", title)
325 del self.poolpool
326 self.poolpool = None
327 self.disp.log_warning("There was no pool to be destroyed.", title)
328 return self.success
329
330 def release_connection_and_cursor(self, connection: Union[mysql.connector.pooling.PooledMySQLConnection, None], cursor: Union[mysql.connector.cursor.MySQLCursor, None] = None) -> None:
331 """
332 Release both the connection and cursor.
333
334 Args:
335 connection (Optional[mysql.connector.pooling.PooledMySQLConnection]): The connection to release.
336 cursor (Optional[mysql.connector.cursor.MySQLCursor]): The cursor to release.
337 """
338 title = "release_connection_and_cursor"
339 msg = "Connections have ended with status: "
340 self.disp.log_debug("Closing cursor.", title)
341 if cursor is not None:
342 status = self.close_cursor(cursor)
343 msg += f"cursor = {status}, "
344 self.disp.log_debug("Closing connection.", title)
345 if connection is not None:
346 status = self.return_connection(connection)
347 msg += f"connection = {status}"
348 self.disp.log_debug(msg, title)
349
350 def run_and_commit(self, query: str, values: Optional[List[Union[str, int, float, None]]] = None, cursor: Union[mysql.connector.cursor.MySQLCursor, None] = None) -> int:
351 """
352 Execute a query and commit changes.
353
354 Args:
355 query (str): The SQL query to execute.
356 values (Optional[List[Union[str, int, float, None]]]): Values to bind to the query.
357 cursor (Optional[mysql.connector.cursor.MySQLCursor]): The cursor to use for execution.
358
359 Returns:
360 int: `self.success` if the query executes successfully, otherwise `self.error`.
361 """
362 title = "run_and_commit"
363 self.disp.log_debug("Running and committing sql query.", title)
364 self.disp.log_debug(
365 f"Arguments: Query='{query}', Values='{values}', cursor='{cursor}'",
366 title
367 )
368 if cursor is None:
369 self.disp.log_debug("No cursor found, generating one.", title)
370 connection = self.get_connection()
371 if connection is None:
372 self.disp.log_critical(SCONST.CONNECTION_FAILED, title)
373 return self.error
374 internal_cursor = self.get_cursor(connection)
375 if internal_cursor is None:
376 self.disp.log_critical(SCONST.CURSOR_FAILED, title)
377 return self.error
378 else:
379 self.disp.log_debug("Cursor found, using it.", title)
380 internal_cursor = cursor
381 try:
382 self.disp.log_debug(
383 f"Executing query: {query} with parameter(s): {values}",
384 title
385 )
386 internal_cursor.execute(query, params=values)
387 self.disp.log_debug("Committing content.", title)
388 con: Optional[mysql.connector.MySQLConnection] = getattr(
389 internal_cursor, "_connection", None)
390 if con:
391 con.commit()
392 else:
393 self.disp.log_warning(
394 "No internal cursor found, skipping manual commit.", title
395 )
396 if cursor is None:
397 self.disp.log_debug(
398 "The cursor was generated by us, releasing.", title
399 )
400 self.release_connection_and_cursor(connection, internal_cursor)
401 else:
402 self.disp.log_debug(
403 "The cursor was provided, not releasing.", title
404 )
405 return self.success
406 except mysql.connector.errors.ProgrammingError as pe:
407 msg = "ProgrammingError: Failed to execute the query."
408 msg += f" Original error: {str(pe)}"
409 self.disp.log_error(msg, title)
410 if cursor is None:
411 self.disp.log_debug(
412 "The cursor was generated by us, releasing.", title
413 )
414 self.release_connection_and_cursor(connection, internal_cursor)
415 else:
416 self.disp.log_debug(
417 "The cursor was provided, not releasing.", title
418 )
419 raise RuntimeError(msg) from pe
420 except mysql.connector.errors.IntegrityError as ie:
421 msg = "IntegrityError: Integrity constraint issue occurred during query execution."
422 msg += f" Original error: {str(ie)}"
423 self.disp.log_error(msg, title)
424 if cursor is None:
425 self.disp.log_debug(
426 "The cursor was generated by us, releasing.", title
427 )
428 self.release_connection_and_cursor(connection, internal_cursor)
429 else:
430 self.disp.log_debug(
431 "The cursor was provided, not releasing.", title
432 )
433 raise RuntimeError(msg) from ie
434 except mysql.connector.errors.OperationalError as oe:
435 msg = "OperationalError: Operational error occurred during query execution."
436 msg += f" Original error: {str(oe)}"
437 self.disp.log_error(msg, title)
438 if cursor is None:
439 self.disp.log_debug(
440 "The cursor was generated by us, releasing.", title
441 )
442 self.release_connection_and_cursor(connection, internal_cursor)
443 else:
444 self.disp.log_debug(
445 "The cursor was provided, not releasing.", title
446 )
447 raise RuntimeError(msg) from oe
448 except mysql.connector.Error as e:
449 msg = "MySQL Error: An unexpected error occurred during query execution."
450 msg += f" Original error: {str(e)}"
451 self.disp.log_error(msg, title)
452 if cursor is None:
453 self.disp.log_debug(
454 "The cursor was generated by us, releasing.", title
455 )
456 self.release_connection_and_cursor(connection, internal_cursor)
457 else:
458 self.disp.log_debug(
459 "The cursor was provided, not releasing.", title
460 )
461 raise RuntimeError(msg) from e
462
463 def run_and_fetch_all(self, query: str, values: Optional[List[Union[str, int, float, None]]] = None, cursor: Union[mysql.connector.cursor.MySQLCursor, None] = None) -> Union[int, Any]:
464 """
465 Execute a SELECT-style query and return fetched rows.
466
467 Args:
468 query (str): The SQL SELECT statement to execute.
469 values (Optional[List[Union[str, int, float, None]]]): Values to bind to the query.
470 cursor (Optional[mysql.connector.cursor.MySQLCursor]): The cursor to use for execution.
471
472 Returns:
473 Union[int, Any]: The fetched rows (usually a List[tuple]) or `self.error` on failure.
474 """
475 title = "run_and_fetchall"
476 if cursor is None:
477 connection = self.get_connection()
478 if connection is None:
479 self.disp.log_critical(SCONST.CONNECTION_FAILED, title)
480 return self.error
481 internal_cursor = self.get_cursor(connection)
482 if internal_cursor is None:
483 self.disp.log_critical(SCONST.CURSOR_FAILED, title)
484 return self.error
485 else:
486 internal_cursor = cursor
487 try:
488 self.disp.log_debug(
489 f"Executing query: {query}, values: {values}.", title)
490 internal_cursor.execute(query, params=values)
491 if internal_cursor is None or internal_cursor.description is None:
492 self.disp.log_error(
493 "Failed to gather data from the table, cursor is invalid.", title
494 )
495 if cursor is None:
496 self.disp.log_debug(
497 "The cursor was generated by us, releasing.", title
498 )
500 connection, internal_cursor
501 )
502 else:
503 self.disp.log_debug(
504 "The cursor was provided, not releasing.", title
505 )
506 return self.error
507 self.disp.log_debug(
508 "Storing a copy of the content of the cursor.", title
509 )
510 raw_data = internal_cursor.fetchall()
511 self.disp.log_debug(f"Raw gathered data {raw_data}", title)
512 data = raw_data.copy()
513 self.disp.log_debug(f"Data gathered: {data}.", title)
514 if cursor is None:
515 self.disp.log_debug(
516 "The cursor was generated by us, releasing.", title
517 )
518 self.release_connection_and_cursor(connection, internal_cursor)
519 else:
520 self.disp.log_debug(
521 "The cursor was provided, not releasing.", title
522 )
523 return data
524 except mysql.connector.errors.ProgrammingError as pe:
525 msg = "ProgrammingError: Failed to execute the query."
526 msg += f" Original error: {str(pe)}"
527 self.disp.log_error(msg, title)
528 if cursor is None:
529 self.disp.log_debug(
530 "The cursor was generated by us, releasing.", title
531 )
532 self.release_connection_and_cursor(connection, internal_cursor)
533 else:
534 self.disp.log_debug(
535 "The cursor was provided, not releasing.", title
536 )
537 raise RuntimeError(msg) from pe
538 except mysql.connector.errors.IntegrityError as ie:
539 msg = "IntegrityError: Integrity constraint issue occurred during query execution."
540 msg += f" Original error: {str(ie)}"
541 self.disp.log_error(msg, title)
542 if cursor is None:
543 self.disp.log_debug(
544 "The cursor was generated by us, releasing.", title
545 )
546 self.release_connection_and_cursor(connection, internal_cursor)
547 else:
548 self.disp.log_debug(
549 "The cursor was provided, not releasing.", title
550 )
551 raise RuntimeError(msg) from ie
552 except mysql.connector.errors.OperationalError as oe:
553 msg = "OperationalError: Operational error occurred during query execution."
554 msg += f" Original error: {str(oe)}"
555 self.disp.log_error(msg, title)
556 if cursor is None:
557 self.disp.log_debug(
558 "The cursor was generated by us, releasing.", title
559 )
560 self.release_connection_and_cursor(connection, internal_cursor)
561 else:
562 self.disp.log_debug(
563 "The cursor was provided, not releasing.", title
564 )
565 raise RuntimeError(msg) from oe
566 except mysql.connector.Error as e:
567 msg = "MySQL Error: An unexpected error occurred during query execution."
568 msg += f" Original error: {str(e)}"
569 self.disp.log_error(msg, title)
570 if cursor is None:
571 self.disp.log_debug(
572 "The cursor was generated by us, releasing.", title
573 )
574 self.release_connection_and_cursor(connection, internal_cursor)
575 else:
576 self.disp.log_debug(
577 "The cursor was provided, not releasing.", title
578 )
579 raise RuntimeError(msg) from e
580
581 def run_editing_command(self, sql_query: str, values: Optional[List[Union[str, int, float, None]]] = None, table: str = "<not_specified>", action_type: str = "update") -> int:
582 """
583 Execute an editing command (e.g., INSERT, UPDATE, DELETE).
584
585 Args:
586 sql_query (str): The SQL query to execute.
587 values (Optional[List[Union[str, int, float, None]]]): Values to bind to the query.
588 table (str): The name of the table being modified.
589 action_type (str): The type of action being performed (e.g., "update").
590
591 Returns:
592 int: `self.success` if the command executes successfully, otherwise `self.error`.
593 """
594 title = "run_editing_command"
595 self.disp.log_debug(
596 "Going to run a command that will alter the database."
597 )
598 self.disp.log_debug(
599 f"Query: '{sql_query}', values: '{values}', table: '{table}', action_type: '{action_type}'",
600 title
601 )
602 try:
603 resp = self.run_and_commit(query=sql_query, values=values)
604 if resp != self.success:
605 self.disp.log_error(
606 f"Failed to {action_type} data in '{table}'.", title
607 )
608 return self.error
609 self.disp.log_debug("command ran successfully.", title)
610 return self.success
611 except mysql.connector.Error as e:
612 self.disp.log_error(
613 f"Failed to {action_type} data in '{table}': {str(e)}", title
614 )
615 return self.error
616
617 def __del__(self) -> None:
618 """_summary_
619 Destructor
620 """
621 self.destroy_pool()
622
623 def is_pool_active(self) -> bool:
624 """
625 Check if the connection pool is active.
626
627 Returns:
628 bool: True if the pool is active, False otherwise.
629 """
630 title = "is_pool_active"
631 self.disp.log_debug("Checking if the connection is active.", title)
632 resp = self.poolpool is not None
633 if resp:
634 self.disp.log_debug("The connection is active.", title)
635 return True
636 self.disp.log_error("The connection is not active.", title)
637 return False
638
639 def is_connection_active(self, connection: mysql.connector.pooling.PooledMySQLConnection) -> bool:
640 """
641 Check if the connection is active.
642
643 Args:
644 connection (mysql.connector.pooling.PooledMySQLConnection): The connection to check.
645
646 Returns:
647 bool: True if the connection is active, False otherwise.
648 """
649 title = "is_connection_active"
650 self.disp.log_debug(
651 "Checking if the connection is active.", title
652 )
653 try:
654 if connection:
655 connection.ping(reconnect=False)
656 self.disp.log_debug("The connection is active.", title)
657 return True
658 except (mysql.connector.Error, mysql.connector.errors.Error):
659 self.disp.log_error("The connection is not active.", title)
660 return False
661 self.disp.log_error("The connection is not active.", title)
662 return False
663
664 def is_cursor_active(self, cursor: mysql.connector.cursor.MySQLCursor) -> bool:
665 """
666 Check if the cursor is active.
667
668 Args:
669 cursor (mysql.connector.cursor.MySQLCursor): The cursor to check.
670
671 Returns:
672 bool: True if the cursor is active, False otherwise.
673 """
674 title = "is_cursor_active"
675 self.disp.log_debug(
676 "Checking if the provided cursor is active.", title
677 )
678 self.disp.log_debug(f"Content of the cursor: {dir(cursor)}.", title)
679 con = getattr(cursor, "_connection", None)
680 resp = cursor is not None and con is not None
681 if resp:
682 self.disp.log_debug("The cursor is active.", title)
683 return True
684 self.disp.log_error("The cursor is not active.", title)
685 return False
mysql.connector.pooling.PooledMySQLConnection get_connection(self)
Union[int, Any] run_and_fetch_all(self, str query, Optional[List[Union[str, int, float, None]]] values=None, Union[mysql.connector.cursor.MySQLCursor, None] cursor=None)
mysql.connector.cursor.MySQLCursor get_cursor(self, mysql.connector.pooling.PooledMySQLConnection connection)
None show_connection_info(self, str func_name="show_connection_info")
None __init__(self, str url, int port, str username, str password, str db_name, int success=0, int error=84, bool debug=False)
bool is_connection_active(self, mysql.connector.pooling.PooledMySQLConnection connection)
int return_connection(self, mysql.connector.pooling.PooledMySQLConnection connection)
int run_and_commit(self, str query, Optional[List[Union[str, int, float, None]]] values=None, Union[mysql.connector.cursor.MySQLCursor, None] cursor=None)
None release_connection_and_cursor(self, Union[mysql.connector.pooling.PooledMySQLConnection, None] connection, Union[mysql.connector.cursor.MySQLCursor, None] cursor=None)
int close_cursor(self, mysql.connector.cursor.MySQLCursor cursor)
bool is_cursor_active(self, mysql.connector.cursor.MySQLCursor cursor)
int run_editing_command(self, str sql_query, Optional[List[Union[str, int, float, None]]] values=None, str table="<not_specified>", str action_type="update")