ormlambda 2.11.2__tar.gz → 3.7.1__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.11.2 → ormlambda-3.7.1}/PKG-INFO +132 -68
- {ormlambda-2.11.2 → ormlambda-3.7.1}/README.md +131 -67
- {ormlambda-2.11.2 → ormlambda-3.7.1}/pyproject.toml +3 -2
- ormlambda-3.7.1/src/ormlambda/__init__.py +22 -0
- ormlambda-3.7.1/src/ormlambda/caster/__init__.py +3 -0
- ormlambda-3.7.1/src/ormlambda/caster/base_caster.py +69 -0
- ormlambda-3.7.1/src/ormlambda/caster/caster.py +48 -0
- ormlambda-3.7.1/src/ormlambda/caster/interfaces/ICaster.py +26 -0
- ormlambda-3.7.1/src/ormlambda/caster/interfaces/__init__.py +1 -0
- ormlambda-3.7.1/src/ormlambda/common/__init__.py +1 -0
- ormlambda-3.7.1/src/ormlambda/common/abstract_classes/__init__.py +3 -0
- ormlambda-3.7.1/src/ormlambda/common/abstract_classes/decomposition_query.py +182 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/common/abstract_classes/non_query_base.py +1 -1
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/common/enums/condition_types.py +2 -1
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/common/enums/join_type.py +4 -1
- ormlambda-3.7.1/src/ormlambda/common/errors/__init__.py +21 -0
- ormlambda-3.7.1/src/ormlambda/common/global_checker.py +28 -0
- ormlambda-3.7.1/src/ormlambda/common/interfaces/ICustomAlias.py +7 -0
- ormlambda-3.7.1/src/ormlambda/common/interfaces/IDecompositionQuery.py +33 -0
- ormlambda-3.7.1/src/ormlambda/common/interfaces/IJoinSelector.py +21 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/common/interfaces/__init__.py +4 -6
- ormlambda-3.7.1/src/ormlambda/components/__init__.py +4 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/components/insert/abstract_insert.py +1 -1
- ormlambda-3.7.1/src/ormlambda/components/select/ISelect.py +17 -0
- ormlambda-3.7.1/src/ormlambda/components/select/__init__.py +1 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/components/update/abstract_update.py +4 -4
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/components/upsert/abstract_upsert.py +1 -1
- ormlambda-3.7.1/src/ormlambda/databases/__init__.py +5 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/__init__.py +4 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/caster/__init__.py +1 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/caster/caster.py +38 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/caster/read.py +39 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/caster/types/__init__.py +8 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/caster/types/bytes.py +31 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/caster/types/datetime.py +34 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/caster/types/float.py +31 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/caster/types/int.py +31 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/caster/types/iterable.py +31 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/caster/types/none.py +30 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/caster/types/point.py +43 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/caster/types/string.py +31 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/caster/write.py +37 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/clauses/ST_AsText.py +36 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/clauses/ST_Contains.py +31 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/databases/my_sql/clauses/__init__.py +6 -4
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/clauses/alias.py +34 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/clauses/count.py +43 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/databases/my_sql/clauses/create_database.py +3 -4
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/databases/my_sql/clauses/delete.py +10 -10
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/databases/my_sql/clauses/drop_database.py +3 -5
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/databases/my_sql/clauses/drop_table.py +3 -3
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/databases/my_sql/clauses/group_by.py +4 -7
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/databases/my_sql/clauses/insert.py +33 -19
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/clauses/joins.py +149 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/databases/my_sql/clauses/limit.py +1 -1
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/databases/my_sql/clauses/offset.py +1 -1
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/clauses/order.py +60 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/clauses/select.py +50 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/clauses/update.py +71 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/databases/my_sql/clauses/upsert.py +2 -2
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/clauses/where.py +45 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/functions/concat.py +38 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/functions/max.py +43 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/functions/min.py +43 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/functions/sum.py +43 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/join_context.py +75 -0
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/repository/__init__.py +1 -0
- {ormlambda-2.11.2/src/ormlambda/databases/my_sql → ormlambda-3.7.1/src/ormlambda/databases/my_sql/repository}/repository.py +114 -74
- ormlambda-3.7.1/src/ormlambda/databases/my_sql/statements.py +421 -0
- ormlambda-3.7.1/src/ormlambda/engine/template.py +47 -0
- ormlambda-3.7.1/src/ormlambda/model/base_model.py +37 -0
- ormlambda-3.7.1/src/ormlambda/repository/__init__.py +2 -0
- ormlambda-3.7.1/src/ormlambda/repository/base_repository.py +14 -0
- ormlambda-3.7.1/src/ormlambda/repository/interfaces/IDatabaseConnection.py +12 -0
- {ormlambda-2.11.2/src/ormlambda/common → ormlambda-3.7.1/src/ormlambda/repository}/interfaces/IRepositoryBase.py +6 -5
- ormlambda-3.7.1/src/ormlambda/repository/interfaces/__init__.py +2 -0
- ormlambda-3.7.1/src/ormlambda/sql/__init__.py +3 -0
- ormlambda-3.7.1/src/ormlambda/sql/clause_info/__init__.py +3 -0
- ormlambda-3.7.1/src/ormlambda/sql/clause_info/clause_info.py +434 -0
- ormlambda-3.7.1/src/ormlambda/sql/clause_info/clause_info_context.py +87 -0
- ormlambda-3.7.1/src/ormlambda/sql/clause_info/interface/IAggregate.py +10 -0
- ormlambda-3.7.1/src/ormlambda/sql/clause_info/interface/__init__.py +1 -0
- ormlambda-3.7.1/src/ormlambda/sql/column.py +126 -0
- ormlambda-3.7.1/src/ormlambda/sql/comparer.py +156 -0
- ormlambda-3.7.1/src/ormlambda/sql/foreign_key.py +115 -0
- ormlambda-3.7.1/src/ormlambda/sql/table/__init__.py +1 -0
- {ormlambda-2.11.2/src/ormlambda/utils → ormlambda-3.7.1/src/ormlambda/sql/table}/fields.py +6 -5
- {ormlambda-2.11.2/src/ormlambda/utils → ormlambda-3.7.1/src/ormlambda/sql/table}/table_constructor.py +43 -91
- ormlambda-3.7.1/src/ormlambda/sql/types.py +25 -0
- ormlambda-3.7.1/src/ormlambda/statements/__init__.py +2 -0
- ormlambda-3.7.1/src/ormlambda/statements/base_statement.py +129 -0
- ormlambda-3.7.1/src/ormlambda/statements/interfaces/IStatements.py +331 -0
- ormlambda-3.7.1/src/ormlambda/statements/interfaces/__init__.py +1 -0
- ormlambda-3.7.1/src/ormlambda/statements/types.py +51 -0
- ormlambda-3.7.1/src/ormlambda/utils/__init__.py +1 -0
- ormlambda-3.7.1/src/ormlambda/utils/module_tree/__init__.py +1 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/utils/module_tree/dynamic_module.py +20 -14
- ormlambda-2.11.2/src/ormlambda/__init__.py +0 -20
- ormlambda-2.11.2/src/ormlambda/common/__init__.py +0 -1
- ormlambda-2.11.2/src/ormlambda/common/abstract_classes/__init__.py +0 -3
- ormlambda-2.11.2/src/ormlambda/common/abstract_classes/abstract_model.py +0 -115
- ormlambda-2.11.2/src/ormlambda/common/abstract_classes/decomposition_query.py +0 -384
- ormlambda-2.11.2/src/ormlambda/common/errors/__init__.py +0 -8
- ormlambda-2.11.2/src/ormlambda/common/interfaces/IAggregate.py +0 -10
- ormlambda-2.11.2/src/ormlambda/common/interfaces/ICustomAlias.py +0 -4
- ormlambda-2.11.2/src/ormlambda/common/interfaces/IDecompositionQuery.py +0 -58
- ormlambda-2.11.2/src/ormlambda/common/interfaces/IStatements.py +0 -348
- ormlambda-2.11.2/src/ormlambda/components/where/__init__.py +0 -1
- ormlambda-2.11.2/src/ormlambda/components/where/abstract_where.py +0 -15
- ormlambda-2.11.2/src/ormlambda/databases/my_sql/__init__.py +0 -2
- ormlambda-2.11.2/src/ormlambda/databases/my_sql/clauses/alias.py +0 -31
- ormlambda-2.11.2/src/ormlambda/databases/my_sql/clauses/count.py +0 -39
- ormlambda-2.11.2/src/ormlambda/databases/my_sql/clauses/joins.py +0 -142
- ormlambda-2.11.2/src/ormlambda/databases/my_sql/clauses/order.py +0 -47
- ormlambda-2.11.2/src/ormlambda/databases/my_sql/clauses/select.py +0 -61
- ormlambda-2.11.2/src/ormlambda/databases/my_sql/clauses/update.py +0 -46
- ormlambda-2.11.2/src/ormlambda/databases/my_sql/clauses/where_condition.py +0 -222
- ormlambda-2.11.2/src/ormlambda/databases/my_sql/functions/concat.py +0 -41
- ormlambda-2.11.2/src/ormlambda/databases/my_sql/functions/max.py +0 -39
- ormlambda-2.11.2/src/ormlambda/databases/my_sql/functions/min.py +0 -39
- ormlambda-2.11.2/src/ormlambda/databases/my_sql/functions/sum.py +0 -39
- ormlambda-2.11.2/src/ormlambda/databases/my_sql/statements.py +0 -325
- ormlambda-2.11.2/src/ormlambda/model_base.py +0 -36
- ormlambda-2.11.2/src/ormlambda/utils/__init__.py +0 -3
- ormlambda-2.11.2/src/ormlambda/utils/column.py +0 -105
- ormlambda-2.11.2/src/ormlambda/utils/foreign_key.py +0 -81
- ormlambda-2.11.2/src/ormlambda/utils/lambda_disassembler/__init__.py +0 -4
- ormlambda-2.11.2/src/ormlambda/utils/lambda_disassembler/dis_types.py +0 -133
- ormlambda-2.11.2/src/ormlambda/utils/lambda_disassembler/disassembler.py +0 -69
- ormlambda-2.11.2/src/ormlambda/utils/lambda_disassembler/dtypes.py +0 -103
- ormlambda-2.11.2/src/ormlambda/utils/lambda_disassembler/name_of.py +0 -41
- ormlambda-2.11.2/src/ormlambda/utils/lambda_disassembler/nested_element.py +0 -44
- ormlambda-2.11.2/src/ormlambda/utils/lambda_disassembler/tree_instruction.py +0 -145
- {ormlambda-2.11.2 → ormlambda-3.7.1}/LICENSE +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/common/abstract_classes/query_base.py +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/common/enums/__init__.py +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/common/interfaces/INonQueryCommand.py +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/common/interfaces/IQueryCommand.py +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/components/delete/IDelete.py +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/components/delete/__init__.py +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/components/delete/abstract_delete.py +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/components/insert/IInsert.py +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/components/insert/__init__.py +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/components/update/IUpdate.py +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/components/update/__init__.py +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/components/upsert/IUpsert.py +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/components/upsert/__init__.py +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/databases/my_sql/functions/__init__.py +0 -0
- {ormlambda-2.11.2/src/ormlambda/components → ormlambda-3.7.1/src/ormlambda/engine}/__init__.py +0 -0
- {ormlambda-2.11.2/src/ormlambda/databases → ormlambda-3.7.1/src/ormlambda/model}/__init__.py +0 -0
- {ormlambda-2.11.2/src/ormlambda/utils → ormlambda-3.7.1/src/ormlambda/sql}/dtypes.py +0 -0
- {ormlambda-2.11.2/src/ormlambda/utils/module_tree → ormlambda-3.7.1/src/ormlambda/sql/interfaces}/__init__.py +0 -0
- {ormlambda-2.11.2 → ormlambda-3.7.1}/src/ormlambda/utils/module_tree/dfs_traversal.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: ormlambda
|
3
|
-
Version:
|
3
|
+
Version: 3.7.1
|
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
|
@@ -9,6 +9,7 @@ Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.12
|
10
10
|
Requires-Dist: fluent-validation (==4.3.1)
|
11
11
|
Requires-Dist: mysql-connector-python (>=9.0.0,<10.0.0)
|
12
|
+
Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
|
12
13
|
Requires-Dist: shapely (>=2.0.6,<3.0.0)
|
13
14
|
Description-Content-Type: text/markdown
|
14
15
|
|
@@ -36,9 +37,17 @@ database = MySQLRepository(user=USERNAME, password=PASSWORD, database="sakila",
|
|
36
37
|
|
37
38
|
## Select all columns
|
38
39
|
```python
|
39
|
-
from
|
40
|
+
from ormlambda import ORM
|
41
|
+
from ormlambda.databases.my_sql import MySQLRepository
|
42
|
+
|
43
|
+
from models.address import Address
|
44
|
+
from config import config_dict
|
45
|
+
|
46
|
+
db = MySQLRepository(**config_dict)
|
47
|
+
|
48
|
+
AddressModel = ORM(Address,db)
|
40
49
|
|
41
|
-
result = AddressModel
|
50
|
+
result = AddressModel.select()
|
42
51
|
```
|
43
52
|
The `result` var will be of type `tuple[Address, ...]`
|
44
53
|
|
@@ -46,11 +55,13 @@ The `result` var will be of type `tuple[Address, ...]`
|
|
46
55
|
Once the `AddressModel` class is created, we will not only be able to access all the information in that table, but also all the information in all the tables that have foreign keys related to it."
|
47
56
|
|
48
57
|
```python
|
49
|
-
from
|
50
|
-
from models.address import AddressModel
|
58
|
+
from models.address import Address
|
51
59
|
|
60
|
+
db = MySQLRepository(**config_dict)
|
52
61
|
|
53
|
-
|
62
|
+
AddressModel = ORM(Address,db)
|
63
|
+
|
64
|
+
result = AddressModel.where(Address.City.Country.country.regex(r"^[aA]")).select(
|
54
65
|
lambda address: (
|
55
66
|
address,
|
56
67
|
address.City,
|
@@ -64,31 +75,51 @@ If we were used `select_one` method, we retrieved `tuple[Address, City, Country]
|
|
64
75
|
|
65
76
|
## Filter by `where` condition
|
66
77
|
|
78
|
+
we can use only the Original Table to pass the variables like
|
67
79
|
```python
|
68
|
-
result = AddressModel
|
80
|
+
result = AddressModel.where(
|
81
|
+
[
|
82
|
+
Address.address_id >= 10,
|
83
|
+
Address.address_id <= 30,
|
84
|
+
]
|
85
|
+
).select()
|
69
86
|
```
|
87
|
+
Or by using a lambda function that returns an iterable for tables where the name is unusually long.
|
88
|
+
|
89
|
+
```python
|
90
|
+
result = AddressModel.where(
|
91
|
+
lambda x: [
|
92
|
+
x.address_id >= 10,
|
93
|
+
x.address_id <= 30,
|
94
|
+
]
|
95
|
+
).select()
|
70
96
|
|
97
|
+
```
|
71
98
|
Additionally, we can filter by others tables. For example, we can return all addresses for each city where `country_id` = 87 (Spain)
|
72
99
|
|
73
100
|
```python
|
74
|
-
result = AddressModel
|
101
|
+
result = AddressModel.where(Address.City.Country.country_id == 87).select()
|
75
102
|
```
|
76
103
|
|
77
104
|
We can also return `Address`, `City` or `Country` if needed.
|
78
105
|
|
79
106
|
```python
|
80
|
-
result = AddressModel
|
107
|
+
result = AddressModel.where(Address.City.Country.country_id == 87).select(lambda x: (x, x.City, x.City.Country))
|
81
108
|
```
|
82
109
|
|
83
110
|
### Pass variables to the `where` method
|
84
|
-
Since we generally work with lambda methods, I often have to work with `bytecode` to retrieve the name of the string variables. For this reason, it's imperative that we map these variables to replace them with the actual values.
|
85
|
-
|
86
111
|
```python
|
87
112
|
LOWER = 10
|
88
113
|
UPPER = 30
|
89
|
-
|
114
|
+
|
115
|
+
AddressModel.where(
|
116
|
+
[
|
117
|
+
Address.address_id >= LOWER,
|
118
|
+
Address.address_id <= UPPER,
|
119
|
+
]
|
120
|
+
).select()
|
90
121
|
```
|
91
|
-
|
122
|
+
|
92
123
|
|
93
124
|
## Writable methods INSERT, UPDATE, DELETE
|
94
125
|
The easiest way to add or delete data in your database is by using its appropiate methods. You just need to instantiate an object with the data and pass it to the method
|
@@ -97,22 +128,21 @@ The easiest way to add or delete data in your database is by using its appropiat
|
|
97
128
|
```python
|
98
129
|
address = Address(address_id=1, address="C/ ...", phone="XXXXXXXXX", postal_code="28026")
|
99
130
|
|
100
|
-
AddressModel
|
131
|
+
AddressModel.insert(address)
|
101
132
|
```
|
102
133
|
|
103
134
|
### Update
|
104
|
-
|
105
135
|
You can use either the properties of the same object or `str` values.
|
106
136
|
```python
|
107
137
|
|
108
|
-
AddressModel
|
138
|
+
AddressModel.where(lambda x: x.address_id == 1).update(
|
109
139
|
{
|
110
140
|
Address.phone: "YYYYYYYYY",
|
111
141
|
Address.postal_code: "28030",
|
112
142
|
}
|
113
143
|
)
|
114
144
|
|
115
|
-
AddressModel
|
145
|
+
AddressModel.where(lambda x: x.address_id == 1).update(
|
116
146
|
{
|
117
147
|
"phone": "YYYYYYYYY",
|
118
148
|
"postal_code": "28030",
|
@@ -122,7 +152,7 @@ AddressModel(database).where(lambda x: x.address_id == 1).update(
|
|
122
152
|
### Delete
|
123
153
|
|
124
154
|
```python
|
125
|
-
AddressModel
|
155
|
+
AddressModel.where(lambda x: x.address_id == 1).delete()
|
126
156
|
```
|
127
157
|
|
128
158
|
|
@@ -139,67 +169,46 @@ The easiest way to map your tables is:
|
|
139
169
|
|
140
170
|
```python
|
141
171
|
from datetime import datetime
|
142
|
-
|
143
172
|
from ormlambda import (
|
144
|
-
Column,
|
145
173
|
Table,
|
146
|
-
|
174
|
+
Column,
|
147
175
|
ForeignKey,
|
148
176
|
)
|
149
|
-
from ormlambda.common.interfaces import IStatements_two_generic, IRepositoryBase
|
150
|
-
|
151
177
|
|
152
178
|
class Country(Table):
|
153
179
|
__table_name__ = "country"
|
154
180
|
|
155
|
-
country_id: int = Column
|
156
|
-
country: str
|
157
|
-
last_update: datetime
|
158
|
-
|
159
|
-
|
160
|
-
class Address(Table):
|
161
|
-
__table_name__ = "address"
|
162
|
-
|
163
|
-
address_id: int = Column[int](is_primary_key=True)
|
164
|
-
address: str
|
165
|
-
address2: str
|
166
|
-
district: str
|
167
|
-
city_id: int
|
168
|
-
postal_code: str
|
169
|
-
phone: str
|
170
|
-
location: str
|
171
|
-
last_update: datetime = Column[datetime](is_auto_generated=True)
|
172
|
-
|
173
|
-
City = ForeignKey["Address", City](__table_name__, City, lambda a, c: a.city_id == c.city_id)
|
181
|
+
country_id: Column[int] = Column(int, is_primary_key=True)
|
182
|
+
country: Column[str]
|
183
|
+
last_update: Column[datetime]
|
174
184
|
|
175
185
|
|
176
186
|
class City(Table):
|
177
187
|
__table_name__ = "city"
|
178
188
|
|
179
|
-
city_id: int = Column
|
180
|
-
city: str
|
181
|
-
country_id: int
|
182
|
-
last_update: datetime
|
183
|
-
|
184
|
-
Country = ForeignKey["City", Country](__table_name__, Country, lambda ci, co: ci.country_id == co.country_id)
|
185
|
-
```
|
189
|
+
city_id: Column[int] = Column(int, is_primary_key=True)
|
190
|
+
city: Column[str]
|
191
|
+
country_id: Column[int]
|
192
|
+
last_update: Column[datetime]
|
186
193
|
|
187
|
-
|
194
|
+
Country = ForeignKey["City", Country](Country, lambda ci, co: ci.country_id == co.country_id)
|
188
195
|
|
189
|
-
```python
|
190
|
-
class CountryModel(BaseModel[Country]):
|
191
|
-
def __new__[TRepo](cls, repository: IRepositoryBase[TRepo]):
|
192
|
-
return super().__new__(cls, Country, repository)
|
193
196
|
|
197
|
+
class Address(Table):
|
198
|
+
__table_name__ = "address"
|
194
199
|
|
195
|
-
|
196
|
-
|
197
|
-
|
200
|
+
address_id: Column[int] = Column(int, is_primary_key=True)
|
201
|
+
address: Column[str]
|
202
|
+
address2: Column[str]
|
203
|
+
district: Column[str]
|
204
|
+
city_id: Column[int]
|
205
|
+
postal_code: Column[str]
|
206
|
+
phone: Column[str]
|
207
|
+
location: Column[str]
|
208
|
+
last_update: Column[datetime] = Column(datetime, is_auto_generated=True)
|
198
209
|
|
210
|
+
City = ForeignKey["Address", City](City, lambda a, c: a.city_id == c.city_id)
|
199
211
|
|
200
|
-
class CityModel(BaseModel[City]):
|
201
|
-
def __new__[TRepo](cls, repository: IRepositoryBase[TRepo]):
|
202
|
-
return super().__new__(cls, City, repository)
|
203
212
|
```
|
204
213
|
|
205
214
|
# Creating complex queries with lambda
|
@@ -211,10 +220,10 @@ To retrieve all `Address` object where the fk reference to the `City` table, and
|
|
211
220
|
|
212
221
|
```python
|
213
222
|
result = (
|
214
|
-
AddressModel
|
223
|
+
AddressModel
|
215
224
|
.order(lambda a: a.address_id, order_type="DESC")
|
216
225
|
.where(lambda x: x.City.Country.country_id >= 50)
|
217
|
-
.select(
|
226
|
+
.select(Address)
|
218
227
|
)
|
219
228
|
|
220
229
|
```
|
@@ -223,9 +232,9 @@ Also you can use `ConditionType` enum for `regular expressions` and get, for exa
|
|
223
232
|
|
224
233
|
```python
|
225
234
|
address, city, country = (
|
226
|
-
AddressModel
|
227
|
-
.order(
|
228
|
-
.where(
|
235
|
+
AddressModel
|
236
|
+
.order(Address.address_id, order_type="DESC")
|
237
|
+
.where(Address.City.Country.country.regex(r"^[A]"))
|
229
238
|
.limit(100)
|
230
239
|
.select(
|
231
240
|
lambda a: (
|
@@ -238,7 +247,6 @@ address, city, country = (
|
|
238
247
|
|
239
248
|
|
240
249
|
for a in address:
|
241
|
-
|
242
250
|
print(a.address_id)
|
243
251
|
|
244
252
|
for c in city:
|
@@ -253,8 +261,7 @@ In the example above, we see that the `result` var returns a tuple of tuples. Ho
|
|
253
261
|
|
254
262
|
```python
|
255
263
|
result = (
|
256
|
-
|
257
|
-
.where(lambda x: (x.City.Country, ConditionType.REGEXP, r"^[A]"))
|
264
|
+
AddressModel.where(Address.City.Country.country.regex(r"^[A]"))
|
258
265
|
.limit(100)
|
259
266
|
.select(
|
260
267
|
lambda a: (
|
@@ -270,4 +277,61 @@ result = (
|
|
270
277
|
|
271
278
|
with this approach, we will obtain a dictionary where the key will be the concatenation between the selected table name and the column name specified in the lambda function, to avoid overwritting data from tables that sharing column names.
|
272
279
|
|
280
|
+
# Other methods
|
273
281
|
|
282
|
+
## max
|
283
|
+
```python
|
284
|
+
res = AddressModel.max(Address.address_id, execute=True)
|
285
|
+
```
|
286
|
+
## min
|
287
|
+
```python
|
288
|
+
res = AddressModel.min(Address.address_id, execute=True)
|
289
|
+
```
|
290
|
+
## sum
|
291
|
+
```python
|
292
|
+
res = AddressModel.sum(Address.address_id, execute=True)
|
293
|
+
```
|
294
|
+
## count
|
295
|
+
```python
|
296
|
+
res = AddressModel.count(Address.address_id, execute=True)
|
297
|
+
```
|
298
|
+
|
299
|
+
## Combine aggregation method
|
300
|
+
As shown in the previous examples, setting the `execute` attribute to `True` allows us to perform the corresponding query in a single line. However, if you're looking to improve efficiency, you can combine all of them into one query.
|
301
|
+
```python
|
302
|
+
result = AddressModel.select_one(
|
303
|
+
lambda x: (
|
304
|
+
AddressModel.min(x.address_id),
|
305
|
+
AddressModel.max(x.address_id),
|
306
|
+
AddressModel.count(x.address_id),
|
307
|
+
),flavour=dict
|
308
|
+
)
|
309
|
+
```
|
310
|
+
Getting something like
|
311
|
+
|
312
|
+
```python
|
313
|
+
# {
|
314
|
+
# "min": 1,
|
315
|
+
# "max": 605,
|
316
|
+
# "count": 603,
|
317
|
+
# }
|
318
|
+
```
|
319
|
+
|
320
|
+
You also can use custom alias for each method
|
321
|
+
|
322
|
+
```python
|
323
|
+
AddressModel.select_one(
|
324
|
+
lambda x: (
|
325
|
+
AddressModel.min(x.address_id),
|
326
|
+
AddressModel.max(x.address_id, alias="custom-max"),
|
327
|
+
AddressModel.count(x.address_id),
|
328
|
+
),
|
329
|
+
flavour=dict,
|
330
|
+
)
|
331
|
+
|
332
|
+
# {
|
333
|
+
# "min": 1,
|
334
|
+
# "custom-max": 605,
|
335
|
+
# "count": 603,
|
336
|
+
# }
|
337
|
+
```
|
@@ -22,9 +22,17 @@ database = MySQLRepository(user=USERNAME, password=PASSWORD, database="sakila",
|
|
22
22
|
|
23
23
|
## Select all columns
|
24
24
|
```python
|
25
|
-
from
|
25
|
+
from ormlambda import ORM
|
26
|
+
from ormlambda.databases.my_sql import MySQLRepository
|
27
|
+
|
28
|
+
from models.address import Address
|
29
|
+
from config import config_dict
|
30
|
+
|
31
|
+
db = MySQLRepository(**config_dict)
|
32
|
+
|
33
|
+
AddressModel = ORM(Address,db)
|
26
34
|
|
27
|
-
result = AddressModel
|
35
|
+
result = AddressModel.select()
|
28
36
|
```
|
29
37
|
The `result` var will be of type `tuple[Address, ...]`
|
30
38
|
|
@@ -32,11 +40,13 @@ The `result` var will be of type `tuple[Address, ...]`
|
|
32
40
|
Once the `AddressModel` class is created, we will not only be able to access all the information in that table, but also all the information in all the tables that have foreign keys related to it."
|
33
41
|
|
34
42
|
```python
|
35
|
-
from
|
36
|
-
from models.address import AddressModel
|
43
|
+
from models.address import Address
|
37
44
|
|
45
|
+
db = MySQLRepository(**config_dict)
|
38
46
|
|
39
|
-
|
47
|
+
AddressModel = ORM(Address,db)
|
48
|
+
|
49
|
+
result = AddressModel.where(Address.City.Country.country.regex(r"^[aA]")).select(
|
40
50
|
lambda address: (
|
41
51
|
address,
|
42
52
|
address.City,
|
@@ -50,31 +60,51 @@ If we were used `select_one` method, we retrieved `tuple[Address, City, Country]
|
|
50
60
|
|
51
61
|
## Filter by `where` condition
|
52
62
|
|
63
|
+
we can use only the Original Table to pass the variables like
|
53
64
|
```python
|
54
|
-
result = AddressModel
|
65
|
+
result = AddressModel.where(
|
66
|
+
[
|
67
|
+
Address.address_id >= 10,
|
68
|
+
Address.address_id <= 30,
|
69
|
+
]
|
70
|
+
).select()
|
55
71
|
```
|
72
|
+
Or by using a lambda function that returns an iterable for tables where the name is unusually long.
|
73
|
+
|
74
|
+
```python
|
75
|
+
result = AddressModel.where(
|
76
|
+
lambda x: [
|
77
|
+
x.address_id >= 10,
|
78
|
+
x.address_id <= 30,
|
79
|
+
]
|
80
|
+
).select()
|
56
81
|
|
82
|
+
```
|
57
83
|
Additionally, we can filter by others tables. For example, we can return all addresses for each city where `country_id` = 87 (Spain)
|
58
84
|
|
59
85
|
```python
|
60
|
-
result = AddressModel
|
86
|
+
result = AddressModel.where(Address.City.Country.country_id == 87).select()
|
61
87
|
```
|
62
88
|
|
63
89
|
We can also return `Address`, `City` or `Country` if needed.
|
64
90
|
|
65
91
|
```python
|
66
|
-
result = AddressModel
|
92
|
+
result = AddressModel.where(Address.City.Country.country_id == 87).select(lambda x: (x, x.City, x.City.Country))
|
67
93
|
```
|
68
94
|
|
69
95
|
### Pass variables to the `where` method
|
70
|
-
Since we generally work with lambda methods, I often have to work with `bytecode` to retrieve the name of the string variables. For this reason, it's imperative that we map these variables to replace them with the actual values.
|
71
|
-
|
72
96
|
```python
|
73
97
|
LOWER = 10
|
74
98
|
UPPER = 30
|
75
|
-
|
99
|
+
|
100
|
+
AddressModel.where(
|
101
|
+
[
|
102
|
+
Address.address_id >= LOWER,
|
103
|
+
Address.address_id <= UPPER,
|
104
|
+
]
|
105
|
+
).select()
|
76
106
|
```
|
77
|
-
|
107
|
+
|
78
108
|
|
79
109
|
## Writable methods INSERT, UPDATE, DELETE
|
80
110
|
The easiest way to add or delete data in your database is by using its appropiate methods. You just need to instantiate an object with the data and pass it to the method
|
@@ -83,22 +113,21 @@ The easiest way to add or delete data in your database is by using its appropiat
|
|
83
113
|
```python
|
84
114
|
address = Address(address_id=1, address="C/ ...", phone="XXXXXXXXX", postal_code="28026")
|
85
115
|
|
86
|
-
AddressModel
|
116
|
+
AddressModel.insert(address)
|
87
117
|
```
|
88
118
|
|
89
119
|
### Update
|
90
|
-
|
91
120
|
You can use either the properties of the same object or `str` values.
|
92
121
|
```python
|
93
122
|
|
94
|
-
AddressModel
|
123
|
+
AddressModel.where(lambda x: x.address_id == 1).update(
|
95
124
|
{
|
96
125
|
Address.phone: "YYYYYYYYY",
|
97
126
|
Address.postal_code: "28030",
|
98
127
|
}
|
99
128
|
)
|
100
129
|
|
101
|
-
AddressModel
|
130
|
+
AddressModel.where(lambda x: x.address_id == 1).update(
|
102
131
|
{
|
103
132
|
"phone": "YYYYYYYYY",
|
104
133
|
"postal_code": "28030",
|
@@ -108,7 +137,7 @@ AddressModel(database).where(lambda x: x.address_id == 1).update(
|
|
108
137
|
### Delete
|
109
138
|
|
110
139
|
```python
|
111
|
-
AddressModel
|
140
|
+
AddressModel.where(lambda x: x.address_id == 1).delete()
|
112
141
|
```
|
113
142
|
|
114
143
|
|
@@ -125,67 +154,46 @@ The easiest way to map your tables is:
|
|
125
154
|
|
126
155
|
```python
|
127
156
|
from datetime import datetime
|
128
|
-
|
129
157
|
from ormlambda import (
|
130
|
-
Column,
|
131
158
|
Table,
|
132
|
-
|
159
|
+
Column,
|
133
160
|
ForeignKey,
|
134
161
|
)
|
135
|
-
from ormlambda.common.interfaces import IStatements_two_generic, IRepositoryBase
|
136
|
-
|
137
162
|
|
138
163
|
class Country(Table):
|
139
164
|
__table_name__ = "country"
|
140
165
|
|
141
|
-
country_id: int = Column
|
142
|
-
country: str
|
143
|
-
last_update: datetime
|
144
|
-
|
145
|
-
|
146
|
-
class Address(Table):
|
147
|
-
__table_name__ = "address"
|
148
|
-
|
149
|
-
address_id: int = Column[int](is_primary_key=True)
|
150
|
-
address: str
|
151
|
-
address2: str
|
152
|
-
district: str
|
153
|
-
city_id: int
|
154
|
-
postal_code: str
|
155
|
-
phone: str
|
156
|
-
location: str
|
157
|
-
last_update: datetime = Column[datetime](is_auto_generated=True)
|
158
|
-
|
159
|
-
City = ForeignKey["Address", City](__table_name__, City, lambda a, c: a.city_id == c.city_id)
|
166
|
+
country_id: Column[int] = Column(int, is_primary_key=True)
|
167
|
+
country: Column[str]
|
168
|
+
last_update: Column[datetime]
|
160
169
|
|
161
170
|
|
162
171
|
class City(Table):
|
163
172
|
__table_name__ = "city"
|
164
173
|
|
165
|
-
city_id: int = Column
|
166
|
-
city: str
|
167
|
-
country_id: int
|
168
|
-
last_update: datetime
|
169
|
-
|
170
|
-
Country = ForeignKey["City", Country](__table_name__, Country, lambda ci, co: ci.country_id == co.country_id)
|
171
|
-
```
|
174
|
+
city_id: Column[int] = Column(int, is_primary_key=True)
|
175
|
+
city: Column[str]
|
176
|
+
country_id: Column[int]
|
177
|
+
last_update: Column[datetime]
|
172
178
|
|
173
|
-
|
179
|
+
Country = ForeignKey["City", Country](Country, lambda ci, co: ci.country_id == co.country_id)
|
174
180
|
|
175
|
-
```python
|
176
|
-
class CountryModel(BaseModel[Country]):
|
177
|
-
def __new__[TRepo](cls, repository: IRepositoryBase[TRepo]):
|
178
|
-
return super().__new__(cls, Country, repository)
|
179
181
|
|
182
|
+
class Address(Table):
|
183
|
+
__table_name__ = "address"
|
180
184
|
|
181
|
-
|
182
|
-
|
183
|
-
|
185
|
+
address_id: Column[int] = Column(int, is_primary_key=True)
|
186
|
+
address: Column[str]
|
187
|
+
address2: Column[str]
|
188
|
+
district: Column[str]
|
189
|
+
city_id: Column[int]
|
190
|
+
postal_code: Column[str]
|
191
|
+
phone: Column[str]
|
192
|
+
location: Column[str]
|
193
|
+
last_update: Column[datetime] = Column(datetime, is_auto_generated=True)
|
184
194
|
|
195
|
+
City = ForeignKey["Address", City](City, lambda a, c: a.city_id == c.city_id)
|
185
196
|
|
186
|
-
class CityModel(BaseModel[City]):
|
187
|
-
def __new__[TRepo](cls, repository: IRepositoryBase[TRepo]):
|
188
|
-
return super().__new__(cls, City, repository)
|
189
197
|
```
|
190
198
|
|
191
199
|
# Creating complex queries with lambda
|
@@ -197,10 +205,10 @@ To retrieve all `Address` object where the fk reference to the `City` table, and
|
|
197
205
|
|
198
206
|
```python
|
199
207
|
result = (
|
200
|
-
AddressModel
|
208
|
+
AddressModel
|
201
209
|
.order(lambda a: a.address_id, order_type="DESC")
|
202
210
|
.where(lambda x: x.City.Country.country_id >= 50)
|
203
|
-
.select(
|
211
|
+
.select(Address)
|
204
212
|
)
|
205
213
|
|
206
214
|
```
|
@@ -209,9 +217,9 @@ Also you can use `ConditionType` enum for `regular expressions` and get, for exa
|
|
209
217
|
|
210
218
|
```python
|
211
219
|
address, city, country = (
|
212
|
-
AddressModel
|
213
|
-
.order(
|
214
|
-
.where(
|
220
|
+
AddressModel
|
221
|
+
.order(Address.address_id, order_type="DESC")
|
222
|
+
.where(Address.City.Country.country.regex(r"^[A]"))
|
215
223
|
.limit(100)
|
216
224
|
.select(
|
217
225
|
lambda a: (
|
@@ -224,7 +232,6 @@ address, city, country = (
|
|
224
232
|
|
225
233
|
|
226
234
|
for a in address:
|
227
|
-
|
228
235
|
print(a.address_id)
|
229
236
|
|
230
237
|
for c in city:
|
@@ -239,8 +246,7 @@ In the example above, we see that the `result` var returns a tuple of tuples. Ho
|
|
239
246
|
|
240
247
|
```python
|
241
248
|
result = (
|
242
|
-
|
243
|
-
.where(lambda x: (x.City.Country, ConditionType.REGEXP, r"^[A]"))
|
249
|
+
AddressModel.where(Address.City.Country.country.regex(r"^[A]"))
|
244
250
|
.limit(100)
|
245
251
|
.select(
|
246
252
|
lambda a: (
|
@@ -256,3 +262,61 @@ result = (
|
|
256
262
|
|
257
263
|
with this approach, we will obtain a dictionary where the key will be the concatenation between the selected table name and the column name specified in the lambda function, to avoid overwritting data from tables that sharing column names.
|
258
264
|
|
265
|
+
# Other methods
|
266
|
+
|
267
|
+
## max
|
268
|
+
```python
|
269
|
+
res = AddressModel.max(Address.address_id, execute=True)
|
270
|
+
```
|
271
|
+
## min
|
272
|
+
```python
|
273
|
+
res = AddressModel.min(Address.address_id, execute=True)
|
274
|
+
```
|
275
|
+
## sum
|
276
|
+
```python
|
277
|
+
res = AddressModel.sum(Address.address_id, execute=True)
|
278
|
+
```
|
279
|
+
## count
|
280
|
+
```python
|
281
|
+
res = AddressModel.count(Address.address_id, execute=True)
|
282
|
+
```
|
283
|
+
|
284
|
+
## Combine aggregation method
|
285
|
+
As shown in the previous examples, setting the `execute` attribute to `True` allows us to perform the corresponding query in a single line. However, if you're looking to improve efficiency, you can combine all of them into one query.
|
286
|
+
```python
|
287
|
+
result = AddressModel.select_one(
|
288
|
+
lambda x: (
|
289
|
+
AddressModel.min(x.address_id),
|
290
|
+
AddressModel.max(x.address_id),
|
291
|
+
AddressModel.count(x.address_id),
|
292
|
+
),flavour=dict
|
293
|
+
)
|
294
|
+
```
|
295
|
+
Getting something like
|
296
|
+
|
297
|
+
```python
|
298
|
+
# {
|
299
|
+
# "min": 1,
|
300
|
+
# "max": 605,
|
301
|
+
# "count": 603,
|
302
|
+
# }
|
303
|
+
```
|
304
|
+
|
305
|
+
You also can use custom alias for each method
|
306
|
+
|
307
|
+
```python
|
308
|
+
AddressModel.select_one(
|
309
|
+
lambda x: (
|
310
|
+
AddressModel.min(x.address_id),
|
311
|
+
AddressModel.max(x.address_id, alias="custom-max"),
|
312
|
+
AddressModel.count(x.address_id),
|
313
|
+
),
|
314
|
+
flavour=dict,
|
315
|
+
)
|
316
|
+
|
317
|
+
# {
|
318
|
+
# "min": 1,
|
319
|
+
# "custom-max": 605,
|
320
|
+
# "count": 603,
|
321
|
+
# }
|
322
|
+
```
|
@@ -3,7 +3,7 @@ line-length = 320
|
|
3
3
|
|
4
4
|
[tool.poetry]
|
5
5
|
name = "ormlambda"
|
6
|
-
version = "
|
6
|
+
version = "3.7.1"
|
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"
|
@@ -13,12 +13,13 @@ python = "^3.12"
|
|
13
13
|
mysql-connector-python= "^9.0.0"
|
14
14
|
fluent-validation = "4.3.1"
|
15
15
|
shapely = "^2.0.6"
|
16
|
+
python-dotenv = "^1.0.1"
|
16
17
|
|
17
18
|
[tool.poetry.group.test.dependencies]
|
18
19
|
pandas = "^2.2.2"
|
19
20
|
ruff = "^0.4.5"
|
20
|
-
python-decouple = "^3.8"
|
21
21
|
parameterized = "^0.9.0"
|
22
|
+
pydantic = "^2.11.1"
|
22
23
|
|
23
24
|
|
24
25
|
[build-system]
|