2 File in charge of storing the functions that will interract directly with the database.
5from typing
import List, Dict, Union, Any
9from display_tty
import Disp, TOML_CONF, SAVE_TO_FILE, FILE_NAME
12from .
import sql_constants
as SCONST
13from .sql_injection
import SQLInjection
14from .sql_connections
import SQLManageConnections
15from .sql_sanitisation_functions
import SQLSanitiseFunctions
22 def __init__(self, sql_pool: SQLManageConnections, success: int = 0, error: int = 84, debug: bool =
False) ->
None:
24 The class in charge of managing sql queries (it contains the required boilerplate functions).
27 sql_pool (SQLManageConnections): _description_
28 success (int, optional): _description_. Defaults to 0.
29 error (int, optional): _description_. Defaults to 84.
30 debug (bool, optional): _description_. Defaults to False.
43 logger=self.__class__.__name__
58 Get the names of the columns in a table.
61 table_name (str): _description_
64 List[str]: _description_
66 title =
"get_table_column_names"
69 if isinstance(columns, int)
is True:
71 f
"Failed to describe table {table_name}.",
79 except RuntimeError
as e:
80 msg =
"Error: Failed to get column names of the tables.\n"
81 msg += f
"\"{str(e)}\""
82 self.
disp.log_error(msg,
"get_table_column_names")
87 Get the names of the tables in the database.
90 List[str]: _description_
92 title =
"get_table_names"
93 self.
disp.log_debug(
"Getting table names.", title)
94 resp = self.
sql_pool.run_and_fetch_all(query=
"SHOW TABLES")
95 if isinstance(resp, int)
is True:
97 "Failed to fetch the table names.",
104 self.
disp.log_debug(
"Tables fetched", title)
109 Fetch the headers (description) of a table from the database.
112 table (str): _description_: The name of the table to describe.
115 RuntimeError: _description_: If there is a critical issue with the table or the database connection.
118 Union[int, List[Any]]: _description_: A list containing the description of the table, or self.error if an error occurs.
120 title =
"describe_table"
121 self.
disp.log_debug(f
"Describing table {table}", title)
123 self.
disp.log_error(
"Injection detected.",
"sql")
126 resp = self.
sql_pool.run_and_fetch_all(query=f
"DESCRIBE {table}")
127 if isinstance(resp, int)
is True:
129 f
"Failed to describe table {table}", title
133 except mysql.connector.errors.ProgrammingError
as pe:
134 msg = f
"ProgrammingError: The table '{table}'"
135 msg +=
"does not exist or the query failed."
136 self.
disp.log_critical(msg, title)
137 raise RuntimeError(msg)
from pe
138 except mysql.connector.errors.IntegrityError
as ie:
139 msg =
"IntegrityError: There was an integrity constraint "
140 msg += f
"issue while describing the table '{table}'."
141 self.
disp.log_critical(msg, title)
142 raise RuntimeError(msg)
from ie
143 except mysql.connector.errors.OperationalError
as oe:
144 msg =
"OperationalError: There was an operational error "
145 msg += f
"while describing the table '{table}'."
146 self.
disp.log_critical(msg, title)
147 raise RuntimeError(msg)
from oe
148 except mysql.connector.Error
as e:
149 msg =
"MySQL Error: An unexpected error occurred while "
150 msg += f
"describing the table '{table}'."
151 self.
disp.log_critical(msg, title)
152 raise RuntimeError(msg)
from e
153 except RuntimeError
as e:
154 msg =
"A runtime error occurred during the table description process."
155 self.
disp.log_critical(msg, title)
156 raise RuntimeError(msg)
from e
158 def insert_data_into_table(self, table: str, data: Union[List[List[str]], List[str]], column: Union[List[str],
None] =
None) -> int:
160 Insert data into a table.
163 table (str): _description_
164 data (List[List[str]]): _description_
165 column (List[str]): _description_
170 title =
"insert_data_into_table"
171 self.
disp.log_debug(
"Inserting data into the table.", title)
174 if self.
sql_injection.check_if_injections_in_strings([table, data, column])
is True:
175 self.
disp.log_error(
"Injection detected.",
"sql")
183 column_str =
", ".join(column)
184 column_length = len(column)
186 if isinstance(data, List)
is True and (len(data) > 0
and isinstance(data[0], List)
is True):
187 self.
disp.log_debug(
"processing double array", title)
189 max_lengths = len(data)
190 for index, line
in enumerate(data):
192 line, column, column_length
194 if index < max_lengths - 1:
196 if index == max_lengths - 1:
199 elif isinstance(data, List)
is True:
200 self.
disp.log_debug(
"processing single array", title)
202 data, column, column_length
206 "data is expected to be, either of type: List[str] or List[List[str]]",
210 sql_query = f
"INSERT INTO {table} ({column_str}) VALUES {values}"
211 self.
disp.log_debug(f
"sql_query = '{sql_query}'", title)
212 return self.
sql_pool.run_editing_command(sql_query, table,
"insert")
214 def get_data_from_table(self, table: str, column: Union[str, List[str]], where: Union[str, List[str]] =
"", beautify: bool =
True) -> Union[int, List[Dict[str, Any]]]:
218 table (str): _description_
219 column (Union[str, List[str]]): _description_
220 where (Union[str, List[str]]): _description_
223 Union[int, List[Dict[str, Any]]]: _description_: Will return the data you requested, self.error otherwise
225 title =
"get_data_from_table"
226 self.
disp.log_debug(f
"fetching data from the table {table}", title)
227 if self.
sql_injection.check_if_injections_in_strings([table, column])
is True or self.
sql_injection.check_if_symbol_and_command_injection(where)
is True:
228 self.
disp.log_error(
"Injection detected.",
"sql")
230 if isinstance(column, list)
is True:
232 column =
", ".join(column)
233 sql_command = f
"SELECT {column} FROM {table}"
234 if isinstance(where, (str, List))
is True:
238 if isinstance(where, List)
is True:
239 where =
" AND ".join(where)
241 sql_command += f
" WHERE {where}"
242 self.
disp.log_debug(f
"sql_query = '{sql_command}'", title)
243 resp = self.
sql_pool.run_and_fetch_all(query=sql_command)
244 if isinstance(resp, int)
is True and resp != self.
success:
246 "Failed to fetch the data from the table.", title
249 self.
disp.log_debug(f
"Queried data: {resp}", title)
250 if beautify
is False:
255 def get_table_size(self, table: str, column: Union[str, List[str]], where: Union[str, List[str]] =
"") -> Union[int]:
257 Get the size of a table.
260 table (str): _description_
261 column (Union[str, List[str]]): _description_
262 where (Union[str, List[str]]): _description_
265 int: _description_: Return the size of the table, -1 if an error occurred.
267 title =
"get_table_size"
268 self.
disp.log_debug(f
"fetching data from the table {table}", title)
269 if self.
sql_injection.check_if_injections_in_strings([table, column])
is True or self.
sql_injection.check_if_symbol_and_command_injection(where)
is True:
270 self.
disp.log_error(
"Injection detected.",
"sql")
271 return SCONST.GET_TABLE_SIZE_ERROR
272 if isinstance(column, list)
is True:
273 column =
", ".join(column)
274 sql_command = f
"SELECT COUNT({column}) FROM {table}"
275 if isinstance(where, (str, List))
is True:
279 if isinstance(where, List)
is True:
280 where =
" AND ".join(where)
282 sql_command += f
" WHERE {where}"
283 self.
disp.log_debug(f
"sql_query = '{sql_command}'", title)
284 resp = self.
sql_pool.run_and_fetch_all(query=sql_command)
285 if isinstance(resp, int)
is True and resp != self.
success:
287 "Failed to fetch the data from the table.", title
289 return SCONST.GET_TABLE_SIZE_ERROR
292 "There was no data returned by the query.", title
294 return SCONST.GET_TABLE_SIZE_ERROR
295 if isinstance(resp[0], tuple)
is False:
296 self.
disp.log_error(
"The data returned is not a tuple.", title)
297 return SCONST.GET_TABLE_SIZE_ERROR
300 def update_data_in_table(self, table: str, data: List[str], column: List, where: Union[str, List[str]] =
"") -> int:
302 Update the data contained in a table.
305 table (str): _description_
306 data (Union[List[List[str]], List[str]]): _description_
307 column (List): _description_
312 title =
"update_data_in_table"
313 msg = f
"Updating the data contained in the table: {table}"
314 self.
disp.log_debug(msg, title)
318 if self.
sql_injection.check_if_injections_in_strings([table, column, data])
is True or self.
sql_injection.check_if_symbol_and_command_injection(where)
is True:
319 self.
disp.log_error(
"Injection detected.",
"sql")
327 if isinstance(column, str)
and isinstance(data, str):
330 column_length = len(column)
332 column_length = len(column)
334 f
"data = {data}, column = {column}, length = {column_length}",
342 if isinstance(where, List)
is True:
343 where =
" AND ".join(where)
346 data, column, column_length
349 sql_query = f
"UPDATE {table} SET {update_line}"
352 sql_query += f
" WHERE {where}"
354 self.
disp.log_debug(f
"sql_query = '{sql_query}'", title)
356 return self.
sql_pool.run_editing_command(sql_query, table,
"update")
360 Insert or update data into a given table.
363 table (str): Table name.
364 data (Union[List[List[str]], List[str]]): Data to insert or update.
365 columns (Union[List[str], None], optional): Column names. Defaults to None.
368 int: Success or error code.
370 title =
"insert_or_update_data_into_table"
372 "Inserting or updating data into the table.", title)
374 if self.
sql_injection.check_if_injections_in_strings([table] + (columns
or []))
is True:
375 self.
disp.log_error(
"SQL Injection detected.",
"sql")
382 table=table, column=columns, where=
"", beautify=
False
384 if isinstance(table_content, int)
and table_content != self.
success:
385 self.
disp.log_critical(
386 f
"Failed to retrieve data from table {table}", title
390 if isinstance(data, list)
and data
and isinstance(data[0], list):
391 self.
disp.log_debug(
"Processing double data list", title)
392 table_content_dict = {str(line[0]): line
for line
in table_content}
396 self.
disp.log_warning(
"Empty line, skipping.", title)
399 if node0
in table_content_dict:
401 table, line, columns,
402 f
"{columns[0]} = {node0}"
407 elif isinstance(data, list):
408 self.
disp.log_debug(
"Processing single data list", title)
410 self.
disp.log_warning(
"Empty data list, skipping.", title)
414 for line
in table_content:
415 if str(line[0]) == node0:
421 "Data must be of type List[str] or List[List[str]]", title
427 Remove the data from a table.
429 table (str): _description_
430 data (List): _description_
431 column (List): _description_
437 f
"Removing data from table {table}",
438 "remove_data_from_table"
440 if self.
sql_injection.check_if_sql_injection(table)
is True or self.
sql_injection.check_if_symbol_and_command_injection(where)
is True:
441 self.
disp.log_error(
"Injection detected.",
"sql")
444 if isinstance(where, List)
is True:
445 where =
" AND ".join(where)
447 sql_query = f
"DELETE FROM {table}"
450 sql_query += f
" WHERE {where}"
453 f
"sql_query = '{sql_query}'",
454 "remove_data_from_table"
457 return self.
sql_pool.run_editing_command(sql_query, table,
"delete")
int insert_data_into_table(self, str table, Union[List[List[str]], List[str]] data, Union[List[str], None] column=None)
Union[int] get_table_size(self, str table, Union[str, List[str]] column, Union[str, List[str]] where="")
int update_data_in_table(self, str table, List[str] data, List column, Union[str, List[str]] where="")
Union[int, List[Dict[str, Any]]] get_data_from_table(self, str table, Union[str, List[str]] column, Union[str, List[str]] where="", bool beautify=True)
int insert_or_update_data_into_table(self, str table, Union[List[List[str]], List[str]] data, Union[List[str], None] columns=None)
SQLInjection sql_injection
None __init__(self, SQLManageConnections sql_pool, int success=0, int error=84, bool debug=False)
Union[int, List[Any]] describe_table(self, str table)
Union[List[str], int] get_table_column_names(self, str table_name)
Union[int, List[str]] get_table_names(self)
SQLSanitiseFunctions sanitize_functions
SQLManageConnections sql_pool
int remove_data_from_table(self, str table, Union[str, List[str]] where="")