Skip to content

Commit f091561

Browse files
Add files via upload
1 parent f2a6200 commit f091561

File tree

5 files changed

+1492
-0
lines changed

5 files changed

+1492
-0
lines changed

__init__.py

Whitespace-only changes.

backend.py

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
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

Comments
 (0)