1+ import mysql .connector
2+ from typing import Union
3+ from uuid import uuid4
4+ from components import *
5+
6+ class Connector :
7+ """
8+ Represents the MySQL connector. This is the parent class of MySQL.
9+ """
10+ def __init__ (self , credentials : dict , * , concatenate : bool = False ) -> None :
11+ self .credentials = dict ()
12+ self .concatenate = concatenate
13+ self .connector = None
14+ self .session_id = uuid4 ()
15+ self .__ALLOWED_KEYS__ = (
16+ "host" ,
17+ "user" ,
18+ "password" ,
19+ "database" ,
20+ "port"
21+ )
22+
23+ self .results = []
24+
25+ if all (key in self .__ALLOWED_KEYS__ for key in credentials .keys ()):
26+ for key , val in credentials .items ():
27+ self .credentials [key ] = val
28+
29+ def __get_credentials__ (self ) -> dict :
30+ return self .credentials
31+
32+ def build (self ):
33+ self .connector = mysql .connector .connect (** self .credentials )
34+ return self
35+
36+ class MySQL (Connector ):
37+ """
38+ Represents a MySQL instance.
39+ """
40+ def __init__ (self , credentials : dict , * , concatenate : bool = False ) -> None :
41+ super ().__init__ (credentials , concatenate = concatenate )
42+ self .build ()
43+ self .query = Query ()
44+
45+ def EXECUTE (self , query : Union [SelectQuery , InsertQuery , UpdateQuery , DeleteQuery , str ], * args ):
46+ """
47+ Execute a `MySQL` query. It can take a custom SQL query string, or a `SelectQuery`, `InsertQuery`, `UpdateQuery`, `DeleteQuery`.
48+
49+ ```
50+ mysql = MySQL(...)
51+ mysql.EXECUTE("SELECT * FROM TABLE;")
52+ ```
53+
54+ or you can access the MySQL query builder `MySQL.query`:
55+
56+ ```
57+ mysql.query.Select(...)
58+ mysql.query.From(...)
59+ query = mysql.query.build()
60+ mysql.EXECUTE(query)
61+ ```
62+ """
63+ self .connector ._open_connection ()
64+ cursor = self .connector .cursor ()
65+ cursor .execute (query )
66+ results = []
67+ if isinstance (query , SelectQuery ) or query .upper ().startswith ("SELECT" ):
68+ results = cursor .fetchall ()
69+ cursor .close ()
70+ self .connector .close ()
71+ return results
72+
73+ def CREATE_TABLE (self ,
74+ TABLE : Union [str , Table ],
75+ COLUMNS : list [ColumnType ] = None ,
76+ CONSTRAINTS : list [ConstraintType ] = None ,
77+ IF_NOT_EXISTS : bool = False ) -> Table :
78+ """
79+ MySQL `CREATE TABLE` query method. Use this method to create a new table in your database.
80+
81+ ```
82+ >> mysql = MySQL(...)
83+ >> mysql.CREATE_TABLE("TABLE", [ColumnType(...), ...], IF_NOT_EXISTS = True)
84+ ```
85+
86+ or make use of the `Table` builder class from `mysqlhelper.components`:
87+
88+ ```
89+ >> table = Table(
90+ name = "TABLE",
91+ columns = [
92+ ColumnType(...),
93+ ...
94+ ],
95+ constraints = ...,
96+ if_not_exists = ...
97+ )
98+ >> mysql.CREATE_TABLE(table)
99+ ```
100+ """
101+
102+ if isinstance (TABLE , Table ):
103+ table = TABLE
104+ else :
105+ table = Table (
106+ name = TABLE ,
107+ columns = COLUMNS ,
108+ constraints = CONSTRAINTS ,
109+ if_not_exists = IF_NOT_EXISTS
110+ )
111+
112+ query = self .query .createTable (table )
113+
114+ self .EXECUTE (query )
115+
116+ return table
117+
118+ def SELECT (self ,
119+ COLUMNS : list [Union [ColumnType , AggregateFunctionType , str ]],
120+ FROM : Union [Table , MySqlMethod , str ],
121+ WHERE : Union [str , list [str ]] = None ,
122+ JOIN : Union [list , tuple ] = None ,
123+ GROUP_BY : Union [str , ColumnType ] = None ,
124+ HAVING : Union [list [Union [OperatorMethod [Union [AggregateFunctionType , ColumnType , str ], str ], str ]], str ] = None ,
125+ ORDER_BY : Union [ColumnType , AggregateFunctionType , str ] = None
126+ ):
127+ """
128+ Represents the MySQL `SELECT` statement.
129+
130+ Parameters
131+ ----------
132+ - `COLUMNS`: `list[ColumnType|AggregateFunctionType|str]` A list of columns.
133+ - `FROM`: `Table|MySqlMethod|str` Table you want to select from.
134+ - `WHERE`: `str|list[str]` (Optional) Condition(s) for the `SELECT` statement.
135+ - `JOIN`. `list|tuple` (Optional) Join two tables. Note: You must specify the following in the correct order `JOIN_TYPE`, `LEFT_TABLE` and `RIGHT_TABLE` e.g. `("INNER", table1, table2)`.
136+ - `GROUP_BY`: `str|ColumnType` (Optional) MySQL `GROUP BY` statement to aggregate rows by each unique value.
137+ - `HAVING`: `list[OperatorMethod|str]|str` (Optional) Can only be used if `GROUP_BY` is defined. MySQL `HAVING` statement used to filter aggregated columns.
138+ - `ORDER_BY`: `ColumnType|AggregateFunctionType|str` (Optional) Order table with respect to a given column or aggregator.
139+
140+ Returns
141+ -------
142+ Returns `MySQLMethod`, which contains information about the executed query. The `get_results` method returns the query response. The `get` method returns the query.
143+ """
144+
145+ self .query .Select (columns = COLUMNS )
146+ if JOIN :
147+ try :
148+ self .query .From (self .query .JOIN (* JOIN ))
149+ except :
150+ raise ValueError ("Please double check that your JOIN iterable is correct. Must be of length 5: [JOIN TYPE, LEFT TABLE, RIGHT TABLE, ON LEFT, ON RIGHT]." )
151+ else :
152+ if isinstance (FROM , MySqlMethod ) and FROM .__methodname__ ().lower () == "select" :
153+ FROM = FROM .get ()
154+ self .query .From (FROM )
155+
156+ if WHERE : self .query .Where (WHERE )
157+ if GROUP_BY : self .query .groupBy (GROUP_BY )
158+ if HAVING : self .query .Having (HAVING )
159+ if ORDER_BY : self .query .orderBy (ORDER_BY )
160+
161+ query = self .query .build ()
162+ results = self .EXECUTE (query )
163+
164+ return MySqlMethod (query , "select" , results )
165+
166+ def INSERT (self , INTO : Union [Table , str ],
167+ COLUMNS : list [Union [ColumnType , str ]],
168+ VALUES : Union [list , MySqlMethod ]
169+ ):
170+ """
171+ Represents the MySQL `INSERT` statement.
172+
173+ Parameters
174+ ----------
175+ - `INTO`: `Table|str` The table to insert into.
176+ - `COLUMNS`: `list[ColumnType|str]` The columns that are being considered.
177+ - `VALUES`: `list|MySqlMethod` The values to be inserted into the table or a `SELECT` query. The latter will copy all the values from one table to the other.
178+
179+ Returns
180+ -------
181+ Returns `MySQLMethod`, which contains information about the executed query. The `get` method returns the query.
182+ """
183+
184+ self .query .Insert (INTO , COLUMNS )
185+ self .query .Values (VALUES )
186+
187+ query = self .query .build ()
188+ self .EXECUTE (query )
189+
190+ return MySqlMethod (query , "insert" )
191+
192+ def UPDATE (self ,
193+ TABLE : Union [Table , str ],
194+ SET : list [tuple [Union [ColumnType , str ], Union [str , int , float , datetime ]]],
195+ WHERE : Union [str , list [str ]] = None
196+ ):
197+ """
198+ Represents the MySQL `UPDATE` statement.
199+
200+ Parameters
201+ ----------
202+ - `TABLE`: `Table|str` The table to update.
203+ - `SET`: `list[ColumnType|str, str|int|float|datetime]` The update values.
204+ - `WHERE`: `str|list[str]` (Optional) Condition(s) for the `INSERT` statement.
205+
206+ Returns
207+ -------
208+ Returns `MySQLMethod`, which contains information about the executed query. The `get` method returns the query.
209+ """
210+
211+ self .query .Update (TABLE )
212+ self .query .Set (SET )
213+ if WHERE : self .query .Where (WHERE )
214+
215+ query = self .query .build ()
216+
217+ self .EXECUTE (query )
218+
219+ return MySqlMethod (query , "update" )
220+
221+ def DELETE (self ,
222+ FROM : Union [Table , str , SelectQuery ],
223+ WHERE : Union [str , list [str ]]):
224+ """
225+ Represents the MySQL `DELETE` statement.
226+
227+ Parameters
228+ ----------
229+ - `FROM`: `Table|str|SelectQuery` Table to delete from.
230+ - `WHERE`: `str|list[str]` (Options) Condition for the `DELETE` statement. Note: If it is not passed, all the rows will be deleted.
231+
232+ Returns
233+ -------
234+ Returns `MySQLMethod`, which contains information about the executed query. The `get` method returns the query.
235+ """
236+
237+ self .query .Delete (self .query .From (FROM , record = False ), self .query .Where (WHERE , record = False ))
238+ query = self .query .build ()
239+ self .EXECUTE (query )
240+
241+ return MySqlMethod (query , "delete" )
242+
243+ def DROP_TABLE (self ,
244+ TABLE : Union [Table , str ]) -> bool :
245+ """
246+ Represents the MySQL `DROP TABLE` statement.
247+
248+ Parameters
249+ ----------
250+ - `TABLE`: `Table|str` Table to drop.
251+
252+ Returns
253+ -------
254+ Returns `True` on success.
255+ """
256+
257+ self .EXECUTE (self .query .dropTable (TABLE ))
258+
259+ return True
0 commit comments