ormlambda 4.4.4__tar.gz → 4.4.14__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-4.4.4 → ormlambda-4.4.14}/PKG-INFO +8 -4
- {ormlambda-4.4.4 → ormlambda-4.4.14}/README.md +2 -2
- {ormlambda-4.4.4 → ormlambda-4.4.14}/pyproject.toml +1 -1
- ormlambda-4.4.14/src/ormlambda/common/constants.py +1 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/common/errors/__init__.py +10 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/base.py +31 -30
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/repository/repository.py +0 -2
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clause_info/clause_info.py +90 -74
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/column/column.py +20 -15
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/compiler.py +6 -1
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/ddl.py +2 -2
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/sqltypes.py +3 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/table/table.py +2 -2
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/statements/interfaces/IStatements.py +11 -3
- ormlambda-4.4.4/src/ormlambda/common/constants.py +0 -1
- {ormlambda-4.4.4 → ormlambda-4.4.14}/AUTHORS +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/LICENSE +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/caster/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/caster/base_caster.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/caster/caster.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/caster/interfaces/ICaster.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/caster/interfaces/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/common/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/common/enums/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/common/enums/condition_types.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/common/enums/join_type.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/common/enums/order_type.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/common/enums/union_type.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/common/global_checker.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/common/interfaces/IJoinSelector.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/common/interfaces/IQueryCommand.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/common/interfaces/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/default/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/default/base.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/caster.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/types/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/types/boolean.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/types/bytes.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/types/date.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/types/datetime.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/types/decimal.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/types/float.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/types/int.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/types/iterable.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/types/json.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/types/none.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/types/point.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/caster/types/string.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/clauses/ST_AsText.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/clauses/ST_Contains.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/clauses/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/mysqlconnector.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/repository/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/repository/pool_types.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/mysql/types.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/sqlite/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/sqlite/base.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/dialects/sqlite/pysqlite.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/engine/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/engine/base.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/engine/create.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/engine/url.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/engine/utils.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/env.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/model/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/model/base_model.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/repository/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/repository/base_repository.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/repository/interfaces/IDatabaseConnection.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/repository/interfaces/IRepositoryBase.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/repository/interfaces/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/repository/response.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clause_info/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clause_info/interface/IClauseInfo.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clause_info/interface/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/alias.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/delete.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/group_by.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/having.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/insert.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/join/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/join/join_context.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/joins.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/limit.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/offset.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/order.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/select.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/update.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/upsert.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/clauses/where.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/column/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/column/column_proxy.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/column/metadata.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/column_table_proxy.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/comparer.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/context/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/elements.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/foreign_key.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/aggregate/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/aggregate/avg.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/aggregate/concat.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/aggregate/count.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/aggregate/max.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/aggregate/min.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/aggregate/sum.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/base.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/datetime/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/interface/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/mathematical/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/mathematical/abs.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/mathematical/ceil.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/mathematical/floor.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/mathematical/mod.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/mathematical/pow.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/mathematical/rand.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/mathematical/round.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/mathematical/sqrt.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/mathematical/truncate.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/functions/string/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/table/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/table/fields.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/table/table_constructor.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/table/table_proxy.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/type_api.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/types.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/sql/visitors.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/statements/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/statements/base_statement.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/statements/interfaces/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/statements/query_builder.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/statements/statements.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/statements/types.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/util/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/util/langhelpers.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/util/module_tree/__init__.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/util/module_tree/dfs_traversal.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/util/module_tree/dynamic_module.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/util/preloaded.py +0 -0
- {ormlambda-4.4.4 → ormlambda-4.4.14}/src/ormlambda/util/typing.py +0 -0
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: ormlambda
|
|
3
|
-
Version: 4.4.
|
|
3
|
+
Version: 4.4.14
|
|
4
4
|
Summary: ORM designed to interact with the database (currently with MySQL) using lambda functions and nested functions
|
|
5
|
+
License-File: AUTHORS
|
|
6
|
+
License-File: LICENSE
|
|
5
7
|
Author: p-hzamora
|
|
6
8
|
Author-email: p.hzamora@icloud.com
|
|
7
9
|
Requires-Python: >=3.12,<4.0
|
|
8
10
|
Classifier: Programming Language :: Python :: 3
|
|
9
11
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
10
14
|
Requires-Dist: mysql-connector-python (>=9.0.0,<10.0.0)
|
|
11
15
|
Requires-Dist: shapely (>=2.0.6,<3.0.0)
|
|
12
16
|
Description-Content-Type: text/markdown
|
|
@@ -76,7 +80,7 @@ db = create_engine('mysql://root:1234@localhost:3306/sakila')
|
|
|
76
80
|
|
|
77
81
|
AddressModel = ORM(Address, db)
|
|
78
82
|
|
|
79
|
-
result = AddressModel.where(
|
|
83
|
+
result = AddressModel.where(lambda x: x.City.Country.country.regex(r"^[aA]")).select(
|
|
80
84
|
lambda address: (
|
|
81
85
|
address,
|
|
82
86
|
address.City,
|
|
@@ -104,7 +108,7 @@ result = AddressModel.where(
|
|
|
104
108
|
Additionally, we can filter by others tables. For example, we can return all addresses for each city where `country_id` = 87 (Spain)
|
|
105
109
|
|
|
106
110
|
```python
|
|
107
|
-
result = AddressModel.where(
|
|
111
|
+
result = AddressModel.where(lambda x: x.City.Country.country_id == 87).select()
|
|
108
112
|
```
|
|
109
113
|
|
|
110
114
|
We can also return `Address`, `City` or `Country` if needed.
|
|
@@ -63,7 +63,7 @@ db = create_engine('mysql://root:1234@localhost:3306/sakila')
|
|
|
63
63
|
|
|
64
64
|
AddressModel = ORM(Address, db)
|
|
65
65
|
|
|
66
|
-
result = AddressModel.where(
|
|
66
|
+
result = AddressModel.where(lambda x: x.City.Country.country.regex(r"^[aA]")).select(
|
|
67
67
|
lambda address: (
|
|
68
68
|
address,
|
|
69
69
|
address.City,
|
|
@@ -91,7 +91,7 @@ result = AddressModel.where(
|
|
|
91
91
|
Additionally, we can filter by others tables. For example, we can return all addresses for each city where `country_id` = 87 (Spain)
|
|
92
92
|
|
|
93
93
|
```python
|
|
94
|
-
result = AddressModel.where(
|
|
94
|
+
result = AddressModel.where(lambda x: x.City.Country.country_id == 87).select()
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
We can also return `Address`, `City` or `Country` if needed.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "ormlambda"
|
|
3
|
-
version = "4.4.
|
|
3
|
+
version = "4.4.14"
|
|
4
4
|
description = "ORM designed to interact with the database (currently with MySQL) using lambda functions and nested functions"
|
|
5
5
|
authors = ["p-hzamora <p.hzamora@icloud.com>"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
DOT = "."
|
|
@@ -9,6 +9,16 @@ if tp.TYPE_CHECKING:
|
|
|
9
9
|
from ormlambda.sql import Column
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
class ReplacePlaceholderError(ValueError):
|
|
13
|
+
def __init__(self, placeholder: str, attribute: str, *args):
|
|
14
|
+
super().__init__(*args)
|
|
15
|
+
self.placeholder: str = placeholder
|
|
16
|
+
self.attr: str = attribute
|
|
17
|
+
|
|
18
|
+
def __str__(self):
|
|
19
|
+
return "You cannot use {" + self.placeholder + "} placeholder without using '" + self.attr + "' attribute"
|
|
20
|
+
|
|
21
|
+
|
|
12
22
|
class UnmatchedLambdaParameterError(Exception):
|
|
13
23
|
def __init__(self, expected_params: int, function: tp.Callable[..., tp.Any], *args: object) -> None:
|
|
14
24
|
super().__init__(*args)
|
|
@@ -11,15 +11,6 @@ from .. import default
|
|
|
11
11
|
from typing import TYPE_CHECKING, Any, Iterable, Type
|
|
12
12
|
from ormlambda.sql.comparer import Comparer, ComparerCluster
|
|
13
13
|
|
|
14
|
-
if TYPE_CHECKING:
|
|
15
|
-
from ormlambda.sql.functions.interface import IFunction
|
|
16
|
-
from ormlambda.sql.types import ColumnType
|
|
17
|
-
from test.test_clause_info import ST_Contains
|
|
18
|
-
from ormlambda import JoinSelector
|
|
19
|
-
from ormlambda.sql.column.column import Column
|
|
20
|
-
from mysql import connector
|
|
21
|
-
from ormlambda.dialects.mysql.clauses import ST_AsText
|
|
22
|
-
|
|
23
14
|
from .types import (
|
|
24
15
|
_NumericType,
|
|
25
16
|
_NumericCommonType,
|
|
@@ -64,6 +55,14 @@ from .repository import MySQLRepository
|
|
|
64
55
|
|
|
65
56
|
|
|
66
57
|
if TYPE_CHECKING:
|
|
58
|
+
from ormlambda.sql.functions.interface import IFunction
|
|
59
|
+
from ormlambda.sql.types import ColumnType
|
|
60
|
+
from test.test_clause_info import ST_Contains
|
|
61
|
+
from ormlambda import JoinSelector
|
|
62
|
+
from ormlambda.sql.column.column import Column
|
|
63
|
+
from mysql import connector
|
|
64
|
+
from ormlambda.dialects.mysql.clauses import ST_AsText
|
|
65
|
+
|
|
67
66
|
from ormlambda.sql.clauses import (
|
|
68
67
|
Select,
|
|
69
68
|
Insert,
|
|
@@ -101,15 +100,12 @@ class MySQLCompiler(compiler.SQLCompiler):
|
|
|
101
100
|
render_table_with_column_in_update_from = True
|
|
102
101
|
"""Overridden from base SQLCompiler value"""
|
|
103
102
|
|
|
104
|
-
def visit_table(self, table: Table):
|
|
105
|
-
return ClauseInfo(table=table, dialect=self.dialect).query(dialect=self.dialect)
|
|
106
|
-
|
|
107
103
|
def visit_table_proxy(self, table: TableProxy, **kw) -> str:
|
|
108
104
|
param = {
|
|
109
|
-
"table":
|
|
110
|
-
"column":
|
|
111
|
-
"dialect": self.dialect,
|
|
105
|
+
"table": table._table_class,
|
|
106
|
+
"column": None,
|
|
112
107
|
"alias_clause": alias if (alias := table.get_table_chain()) else None,
|
|
108
|
+
"dialect": self.dialect,
|
|
113
109
|
**kw,
|
|
114
110
|
}
|
|
115
111
|
return ClauseInfo(**param).query(dialect=self.dialect)
|
|
@@ -132,7 +128,7 @@ class MySQLCompiler(compiler.SQLCompiler):
|
|
|
132
128
|
params = {
|
|
133
129
|
"table": column.table,
|
|
134
130
|
"column": column,
|
|
135
|
-
"alias_table": alias_table
|
|
131
|
+
"alias_table": alias_table,
|
|
136
132
|
"alias_clause": column.alias or "{column}",
|
|
137
133
|
"dtype": column._column.dtype,
|
|
138
134
|
"dialect": self.dialect,
|
|
@@ -216,9 +212,9 @@ class MySQLCompiler(compiler.SQLCompiler):
|
|
|
216
212
|
rt = join.rcon.table
|
|
217
213
|
rtable = TableProxy(table_class=rt, path=join.rcon.path)
|
|
218
214
|
|
|
219
|
-
from_clause = rtable.compile(self.dialect,
|
|
215
|
+
from_clause = rtable.compile(self.dialect, alias_table=join.alias, first_apperance=True).string
|
|
220
216
|
left_table_clause = join.lcon.compile(self.dialect, alias_clause=None).string
|
|
221
|
-
right_table_clause = join.rcon.compile(self.dialect,
|
|
217
|
+
right_table_clause = join.rcon.compile(self.dialect, alias_clause=None).string
|
|
222
218
|
list_ = [
|
|
223
219
|
join._by.value, # inner join
|
|
224
220
|
from_clause,
|
|
@@ -242,9 +238,11 @@ class MySQLCompiler(compiler.SQLCompiler):
|
|
|
242
238
|
columns = ClauseInfo.join_clauses(select.columns, sep, dialect=self.dialect, **params)
|
|
243
239
|
|
|
244
240
|
from_ = ClauseInfo(
|
|
245
|
-
select._table,
|
|
246
|
-
None,
|
|
241
|
+
table=select._table,
|
|
242
|
+
column=None,
|
|
243
|
+
alias_table="{table}",
|
|
247
244
|
dialect=self.dialect,
|
|
245
|
+
first_apperance=True,
|
|
248
246
|
).query(self.dialect)
|
|
249
247
|
|
|
250
248
|
return f"SELECT{sep}{columns}{sep}FROM {from_}"
|
|
@@ -467,7 +465,7 @@ class MySQLCompiler(compiler.SQLCompiler):
|
|
|
467
465
|
else:
|
|
468
466
|
column = count.column
|
|
469
467
|
|
|
470
|
-
return ClauseInfo.
|
|
468
|
+
return ClauseInfo.concat_clause_with_his_alias(f"COUNT({column})", count.alias)
|
|
471
469
|
|
|
472
470
|
def visit_order(self, order: Order, **kw) -> str:
|
|
473
471
|
ORDER = "ORDER BY"
|
|
@@ -514,10 +512,10 @@ class MySQLCompiler(compiler.SQLCompiler):
|
|
|
514
512
|
clause_info = ClauseInfo(
|
|
515
513
|
table=None,
|
|
516
514
|
column=f"CONCAT({', '.join(columns)})",
|
|
517
|
-
alias_clause=concat.alias,
|
|
518
515
|
dialect=self.dialect,
|
|
516
|
+
literal=True
|
|
519
517
|
)
|
|
520
|
-
return clause_info.query(self.dialect)
|
|
518
|
+
return f"{clause_info.query(self.dialect)} AS {ClauseInfo.wrapped_with_quotes(concat.alias)}"
|
|
521
519
|
|
|
522
520
|
def visit_max(self, obj: Max, **kw) -> str:
|
|
523
521
|
return self._compile_aggregate_method("MAX", obj, **kw)
|
|
@@ -546,7 +544,7 @@ class MySQLCompiler(compiler.SQLCompiler):
|
|
|
546
544
|
def visit_pow(self, obj: Pow, **kw) -> str:
|
|
547
545
|
attr = {**kw, "alias_clause": None}
|
|
548
546
|
column = obj.column.compile(self.dialect, **attr).string
|
|
549
|
-
return ClauseInfo.
|
|
547
|
+
return ClauseInfo.concat_clause_with_his_alias(f"POW({column}, {obj._exponent})", obj.alias)
|
|
550
548
|
|
|
551
549
|
def visit_sqrt(self, obj: Sqrt, **kw) -> str:
|
|
552
550
|
return self._compile_aggregate_method("SQRT", obj, **kw)
|
|
@@ -554,7 +552,7 @@ class MySQLCompiler(compiler.SQLCompiler):
|
|
|
554
552
|
def visit_mod(self, obj: Mod, **kw) -> str:
|
|
555
553
|
attr = {**kw, "alias_clause": None}
|
|
556
554
|
column = obj.column.compile(self.dialect, **attr).string
|
|
557
|
-
return ClauseInfo.
|
|
555
|
+
return ClauseInfo.concat_clause_with_his_alias(f"MOD({column}, {obj._divisor})", obj.alias)
|
|
558
556
|
|
|
559
557
|
def visit_rand(self, obj: Rand, **kw) -> str:
|
|
560
558
|
return self._compile_aggregate_method("RAND", obj, **kw)
|
|
@@ -562,22 +560,24 @@ class MySQLCompiler(compiler.SQLCompiler):
|
|
|
562
560
|
def visit_truncate(self, obj: Truncate, **kw) -> str:
|
|
563
561
|
attr = {**kw, "alias_clause": None}
|
|
564
562
|
column = obj.column.compile(self.dialect, **attr).string
|
|
565
|
-
return ClauseInfo.
|
|
563
|
+
return ClauseInfo.concat_clause_with_his_alias(f"TRUNCATE({column}, {obj._decimal})", obj.alias)
|
|
566
564
|
|
|
567
565
|
def _compile_aggregate_method(self, name: str, function: IFunction, **kw) -> str:
|
|
568
566
|
attr = {**kw, "alias_clause": None}
|
|
569
567
|
column = function.column.compile(self.dialect, **attr).string
|
|
570
|
-
return ClauseInfo.
|
|
568
|
+
return ClauseInfo.concat_clause_with_his_alias(f"{name}({column})", function.alias)
|
|
571
569
|
|
|
572
570
|
def visit_st_astext(self, st_astext: ST_AsText) -> str:
|
|
573
571
|
# avoid use placeholder when using IFunction because no make sense.
|
|
574
572
|
if st_astext.alias and (found := ClauseInfo._keyRegex.findall(st_astext.alias)):
|
|
575
573
|
raise NotKeysInIFunctionError(found)
|
|
576
|
-
return ClauseInfo.
|
|
574
|
+
return ClauseInfo.concat_clause_with_his_alias(f"ST_AsText({st_astext.column.compile(self.dialect, alias_clause=None).string})", st_astext.alias)
|
|
577
575
|
|
|
578
576
|
def visit_st_contains(self, st_contains: ST_Contains) -> str:
|
|
577
|
+
# FIXME [ ]: It's not working as expected. Should be something like
|
|
578
|
+
# ST_Contains(`table_type`.points, ST_GeomFromText(%s))
|
|
579
579
|
attr1 = st_contains.column.compile(self.dialect, alias_clause=None).string
|
|
580
|
-
attr2 = ClauseInfo(None, st_contains.point, dialect=self.dialect).query(self.dialect
|
|
580
|
+
attr2 = ClauseInfo(None, st_contains.point, dialect=self.dialect).query(self.dialect)
|
|
581
581
|
return f"ST_Contains({attr1}, {attr2})"
|
|
582
582
|
|
|
583
583
|
|
|
@@ -602,7 +602,8 @@ class MySQLDDLCompiler(compiler.DDLCompiler):
|
|
|
602
602
|
compare = fk.resolved_function()
|
|
603
603
|
lcon = compare.left_condition
|
|
604
604
|
rcon = compare.right_condition
|
|
605
|
-
|
|
605
|
+
rdb = f"{ClauseInfo.wrapped_with_quotes(db)}." if (db := compare.right_condition.table.__db_name__) else ""
|
|
606
|
+
return f"FOREIGN KEY ({lcon.column_name}) REFERENCES {rdb}{rcon.table.__table_name__}({rcon.column_name})"
|
|
606
607
|
|
|
607
608
|
|
|
608
609
|
class MySQLTypeCompiler(compiler.GenericTypeCompiler):
|
|
@@ -187,8 +187,6 @@ class MySQLRepository(BaseRepository[MySQLConnectionPool]):
|
|
|
187
187
|
@override
|
|
188
188
|
def table_exists(self, name: str) -> bool:
|
|
189
189
|
with self.get_connection() as cnx:
|
|
190
|
-
if not cnx.database:
|
|
191
|
-
raise Exception("No database selected")
|
|
192
190
|
with cnx.cursor(buffered=True) as cursor:
|
|
193
191
|
cursor.execute(f"SHOW TABLES LIKE {Caster.PLACEHOLDER};", (name,))
|
|
194
192
|
res = cursor.fetchmany(1)
|
|
@@ -4,7 +4,7 @@ import typing as tp
|
|
|
4
4
|
import re
|
|
5
5
|
|
|
6
6
|
from ormlambda.sql.types import ASTERISK
|
|
7
|
-
from ormlambda.common.errors import DuplicatedClauseNameError
|
|
7
|
+
from ormlambda.common.errors import DuplicatedClauseNameError, ReplacePlaceholderError
|
|
8
8
|
from .interface import IClauseInfo
|
|
9
9
|
from ormlambda.common import GlobalChecker, DOT
|
|
10
10
|
from ormlambda import util
|
|
@@ -19,16 +19,6 @@ if tp.TYPE_CHECKING:
|
|
|
19
19
|
from ormlambda.dialects import Dialect
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
class ReplacePlaceholderError(ValueError):
|
|
23
|
-
def __init__(self, placeholder: str, attribute: str, *args):
|
|
24
|
-
super().__init__(*args)
|
|
25
|
-
self.placeholder: str = placeholder
|
|
26
|
-
self.attr: str = attribute
|
|
27
|
-
|
|
28
|
-
def __str__(self):
|
|
29
|
-
return "You cannot use {" + self.placeholder + "} placeholder without using '" + self.attr + "' attribute"
|
|
30
|
-
|
|
31
|
-
|
|
32
22
|
class ClauseInfo[T: Table](IClauseInfo[T]):
|
|
33
23
|
_keyRegex: re.Pattern = re.compile(r"{([^{}:]+)}")
|
|
34
24
|
|
|
@@ -43,11 +33,11 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
|
|
|
43
33
|
@tp.overload
|
|
44
34
|
def __init__(self, table: TableType[T], keep_asterisk: tp.Optional[bool] = ...): ...
|
|
45
35
|
@tp.overload
|
|
46
|
-
def __init__(self, table: TableType[T], preserve_context: tp.Optional[bool] = ...): ...
|
|
47
|
-
@tp.overload
|
|
48
36
|
def __init__[TProp](self, table: TableType[T], dtype: tp.Optional[TProp] = ...): ...
|
|
49
37
|
@tp.overload
|
|
50
38
|
def __init__(self, table: TableType[T], literal: bool = ...): ...
|
|
39
|
+
@tp.overload
|
|
40
|
+
def __init__(self, table: TableType[T], first_apperance: bool = ...): ...
|
|
51
41
|
|
|
52
42
|
@tp.overload
|
|
53
43
|
def __init__(self, dialect: Dialect, *args, **kwargs): ...
|
|
@@ -59,9 +49,9 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
|
|
|
59
49
|
alias_table: tp.Optional[AliasType[ColumnProxy]] = None,
|
|
60
50
|
alias_clause: tp.Optional[AliasType[ColumnProxy]] = None,
|
|
61
51
|
keep_asterisk: bool = False,
|
|
62
|
-
preserve_context: bool = False,
|
|
63
52
|
dtype: tp.Optional[TProp] = None,
|
|
64
53
|
literal: bool = False,
|
|
54
|
+
first_apperance: bool = False,
|
|
65
55
|
*,
|
|
66
56
|
dialect: Dialect,
|
|
67
57
|
**kw,
|
|
@@ -75,21 +65,22 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
|
|
|
75
65
|
self._alias_table: tp.Optional[AliasType[ColumnProxy]] = alias_table
|
|
76
66
|
self._alias_clause: tp.Optional[AliasType[ColumnProxy]] = alias_clause
|
|
77
67
|
self._keep_asterisk: bool = keep_asterisk
|
|
78
|
-
self._preserve_context: bool = preserve_context
|
|
79
68
|
self._dtype = dtype
|
|
80
69
|
self._literal = literal
|
|
70
|
+
self._first_apperance = first_apperance
|
|
81
71
|
|
|
82
72
|
self._dialect: Dialect = dialect
|
|
83
73
|
|
|
84
74
|
self._placeholderValues: dict[str, tp.Callable[[TProp], str]] = {
|
|
85
75
|
"column": self.replace_column_placeholder,
|
|
86
76
|
"table": self.replace_table_placeholder,
|
|
77
|
+
"db": self.replace_db_placeholder,
|
|
87
78
|
}
|
|
88
79
|
|
|
89
80
|
super().__init__(**kw)
|
|
90
81
|
|
|
91
82
|
def __repr__(self) -> str:
|
|
92
|
-
return f"{type(self).__name__}:
|
|
83
|
+
return f"{type(self).__name__}: {self.table}->{self.column}"
|
|
93
84
|
|
|
94
85
|
def replace_column_placeholder[TProp](self, column: ColumnType[TProp]) -> str:
|
|
95
86
|
if not column:
|
|
@@ -97,15 +88,35 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
|
|
|
97
88
|
return self._column_resolver(column)
|
|
98
89
|
|
|
99
90
|
def replace_table_placeholder[TProp](self, _: ColumnType[TProp]) -> str:
|
|
100
|
-
if not self.
|
|
91
|
+
if not self._table:
|
|
101
92
|
raise ReplacePlaceholderError("table", "table")
|
|
102
|
-
return self.table.__table_name__
|
|
103
93
|
|
|
94
|
+
# We need to return the name itself without database because we're using it to replace {table} not {db}
|
|
95
|
+
return self._table.__table_name__
|
|
96
|
+
|
|
97
|
+
def replace_db_placeholder[TProp](self, _: ColumnType[TProp]) -> str:
|
|
98
|
+
if not self._table:
|
|
99
|
+
raise ReplacePlaceholderError("db", "table")
|
|
100
|
+
|
|
101
|
+
# We need to return the name itself without database because we're using it to replace {table} not {db}
|
|
102
|
+
return self._table.__db_name__
|
|
103
|
+
|
|
104
|
+
@util.preload_module("ormlambda.sql")
|
|
104
105
|
@property
|
|
105
|
-
def table(self) ->
|
|
106
|
+
def table(self) -> str:
|
|
107
|
+
if not self._first_apperance and self.alias_table:
|
|
108
|
+
return self.wrapped_with_quotes(self.alias_table)
|
|
109
|
+
|
|
110
|
+
ForeignKey = util.preloaded.sql_foreign_key.ForeignKey
|
|
106
111
|
if self.is_foreign_key(self._table):
|
|
107
|
-
|
|
108
|
-
|
|
112
|
+
table = tp.cast(ForeignKey, self._table).tright
|
|
113
|
+
else:
|
|
114
|
+
table = self._table
|
|
115
|
+
|
|
116
|
+
if not table:
|
|
117
|
+
return None
|
|
118
|
+
|
|
119
|
+
return table.__table_name__ if not table.__db_name__ else self.join_db_and_table(table)
|
|
109
120
|
|
|
110
121
|
@table.setter
|
|
111
122
|
def table(self, value: TableType[T]) -> None:
|
|
@@ -113,26 +124,34 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
|
|
|
113
124
|
|
|
114
125
|
@property
|
|
115
126
|
def alias_clause(self) -> tp.Optional[str]:
|
|
116
|
-
|
|
117
|
-
|
|
127
|
+
"""
|
|
128
|
+
It must be conditioned by the column. If no columns is set and an alias_clause is specified, the alias will not be applied.
|
|
129
|
+
"""
|
|
130
|
+
if not self.column:
|
|
131
|
+
return None
|
|
132
|
+
return self._alias_resolver(self._alias_clause)
|
|
118
133
|
|
|
119
|
-
# TODOL [ ]: if we using this setter, we don't update the _context with the new value. Study if it's necessary
|
|
120
134
|
@alias_clause.setter
|
|
121
135
|
def alias_clause(self, value: str) -> str:
|
|
122
136
|
self._alias_clause = value
|
|
123
137
|
|
|
124
138
|
@property
|
|
125
139
|
def alias_table(self) -> tp.Optional[str]:
|
|
126
|
-
|
|
140
|
+
return self._alias_resolver(self._alias_table)
|
|
127
141
|
|
|
128
|
-
return self._alias_resolver(alias)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
# TODOL [ ]: if we using this setter, we don't update the _context with the new value. Study if it's necessary
|
|
132
142
|
@alias_table.setter
|
|
133
143
|
def alias_table(self, value: str) -> str:
|
|
134
144
|
self._alias_table = value
|
|
135
145
|
|
|
146
|
+
def _alias_resolver(self, alias: AliasType[ColumnProxy]) -> tp.Optional[str]:
|
|
147
|
+
if alias is None:
|
|
148
|
+
return None
|
|
149
|
+
|
|
150
|
+
if callable(alias):
|
|
151
|
+
return self._alias_resolver(alias(self._column))
|
|
152
|
+
|
|
153
|
+
return self._replace_placeholder(alias)
|
|
154
|
+
|
|
136
155
|
def replaced_alias(self, value: str) -> tp.Optional[str]:
|
|
137
156
|
return value
|
|
138
157
|
|
|
@@ -164,7 +183,7 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
|
|
|
164
183
|
return self._dtype
|
|
165
184
|
|
|
166
185
|
if isinstance(self._column, Column):
|
|
167
|
-
return self._column.
|
|
186
|
+
return self._column.dtype
|
|
168
187
|
|
|
169
188
|
if isinstance(self._column, type):
|
|
170
189
|
return self._column
|
|
@@ -176,36 +195,40 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
|
|
|
176
195
|
def compile(self, dialect: Dialect, **kwargs) -> str:
|
|
177
196
|
return self._create_query(dialect, **kwargs)
|
|
178
197
|
|
|
179
|
-
def _create_query(self, dialect: Dialect
|
|
198
|
+
def _create_query(self, dialect: Dialect) -> str:
|
|
180
199
|
# when passing some value that is not a column name
|
|
181
|
-
if not self.table and not self._alias_clause:
|
|
182
|
-
return self.column
|
|
183
|
-
|
|
184
|
-
if not self.table and self._alias_clause:
|
|
185
|
-
# it means that we are passing an object with alias. We should delete '' around the object
|
|
186
|
-
alias_clause = self.alias_clause
|
|
187
|
-
return self.concat_alias_and_column(self._column, alias_clause)
|
|
188
200
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
if not self._alias_table:
|
|
192
|
-
return self.join_db_and_table(self.table)
|
|
201
|
+
table = self.table
|
|
202
|
+
column = self.column
|
|
193
203
|
|
|
194
|
-
|
|
195
|
-
return self.
|
|
204
|
+
if self._first_apperance:
|
|
205
|
+
return self.concat_clause_with_his_alias(table, self.alias_table)
|
|
196
206
|
|
|
197
207
|
if self._return_all_columns():
|
|
198
208
|
return self._get_all_columns(dialect)
|
|
199
|
-
return self._join_table_and_column(self._column, dialect)
|
|
200
209
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
210
|
+
if not table:
|
|
211
|
+
return column
|
|
212
|
+
|
|
213
|
+
if not column:
|
|
214
|
+
if self.alias_clause:
|
|
215
|
+
return self.concat_clause_with_his_alias(table, self.alias_clause)
|
|
216
|
+
return table
|
|
217
|
+
|
|
218
|
+
clause = f"{table}{DOT}{column}"
|
|
204
219
|
|
|
205
|
-
|
|
220
|
+
caster = dialect.caster()
|
|
221
|
+
|
|
222
|
+
dtype = str if self.is_table(self.dtype) else self.dtype
|
|
223
|
+
wrapped_clause = caster.for_value(clause, dtype).wildcard_to_select(clause)
|
|
224
|
+
return self.concat_clause_with_his_alias(wrapped_clause, self.alias_clause)
|
|
206
225
|
|
|
207
|
-
|
|
226
|
+
@classmethod
|
|
227
|
+
def join_db_and_table(cls, table: Table) -> str:
|
|
228
|
+
db = table.__db_name__
|
|
229
|
+
tbl = table.__table_name__
|
|
208
230
|
|
|
231
|
+
wrapped_table = cls.wrapped_with_quotes(tbl)
|
|
209
232
|
if db:
|
|
210
233
|
wrapped_db = cls.wrapped_with_quotes(db)
|
|
211
234
|
return f"{wrapped_db}{DOT}{wrapped_table}"
|
|
@@ -216,24 +239,24 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
|
|
|
216
239
|
def _join_table_and_column[TProp](self, column: ColumnType[TProp], dialect: Dialect) -> str:
|
|
217
240
|
ColumnProxy = util.preloaded.sql_column.ColumnProxy
|
|
218
241
|
|
|
219
|
-
|
|
242
|
+
# Avoid adding 'database name' when we have alias_table
|
|
220
243
|
|
|
221
|
-
if
|
|
222
|
-
col = column.table if hasattr(column, "table") else column
|
|
223
|
-
table = self.join_db_and_table(col, self.alias_table)
|
|
224
|
-
elif isinstance(column, ColumnProxy):
|
|
244
|
+
if isinstance(column, ColumnProxy):
|
|
225
245
|
table_name: str = column.get_table_chain()
|
|
226
|
-
|
|
246
|
+
|
|
247
|
+
self.alias_table = table_name
|
|
227
248
|
else:
|
|
228
|
-
table = self.table
|
|
249
|
+
table = self.table
|
|
229
250
|
|
|
230
251
|
column: str = self._column_resolver(column)
|
|
231
252
|
|
|
232
253
|
table_column = f"{table}{DOT}{column}"
|
|
233
254
|
|
|
255
|
+
caster = dialect.caster()
|
|
256
|
+
|
|
234
257
|
dtype = str if self.is_table(self.dtype) else self.dtype
|
|
235
258
|
wrapped_column = caster.for_value(table_column, dtype).wildcard_to_select(table_column)
|
|
236
|
-
return self.
|
|
259
|
+
return self.concat_clause_with_his_alias(wrapped_column, self.alias_clause)
|
|
237
260
|
|
|
238
261
|
def _return_all_columns(self) -> bool:
|
|
239
262
|
if self._keep_asterisk:
|
|
@@ -251,7 +274,7 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
|
|
|
251
274
|
def _get_all_columns(self, dialect: Dialect) -> str:
|
|
252
275
|
def ClauseCreator(column: str) -> ClauseInfo:
|
|
253
276
|
return ClauseInfo(
|
|
254
|
-
table=self.
|
|
277
|
+
table=self._table,
|
|
255
278
|
column=column,
|
|
256
279
|
alias_table=self._alias_table,
|
|
257
280
|
alias_clause=self._alias_clause,
|
|
@@ -262,12 +285,14 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
|
|
|
262
285
|
if self._alias_table and self._alias_clause: # We'll add an "*" when we are certain that we have included 'alias_clause' attr
|
|
263
286
|
return self._join_table_and_column(ASTERISK, dialect)
|
|
264
287
|
|
|
265
|
-
columns: list[ClauseInfo] = [ClauseCreator(column).query(dialect) for column in self.
|
|
288
|
+
columns: list[ClauseInfo] = [ClauseCreator(column).query(dialect) for column in self._table.get_columns()]
|
|
266
289
|
|
|
267
290
|
return ", ".join(columns)
|
|
268
291
|
|
|
269
|
-
# FIXME [x]: Study how to deacoplate from mysql database
|
|
270
292
|
def _column_resolver[TProp](self, column: ColumnType[TProp]) -> str:
|
|
293
|
+
if not column:
|
|
294
|
+
return None
|
|
295
|
+
|
|
271
296
|
if isinstance(column, ClauseInfo):
|
|
272
297
|
return column.query(self._dialect)
|
|
273
298
|
|
|
@@ -313,21 +338,12 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
|
|
|
313
338
|
return func(self._column)
|
|
314
339
|
|
|
315
340
|
@classmethod
|
|
316
|
-
def
|
|
341
|
+
def concat_clause_with_his_alias(cls, clause: str, alias_clause: tp.Optional[str] = None) -> str:
|
|
317
342
|
if alias_clause is None:
|
|
318
|
-
return
|
|
319
|
-
alias = f"{
|
|
343
|
+
return clause
|
|
344
|
+
alias = f"{clause} AS {cls.wrapped_with_quotes(alias_clause)}"
|
|
320
345
|
return alias
|
|
321
346
|
|
|
322
|
-
def _alias_resolver(self, alias: AliasType[ColumnProxy]) -> tp.Optional[str]:
|
|
323
|
-
if alias is None:
|
|
324
|
-
return None
|
|
325
|
-
|
|
326
|
-
if callable(alias):
|
|
327
|
-
return self._alias_resolver(alias(self._column))
|
|
328
|
-
|
|
329
|
-
return self._replace_placeholder(alias)
|
|
330
|
-
|
|
331
347
|
@util.preload_module("ormlambda.sql.clauses")
|
|
332
348
|
@staticmethod
|
|
333
349
|
def join_clauses(clauses: list[ColumnProxy], chr: str = " ", *, dialect: Dialect, **kw) -> str:
|
|
@@ -340,7 +356,7 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
|
|
|
340
356
|
if isinstance(c, IComparer):
|
|
341
357
|
comparer = f"({c.compile(dialect, alias_clause=None).string})"
|
|
342
358
|
|
|
343
|
-
query = ClauseInfo(None, comparer,
|
|
359
|
+
query = ClauseInfo(None, comparer, dialect=dialect, literal=True).query(dialect) + " AS " + ClauseInfo.wrapped_with_quotes(c.alias)
|
|
344
360
|
queries.append(query)
|
|
345
361
|
continue
|
|
346
362
|
# That update control the alias we set by default on select clause
|
|
@@ -138,6 +138,25 @@ class Column[TProp](ClauseElement):
|
|
|
138
138
|
"""Read the metada when using Annotated typing class, and set the attributes accordingly"""
|
|
139
139
|
|
|
140
140
|
TypeEngine = util.preloaded.sql_type_api.TypeEngine
|
|
141
|
+
ANNOTATED_SELECTOR: dict[ObjType, Callable[[Column, ObjType], None]] = {
|
|
142
|
+
TypeEngine: lambda x, data: setattr(x, "_dtype", data),
|
|
143
|
+
PrimaryKey: lambda x, _: setattr(x, "is_primary_key", True),
|
|
144
|
+
AutoGenerated: lambda x, _: setattr(x, "is_auto_generated", True),
|
|
145
|
+
AutoIncrement: lambda x, _: setattr(x, "is_auto_increment", True),
|
|
146
|
+
Unique: lambda x, _: setattr(x, "is_unique", True),
|
|
147
|
+
CheckTypes: lambda x, _: setattr(x, "_check", True),
|
|
148
|
+
Default: lambda x, meta: (
|
|
149
|
+
setattr(x, "default_value", cast(Default, meta).value),
|
|
150
|
+
setattr(x, "is_auto_generated", True),
|
|
151
|
+
),
|
|
152
|
+
NotNull: lambda x, _: setattr(x, "is_not_null", True),
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
def get_handler(obj_type: ObjType) -> Optional[Callable[[Column, ObjType], None]]:
|
|
156
|
+
for key, handler in ANNOTATED_SELECTOR.items():
|
|
157
|
+
if issubclass(obj_type, key):
|
|
158
|
+
return handler
|
|
159
|
+
return None
|
|
141
160
|
|
|
142
161
|
annotations = get_type_hints(obj, include_extras=True)
|
|
143
162
|
if name in annotations:
|
|
@@ -149,24 +168,10 @@ class Column[TProp](ClauseElement):
|
|
|
149
168
|
|
|
150
169
|
type ObjType = Metadata | TypeEngine
|
|
151
170
|
|
|
152
|
-
ANNOTATED_SELECTOR: dict[ObjType, Callable[[Column, ObjType], None]] = {
|
|
153
|
-
TypeEngine: lambda x, data: setattr(x, "_dtype", data),
|
|
154
|
-
PrimaryKey: lambda x, _: setattr(x, "is_primary_key", True),
|
|
155
|
-
AutoGenerated: lambda x, _: setattr(x, "is_auto_generated", True),
|
|
156
|
-
AutoIncrement: lambda x, _: setattr(x, "is_auto_increment", True),
|
|
157
|
-
Unique: lambda x, _: setattr(x, "is_unique", True),
|
|
158
|
-
CheckTypes: lambda x, _: setattr(x, "_check", True),
|
|
159
|
-
Default: lambda x, meta: (
|
|
160
|
-
setattr(x, "default_value", cast(Default, meta).value),
|
|
161
|
-
setattr(x, "is_auto_generated", True),
|
|
162
|
-
),
|
|
163
|
-
NotNull: lambda x, _: setattr(x, "is_not_null", True),
|
|
164
|
-
}
|
|
165
|
-
|
|
166
171
|
for meta in metadata:
|
|
167
172
|
if not isinstance(meta, Metadata | TypeEngine):
|
|
168
173
|
raise ValueError(f"When using 'Annotated' to pass metadata into Column, you must instantiate those metadata. You passed '{meta.__name__}'")
|
|
169
|
-
func =
|
|
174
|
+
func = get_handler(type(meta))
|
|
170
175
|
|
|
171
176
|
if not func:
|
|
172
177
|
continue
|
|
@@ -13,8 +13,10 @@ from ormlambda.sql.sqltypes import resolve_primitive_types
|
|
|
13
13
|
|
|
14
14
|
from .visitors import Visitor
|
|
15
15
|
from ormlambda.sql.type_api import TypeEngine
|
|
16
|
+
from ormlambda.sql.clause_info import ClauseInfo
|
|
16
17
|
|
|
17
18
|
if TYPE_CHECKING:
|
|
19
|
+
from ormlambda import Table
|
|
18
20
|
from ormlambda import Column
|
|
19
21
|
from .visitors import Element
|
|
20
22
|
from .elements import ClauseElement
|
|
@@ -141,6 +143,9 @@ class TypeCompiler(Visitor):
|
|
|
141
143
|
class SQLCompiler(Compiled):
|
|
142
144
|
is_sql = True
|
|
143
145
|
|
|
146
|
+
def visit_table(self, table: Table):
|
|
147
|
+
return ClauseInfo(table=table, dialect=self.dialect).query(dialect=self.dialect)
|
|
148
|
+
|
|
144
149
|
|
|
145
150
|
class DDLCompiler(Compiled):
|
|
146
151
|
is_ddl = True
|
|
@@ -210,7 +215,7 @@ class DDLCompiler(Compiled):
|
|
|
210
215
|
foreign_keys_string.append(fk.compile(self.dialect, orig_table=tablecls).string)
|
|
211
216
|
table_options = " ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
|
|
212
217
|
|
|
213
|
-
sql = f"CREATE TABLE {tablecls
|
|
218
|
+
sql = f"CREATE TABLE {SQLCompiler.visit_table(self,tablecls)} (\n\t"
|
|
214
219
|
sql += ",\n\t".join(column_sql)
|
|
215
220
|
sql += "\n\t" if not foreign_keys else ",\n\t"
|
|
216
221
|
sql += ",\n\t".join(foreign_keys_string)
|