ormlambda 1.2.2__py3-none-any.whl → 1.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ormlambda/__init__.py CHANGED
@@ -4,6 +4,7 @@ from .common.enums import ( # noqa: F401
4
4
  ConditionType,
5
5
  )
6
6
 
7
+ from .common.abstract_classes import AbstractSQLStatements # noqa: F401
7
8
  from .common.interfaces import IRepositoryBase # noqa: F401
8
9
  from .utils import Table, Column, ForeignKey # noqa: F401
9
10
  from .utils.lambda_disassembler import Disassembler, nameof # noqa: F401
@@ -1,37 +1,14 @@
1
1
  from __future__ import annotations
2
- from typing import Any, Callable, Optional, Type, override, Iterable, Literal, TYPE_CHECKING
3
- from enum import Enum
2
+ from typing import Any, Type, override, Iterable, Literal, TYPE_CHECKING
4
3
  from collections import defaultdict
5
- from abc import abstractmethod
6
- import inspect
7
4
 
8
- from ormlambda.utils import ForeignKey, Table
9
5
 
6
+ from ormlambda.utils import Table
10
7
  from ormlambda.common.interfaces import IQuery, IRepositoryBase, IStatements_two_generic
11
8
 
12
9
  if TYPE_CHECKING:
13
- from ormlambda.common.interfaces.IStatements import OrderType
14
-
15
- from ormlambda.components.update import UpdateQueryBase
16
10
  from ormlambda.components.select import ISelect
17
- from ormlambda.components.delete import DeleteQueryBase
18
- from ormlambda.components.upsert import UpsertQueryBase
19
11
  from ormlambda.components.select import TableColumn
20
- from ormlambda.components.insert import InsertQueryBase
21
- from ormlambda.components.where.abstract_where import AbstractWhere
22
-
23
- from ormlambda.databases.my_sql.clauses.select import SelectQuery
24
- from ormlambda.databases.my_sql.clauses.count import CountQuery
25
-
26
-
27
- class JoinType(Enum):
28
- RIGHT_INCLUSIVE = "RIGHT JOIN"
29
- LEFT_INCLUSIVE = "LEFT JOIN"
30
- RIGHT_EXCLUSIVE = "RIGHT JOIN"
31
- LEFT_EXCLUSIVE = "LEFT JOIN"
32
- FULL_OUTER_INCLUSIVE = "RIGHT JOIN"
33
- FULL_OUTER_EXCLUSIVE = "RIGHT JOIN"
34
- INNER_JOIN = "INNER JOIN"
35
12
 
36
13
 
37
14
  ORDER_QUERIES = Literal["select", "join", "where", "order", "with", "group by", "limit", "offset"]
@@ -42,7 +19,7 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
42
19
  __order__: tuple[str, ...] = ("select", "join", "where", "order", "with", "group by", "limit", "offset")
43
20
 
44
21
  def __init__(self, model: T, repository: IRepositoryBase[TRepo]) -> None:
45
- self.valid_repository(repository)
22
+ self.__valid_repository(repository)
46
23
 
47
24
  self._model: T = model
48
25
  self._repository: IRepositoryBase[TRepo] = repository
@@ -54,160 +31,17 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
54
31
  raise Exception(f"'{model}' class does not inherit from Table class")
55
32
 
56
33
  @staticmethod
57
- def valid_repository(repository: Any) -> bool:
34
+ def __valid_repository(repository: Any) -> bool:
58
35
  if not isinstance(repository, IRepositoryBase):
59
36
  raise ValueError(f"'repository' attribute does not instance of '{IRepositoryBase.__name__}'")
60
37
  return True
61
38
 
62
- @property
63
- @abstractmethod
64
- def INSERT_QUERY(self) -> Type[InsertQueryBase[T, TRepo]]: ...
65
- @property
66
- @abstractmethod
67
- def UPSERT_QUERY(self) -> Type[UpsertQueryBase[T, TRepo]]: ...
68
- @property
69
- @abstractmethod
70
- def UPDATE_QUERY(self) -> Type[UpdateQueryBase[T, TRepo]]: ...
71
- @property
72
- @abstractmethod
73
- def DELETE_QUERY(self) -> Type[DeleteQueryBase[T, TRepo]]: ...
74
- @property
75
- @abstractmethod
76
- def LIMIT_QUERY(self) -> Type[IQuery]: ...
77
- @property
78
- @abstractmethod
79
- def OFFSET_QUERY(self) -> Type[IQuery]: ...
80
- @property
81
- @abstractmethod
82
- def JOIN_QUERY(self) -> Type[IQuery]: ...
83
- @property
84
- @abstractmethod
85
- def WHERE_QUERY(self) -> Type[IQuery]: ...
86
- @property
87
- @abstractmethod
88
- def ORDER_QUERY(self) -> Type[IQuery]: ...
89
- @property
90
- @abstractmethod
91
- def SELECT_QUERY(self) -> Type[SelectQuery]: ...
39
+ def __repr__(self):
40
+ return f"<Model: {self.__class__.__name__}>"
92
41
 
93
42
  @property
94
- @abstractmethod
95
- def COUNT(self) -> Type[CountQuery]: ...
96
-
97
- @override
98
- def create_table(self) -> None:
99
- if not self._repository.table_exists(self._model.__table_name__):
100
- self._repository.execute(self._model.create_table_query())
101
- return None
102
-
103
- @override
104
- def table_exists(self) -> bool:
105
- return self._repository.table_exists(self._model.__table_name__)
106
-
107
- @override
108
- def insert(self, instances: T | list[T]) -> None:
109
- insert = self.INSERT_QUERY(self._model, self._repository)
110
- insert.insert(instances)
111
- insert.execute()
112
- self._query_list.clear()
113
- return None
114
-
115
- @override
116
- def delete(self, instances: Optional[T | list[T]] = None) -> None:
117
- if instances is None:
118
- response = self.select()
119
- if len(response) == 0:
120
- return None
121
- # [0] because if we do not select anything, we retrieve all columns of the unic model, stored in tuple[tuple[model]] structure.
122
- # We always going to have a tuple of one element
123
- return self.delete(response)
124
-
125
- delete = self.DELETE_QUERY(self._model, self._repository)
126
- delete.delete(instances)
127
- delete.execute()
128
- # not necessary to call self._query_list.clear() because select() method already call it
129
- return None
130
-
131
- @override
132
- def upsert(self, instances: T | list[T]) -> None:
133
- upsert = self.UPSERT_QUERY(self._model, self._repository)
134
- upsert.upsert(instances)
135
- upsert.execute()
136
- self._query_list.clear()
137
- return None
138
-
139
- @override
140
- def update(self, dicc: dict[str, Any] | list[dict[str, Any]]) -> None:
141
- update = self.UPDATE_QUERY(self._model, self._repository, self._query_list["where"])
142
- update.update(dicc)
143
- update.execute()
144
- self._query_list.clear()
145
- return None
146
-
147
43
  @override
148
- def limit(self, number: int) -> "IStatements_two_generic[T,TRepo]":
149
- limit = self.LIMIT_QUERY(number)
150
- # Only can be one LIMIT SQL parameter. We only use the last LimitQuery
151
- limit_list = self._query_list["limit"]
152
- if len(limit_list) > 0:
153
- self._query_list["limit"] = [limit]
154
- else:
155
- self._query_list["limit"].append(limit)
156
- return self
157
-
158
- @override
159
- def offset(self, number: int) -> "IStatements_two_generic[T,TRepo]":
160
- offset = self.OFFSET_QUERY(number)
161
- self._query_list["offset"].append(offset)
162
- return self
163
-
164
- @override
165
- def count(self) -> int:
166
- count_select: IQuery = self.COUNT(self._model)
167
- self._query_list["select"].append(count_select)
168
- query = self.build()
169
- return self.repository.read_sql(query)[0][0]
170
-
171
- @override
172
- def join(self, table_left: Table, table_right: Table, *, by: str) -> "IStatements_two_generic[T,TRepo]":
173
- where = ForeignKey.MAPPED[table_left.__table_name__][table_right.__table_name__]
174
- join_query = self.JOIN_QUERY[table_left, Table](table_left, table_right, JoinType(by), where=where)
175
- self._query_list["join"].append(join_query)
176
- return self
177
-
178
- @override
179
- def where(self, lambda_: Callable[[T], bool] = lambda: None, **kwargs) -> "IStatements_two_generic[T,TRepo]":
180
- # FIXME [x]: I've wrapped self._model into tuple to pass it instance attr. Idk if it's correct
181
- where_query = self.WHERE_QUERY[T](function=lambda_, instances=(self._model,), **kwargs)
182
- self._query_list["where"].append(where_query)
183
- return self
184
-
185
- @override
186
- def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type: OrderType) -> "IStatements_two_generic[T,TRepo]":
187
- order = self.ORDER_QUERY[T](self._model, _lambda_col, order_type)
188
- self._query_list["order"].append(order)
189
- return self
190
-
191
- @override
192
- def select[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] = lambda: None, *, flavour: Optional[Type[TFlavour]] = None, by: JoinType = JoinType.INNER_JOIN):
193
- if len(inspect.signature(selector).parameters) == 0:
194
- # COMMENT: if we do not specify any lambda function we assumed the user want to retreive only elements of the Model itself avoiding other models
195
- result = self.select(selector=lambda x: (x,), flavour=flavour, by=by)
196
- # COMMENT: Always we want to retrieve tuple[tuple[Any]]. That's the reason to return result[0] when we ensure the user want only objects of the first table.
197
- # Otherwise, we wil return the result itself
198
- if flavour:
199
- return result
200
- return () if not result else result[0]
201
- select: ISelect = self.SELECT_QUERY(self._model, select_lambda=selector, by=by)
202
- self._query_list["select"].append(select)
203
-
204
- query: str = self.build()
205
- if flavour:
206
- result = self._return_flavour(query, flavour)
207
- if issubclass(flavour, tuple) and isinstance(selector(self._model), property):
208
- return tuple([x[0] for x in result])
209
- return result
210
- return self._return_model(select, query)
44
+ def repository(self) -> IRepositoryBase[TRepo]: ...
211
45
 
212
46
  def _return_flavour[TValue](self, query, flavour: Type[TValue]) -> tuple[TValue]:
213
47
  return self._repository.read_sql(query, flavour=flavour)
@@ -220,72 +54,6 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
220
54
 
221
55
  return response_sql
222
56
 
223
- @override
224
- def select_one[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] = lambda: None, *, flavour: Optional[Type[TFlavour]] = None, by: JoinType = JoinType.INNER_JOIN):
225
- self.limit(1)
226
- if len(inspect.signature(selector).parameters) == 0:
227
- response = self.select(selector=lambda x: (x,), flavour=flavour, by=by)
228
- else:
229
- response = self.select(selector=selector, flavour=flavour, by=by)
230
-
231
- if flavour:
232
- return response[0] if response else None
233
-
234
- # response var could be return more than one element when we work with models an we
235
- # select columns from different tables using a join query
236
- if len(response) == 1 and len(response[0]) == 1:
237
- return response[0][0]
238
- return tuple([res[0] for res in response])
239
-
240
- @override
241
- def build(self) -> str:
242
- query: str = ""
243
-
244
- self._create_necessary_inner_join()
245
- for x in self.__order__:
246
- if sub_query := self._query_list.get(x, None):
247
- if isinstance(sub_query[0], self.WHERE_QUERY):
248
- query_ = self.__build_where_clause(sub_query)
249
-
250
- # we must check if any join already exists on query string
251
- elif isinstance(sub_query[0], self.JOIN_QUERY):
252
- select_query: str = self._query_list["select"][0].query
253
- query_ = ""
254
- for join in sub_query:
255
- if join.query not in select_query:
256
- query_ += f"\n{join.query}"
257
- else:
258
- query_ = "\n".join([x.query for x in sub_query])
259
-
260
- query += f"\n{query_}" if query != "" else query_
261
- self._query_list.clear()
262
- return query
263
-
264
- def __build_where_clause(self, where_condition: list[AbstractWhere]) -> str:
265
- query: str = where_condition[0].query
266
-
267
- for where in where_condition[1:]:
268
- q = where.query.replace(where.WHERE, "AND")
269
- and_, clause = q.split(" ", maxsplit=1)
270
- query += f" {and_} ({clause})"
271
- return query
272
-
273
- def _create_necessary_inner_join(self) -> None:
274
- # When we applied filters in any table that we wont select any column, we need to add manually all neccessary joins to achieve positive result.
275
- if "where" not in self._query_list:
276
- return None
277
-
278
- where: AbstractWhere = self._query_list["where"][0]
279
- involved_tables = where.get_involved_tables()
280
-
281
- select: ISelect = self._query_list["select"][0]
282
- if not involved_tables or (set(involved_tables) == set(select.tables_heritage)):
283
- return None
284
-
285
- for l_tbl, r_tbl in involved_tables:
286
- # FIXME [ ]: Checked what function was called by the self.join method before the change
287
- self.join(l_tbl, r_tbl, by="INNER JOIN")
288
-
289
57
 
290
58
  class ClusterQuery:
291
59
  def __init__(self, select: ISelect, response_sql: tuple[dict[str, Any]]) -> None:
@@ -25,7 +25,7 @@ class IRepositoryBase[T](ABC):
25
25
  def is_connected(self) -> bool: ...
26
26
 
27
27
  @abstractmethod
28
- def connect(self, **kwargs: Any) -> "IRepositoryBase[T]": ...
28
+ def connect(self, **kwargs: Any) -> None: ...
29
29
 
30
30
  @abstractmethod
31
31
  def close_connection(self) -> None: ...
@@ -85,7 +85,7 @@ class MySQLRepository(IRepositoryBase[MySQLConnection]):
85
85
  return self._connection.is_connected()
86
86
 
87
87
  @override
88
- def connect(self) -> IRepositoryBase[MySQLConnection]:
88
+ def connect(self) -> None:
89
89
  # return MySQLConnectionPool(pool_name="mypool", pool_size=5, **kwargs)
90
90
  self._connection.connect(**self._data_config)
91
91
  return None
@@ -1,14 +1,18 @@
1
1
  from __future__ import annotations
2
- from typing import override, Type, TYPE_CHECKING
2
+ from typing import override, Type, TYPE_CHECKING, Any, Callable, Optional
3
3
 
4
4
  if TYPE_CHECKING:
5
5
  from ormlambda import Table
6
6
  from ormlambda.components.select import ISelect
7
+ from ormlambda.components.where.abstract_where import AbstractWhere
8
+ from ormlambda.common.interfaces.IStatements import OrderType
9
+ from ormlambda.common.interfaces import IQuery, IRepositoryBase, IStatements_two_generic
10
+
11
+ from ormlambda.databases.my_sql.clauses.select import SelectQuery
12
+ from ormlambda.databases.my_sql.clauses.count import CountQuery
7
13
 
8
- from ormlambda.common.abstract_classes import AbstractSQLStatements
9
-
10
- from ormlambda.common.interfaces import IQuery, IRepositoryBase
11
14
 
15
+ from ormlambda import AbstractSQLStatements
12
16
  from .clauses import DeleteQuery
13
17
  from .clauses import InsertQuery
14
18
  from .clauses import JoinSelector
@@ -24,72 +28,200 @@ from .clauses import CountQuery
24
28
  from mysql.connector import MySQLConnection
25
29
 
26
30
 
31
+
32
+ import inspect
33
+
34
+ from ormlambda.utils import ForeignKey, Table
35
+ from ormlambda.common.enums import JoinType
36
+
37
+
38
+
27
39
  class MySQLStatements[T: Table](AbstractSQLStatements[T, MySQLConnection]):
28
40
  def __init__(self, model: T, repository: IRepositoryBase[MySQLConnection]) -> None:
29
41
  super().__init__(model, repository=repository)
30
42
 
31
- # region Private methods
32
- def __repr__(self):
33
- return f"<Model: {self.__class__.__name__}>"
43
+ @property
44
+ @override
45
+ def repository(self) -> IRepositoryBase[MySQLConnection]:
46
+ return self._repository
34
47
 
35
- # endregion
48
+ @override
49
+ def create_table(self) -> None:
50
+ if not self._repository.table_exists(self._model.__table_name__):
51
+ self._repository.execute(self._model.create_table_query())
52
+ return None
36
53
 
37
- @property
38
54
  @override
39
- def INSERT_QUERY(self) -> Type[InsertQuery]:
40
- return InsertQuery
55
+ def table_exists(self) -> bool:
56
+ return self._repository.table_exists(self._model.__table_name__)
41
57
 
42
- @property
43
58
  @override
44
- def UPSERT_QUERY(self) -> Type[UpsertQuery]:
45
- return UpsertQuery
59
+ def insert(self, instances: T | list[T]) -> None:
60
+ insert = InsertQuery(self._model, self._repository)
61
+ insert.insert(instances)
62
+ insert.execute()
63
+ self._query_list.clear()
64
+ return None
46
65
 
47
- @property
48
66
  @override
49
- def UPDATE_QUERY(self) -> Type[UpsertQuery]:
50
- return UpdateQuery
67
+ def delete(self, instances: Optional[T | list[T]] = None) -> None:
68
+ if instances is None:
69
+ response = self.select()
70
+ if len(response) == 0:
71
+ return None
72
+ # [0] because if we do not select anything, we retrieve all columns of the unic model, stored in tuple[tuple[model]] structure.
73
+ # We always going to have a tuple of one element
74
+ return self.delete(response)
75
+
76
+ delete = DeleteQuery(self._model, self._repository)
77
+ delete.delete(instances)
78
+ delete.execute()
79
+ # not necessary to call self._query_list.clear() because select() method already call it
80
+ return None
51
81
 
52
82
  @override
53
- @property
54
- def DELETE_QUERY(self) -> Type[DeleteQuery]:
55
- return DeleteQuery
83
+ def upsert(self, instances: T | list[T]) -> None:
84
+ upsert = UpsertQuery(self._model, self._repository)
85
+ upsert.upsert(instances)
86
+ upsert.execute()
87
+ self._query_list.clear()
88
+ return None
56
89
 
57
- @property
58
90
  @override
59
- def LIMIT_QUERY(self) -> Type[IQuery]:
60
- return LimitQuery
91
+ def update(self, dicc: dict[str, Any] | list[dict[str, Any]]) -> None:
92
+ update = UpdateQuery(self._model, self._repository, self._query_list["where"])
93
+ update.update(dicc)
94
+ update.execute()
95
+ self._query_list.clear()
96
+ return None
61
97
 
62
- @property
63
98
  @override
64
- def OFFSET_QUERY(self) -> Type[IQuery]:
65
- return OffsetQuery
99
+ def limit(self, number: int) -> IStatements_two_generic[T, MySQLConnection]:
100
+ limit = LimitQuery(number)
101
+ # Only can be one LIMIT SQL parameter. We only use the last LimitQuery
102
+ limit_list = self._query_list["limit"]
103
+ if len(limit_list) > 0:
104
+ self._query_list["limit"] = [limit]
105
+ else:
106
+ self._query_list["limit"].append(limit)
107
+ return self
66
108
 
67
- @property
68
109
  @override
69
- def COUNT(self) -> int:
70
- return CountQuery
110
+ def offset(self, number: int) -> IStatements_two_generic[T, MySQLConnection]:
111
+ offset = OffsetQuery(number)
112
+ self._query_list["offset"].append(offset)
113
+ return self
71
114
 
72
- @property
73
115
  @override
74
- def JOIN_QUERY(self) -> Type[IQuery]:
75
- return JoinSelector
116
+ def count(self) -> int:
117
+ count_select: IQuery = CountQuery(self._model)
118
+ self._query_list["select"].append(count_select)
119
+ query = self.build()
120
+ return self.repository.read_sql(query)[0][0]
76
121
 
77
- @property
78
122
  @override
79
- def WHERE_QUERY(self) -> Type[IQuery]:
80
- return WhereCondition
123
+ def join(self, table_left: Table, table_right: Table, *, by: str) -> IStatements_two_generic[T, MySQLConnection]:
124
+ where = ForeignKey.MAPPED[table_left.__table_name__][table_right.__table_name__]
125
+ join_query = JoinSelector[table_left, Table](table_left, table_right, JoinType(by), where=where)
126
+ self._query_list["join"].append(join_query)
127
+ return self
81
128
 
82
- @property
83
129
  @override
84
- def ORDER_QUERY(self) -> Type[IQuery]:
85
- return OrderQuery
130
+ def where(self, lambda_: Callable[[T], bool] = lambda: None, **kwargs) -> IStatements_two_generic[T, MySQLConnection]:
131
+ # FIXME [x]: I've wrapped self._model into tuple to pass it instance attr. Idk if it's correct
132
+ where_query = WhereCondition[T](function=lambda_, instances=(self._model,), **kwargs)
133
+ self._query_list["where"].append(where_query)
134
+ return self
86
135
 
87
- @property
88
136
  @override
89
- def SELECT_QUERY(self) -> Type[ISelect]:
90
- return SelectQuery
137
+ def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type: OrderType) -> IStatements_two_generic[T, MySQLConnection]:
138
+ order = OrderQuery[T](self._model, _lambda_col, order_type)
139
+ self._query_list["order"].append(order)
140
+ return self
91
141
 
92
- @property
93
142
  @override
94
- def repository(self) -> IRepositoryBase[MySQLConnection]:
95
- return self._repository
143
+ def select[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] = lambda: None, *, flavour: Optional[Type[TFlavour]] = None, by: JoinType = JoinType.INNER_JOIN):
144
+ if len(inspect.signature(selector).parameters) == 0:
145
+ # COMMENT: if we do not specify any lambda function we assumed the user want to retreive only elements of the Model itself avoiding other models
146
+ result = self.select(selector=lambda x: (x,), flavour=flavour, by=by)
147
+ # COMMENT: Always we want to retrieve tuple[tuple[Any]]. That's the reason to return result[0] when we ensure the user want only objects of the first table.
148
+ # Otherwise, we wil return the result itself
149
+ if flavour:
150
+ return result
151
+ return () if not result else result[0]
152
+ select: ISelect = SelectQuery(self._model, select_lambda=selector, by=by)
153
+ self._query_list["select"].append(select)
154
+
155
+ query: str = self.build()
156
+ if flavour:
157
+ result = self._return_flavour(query, flavour)
158
+ if issubclass(flavour, tuple) and isinstance(selector(self._model), property):
159
+ return tuple([x[0] for x in result])
160
+ return result
161
+ return self._return_model(select, query)
162
+
163
+ @override
164
+ def select_one[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] = lambda: None, *, flavour: Optional[Type[TFlavour]] = None, by: JoinType = JoinType.INNER_JOIN):
165
+ self.limit(1)
166
+ if len(inspect.signature(selector).parameters) == 0:
167
+ response = self.select(selector=lambda x: (x,), flavour=flavour, by=by)
168
+ else:
169
+ response = self.select(selector=selector, flavour=flavour, by=by)
170
+
171
+ if flavour:
172
+ return response[0] if response else None
173
+
174
+ # response var could be return more than one element when we work with models an we
175
+ # select columns from different tables using a join query
176
+ if len(response) == 1 and len(response[0]) == 1:
177
+ return response[0][0]
178
+ return tuple([res[0] for res in response])
179
+
180
+ @override
181
+ def build(self) -> str:
182
+ query: str = ""
183
+
184
+ self.__create_necessary_inner_join()
185
+ for x in self.__order__:
186
+ if sub_query := self._query_list.get(x, None):
187
+ if isinstance(sub_query[0], WhereCondition):
188
+ query_ = self.__build_where_clause(sub_query)
189
+
190
+ # we must check if any join already exists on query string
191
+ elif isinstance(sub_query[0], JoinSelector):
192
+ select_query: str = self._query_list["select"][0].query
193
+ query_ = ""
194
+ for join in sub_query:
195
+ if join.query not in select_query:
196
+ query_ += f"\n{join.query}"
197
+ else:
198
+ query_ = "\n".join([x.query for x in sub_query])
199
+
200
+ query += f"\n{query_}" if query != "" else query_
201
+ self._query_list.clear()
202
+ return query
203
+
204
+ def __build_where_clause(self, where_condition: list[AbstractWhere]) -> str:
205
+ query: str = where_condition[0].query
206
+
207
+ for where in where_condition[1:]:
208
+ q = where.query.replace(where.WHERE, "AND")
209
+ and_, clause = q.split(" ", maxsplit=1)
210
+ query += f" {and_} ({clause})"
211
+ return query
212
+
213
+ def __create_necessary_inner_join(self) -> None:
214
+ # When we applied filters in any table that we wont select any column, we need to add manually all neccessary joins to achieve positive result.
215
+ if "where" not in self._query_list:
216
+ return None
217
+
218
+ where: AbstractWhere = self._query_list["where"][0]
219
+ involved_tables = where.get_involved_tables()
220
+
221
+ select: ISelect = self._query_list["select"][0]
222
+ if not involved_tables or (set(involved_tables) == set(select.tables_heritage)):
223
+ return None
224
+
225
+ for l_tbl, r_tbl in involved_tables:
226
+ # FIXME [ ]: Checked what function was called by the self.join method before the change
227
+ self.join(l_tbl, r_tbl, by="INNER JOIN")
ormlambda/model_base.py CHANGED
@@ -10,7 +10,7 @@ from .databases.my_sql import MySQLStatements, MySQLRepository
10
10
  # endregion
11
11
 
12
12
 
13
- class BaseModel[T: Table]:
13
+ class BaseModel[T: Type[Table]]:
14
14
  """
15
15
  Class to select the correct AbstractSQLStatements class depends on the repository.
16
16
 
@@ -27,7 +27,7 @@ class BaseModel[T: Table]:
27
27
  cls: AbstractSQLStatements[T, TRepo] = cls.statements_dicc.get(type(repository), None)
28
28
 
29
29
  if not cls:
30
- raise Exception(f"Repository selected does not exits '{repository}'")
30
+ raise Exception(f"The selected repository '{repository}' does not exist.")
31
31
 
32
32
  self = object().__new__(cls)
33
33
  cls.__init__(self, model, repository)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ormlambda
3
- Version: 1.2.2
3
+ Version: 1.3.0
4
4
  Summary: ORM designed to interact with the database (currently with MySQL) using lambda functions and nested functions
5
5
  Author: p-hzamora
6
6
  Author-email: p.hzamora@icloud.com
@@ -1,7 +1,7 @@
1
- ormlambda/__init__.py,sha256=eAkyO2ZnXFDZfquCiSGmh_kblT-WapEDd4ZnnfS0fOo,465
1
+ ormlambda/__init__.py,sha256=L-Enc4FPmW3ldBMnWOU3gLn9i4FEc7sQzLWy2mIEti8,538
2
2
  ormlambda/common/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
3
3
  ormlambda/common/abstract_classes/__init__.py,sha256=tk2J4Mn_nD-1ZjtMVBE5FH7KR_8ppN_1Kx1s6c38GjM,167
4
- ormlambda/common/abstract_classes/abstract_model.py,sha256=0ksGlFS2HBoN2ImNod944xBBE3xm2j91pxdHSXh7dVk,13533
4
+ ormlambda/common/abstract_classes/abstract_model.py,sha256=Eguy4jQQdLAKvYZgDqUB1V4driBsYoiDuyPZ-DwPi5A,3867
5
5
  ormlambda/common/abstract_classes/non_query_base.py,sha256=5jhvyT7OZaJxlGp9XMP3vQ4ei5QQZBn-fFtJnD640mE,980
6
6
  ormlambda/common/abstract_classes/query_base.py,sha256=6qUFPwsVx45kUW3b66pHiSyjhcH4mzbdkddlGeUnG7c,266
7
7
  ormlambda/common/enums/__init__.py,sha256=4lVKCHi1JalwgNzjsAXqX-C54NJEH83y2v5baMO8fN4,103
@@ -9,7 +9,7 @@ ormlambda/common/enums/condition_types.py,sha256=mDPMrtzZu4IYv3-q5Zw4NNgwUoNAx4l
9
9
  ormlambda/common/enums/join_type.py,sha256=7LEhE34bzYOwJxe8yxPJo_EjQpGylgClAPX1Wt3z4n4,292
10
10
  ormlambda/common/interfaces/INonQueryCommand.py,sha256=7CjLW4sKqkR5zUIGvhRXOtzTs6vypJW1a9EJHlgCw2c,260
11
11
  ormlambda/common/interfaces/IQueryCommand.py,sha256=hfzCosK4-n8RJIb2PYs8b0qU3TNmfYluZXBf47KxxKs,331
12
- ormlambda/common/interfaces/IRepositoryBase.py,sha256=ABdecwq4G_Gg4wvjpj7LWDntdjRmcMMLWOuG2pfAqfg,1939
12
+ ormlambda/common/interfaces/IRepositoryBase.py,sha256=UAnt_ZFwfyx6vDXiWoF69rqbLySirhDlVEghMYzuDJ0,1923
13
13
  ormlambda/common/interfaces/IStatements.py,sha256=tDQ7LviuNOCPCblSCvpnwSC5dyygWVpQ_TvxtJ2Jzp4,9628
14
14
  ormlambda/common/interfaces/__init__.py,sha256=4tthR8pNIHGvgu0n7i3ZEQYP_R3wmqh40l34cAZbM2o,244
15
15
  ormlambda/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -47,9 +47,9 @@ ormlambda/databases/my_sql/clauses/select.py,sha256=fUeyh2FKud1FOWUGrZCiX-Q2YAcC
47
47
  ormlambda/databases/my_sql/clauses/update.py,sha256=3Htw0_PT3EckEiF214-V2r63lcNoRBroKZI9yg48Ddg,1867
48
48
  ormlambda/databases/my_sql/clauses/upsert.py,sha256=eW2pQ4ax-GKuXiaWKoSRSS1GrHuILJBsmj83ADbBQ34,1951
49
49
  ormlambda/databases/my_sql/clauses/where_condition.py,sha256=eG514q4Boc2HCZl9MlI5vBKhwQHS9ANpHcTFgLw85vw,8314
50
- ormlambda/databases/my_sql/repository.py,sha256=2fgejhGcI48XfUMpTAJrT-PPnNHTaaEiOW8Y5wRv3yc,7191
51
- ormlambda/databases/my_sql/statements.py,sha256=1umK_89JWIfViz1cHfTwqIOvMkYZT2IijDiNRmbUvJ4,2300
52
- ormlambda/model_base.py,sha256=jH3MTAsVF3V2jXvtKCtpAC-Q102UfBPZ0YiM0nqp-6M,1053
50
+ ormlambda/databases/my_sql/repository.py,sha256=xKbtitr2R7V89La_hL1TE-sexfQqw-s5N51SIuCXH7I,7163
51
+ ormlambda/databases/my_sql/statements.py,sha256=3WKlQrxSksceJQXeGh16DRu-Upr_lsY9JZpt4bB2kwk,9452
52
+ ormlambda/model_base.py,sha256=x7PUPNslRh4hTNsDDUwuh_maKjEFsHIvee4a6rcyNV8,1064
53
53
  ormlambda/utils/__init__.py,sha256=ywMdWqmA2jHj19-W-S04yfaYF5hv4IZ1lZDq0B8Jnjs,142
54
54
  ormlambda/utils/column.py,sha256=5FAGzCU4yvNS4MhwJJ5i73h7RvHD5UCVox0NdzMsMiE,1945
55
55
  ormlambda/utils/dtypes.py,sha256=1kRsT5JggNS1DMWgSUdBb67CefQHnZ-VTN1WI7nN2yQ,7879
@@ -65,7 +65,7 @@ ormlambda/utils/module_tree/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
65
65
  ormlambda/utils/module_tree/dfs_traversal.py,sha256=lSF03G63XtJFLp03ueAmsHMBvhUkjptDbK3IugXm8iU,1425
66
66
  ormlambda/utils/module_tree/dynamic_module.py,sha256=zwvjU3U2cz6H2CDp9Gncs5D5bSAyfITNa2SDqFDl8rw,8551
67
67
  ormlambda/utils/table_constructor.py,sha256=I2oFTfa6BPTILY6UDYGZy4fJxZazZMkH89NObkfRemo,11480
68
- ormlambda-1.2.2.dist-info/LICENSE,sha256=xBprFw8GJLdHMOoUqDk0427EvjIcbEREvXXVFULuuXU,1080
69
- ormlambda-1.2.2.dist-info/METADATA,sha256=HkOi6OeDGnCuKDg9FOMaEgYuCvO2iMZrPuVkvw8RBsA,8428
70
- ormlambda-1.2.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
71
- ormlambda-1.2.2.dist-info/RECORD,,
68
+ ormlambda-1.3.0.dist-info/LICENSE,sha256=xBprFw8GJLdHMOoUqDk0427EvjIcbEREvXXVFULuuXU,1080
69
+ ormlambda-1.3.0.dist-info/METADATA,sha256=npu-nY-qxCZebgn5C1oXA87apBV-z3Vnsv75OEumy3w,8428
70
+ ormlambda-1.3.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
71
+ ormlambda-1.3.0.dist-info/RECORD,,