ormlambda 2.8.0__py3-none-any.whl → 2.9.4__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 +18 -9
- ormlambda/common/abstract_classes/abstract_model.py +39 -26
- ormlambda/common/abstract_classes/decomposition_query.py +124 -86
- ormlambda/common/errors/__init__.py +3 -0
- ormlambda/common/interfaces/ICustomAlias.py +4 -0
- ormlambda/common/interfaces/IDecompositionQuery.py +5 -1
- ormlambda/common/interfaces/IRepositoryBase.py +1 -1
- ormlambda/common/interfaces/IStatements.py +109 -47
- ormlambda/databases/my_sql/clauses/alias.py +31 -0
- ormlambda/databases/my_sql/clauses/group_by.py +2 -2
- ormlambda/databases/my_sql/clauses/insert.py +24 -12
- ormlambda/databases/my_sql/clauses/joins.py +39 -1
- ormlambda/databases/my_sql/clauses/order.py +31 -17
- ormlambda/databases/my_sql/clauses/select.py +19 -12
- ormlambda/databases/my_sql/clauses/update.py +11 -17
- ormlambda/databases/my_sql/repository.py +79 -18
- ormlambda/databases/my_sql/statements.py +76 -53
- ormlambda/model_base.py +3 -3
- ormlambda/utils/column.py +52 -13
- ormlambda/utils/dtypes.py +4 -12
- ormlambda/utils/fields.py +60 -0
- ormlambda/utils/table_constructor.py +67 -95
- {ormlambda-2.8.0.dist-info → ormlambda-2.9.4.dist-info}/METADATA +3 -2
- {ormlambda-2.8.0.dist-info → ormlambda-2.9.4.dist-info}/RECORD +26 -22
- {ormlambda-2.8.0.dist-info → ormlambda-2.9.4.dist-info}/LICENSE +0 -0
- {ormlambda-2.8.0.dist-info → ormlambda-2.9.4.dist-info}/WHEEL +0 -0
@@ -1,7 +1,8 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
-
from typing import Any, Callable, Iterable, Optional, Literal, Type, Union, overload, TYPE_CHECKING
|
2
|
+
from typing import Any, Callable, Iterable, Optional, Literal, Type, Union, overload, TYPE_CHECKING
|
3
3
|
from enum import Enum
|
4
4
|
from abc import abstractmethod, ABC
|
5
|
+
import enum
|
5
6
|
|
6
7
|
from .IRepositoryBase import IRepositoryBase
|
7
8
|
from ormlambda.common.enums import JoinType
|
@@ -10,19 +11,54 @@ if TYPE_CHECKING:
|
|
10
11
|
from ormlambda import Table
|
11
12
|
from .IAggregate import IAggregate
|
12
13
|
|
13
|
-
|
14
|
+
|
15
|
+
class OrderType(enum.Enum):
|
16
|
+
ASC = "ASC"
|
17
|
+
DESC = "DESC"
|
18
|
+
|
19
|
+
|
20
|
+
type OrderTypes = Literal["ASC", "DESC"] | OrderType | Iterable[OrderType]
|
21
|
+
|
22
|
+
|
23
|
+
type Tuple[T] = tuple[T, ...]
|
24
|
+
|
25
|
+
type SelectRes1[T1] = tuple[Tuple[T1]]
|
26
|
+
type SelectRes2[T1, T2] = tuple[*SelectRes1[T1], Tuple[T2]]
|
27
|
+
type SelectRes3[T1, T2, T3] = tuple[*SelectRes2[T1, T2], Tuple[T3]]
|
28
|
+
type SelectRes4[T1, T2, T3, T4] = tuple[*SelectRes3[T1, T2, T3], Tuple[T4]]
|
29
|
+
type SelectRes5[T1, T2, T3, T4, T5] = tuple[*SelectRes4[T1, T2, T3, T4], Tuple[T5]]
|
30
|
+
type SelectRes6[T1, T2, T3, T4, T5, T6] = tuple[*SelectRes5[T1, T2, T3, T4, T5], Tuple[T6]]
|
31
|
+
type SelectRes7[T1, T2, T3, T4, T5, T6, T7] = tuple[*SelectRes6[T1, T2, T3, T4, T5, T6], Tuple[T7]]
|
32
|
+
type SelectRes8[T1, T2, T3, T4, T5, T6, T7, T8] = tuple[*SelectRes7[T1, T2, T3, T4, T5, T6, T7], Tuple[T8]]
|
33
|
+
type SelectRes9[T1, T2, T3, T4, T5, T6, T7, T8, T9] = tuple[*SelectRes8[T1, T2, T3, T4, T5, T6, T7, T8], Tuple[T9]]
|
34
|
+
type SelectRes10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] = tuple[*SelectRes9[T1, T2, T3, T4, T5, T6, T7, T8, T9], Tuple[T10]]
|
35
|
+
|
36
|
+
|
37
|
+
type WhereCondition[T, T1] = Callable[[T, T1], bool]
|
38
|
+
type JoinCondition[T, T1] = tuple[T1, WhereCondition[T, T1]]
|
39
|
+
|
40
|
+
type TupleJoins1[T, T1] = tuple[JoinCondition[T, T1]]
|
41
|
+
type TupleJoins2[T, T1, T2] = tuple[*TupleJoins1[T, T1], JoinCondition[T, T2]]
|
42
|
+
type TupleJoins3[T, T1, T2, T3] = tuple[*TupleJoins2[T, T1, T2], JoinCondition[T, T3]]
|
43
|
+
type TupleJoins4[T, T1, T2, T3, T4] = tuple[*TupleJoins3[T, T1, T2, T3], JoinCondition[T, T4]]
|
44
|
+
type TupleJoins5[T, T1, T2, T3, T4, T5] = tuple[*TupleJoins4[T, T1, T2, T3, T4], JoinCondition[T, T5]]
|
45
|
+
type TupleJoins6[T, T1, T2, T3, T4, T5, T6] = tuple[*TupleJoins5[T, T1, T2, T3, T4, T5], JoinCondition[T, T6]]
|
46
|
+
|
14
47
|
|
15
48
|
# TODOH: This var is duplicated from 'src\ormlambda\databases\my_sql\clauses\create_database.py'
|
16
49
|
TypeExists = Literal["fail", "replace", "append"]
|
17
50
|
|
18
|
-
T =
|
19
|
-
WhereTypes = Union[Callable[[T], bool], Iterable[Callable[[T], bool]]]
|
51
|
+
type WhereTypes[T, *Ts] = Union[Callable[[T, *Ts], bool], Iterable[Callable[[T, *Ts], bool]]]
|
20
52
|
|
21
53
|
|
22
|
-
class IStatements[T
|
54
|
+
class IStatements[T, *Ts](ABC):
|
23
55
|
@abstractmethod
|
24
56
|
def create_table(self, if_exists: TypeExists) -> None: ...
|
25
57
|
|
58
|
+
# #TODOL [ ]: We must to implement this mehtod
|
59
|
+
# @abstractmethod
|
60
|
+
# def drop_table(self)->None: ...
|
61
|
+
|
26
62
|
@abstractmethod
|
27
63
|
def table_exists(self) -> bool: ...
|
28
64
|
|
@@ -109,18 +145,13 @@ class IStatements[T: Table](ABC):
|
|
109
145
|
@overload
|
110
146
|
def delete(self, instance: list[T]) -> None: ...
|
111
147
|
@abstractmethod
|
112
|
-
def delete(self, instance: Optional[T | list[T]] =
|
148
|
+
def delete(self, instance: Optional[T | list[T]] = ...) -> None: ...
|
113
149
|
|
114
150
|
# endregion
|
115
|
-
# region join
|
116
|
-
@abstractmethod
|
117
|
-
def join(self, table_left: Table, table_right: Table, *, by: str) -> IStatements[T]: ...
|
118
151
|
|
119
|
-
# endregion
|
120
152
|
# region where
|
121
|
-
|
122
153
|
@overload
|
123
|
-
def where(self, conditions: Iterable[Callable[[T], bool]]) -> IStatements[T]:
|
154
|
+
def where(self, conditions: Iterable[Callable[[T, *Ts], bool]]) -> IStatements[T, *Ts]:
|
124
155
|
"""
|
125
156
|
This method creates where clause by passing the Iterable in lambda function
|
126
157
|
EXAMPLE
|
@@ -131,7 +162,7 @@ class IStatements[T: Table](ABC):
|
|
131
162
|
...
|
132
163
|
|
133
164
|
@overload
|
134
|
-
def where(self, conditions: Callable[[T], bool], **kwargs) -> IStatements[T]:
|
165
|
+
def where(self, conditions: Callable[[T, *Ts], bool], **kwargs) -> IStatements[T, *Ts]:
|
135
166
|
"""
|
136
167
|
PARAM
|
137
168
|
-
|
@@ -148,16 +179,16 @@ class IStatements[T: Table](ABC):
|
|
148
179
|
...
|
149
180
|
|
150
181
|
@abstractmethod
|
151
|
-
def where(self, conditions: WhereTypes = lambda: None, **kwargs) -> IStatements[T]: ...
|
182
|
+
def where(self, conditions: WhereTypes[T, *Ts] = lambda: None, **kwargs) -> IStatements[T, *Ts]: ...
|
152
183
|
|
153
184
|
# endregion
|
154
185
|
# region order
|
155
186
|
@overload
|
156
187
|
def order[TValue](self, _lambda_col: Callable[[T], TValue]) -> IStatements[T]: ...
|
157
188
|
@overload
|
158
|
-
def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type:
|
189
|
+
def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type: OrderTypes) -> IStatements[T]: ...
|
159
190
|
@abstractmethod
|
160
|
-
def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type:
|
191
|
+
def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type: OrderTypes) -> IStatements[T]: ...
|
161
192
|
|
162
193
|
# endregion
|
163
194
|
# region concat
|
@@ -191,72 +222,94 @@ class IStatements[T: Table](ABC):
|
|
191
222
|
alias: bool = ...,
|
192
223
|
alias_name: Optional[str] = ...,
|
193
224
|
) -> TProp: ...
|
225
|
+
|
226
|
+
# endregion
|
227
|
+
# region join
|
228
|
+
|
229
|
+
@overload
|
230
|
+
def join[T1](self, joins: JoinCondition[T, T1]) -> IStatements[T, T1]: ...
|
231
|
+
@overload
|
232
|
+
def join[T1](self, joins: TupleJoins1[T, T1]) -> IStatements[T, T1]: ...
|
233
|
+
@overload
|
234
|
+
def join[T1, T2](self, joins: TupleJoins2[T, T1, T2]) -> IStatements[T, T1, T2]: ...
|
235
|
+
@overload
|
236
|
+
def join[T1, T2, T3](self, joins: TupleJoins3[T, T1, T2, T3]) -> IStatements[T, T1, T2, T3]: ...
|
237
|
+
@overload
|
238
|
+
def join[T1, T2, T3, T4](self, joins: TupleJoins4[T, T1, T2, T3, T4]) -> IStatements[T, T1, T2, T3, T4]: ...
|
239
|
+
@overload
|
240
|
+
def join[T1, T2, T3, T4, T5](self, joins: TupleJoins5[T, T1, T2, T3, T4, T5]) -> IStatements[T, T1, T2, T3, T4, T5]: ...
|
241
|
+
@overload
|
242
|
+
def join[T1, T2, T3, T4, T5, T6](self, joins: TupleJoins6[T, T1, T2, T3, T4, T5, T6]) -> IStatements[T, T1, T2, T3, T4, T5, T6]: ...
|
243
|
+
|
244
|
+
@abstractmethod
|
245
|
+
def join[*FKTables](self, joins) -> IStatements[T, *FKTables]: ...
|
246
|
+
|
194
247
|
# endregion
|
195
248
|
# region select
|
196
249
|
@overload
|
197
|
-
def select(self) ->
|
250
|
+
def select(self) -> SelectRes1[T]: ...
|
198
251
|
@overload
|
199
|
-
def select[T1](self, selector: Callable[[T], T1], *, by: Optional[Enum] =
|
252
|
+
def select[T1](self, selector: Callable[[T], T1], *, by: Optional[Enum] = ...) -> SelectRes1[T1]: ...
|
200
253
|
@overload
|
201
|
-
def select[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] =
|
254
|
+
def select[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] = ...) -> SelectRes1[T1]: ...
|
202
255
|
@overload
|
203
|
-
def select[T1, T2](self, selector: Callable[[T], tuple[T1, T2]], *, by: Optional[Enum] =
|
256
|
+
def select[T1, T2](self, selector: Callable[[T, *Ts], tuple[T1, T2]], *, by: Optional[Enum] = ...) -> SelectRes2[T1, T2]: ...
|
204
257
|
@overload
|
205
|
-
def select[T1, T2, T3](self, selector: Callable[[T], tuple[T1, T2, T3]], *, by: Optional[Enum] =
|
258
|
+
def select[T1, T2, T3](self, selector: Callable[[T, *Ts], tuple[T1, T2, T3]], *, by: Optional[Enum] = ...) -> SelectRes3[T1, T2, T3]: ...
|
206
259
|
@overload
|
207
|
-
def select[T1, T2, T3, T4](self, selector: Callable[[T], tuple[T1, T2, T3, T4]], *, by: Optional[Enum] =
|
260
|
+
def select[T1, T2, T3, T4](self, selector: Callable[[T, *Ts], tuple[T1, T2, T3, T4]], *, by: Optional[Enum] = ...) -> SelectRes4[T1, T2, T3, T4]: ...
|
208
261
|
@overload
|
209
|
-
def select[T1, T2, T3, T4, T5](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5]], *, by: Optional[Enum] =
|
262
|
+
def select[T1, T2, T3, T4, T5](self, selector: Callable[[T, *Ts], tuple[T1, T2, T3, T4, T5]], *, by: Optional[Enum] = ...) -> SelectRes5[T1, T2, T3, T4, T5]: ...
|
210
263
|
@overload
|
211
|
-
def select[T1, T2, T3, T4, T5, T6](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6]], *, by: Optional[Enum] =
|
264
|
+
def select[T1, T2, T3, T4, T5, T6](self, selector: Callable[[T, *Ts], tuple[T1, T2, T3, T4, T5, T6]], *, by: Optional[Enum] = ...) -> SelectRes6[T1, T2, T3, T4, T5, T6]: ...
|
212
265
|
@overload
|
213
|
-
def select[T1, T2, T3, T4, T5, T6, T7](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7]], *, by: Optional[Enum] =
|
266
|
+
def select[T1, T2, T3, T4, T5, T6, T7](self, selector: Callable[[T, *Ts], tuple[T1, T2, T3, T4, T5, T6, T7]], *, by: Optional[Enum] = ...) -> SelectRes7[T1, T2, T3, T4, T5, T6, T7]: ...
|
214
267
|
@overload
|
215
|
-
def select[T1, T2, T3, T4, T5, T6, T7, T8](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7, T8]], *, by: Optional[Enum] =
|
268
|
+
def select[T1, T2, T3, T4, T5, T6, T7, T8](self, selector: Callable[[T, *Ts], tuple[T1, T2, T3, T4, T5, T6, T7, T8]], *, by: Optional[Enum] = ...) -> SelectRes8[T1, T2, T3, T4, T5, T6, T7, T8]: ...
|
216
269
|
@overload
|
217
|
-
def select[T1, T2, T3, T4, T5, T6, T7, T8, T9](
|
218
|
-
self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7, T8, T9]], *, by: Optional[Enum] = JoinType.INNER_JOIN
|
219
|
-
) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...], tuple[T7, ...], tuple[T8, ...], tuple[T9, ...]]: ...
|
270
|
+
def select[T1, T2, T3, T4, T5, T6, T7, T8, T9](self, selector: Callable[[T, *Ts], tuple[T1, T2, T3, T4, T5, T6, T7, T8, T9]], *, by: Optional[Enum] = ...) -> SelectRes9[T1, T2, T3, T4, T5, T6, T7, T8, T9]: ...
|
220
271
|
@overload
|
221
|
-
def select[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](
|
222
|
-
|
223
|
-
|
272
|
+
def select[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](self, selector: Callable[[T, *Ts], tuple[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]], *, by: Optional[Enum] = ...) -> SelectRes10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]: ...
|
273
|
+
|
274
|
+
@overload
|
275
|
+
def select[TFlavour](self, selector: Optional[Callable[[T, *Ts], tuple]] = ..., *, cast_to_tuple: bool = ..., flavour: Type[TFlavour], by: Optional[Enum] = ..., **kwargs) -> TFlavour: ...
|
224
276
|
@overload
|
225
|
-
def select[
|
277
|
+
def select[TRes](self, selector: Optional[Callable[[T, *Ts], TRes]] = ..., *, flavour: Type[tuple], by: Optional[Enum] = ..., **kwargs) -> tuple[TRes, ...]: ...
|
226
278
|
@overload
|
227
|
-
def select[
|
279
|
+
def select[TRes](self, selector: Optional[Callable[[T, *Ts], tuple[TRes]]] = ..., *, flavour: Type[tuple], by: Optional[Enum] = ..., **kwargs) -> tuple[TRes, ...]: ...
|
228
280
|
@overload
|
229
|
-
def select[*
|
281
|
+
def select[*TRes](self, selector: Optional[Callable[[T, *Ts], tuple[*TRes]]] = ..., *, flavour: Type[tuple], by: Optional[Enum] = ..., **kwargs) -> tuple[tuple[*TRes]]: ...
|
230
282
|
@overload
|
231
|
-
def select[TFlavour](self, selector: Optional[Callable[[T], tuple]] =
|
283
|
+
def select[TFlavour](self, selector: Optional[Callable[[T, *Ts], tuple]] = ..., *, flavour: Type[TFlavour], by: Optional[Enum] = ..., **kwargs) -> tuple[TFlavour]: ...
|
284
|
+
|
232
285
|
@abstractmethod
|
233
|
-
def select[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] =
|
286
|
+
def select[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T, *Ts], tuple[TValue, *Ts]]] = ..., *, cast_to_tuple: bool = ..., flavour: Type[TFlavour] = ..., by: JoinType = ..., **kwargs): ...
|
234
287
|
|
235
288
|
# endregion
|
236
289
|
# region select_one
|
237
290
|
@overload
|
238
291
|
def select_one(self) -> T: ...
|
239
292
|
@overload
|
240
|
-
def select_one[TFlavour](self, *, by: Optional[Enum] =
|
293
|
+
def select_one[TFlavour](self, *, by: Optional[Enum] = ..., flavour: Type[TFlavour]) -> TFlavour: ...
|
241
294
|
@overload
|
242
|
-
def select_one[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] =
|
295
|
+
def select_one[T1](self, selector: Callable[[T, *Ts], tuple[T1]], *, by: Optional[Enum] = ...) -> T1: ...
|
243
296
|
@overload
|
244
|
-
def select_one[*
|
297
|
+
def select_one[*TRes](self, selector: Callable[[T, *Ts], tuple[*TRes]], *, by: Optional[Enum] = ...) -> tuple[*TRes]: ...
|
245
298
|
@overload
|
246
|
-
def select_one[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] =
|
299
|
+
def select_one[T1](self, selector: Callable[[T, *Ts], tuple[T1]], *, by: Optional[Enum] = ..., flavour: Type) -> T1: ...
|
247
300
|
@overload
|
248
|
-
def select_one[T1, TFlavour](self, selector: Callable[[T], T1], *, by: Optional[Enum] =
|
301
|
+
def select_one[T1, TFlavour](self, selector: Callable[[T, *Ts], T1], *, by: Optional[Enum] = ..., flavour: Type[TFlavour]) -> T1: ...
|
249
302
|
@overload
|
250
|
-
def select_one[*Ts](self, selector: Callable[[T], tuple[*Ts]], *, by: Optional[Enum] =
|
303
|
+
def select_one[*Ts](self, selector: Callable[[T, *Ts], tuple[*Ts]], *, by: Optional[Enum] = ..., flavour: Type[tuple]) -> tuple[*Ts]: ...
|
251
304
|
@overload
|
252
|
-
def select_one[TFlavour](self, selector: Callable[[T], tuple], *, by: Optional[Enum] =
|
305
|
+
def select_one[TFlavour](self, selector: Callable[[T, *Ts], tuple], *, by: Optional[Enum] = ..., flavour: Type[TFlavour]) -> TFlavour: ...
|
253
306
|
@abstractmethod
|
254
|
-
def select_one[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] = lambda: None, *, flavour: Type[TFlavour] =
|
307
|
+
def select_one[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T, *Ts], tuple[TValue, *Ts]]] = lambda: None, *, flavour: Type[TFlavour] = ..., by: Optional[Enum] = ...): ...
|
255
308
|
|
256
309
|
# endregion
|
257
310
|
# region group_by
|
258
311
|
@abstractmethod
|
259
|
-
def group_by[TRepo
|
312
|
+
def group_by[TRepo](self, column: Callable[[T, *Ts], TRepo]) -> IStatements[T, *Ts]: ...
|
260
313
|
|
261
314
|
# endregion
|
262
315
|
|
@@ -264,7 +317,16 @@ class IStatements[T: Table](ABC):
|
|
264
317
|
def _build(self) -> str: ...
|
265
318
|
|
266
319
|
|
267
|
-
class IStatements_two_generic[T: Table, TRepo](IStatements[T]):
|
320
|
+
class IStatements_two_generic[T: Table, *Ts, TRepo](IStatements[T, *Ts]):
|
268
321
|
@property
|
269
322
|
@abstractmethod
|
270
323
|
def repository(self) -> IRepositoryBase[TRepo]: ...
|
324
|
+
|
325
|
+
@property
|
326
|
+
def query(self) -> str: ...
|
327
|
+
|
328
|
+
@property
|
329
|
+
def model(self) -> Type[T]: ...
|
330
|
+
|
331
|
+
@property
|
332
|
+
def models(self) -> tuple[*Ts]: ...
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import typing as tp
|
2
|
+
from ormlambda.common.abstract_classes.decomposition_query import ClauseInfo, DecompositionQueryBase
|
3
|
+
from ormlambda import Table
|
4
|
+
|
5
|
+
from ormlambda.common.interfaces import ICustomAlias
|
6
|
+
|
7
|
+
|
8
|
+
class Alias[T: tp.Type[Table], *Ts](DecompositionQueryBase[T,*Ts], ICustomAlias[T,*Ts]):
|
9
|
+
def __init__(
|
10
|
+
self,
|
11
|
+
table: T,
|
12
|
+
query: tp.Callable[[T, *Ts], tp.Any],
|
13
|
+
*,
|
14
|
+
alias: bool = True,
|
15
|
+
alias_name: str | None = None,
|
16
|
+
) -> None:
|
17
|
+
super().__init__(
|
18
|
+
table,
|
19
|
+
lambda_query=query,
|
20
|
+
alias=alias,
|
21
|
+
alias_name=alias_name,
|
22
|
+
)
|
23
|
+
|
24
|
+
def alias_children_resolver[Tclause: tp.Type[Table]](self, clause_info: ClauseInfo[Tclause]):
|
25
|
+
return self.alias_name
|
26
|
+
|
27
|
+
@property
|
28
|
+
def query(self) -> str:
|
29
|
+
assert len(self.all_clauses) == 1
|
30
|
+
|
31
|
+
return self.all_clauses[0].query
|
@@ -5,13 +5,13 @@ from ormlambda.common.interfaces.IAggregate import IAggregate
|
|
5
5
|
from ormlambda import Table
|
6
6
|
|
7
7
|
|
8
|
-
class GroupBy[T: tp.Type[Table], TProp](DecompositionQueryBase[T], IAggregate[T]):
|
8
|
+
class GroupBy[T: tp.Type[Table], *Ts, TProp](DecompositionQueryBase[T], IAggregate[T]):
|
9
9
|
CLAUSE: str = "GROUP BY"
|
10
10
|
|
11
11
|
def __init__(
|
12
12
|
self,
|
13
13
|
table: T,
|
14
|
-
column: tp.Callable[[T], TProp],
|
14
|
+
column: tp.Callable[[T, *Ts], TProp],
|
15
15
|
*,
|
16
16
|
alias: bool = True,
|
17
17
|
alias_name: str | None = None,
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import
|
1
|
+
from typing import override, Iterable
|
2
2
|
from mysql.connector import MySQLConnection
|
3
3
|
|
4
4
|
from ormlambda import Table
|
@@ -24,13 +24,24 @@ class InsertQuery[T: Table](InsertQueryBase[T, IRepositoryBase[MySQLConnection]]
|
|
24
24
|
|
25
25
|
@override
|
26
26
|
def insert(self, instances: T | list[T]) -> None:
|
27
|
-
|
28
|
-
self.__fill_dict_list(
|
29
|
-
cols_tuple = new_dict_list[0].keys()
|
30
|
-
join_cols = ", ".join(cols_tuple)
|
31
|
-
unknown_rows = f'({", ".join(["%s"]*len(cols_tuple))})' # The number of "%s" must match the dict 'dicc_0' length
|
27
|
+
valid_cols: list[list[Column]] = []
|
28
|
+
self.__fill_dict_list(valid_cols, instances)
|
32
29
|
|
33
|
-
|
30
|
+
col_names: list[str] = []
|
31
|
+
wildcards: list[str] = []
|
32
|
+
col_values: list[list[str]] = []
|
33
|
+
for i, cols in enumerate(valid_cols):
|
34
|
+
col_values.append([])
|
35
|
+
for col in cols:
|
36
|
+
if i == 0:
|
37
|
+
col_names.append(col.column_name)
|
38
|
+
wildcards.append(col.placeholder)
|
39
|
+
col_values[-1].append(col.column_value_to_query)
|
40
|
+
|
41
|
+
join_cols = ", ".join(col_names)
|
42
|
+
unknown_rows = f'({", ".join(wildcards)})' # The number of "%s" must match the dict 'dicc_0' length
|
43
|
+
|
44
|
+
self._values = [tuple(x) for x in col_values]
|
34
45
|
self._query = f"{self.CLAUSE} {self._model.__table_name__} {f'({join_cols})'} VALUES {unknown_rows}"
|
35
46
|
return None
|
36
47
|
|
@@ -55,17 +66,18 @@ class InsertQuery[T: Table](InsertQueryBase[T, IRepositoryBase[MySQLConnection]]
|
|
55
66
|
return False
|
56
67
|
return True
|
57
68
|
|
58
|
-
def __fill_dict_list(self, list_dict: list[
|
69
|
+
def __fill_dict_list[TProp](self, list_dict: list[str, TProp], values: T | list[T]) -> list[Column]:
|
59
70
|
if issubclass(values.__class__, Table):
|
60
|
-
|
71
|
+
new_list = []
|
61
72
|
for col in values.__dict__.values():
|
62
73
|
if isinstance(col, Column) and self.__is_valid(col):
|
63
|
-
|
64
|
-
|
65
|
-
|
74
|
+
new_list.append(col)
|
75
|
+
|
76
|
+
list_dict.append(new_list)
|
66
77
|
|
67
78
|
elif isinstance(values, Iterable):
|
68
79
|
for x in values:
|
69
80
|
self.__fill_dict_list(list_dict, x)
|
70
81
|
else:
|
71
82
|
raise Exception(f"Tipo de dato'{type(values)}' no esperado")
|
83
|
+
return None
|
@@ -1,7 +1,9 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
-
from
|
2
|
+
from collections import defaultdict
|
3
|
+
from typing import override, Callable, overload, Optional, TYPE_CHECKING, Type
|
3
4
|
|
4
5
|
|
6
|
+
from ormlambda.utils.module_tree.dfs_traversal import DFSTraversal
|
5
7
|
from ormlambda.common.interfaces.IQueryCommand import IQuery
|
6
8
|
from ormlambda import Disassembler
|
7
9
|
from ormlambda import JoinType
|
@@ -21,6 +23,13 @@ class JoinSelector[TLeft, TRight](IQuery):
|
|
21
23
|
"_compareop",
|
22
24
|
)
|
23
25
|
|
26
|
+
@override
|
27
|
+
def __repr__(self) -> str:
|
28
|
+
table_col_left: str = f"{self._orig_table.__table_name__}.{self._left_col}"
|
29
|
+
table_col_right: str = f"{self._table_right.__table_name__}.{self._right_col}"
|
30
|
+
|
31
|
+
return f"{IQuery.__name__}: {self.__class__.__name__} ({table_col_left} == {table_col_right})"
|
32
|
+
|
24
33
|
@overload
|
25
34
|
def __init__(
|
26
35
|
self,
|
@@ -102,3 +111,32 @@ class JoinSelector[TLeft, TRight](IQuery):
|
|
102
111
|
right_col, # second_col
|
103
112
|
]
|
104
113
|
return " ".join(list_)
|
114
|
+
|
115
|
+
@classmethod
|
116
|
+
def sort_join_selectors(cls, joins: set[JoinSelector]) -> tuple[JoinSelector]:
|
117
|
+
# FIXME [x]: How to sort when needed because it's not necessary at this point. It is for testing purpouse
|
118
|
+
if len(joins) == 1:
|
119
|
+
return tuple(joins)
|
120
|
+
|
121
|
+
join_object_map: dict[str, list[JoinSelector]] = defaultdict(list)
|
122
|
+
|
123
|
+
for obj in joins:
|
124
|
+
join_object_map[obj._orig_table].append(obj)
|
125
|
+
|
126
|
+
graph: dict[Type[Table], list[Type[Table]]] = defaultdict(list)
|
127
|
+
for join in joins:
|
128
|
+
graph[join._orig_table].append(join._table_right)
|
129
|
+
|
130
|
+
sorted_graph = DFSTraversal.sort(graph)[::-1]
|
131
|
+
|
132
|
+
if not sorted_graph:
|
133
|
+
return tuple(joins)
|
134
|
+
|
135
|
+
res = []
|
136
|
+
for table in sorted_graph:
|
137
|
+
tables = join_object_map[table]
|
138
|
+
|
139
|
+
if not tables:
|
140
|
+
continue
|
141
|
+
res.extend(tables)
|
142
|
+
return res
|
@@ -1,33 +1,47 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
-
from typing import override, Callable, TYPE_CHECKING
|
2
|
+
from typing import override, Callable, TYPE_CHECKING, Any, Iterable
|
3
|
+
|
4
|
+
from ormlambda.common.abstract_classes.decomposition_query import ClauseInfo
|
5
|
+
|
3
6
|
|
4
7
|
if TYPE_CHECKING:
|
5
8
|
from ormlambda import Table
|
6
9
|
|
7
|
-
from ormlambda.
|
8
|
-
from ormlambda.common.interfaces.IQueryCommand import IQuery
|
10
|
+
from ormlambda.common.abstract_classes.decomposition_query import DecompositionQueryBase
|
9
11
|
from ormlambda.common.interfaces.IStatements import OrderType
|
10
12
|
|
11
|
-
ASC = "ASC"
|
12
|
-
DESC = "DESC"
|
13
13
|
|
14
|
-
|
15
|
-
class OrderQuery[T:Table](IQuery):
|
14
|
+
class OrderQuery[T: Table](DecompositionQueryBase[T]):
|
16
15
|
ORDER = "ORDER BY"
|
17
16
|
|
18
|
-
def __init__(self, instance: T,
|
19
|
-
|
20
|
-
|
17
|
+
def __init__[*Ts](self, instance: T, lambda_query: Callable[[Any], tuple[*Ts]], order_type: Iterable[OrderType]) -> None:
|
18
|
+
super().__init__(instance, lambda_query)
|
19
|
+
|
20
|
+
if isinstance(order_type, str) or not isinstance(order_type, Iterable):
|
21
|
+
order_type = (order_type,)
|
21
22
|
|
22
|
-
self.
|
23
|
-
self._order_lambda: Callable[[T], None] = order_lambda
|
24
|
-
self._order_type: str = order_type
|
25
|
-
self._column: str = TreeInstruction(order_lambda).to_list()[0].nested_element.name
|
23
|
+
self._order_type: list[OrderType] = [self.__cast_to_OrderType(x) for x in order_type]
|
26
24
|
|
27
|
-
def
|
28
|
-
|
25
|
+
def __cast_to_OrderType(self, _value: Any) -> Iterable[OrderType]:
|
26
|
+
if isinstance(_value, OrderType):
|
27
|
+
return _value
|
28
|
+
|
29
|
+
if isinstance(_value, str):
|
30
|
+
try:
|
31
|
+
return OrderType(_value)
|
32
|
+
except Exception:
|
33
|
+
pass
|
34
|
+
raise Exception(f"order_type param only can be 'ASC' or 'DESC' string or '{OrderType.__name__}' enum")
|
35
|
+
|
36
|
+
def alias_children_resolver[Tclause](self, clause_info: ClauseInfo[Tclause]):
|
37
|
+
return None
|
29
38
|
|
30
39
|
@override
|
31
40
|
@property
|
32
41
|
def query(self) -> str:
|
33
|
-
|
42
|
+
assert len(self.all_clauses) == len(self._order_type)
|
43
|
+
|
44
|
+
query: list[str] = []
|
45
|
+
for index, x in enumerate(self.all_clauses):
|
46
|
+
query.append(f"{x.query} {self._order_type[index].value}")
|
47
|
+
return f"{self.ORDER} {", ".join(query)}"
|
@@ -1,53 +1,60 @@
|
|
1
|
-
from
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import override, Type, Callable, TYPE_CHECKING, Optional
|
2
3
|
|
3
4
|
from ormlambda.common.abstract_classes.decomposition_query import DecompositionQueryBase
|
4
5
|
from ormlambda.common.enums.join_type import JoinType
|
5
6
|
from ormlambda.common.interfaces.IAggregate import IAggregate
|
7
|
+
import shapely as shp
|
8
|
+
|
6
9
|
|
7
10
|
if TYPE_CHECKING:
|
8
11
|
from ormlambda import Table
|
12
|
+
from .joins import JoinSelector
|
9
13
|
|
10
14
|
|
11
|
-
class Select[T: Type[Table]](DecompositionQueryBase[T]):
|
15
|
+
class Select[T: Type[Table], *Ts](DecompositionQueryBase[T, *Ts]):
|
12
16
|
CLAUSE: str = "SELECT"
|
13
17
|
|
14
18
|
def __init__(
|
15
19
|
self,
|
16
|
-
|
20
|
+
tables: tuple[T, *Ts],
|
17
21
|
lambda_query: Callable[[T], tuple] = lambda x: x,
|
18
22
|
*,
|
19
23
|
alias: bool = False,
|
20
24
|
alias_name: str | None = None,
|
25
|
+
joins: Optional[list[JoinSelector]] = None,
|
21
26
|
by: JoinType = JoinType.INNER_JOIN,
|
22
27
|
) -> None:
|
23
28
|
super().__init__(
|
24
|
-
|
29
|
+
tables,
|
25
30
|
lambda_query,
|
26
31
|
alias=alias,
|
27
32
|
alias_name=alias_name,
|
28
33
|
by=by,
|
34
|
+
joins=joins,
|
29
35
|
)
|
30
36
|
|
31
37
|
# @classmethod
|
32
38
|
# def alias_children_resolver[Tclause: Type[Table]](self, clause_info: ClauseInfo[Tclause]):
|
33
39
|
# return f"{clause.table.__table_name__}_{name}"
|
34
40
|
|
41
|
+
# TODOL: see who to deal when we will have to add more mysql methods
|
35
42
|
@override
|
36
43
|
@property
|
37
44
|
def query(self) -> str:
|
38
|
-
cols:list[str] = []
|
45
|
+
cols: list[str] = []
|
39
46
|
for x in self.all_clauses:
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
47
|
+
if x.dtype is shp.Point:
|
48
|
+
cols.append(x.concat_with_alias(f"ST_AsText({self.table.__table_name__}.{x.column})"))
|
49
|
+
else:
|
50
|
+
cols.append(x.query)
|
44
51
|
|
52
|
+
if isinstance(x._row_column, IAggregate) and x._row_column.has_foreign_keys:
|
53
|
+
self._joins.update(x._row_column.fk_relationship)
|
45
54
|
|
46
55
|
col: str = ", ".join(cols)
|
47
|
-
query: str = f"{self.CLAUSE} {col} FROM {self.
|
48
|
-
alias = ""
|
56
|
+
query: str = f"{self.CLAUSE} {col} FROM {self.table.__table_name__}"
|
49
57
|
|
50
|
-
query += alias
|
51
58
|
if self.has_foreign_keys:
|
52
59
|
query += " " + self.stringify_foreign_key(" ")
|
53
60
|
|
@@ -27,26 +27,20 @@ class UpdateQuery[T: Type[Table]](UpdateQueryBase[T, IRepositoryBase[MySQLConnec
|
|
27
27
|
if not isinstance(dicc, dict):
|
28
28
|
raise TypeError
|
29
29
|
|
30
|
-
name_cols: list[
|
30
|
+
name_cols: list[Column] = []
|
31
31
|
|
32
32
|
for col, value in dicc.items():
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
name_cols.append(string_col)
|
41
|
-
self._values.append(value)
|
42
|
-
|
43
|
-
set_query: str = ",".join(["=".join([col, "%s"]) for col in name_cols])
|
33
|
+
col: Column = self._model.get_column(col, value)
|
34
|
+
|
35
|
+
if self.__is_valid__(col):
|
36
|
+
name_cols.append(col)
|
37
|
+
self._values.append(col.column_value_to_query)
|
38
|
+
|
39
|
+
set_query: str = ",".join(["=".join([col.column_name, col.placeholder]) for col in name_cols])
|
44
40
|
|
45
41
|
self._query = f"{self.CLAUSE} {self._model.__table_name__} SET {set_query}"
|
42
|
+
self._values = tuple(self._values)
|
46
43
|
return None
|
47
44
|
|
48
|
-
def __is_valid__(self, col:
|
49
|
-
|
50
|
-
|
51
|
-
column: Column = getattr(instance_table, f"_{col}")
|
52
|
-
return not column.is_auto_generated
|
45
|
+
def __is_valid__(self, col: Column) -> bool:
|
46
|
+
return not col.is_auto_generated
|