ormlambda 2.7.2__tar.gz → 2.9.0__tar.gz
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-2.7.2 → ormlambda-2.9.0}/PKG-INFO +3 -2
- {ormlambda-2.7.2 → ormlambda-2.9.0}/pyproject.toml +4 -2
- ormlambda-2.9.0/src/ormlambda/__init__.py +20 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/abstract_classes/abstract_model.py +16 -17
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/abstract_classes/decomposition_query.py +23 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/interfaces/IStatements.py +68 -36
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/__init__.py +1 -1
- {ormlambda-2.7.2/src/ormlambda/databases/my_sql/functions → ormlambda-2.9.0/src/ormlambda/databases/my_sql/clauses}/group_by.py +0 -2
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/insert.py +24 -12
- ormlambda-2.9.0/src/ormlambda/databases/my_sql/clauses/order.py +47 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/select.py +8 -4
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/update.py +11 -17
- ormlambda-2.9.0/src/ormlambda/databases/my_sql/functions/__init__.py +5 -0
- ormlambda-2.9.0/src/ormlambda/databases/my_sql/functions/sum.py +39 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/repository.py +56 -6
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/statements.py +45 -25
- ormlambda-2.9.0/src/ormlambda/utils/column.py +105 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/dtypes.py +4 -12
- ormlambda-2.9.0/src/ormlambda/utils/fields.py +60 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/table_constructor.py +67 -95
- ormlambda-2.7.2/src/ormlambda/__init__.py +0 -11
- ormlambda-2.7.2/src/ormlambda/databases/my_sql/clauses/order.py +0 -33
- ormlambda-2.7.2/src/ormlambda/databases/my_sql/functions/__init__.py +0 -4
- ormlambda-2.7.2/src/ormlambda/utils/column.py +0 -66
- {ormlambda-2.7.2 → ormlambda-2.9.0}/LICENSE +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/README.md +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/abstract_classes/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/abstract_classes/non_query_base.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/abstract_classes/query_base.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/enums/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/enums/condition_types.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/enums/join_type.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/interfaces/IAggregate.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/interfaces/IDecompositionQuery.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/interfaces/INonQueryCommand.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/interfaces/IQueryCommand.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/interfaces/IRepositoryBase.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/interfaces/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/delete/IDelete.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/delete/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/delete/abstract_delete.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/insert/IInsert.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/insert/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/insert/abstract_insert.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/update/IUpdate.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/update/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/update/abstract_update.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/upsert/IUpsert.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/upsert/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/upsert/abstract_upsert.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/where/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/components/where/abstract_where.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/count.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/create_database.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/delete.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/drop_database.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/drop_table.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/joins.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/limit.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/offset.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/upsert.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/clauses/where_condition.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/functions/concat.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/functions/max.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/databases/my_sql/functions/min.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/model_base.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/foreign_key.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/lambda_disassembler/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/lambda_disassembler/dis_types.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/lambda_disassembler/disassembler.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/lambda_disassembler/dtypes.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/lambda_disassembler/name_of.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/lambda_disassembler/nested_element.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/lambda_disassembler/tree_instruction.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/module_tree/__init__.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/module_tree/dfs_traversal.py +0 -0
- {ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/utils/module_tree/dynamic_module.py +0 -0
@@ -1,14 +1,15 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: ormlambda
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.9.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
|
7
7
|
Requires-Python: >=3.12,<4.0
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
9
9
|
Classifier: Programming Language :: Python :: 3.12
|
10
|
-
Requires-Dist: fluent-validation (
|
10
|
+
Requires-Dist: fluent-validation (==4.3.1)
|
11
11
|
Requires-Dist: mysql-connector-python (>=9.0.0,<10.0.0)
|
12
|
+
Requires-Dist: shapely (>=2.0.6,<3.0.0)
|
12
13
|
Description-Content-Type: text/markdown
|
13
14
|
|
14
15
|

|
@@ -3,7 +3,7 @@ line-length = 320
|
|
3
3
|
|
4
4
|
[tool.poetry]
|
5
5
|
name = "ormlambda"
|
6
|
-
version = "2.
|
6
|
+
version = "2.9.0"
|
7
7
|
description = "ORM designed to interact with the database (currently with MySQL) using lambda functions and nested functions"
|
8
8
|
authors = ["p-hzamora <p.hzamora@icloud.com>"]
|
9
9
|
readme = "README.md"
|
@@ -11,12 +11,14 @@ readme = "README.md"
|
|
11
11
|
[tool.poetry.dependencies]
|
12
12
|
python = "^3.12"
|
13
13
|
mysql-connector-python= "^9.0.0"
|
14
|
-
fluent-validation = "
|
14
|
+
fluent-validation = "4.3.1"
|
15
|
+
shapely = "^2.0.6"
|
15
16
|
|
16
17
|
[tool.poetry.group.test.dependencies]
|
17
18
|
pandas = "^2.2.2"
|
18
19
|
ruff = "^0.4.5"
|
19
20
|
python-decouple = "^3.8"
|
21
|
+
parameterized = "^0.9.0"
|
20
22
|
|
21
23
|
|
22
24
|
[build-system]
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# region enums
|
2
|
+
from .common.enums import (
|
3
|
+
JoinType as JoinType,
|
4
|
+
ConditionType as ConditionType,
|
5
|
+
)
|
6
|
+
from ormlambda.common.interfaces.IStatements import OrderType as OrderType
|
7
|
+
# endregion
|
8
|
+
|
9
|
+
from .common.abstract_classes import AbstractSQLStatements as AbstractSQLStatements
|
10
|
+
from .common.interfaces import IRepositoryBase as IRepositoryBase
|
11
|
+
from .utils import (
|
12
|
+
Table as Table,
|
13
|
+
Column as Column,
|
14
|
+
ForeignKey as ForeignKey,
|
15
|
+
)
|
16
|
+
from .utils.lambda_disassembler import (
|
17
|
+
Disassembler as Disassembler,
|
18
|
+
nameof as nameof,
|
19
|
+
)
|
20
|
+
from .model_base import BaseModel as BaseModel # COMMENT: to avoid relative import we need to import BaseModel after import Table,Column, ForeignKey, IRepositoryBase and Disassembler
|
@@ -10,7 +10,6 @@ from ormlambda.common.interfaces.IAggregate import IAggregate
|
|
10
10
|
|
11
11
|
if TYPE_CHECKING:
|
12
12
|
from ormlambda.common.abstract_classes.decomposition_query import DecompositionQueryBase
|
13
|
-
from ormlambda.components.select import ISelect
|
14
13
|
from ormlambda.common.abstract_classes.decomposition_query import ClauseInfo
|
15
14
|
|
16
15
|
|
@@ -46,11 +45,11 @@ class AbstractSQLStatements[T: Table, TRepo](IStatements_two_generic[T, TRepo]):
|
|
46
45
|
@override
|
47
46
|
def repository(self) -> IRepositoryBase[TRepo]: ...
|
48
47
|
|
49
|
-
def _return_flavour[TValue](self, query, flavour: Type[TValue]) -> tuple[TValue]:
|
50
|
-
return self._repository.read_sql(query, flavour=flavour)
|
48
|
+
def _return_flavour[TValue](self, query, flavour: Type[TValue], select) -> tuple[TValue]:
|
49
|
+
return self._repository.read_sql(query, flavour=flavour, model=self._model, select=select)
|
51
50
|
|
52
|
-
def _return_model(self, select
|
53
|
-
response_sql = self._repository.read_sql(query, flavour=dict) # store all columns of the SQL query
|
51
|
+
def _return_model(self, select, query: str):
|
52
|
+
response_sql = self._repository.read_sql(query, flavour=dict, model=self._model, select=select) # store all columns of the SQL query
|
54
53
|
|
55
54
|
if isinstance(response_sql, Iterable):
|
56
55
|
return ClusterQuery[T](select, response_sql).clean_response()
|
@@ -66,7 +65,16 @@ class ClusterQuery[T]:
|
|
66
65
|
self._select: DecompositionQueryBase[T] = select
|
67
66
|
self._response_sql: tuple[dict[str, Any]] = response_sql
|
68
67
|
|
69
|
-
def
|
68
|
+
def clean_response(self) -> tuple[dict[Type[Table], tuple[Table]]]:
|
69
|
+
tbl_dicc: dict[Type[Table], list[Table]] = self.__loop_foo()
|
70
|
+
|
71
|
+
# it not depend of flavour attr
|
72
|
+
for key, val in tbl_dicc.items():
|
73
|
+
tbl_dicc[key] = tuple(val)
|
74
|
+
|
75
|
+
return tuple(tbl_dicc.values())
|
76
|
+
|
77
|
+
def __loop_foo(self) -> dict[Type[Table], list[Table]]:
|
70
78
|
# We must ensure to get the valid attributes for each instance
|
71
79
|
table_initialize = defaultdict(list)
|
72
80
|
|
@@ -75,7 +83,7 @@ class ClusterQuery[T]:
|
|
75
83
|
valid_attr: dict[str, Any] = {}
|
76
84
|
for clause in clauses:
|
77
85
|
if not hasattr(table, clause.column):
|
78
|
-
agg_methods = self.
|
86
|
+
agg_methods = self.__get_all_aggregate_method(clauses)
|
79
87
|
raise ValueError(f"You cannot use aggregation method like '{agg_methods}' to return model objects. Try specifying 'flavour' attribute as 'dict'.")
|
80
88
|
valid_attr[clause.column] = dicc_cols[clause.alias]
|
81
89
|
|
@@ -83,7 +91,7 @@ class ClusterQuery[T]:
|
|
83
91
|
table_initialize[table].append(table(**valid_attr))
|
84
92
|
return table_initialize
|
85
93
|
|
86
|
-
def
|
94
|
+
def __get_all_aggregate_method(self, clauses: list[ClauseInfo]) -> str:
|
87
95
|
res: set[str] = set()
|
88
96
|
|
89
97
|
for clause in clauses:
|
@@ -91,12 +99,3 @@ class ClusterQuery[T]:
|
|
91
99
|
if isinstance(row, IAggregate):
|
92
100
|
res.add(row.__class__.__name__)
|
93
101
|
return ", ".join(res)
|
94
|
-
|
95
|
-
def clean_response(self) -> tuple[dict[Type[Table], tuple[Table]]]:
|
96
|
-
tbl_dicc: dict[Type[Table], list[Table]] = self.loop_foo()
|
97
|
-
|
98
|
-
# it not depend of flavour attr
|
99
|
-
for key, val in tbl_dicc.items():
|
100
|
-
tbl_dicc[key] = tuple(val)
|
101
|
-
|
102
|
-
return tuple(tbl_dicc.values())
|
{ormlambda-2.7.2 → ormlambda-2.9.0}/src/ormlambda/common/abstract_classes/decomposition_query.py
RENAMED
@@ -44,6 +44,13 @@ class ClauseInfo[T: tp.Type[Table]]:
|
|
44
44
|
def query(self) -> str:
|
45
45
|
return self._query
|
46
46
|
|
47
|
+
@property
|
48
|
+
def dtype[TProp](self) -> tp.Optional[tp.Type[TProp]]:
|
49
|
+
try:
|
50
|
+
return self._table.get_column(self.column).dtype
|
51
|
+
except ValueError:
|
52
|
+
return None
|
53
|
+
|
47
54
|
def _resolve_column(self, data: ClauseDataType) -> str:
|
48
55
|
if isinstance(data, property):
|
49
56
|
return self._table.__properties_mapped__[data]
|
@@ -73,6 +80,17 @@ class ClauseInfo[T: tp.Type[Table]]:
|
|
73
80
|
|
74
81
|
|
75
82
|
class DecompositionQueryBase[T: tp.Type[Table]](IDecompositionQuery[T]):
|
83
|
+
@tp.overload
|
84
|
+
def __init__[*Ts](self, table: T, lambda_query: tp.Callable[[T], tuple[*Ts]]) -> None: ...
|
85
|
+
@tp.overload
|
86
|
+
def __init__[*Ts](self, table: T, lambda_query: tp.Callable[[T], tuple[*Ts]], *, alias: bool = ...) -> None: ...
|
87
|
+
@tp.overload
|
88
|
+
def __init__[*Ts](self, table: T, lambda_query: tp.Callable[[T], tuple[*Ts]], *, alias: bool = ..., alias_name: tp.Optional[str] = ...) -> None: ...
|
89
|
+
@tp.overload
|
90
|
+
def __init__[*Ts](self, table: T, lambda_query: tp.Callable[[T], tuple[*Ts]], *, alias: bool = ..., alias_name: tp.Optional[str] = ..., by: JoinType = ...) -> None: ...
|
91
|
+
@tp.overload
|
92
|
+
def __init__[*Ts](self, table: T, lambda_query: tp.Callable[[T], tuple[*Ts]], *, alias: bool = ..., alias_name: tp.Optional[str] = ..., by: JoinType = ..., replace_asterisk_char: bool = ...) -> None: ...
|
93
|
+
|
76
94
|
def __init__[*Ts](
|
77
95
|
self,
|
78
96
|
table: T,
|
@@ -98,6 +116,11 @@ class DecompositionQueryBase[T: tp.Type[Table]](IDecompositionQuery[T]):
|
|
98
116
|
|
99
117
|
self.__clauses_list_generetor(lambda_query)
|
100
118
|
|
119
|
+
def __getitem__(self, key: str) -> ClauseInfo:
|
120
|
+
for clause in self._all_clauses:
|
121
|
+
if clause.alias == key:
|
122
|
+
return clause
|
123
|
+
|
101
124
|
def alias_children_resolver[Tclause: tp.Type[Table]](self, clause_info: ClauseInfo[Tclause]):
|
102
125
|
DEFAULT_ALIAS: str = f"{clause_info._table.__table_name__}_{clause_info._column}"
|
103
126
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
2
2
|
from typing import Any, Callable, Iterable, Optional, Literal, Type, Union, overload, TYPE_CHECKING, TypeVar
|
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,7 +11,15 @@ 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
|
+
OrderTypeString = Literal["ASC", "DESC"]
|
21
|
+
|
22
|
+
OrderTypes = OrderTypeString | OrderType | Iterable[OrderType]
|
14
23
|
|
15
24
|
# TODOH: This var is duplicated from 'src\ormlambda\databases\my_sql\clauses\create_database.py'
|
16
25
|
TypeExists = Literal["fail", "replace", "append"]
|
@@ -91,7 +100,12 @@ class IStatements[T: Table](ABC):
|
|
91
100
|
# endregion
|
92
101
|
# region count
|
93
102
|
@abstractmethod
|
94
|
-
def count(
|
103
|
+
def count(
|
104
|
+
self,
|
105
|
+
selection: Callable[[T], property],
|
106
|
+
alias: bool = ...,
|
107
|
+
alias_name: Optional[str] = ...,
|
108
|
+
) -> int: ...
|
95
109
|
|
96
110
|
# endregion
|
97
111
|
# region delete
|
@@ -104,7 +118,7 @@ class IStatements[T: Table](ABC):
|
|
104
118
|
@overload
|
105
119
|
def delete(self, instance: list[T]) -> None: ...
|
106
120
|
@abstractmethod
|
107
|
-
def delete(self, instance: Optional[T | list[T]] =
|
121
|
+
def delete(self, instance: Optional[T | list[T]] = ...) -> None: ...
|
108
122
|
|
109
123
|
# endregion
|
110
124
|
# region join
|
@@ -150,9 +164,9 @@ class IStatements[T: Table](ABC):
|
|
150
164
|
@overload
|
151
165
|
def order[TValue](self, _lambda_col: Callable[[T], TValue]) -> IStatements[T]: ...
|
152
166
|
@overload
|
153
|
-
def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type:
|
167
|
+
def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type: OrderTypes) -> IStatements[T]: ...
|
154
168
|
@abstractmethod
|
155
|
-
def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type:
|
169
|
+
def order[TValue](self, _lambda_col: Callable[[T], TValue], order_type: OrderTypes) -> IStatements[T]: ...
|
156
170
|
|
157
171
|
# endregion
|
158
172
|
# region concat
|
@@ -162,76 +176,94 @@ class IStatements[T: Table](ABC):
|
|
162
176
|
# endregion
|
163
177
|
# region max
|
164
178
|
@overload
|
165
|
-
def max[TProp](
|
166
|
-
|
167
|
-
|
168
|
-
|
179
|
+
def max[TProp](
|
180
|
+
self,
|
181
|
+
column: Callable[[T], TProp],
|
182
|
+
alias: bool = ...,
|
183
|
+
alias_name: Optional[str] = ...,
|
184
|
+
) -> TProp: ...
|
185
|
+
# endregion
|
186
|
+
# region min
|
187
|
+
@overload
|
188
|
+
def min[TProp](
|
189
|
+
self,
|
190
|
+
column: Callable[[T], TProp],
|
191
|
+
alias: bool = ...,
|
192
|
+
alias_name: Optional[str] = ...,
|
193
|
+
) -> TProp: ...
|
194
|
+
# endregion
|
195
|
+
# region sum
|
196
|
+
@overload
|
197
|
+
def sum[TProp](
|
198
|
+
self,
|
199
|
+
column: Callable[[T], TProp],
|
200
|
+
alias: bool = ...,
|
201
|
+
alias_name: Optional[str] = ...,
|
202
|
+
) -> TProp: ...
|
169
203
|
# endregion
|
170
204
|
# region select
|
171
205
|
@overload
|
172
206
|
def select(self) -> tuple[T, ...]: ...
|
173
207
|
@overload
|
174
|
-
def select[T1](self, selector: Callable[[T], T1], *, by: Optional[Enum] =
|
208
|
+
def select[T1](self, selector: Callable[[T], T1], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...]]: ...
|
175
209
|
@overload
|
176
|
-
def select[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] =
|
210
|
+
def select[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...]]: ...
|
177
211
|
@overload
|
178
|
-
def select[T1, T2](self, selector: Callable[[T], tuple[T1, T2]], *, by: Optional[Enum] =
|
212
|
+
def select[T1, T2](self, selector: Callable[[T], tuple[T1, T2]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...]]: ...
|
179
213
|
@overload
|
180
|
-
def select[T1, T2, T3](self, selector: Callable[[T], tuple[T1, T2, T3]], *, by: Optional[Enum] =
|
214
|
+
def select[T1, T2, T3](self, selector: Callable[[T], tuple[T1, T2, T3]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...]]: ...
|
181
215
|
@overload
|
182
|
-
def select[T1, T2, T3, T4](self, selector: Callable[[T], tuple[T1, T2, T3, T4]], *, by: Optional[Enum] =
|
216
|
+
def select[T1, T2, T3, T4](self, selector: Callable[[T], tuple[T1, T2, T3, T4]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...]]: ...
|
183
217
|
@overload
|
184
|
-
def select[T1, T2, T3, T4, T5](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5]], *, by: Optional[Enum] =
|
218
|
+
def select[T1, T2, T3, T4, T5](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...]]: ...
|
185
219
|
@overload
|
186
|
-
def select[T1, T2, T3, T4, T5, T6](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6]], *, by: Optional[Enum] =
|
220
|
+
def select[T1, T2, T3, T4, T5, T6](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...]]: ...
|
187
221
|
@overload
|
188
|
-
def select[T1, T2, T3, T4, T5, T6, T7](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7]], *, by: Optional[Enum] =
|
222
|
+
def select[T1, T2, T3, T4, T5, T6, T7](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...], tuple[T7, ...]]: ...
|
189
223
|
@overload
|
190
|
-
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] =
|
224
|
+
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] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...], tuple[T7, ...], tuple[T8, ...]]: ...
|
191
225
|
@overload
|
192
|
-
def select[T1, T2, T3, T4, T5, T6, T7, T8, T9](
|
193
|
-
self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7, T8, T9]], *, by: Optional[Enum] = JoinType.INNER_JOIN
|
194
|
-
) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...], tuple[T7, ...], tuple[T8, ...], tuple[T9, ...]]: ...
|
226
|
+
def select[T1, T2, T3, T4, T5, T6, T7, T8, T9](self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7, T8, T9]], *, by: Optional[Enum] = ...) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...], tuple[T7, ...], tuple[T8, ...], tuple[T9, ...]]: ...
|
195
227
|
@overload
|
196
228
|
def select[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](
|
197
|
-
self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]], *, by: Optional[Enum] =
|
229
|
+
self, selector: Callable[[T], tuple[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]], *, by: Optional[Enum] = ...
|
198
230
|
) -> tuple[tuple[T1, ...], tuple[T2, ...], tuple[T3, ...], tuple[T4, ...], tuple[T5, ...], tuple[T6, ...], tuple[T7, ...], tuple[T8, ...], tuple[T9, ...], tuple[T10, ...]]: ...
|
199
231
|
@overload
|
200
|
-
def select[Ts](self, selector: Optional[Callable[[T], Ts]] =
|
232
|
+
def select[Ts](self, selector: Optional[Callable[[T], Ts]] = ..., *, flavour: Type[tuple], by: Optional[Enum] = ...) -> tuple[Ts, ...]: ...
|
201
233
|
@overload
|
202
|
-
def select[Ts](self, selector: Optional[Callable[[T], tuple[Ts]]] =
|
234
|
+
def select[Ts](self, selector: Optional[Callable[[T], tuple[Ts]]] = ..., *, flavour: Type[tuple], by: Optional[Enum] = ...) -> tuple[Ts, ...]: ...
|
203
235
|
@overload
|
204
|
-
def select[*Ts](self, selector: Optional[Callable[[T], tuple[*Ts]]] =
|
236
|
+
def select[*Ts](self, selector: Optional[Callable[[T], tuple[*Ts]]] = ..., *, flavour: Type[tuple], by: Optional[Enum] = ...) -> tuple[tuple[*Ts]]: ...
|
205
237
|
@overload
|
206
|
-
def select[TFlavour](self, selector: Optional[Callable[[T], tuple]] =
|
238
|
+
def select[TFlavour](self, selector: Optional[Callable[[T], tuple]] = ..., *, flavour: Type[TFlavour], by: Optional[Enum] = ...) -> tuple[TFlavour]: ...
|
207
239
|
@abstractmethod
|
208
|
-
def select[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] =
|
240
|
+
def select[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] = ..., *, flavour: Type[TFlavour] = ..., by: JoinType = ...): ...
|
209
241
|
|
210
242
|
# endregion
|
211
243
|
# region select_one
|
212
244
|
@overload
|
213
245
|
def select_one(self) -> T: ...
|
214
246
|
@overload
|
215
|
-
def select_one[TFlavour](self, *, by: Optional[Enum] =
|
247
|
+
def select_one[TFlavour](self, *, by: Optional[Enum] = ..., flavour: Type[TFlavour]) -> TFlavour: ...
|
216
248
|
@overload
|
217
|
-
def select_one[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] =
|
249
|
+
def select_one[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] = ...) -> T1: ...
|
218
250
|
@overload
|
219
|
-
def select_one[*Ts](self, selector: Callable[[T], tuple[*Ts]], *, by: Optional[Enum] =
|
251
|
+
def select_one[*Ts](self, selector: Callable[[T], tuple[*Ts]], *, by: Optional[Enum] = ...) -> tuple[*Ts]: ...
|
220
252
|
@overload
|
221
|
-
def select_one[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] =
|
253
|
+
def select_one[T1](self, selector: Callable[[T], tuple[T1]], *, by: Optional[Enum] = ..., flavour: Type) -> T1: ...
|
222
254
|
@overload
|
223
|
-
def select_one[T1, TFlavour](self, selector: Callable[[T], T1], *, by: Optional[Enum] =
|
255
|
+
def select_one[T1, TFlavour](self, selector: Callable[[T], T1], *, by: Optional[Enum] = ..., flavour: Type[TFlavour]) -> T1: ...
|
224
256
|
@overload
|
225
|
-
def select_one[*Ts](self, selector: Callable[[T], tuple[*Ts]], *, by: Optional[Enum] =
|
257
|
+
def select_one[*Ts](self, selector: Callable[[T], tuple[*Ts]], *, by: Optional[Enum] = ..., flavour: Type[tuple]) -> tuple[*Ts]: ...
|
226
258
|
@overload
|
227
|
-
def select_one[TFlavour](self, selector: Callable[[T], tuple], *, by: Optional[Enum] =
|
259
|
+
def select_one[TFlavour](self, selector: Callable[[T], tuple], *, by: Optional[Enum] = ..., flavour: Type[TFlavour]) -> TFlavour: ...
|
228
260
|
@abstractmethod
|
229
|
-
def select_one[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] = lambda: None, *, flavour: Type[TFlavour] =
|
261
|
+
def select_one[TValue, TFlavour, *Ts](self, selector: Optional[Callable[[T], tuple[TValue, *Ts]]] = lambda: None, *, flavour: Type[TFlavour] = ..., by: Optional[Enum] = ...): ...
|
230
262
|
|
231
263
|
# endregion
|
232
264
|
# region group_by
|
233
265
|
@abstractmethod
|
234
|
-
def group_by[TRepo, *Ts](self, column: Callable[[T], TRepo]
|
266
|
+
def group_by[TRepo, *Ts](self, column: Callable[[T], TRepo]) -> IStatements[T]: ...
|
235
267
|
|
236
268
|
# endregion
|
237
269
|
|
@@ -13,4 +13,4 @@ from .update import UpdateQuery as UpdateQuery
|
|
13
13
|
from .upsert import UpsertQuery as UpsertQuery
|
14
14
|
from .where_condition import WhereCondition as WhereCondition
|
15
15
|
from .count import Count as Count
|
16
|
-
from
|
16
|
+
from .group_by import GroupBy as GroupBy
|
@@ -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
|
@@ -0,0 +1,47 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import override, Callable, TYPE_CHECKING, Any, Iterable
|
3
|
+
|
4
|
+
from ormlambda.common.abstract_classes.decomposition_query import ClauseInfo
|
5
|
+
|
6
|
+
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
from ormlambda import Table
|
9
|
+
|
10
|
+
from ormlambda.common.abstract_classes.decomposition_query import DecompositionQueryBase
|
11
|
+
from ormlambda.common.interfaces.IStatements import OrderType
|
12
|
+
|
13
|
+
|
14
|
+
class OrderQuery[T: Table](DecompositionQueryBase[T]):
|
15
|
+
ORDER = "ORDER BY"
|
16
|
+
|
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,)
|
22
|
+
|
23
|
+
self._order_type: list[OrderType] = [self.__cast_to_OrderType(x) for x in order_type]
|
24
|
+
|
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
|
38
|
+
|
39
|
+
@override
|
40
|
+
@property
|
41
|
+
def query(self) -> str:
|
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)}"
|
@@ -3,6 +3,7 @@ from typing import override, Type, Callable, TYPE_CHECKING
|
|
3
3
|
from ormlambda.common.abstract_classes.decomposition_query import DecompositionQueryBase
|
4
4
|
from ormlambda.common.enums.join_type import JoinType
|
5
5
|
from ormlambda.common.interfaces.IAggregate import IAggregate
|
6
|
+
import shapely as shp
|
6
7
|
|
7
8
|
if TYPE_CHECKING:
|
8
9
|
from ormlambda import Table
|
@@ -32,17 +33,20 @@ class Select[T: Type[Table]](DecompositionQueryBase[T]):
|
|
32
33
|
# def alias_children_resolver[Tclause: Type[Table]](self, clause_info: ClauseInfo[Tclause]):
|
33
34
|
# return f"{clause.table.__table_name__}_{name}"
|
34
35
|
|
36
|
+
# TODOL: see who to deal when we will have to add more mysql methods
|
35
37
|
@override
|
36
38
|
@property
|
37
39
|
def query(self) -> str:
|
38
|
-
cols:list[str] = []
|
40
|
+
cols: list[str] = []
|
39
41
|
for x in self.all_clauses:
|
40
|
-
|
42
|
+
if x.dtype is shp.Point:
|
43
|
+
cols.append(x.concat_with_alias(f"ST_AsText({self._table.__table_name__}.{x.column})"))
|
44
|
+
else:
|
45
|
+
cols.append(x.query)
|
41
46
|
|
42
|
-
if isinstance(x._row_column,IAggregate) and x._row_column.has_foreign_keys:
|
47
|
+
if isinstance(x._row_column, IAggregate) and x._row_column.has_foreign_keys:
|
43
48
|
self._fk_relationship.update(x._row_column.fk_relationship)
|
44
49
|
|
45
|
-
|
46
50
|
col: str = ", ".join(cols)
|
47
51
|
query: str = f"{self.CLAUSE} {col} FROM {self._table.__table_name__}"
|
48
52
|
alias = ""
|
@@ -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
|
@@ -0,0 +1,39 @@
|
|
1
|
+
from ormlambda.common.interfaces import IAggregate
|
2
|
+
import typing as tp
|
3
|
+
|
4
|
+
from ormlambda.common.abstract_classes.decomposition_query import DecompositionQueryBase, ClauseInfo
|
5
|
+
|
6
|
+
if tp.TYPE_CHECKING:
|
7
|
+
from ormlambda import Table
|
8
|
+
|
9
|
+
|
10
|
+
class Sum[T: tp.Type[Table]](DecompositionQueryBase[T], IAggregate[T]):
|
11
|
+
NAME: str = "SUM"
|
12
|
+
|
13
|
+
@tp.overload
|
14
|
+
def __init__[T: tp.Type[Table]](self, table: T, column: tp.Callable[[T], tp.Any], *, alias: bool = True, alias_name: str = ...) -> None: ...
|
15
|
+
|
16
|
+
def __init__(
|
17
|
+
self,
|
18
|
+
table: T,
|
19
|
+
column: str | tp.Callable[[T], tuple],
|
20
|
+
*,
|
21
|
+
alias: bool = True,
|
22
|
+
alias_name: str = "sum",
|
23
|
+
) -> None:
|
24
|
+
super().__init__(
|
25
|
+
table,
|
26
|
+
lambda_query=column,
|
27
|
+
alias=alias,
|
28
|
+
alias_name=alias_name,
|
29
|
+
)
|
30
|
+
|
31
|
+
def alias_children_resolver[Tclause: tp.Type[Table]](self, clause_info: ClauseInfo[Tclause]):
|
32
|
+
if isinstance(clause_info._row_column, IAggregate):
|
33
|
+
return clause_info._row_column.alias
|
34
|
+
return None
|
35
|
+
|
36
|
+
@property
|
37
|
+
def query(self) -> str:
|
38
|
+
col = ", ".join([x.query for x in self.all_clauses])
|
39
|
+
return f"{self.NAME}({col})"
|