ormlambda 3.11.2__tar.gz → 3.34.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-3.34.0/AUTHORS +32 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/PKG-INFO +56 -10
- {ormlambda-3.11.2 → ormlambda-3.34.0}/README.md +55 -9
- {ormlambda-3.11.2 → ormlambda-3.34.0}/pyproject.toml +2 -1
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/__init__.py +3 -1
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/caster/__init__.py +1 -1
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/caster/caster.py +29 -12
- ormlambda-3.34.0/src/ormlambda/common/abstract_classes/clause_info_converter.py +65 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/abstract_classes/decomposition_query.py +27 -68
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/abstract_classes/non_query_base.py +10 -8
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/abstract_classes/query_base.py +3 -1
- ormlambda-3.34.0/src/ormlambda/common/errors/__init__.py +50 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/interfaces/ICustomAlias.py +1 -1
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/interfaces/IQueryCommand.py +6 -2
- ormlambda-3.34.0/src/ormlambda/dialects/__init__.py +39 -0
- ormlambda-3.34.0/src/ormlambda/dialects/default/__init__.py +1 -0
- ormlambda-3.34.0/src/ormlambda/dialects/default/base.py +39 -0
- ormlambda-3.34.0/src/ormlambda/dialects/interface/__init__.py +1 -0
- ormlambda-3.34.0/src/ormlambda/dialects/interface/dialect.py +78 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/__init__.py +38 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/base.py +388 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/caster/caster.py +39 -0
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/__init__.py +1 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/caster/types/boolean.py +35 -0
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/bytes.py +7 -7
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/datetime.py +7 -7
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/float.py +7 -7
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/int.py +7 -7
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/iterable.py +7 -7
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/none.py +8 -7
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/point.py +4 -4
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/string.py +7 -7
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/clauses/ST_AsText.py +8 -7
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/clauses/ST_Contains.py +10 -5
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/__init__.py +13 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/count.py +33 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/delete.py +9 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/group_by.py +17 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/having.py +12 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/insert.py +9 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/joins.py +14 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/limit.py +6 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/offset.py +6 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/order.py +8 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/update.py +8 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/upsert.py +9 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/where.py +7 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/mysqlconnector.py +46 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/repository/__init__.py +1 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/repository/repository.py +212 -0
- ormlambda-3.34.0/src/ormlambda/dialects/mysql/types.py +732 -0
- ormlambda-3.34.0/src/ormlambda/dialects/sqlite/__init__.py +5 -0
- ormlambda-3.34.0/src/ormlambda/dialects/sqlite/base.py +47 -0
- ormlambda-3.34.0/src/ormlambda/dialects/sqlite/pysqlite.py +32 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/engine/__init__.py +1 -0
- ormlambda-3.34.0/src/ormlambda/engine/base.py +77 -0
- ormlambda-3.34.0/src/ormlambda/engine/create.py +21 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/engine/url.py +34 -19
- ormlambda-3.34.0/src/ormlambda/env.py +30 -0
- ormlambda-3.34.0/src/ormlambda/errors.py +17 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/model/base_model.py +7 -9
- ormlambda-3.34.0/src/ormlambda/repository/base_repository.py +44 -0
- ormlambda-3.34.0/src/ormlambda/repository/interfaces/IRepositoryBase.py +149 -0
- ormlambda-3.34.0/src/ormlambda/repository/response.py +134 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/clause_info/__init__.py +2 -1
- ormlambda-3.34.0/src/ormlambda/sql/clause_info/aggregate_function_base.py +96 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/clause_info/clause_info.py +35 -115
- ormlambda-3.34.0/src/ormlambda/sql/clause_info/interface/IClauseInfo.py +37 -0
- ormlambda-3.34.0/src/ormlambda/sql/clause_info/interface/__init__.py +2 -0
- ormlambda-3.34.0/src/ormlambda/sql/clauses/__init__.py +14 -0
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/alias.py +23 -6
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/count.py +15 -1
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/delete.py +22 -7
- ormlambda-3.34.0/src/ormlambda/sql/clauses/group_by.py +30 -0
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/having.py +7 -2
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/insert.py +16 -9
- ormlambda-3.34.0/src/ormlambda/sql/clauses/interfaces/__init__.py +5 -0
- ormlambda-3.34.0/src/ormlambda/sql/clauses/join/__init__.py +1 -0
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql/clauses/join}/join_context.py +15 -7
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/joins.py +29 -19
- ormlambda-3.34.0/src/ormlambda/sql/clauses/limit.py +15 -0
- ormlambda-3.34.0/src/ormlambda/sql/clauses/offset.py +15 -0
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/order.py +14 -24
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/select.py +14 -13
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/update.py +24 -11
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/upsert.py +19 -10
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/where.py +28 -8
- ormlambda-3.34.0/src/ormlambda/sql/column/__init__.py +1 -0
- {ormlambda-3.11.2/src/ormlambda/sql → ormlambda-3.34.0/src/ormlambda/sql/column}/column.py +85 -22
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/comparer.py +51 -37
- ormlambda-3.34.0/src/ormlambda/sql/compiler.py +668 -0
- ormlambda-3.34.0/src/ormlambda/sql/ddl.py +82 -0
- ormlambda-3.34.0/src/ormlambda/sql/elements.py +36 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/foreign_key.py +61 -39
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/functions/concat.py +13 -5
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/functions/max.py +9 -4
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/functions/min.py +9 -13
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/functions/sum.py +8 -10
- ormlambda-3.34.0/src/ormlambda/sql/sqltypes.py +647 -0
- ormlambda-3.34.0/src/ormlambda/sql/table/__init__.py +1 -0
- ormlambda-3.11.2/src/ormlambda/sql/table/table_constructor.py → ormlambda-3.34.0/src/ormlambda/sql/table/table.py +13 -88
- ormlambda-3.34.0/src/ormlambda/sql/table/table_constructor.py +43 -0
- ormlambda-3.34.0/src/ormlambda/sql/type_api.py +35 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/types.py +3 -1
- ormlambda-3.34.0/src/ormlambda/sql/visitors.py +74 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/statements/__init__.py +1 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/statements/base_statement.py +34 -40
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/statements/interfaces/IStatements.py +28 -21
- ormlambda-3.34.0/src/ormlambda/statements/query_builder.py +163 -0
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/statements}/statements.py +68 -210
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/statements/types.py +2 -2
- ormlambda-3.34.0/src/ormlambda/types/__init__.py +24 -0
- ormlambda-3.34.0/src/ormlambda/types/metadata.py +42 -0
- ormlambda-3.34.0/src/ormlambda/util/__init__.py +87 -0
- {ormlambda-3.11.2/src/ormlambda/utils → ormlambda-3.34.0/src/ormlambda/util}/module_tree/dynamic_module.py +4 -3
- ormlambda-3.34.0/src/ormlambda/util/plugin_loader.py +32 -0
- ormlambda-3.34.0/src/ormlambda/util/typing.py +6 -0
- ormlambda-3.11.2/src/ormlambda/common/errors/__init__.py +0 -21
- ormlambda-3.11.2/src/ormlambda/components/__init__.py +0 -4
- ormlambda-3.11.2/src/ormlambda/components/delete/__init__.py +0 -2
- ormlambda-3.11.2/src/ormlambda/components/delete/abstract_delete.py +0 -17
- ormlambda-3.11.2/src/ormlambda/components/insert/__init__.py +0 -2
- ormlambda-3.11.2/src/ormlambda/components/insert/abstract_insert.py +0 -25
- ormlambda-3.11.2/src/ormlambda/components/select/__init__.py +0 -1
- ormlambda-3.11.2/src/ormlambda/components/update/__init__.py +0 -2
- ormlambda-3.11.2/src/ormlambda/components/update/abstract_update.py +0 -29
- ormlambda-3.11.2/src/ormlambda/components/upsert/__init__.py +0 -2
- ormlambda-3.11.2/src/ormlambda/components/upsert/abstract_upsert.py +0 -25
- ormlambda-3.11.2/src/ormlambda/databases/__init__.py +0 -5
- ormlambda-3.11.2/src/ormlambda/databases/my_sql/__init__.py +0 -4
- ormlambda-3.11.2/src/ormlambda/databases/my_sql/caster/caster.py +0 -39
- ormlambda-3.11.2/src/ormlambda/databases/my_sql/clauses/__init__.py +0 -20
- ormlambda-3.11.2/src/ormlambda/databases/my_sql/clauses/create_database.py +0 -35
- ormlambda-3.11.2/src/ormlambda/databases/my_sql/clauses/drop_database.py +0 -17
- ormlambda-3.11.2/src/ormlambda/databases/my_sql/clauses/drop_table.py +0 -23
- ormlambda-3.11.2/src/ormlambda/databases/my_sql/clauses/group_by.py +0 -31
- ormlambda-3.11.2/src/ormlambda/databases/my_sql/clauses/limit.py +0 -17
- ormlambda-3.11.2/src/ormlambda/databases/my_sql/clauses/offset.py +0 -17
- ormlambda-3.11.2/src/ormlambda/databases/my_sql/repository/__init__.py +0 -1
- ormlambda-3.11.2/src/ormlambda/databases/my_sql/repository/repository.py +0 -351
- ormlambda-3.11.2/src/ormlambda/engine/create.py +0 -35
- ormlambda-3.11.2/src/ormlambda/engine/template.py +0 -47
- ormlambda-3.11.2/src/ormlambda/repository/base_repository.py +0 -13
- ormlambda-3.11.2/src/ormlambda/repository/interfaces/IRepositoryBase.py +0 -42
- ormlambda-3.11.2/src/ormlambda/sql/clause_info/interface/__init__.py +0 -1
- ormlambda-3.11.2/src/ormlambda/sql/dtypes.py +0 -94
- ormlambda-3.11.2/src/ormlambda/sql/table/__init__.py +0 -1
- ormlambda-3.11.2/src/ormlambda/utils/__init__.py +0 -1
- {ormlambda-3.11.2 → ormlambda-3.34.0}/LICENSE +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/caster/base_caster.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/caster/interfaces/ICaster.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/caster/interfaces/__init__.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/__init__.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/abstract_classes/__init__.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/enums/__init__.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/enums/condition_types.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/enums/join_type.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/global_checker.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/interfaces/IDecompositionQuery.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/interfaces/IJoinSelector.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/interfaces/INonQueryCommand.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/interfaces/__init__.py +0 -0
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/__init__.py +0 -0
- /ormlambda-3.11.2/src/ormlambda/databases/my_sql/types.py → /ormlambda-3.34.0/src/ormlambda/dialects/mysql/repository/pool_types.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/engine/utils.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/model/__init__.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/repository/__init__.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/repository/interfaces/IDatabaseConnection.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/repository/interfaces/__init__.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/__init__.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/clause_info/clause_info_context.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/clause_info/interface/IAggregate.py +0 -0
- {ormlambda-3.11.2/src/ormlambda/components/delete → ormlambda-3.34.0/src/ormlambda/sql/clauses/interfaces}/IDelete.py +0 -0
- {ormlambda-3.11.2/src/ormlambda/components/insert → ormlambda-3.34.0/src/ormlambda/sql/clauses/interfaces}/IInsert.py +0 -0
- {ormlambda-3.11.2/src/ormlambda/components/select → ormlambda-3.34.0/src/ormlambda/sql/clauses/interfaces}/ISelect.py +0 -0
- {ormlambda-3.11.2/src/ormlambda/components/update → ormlambda-3.34.0/src/ormlambda/sql/clauses/interfaces}/IUpdate.py +0 -0
- {ormlambda-3.11.2/src/ormlambda/components/upsert → ormlambda-3.34.0/src/ormlambda/sql/clauses/interfaces}/IUpsert.py +0 -0
- {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/functions/__init__.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/interfaces/__init__.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/table/fields.py +0 -0
- {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/statements/interfaces/__init__.py +0 -0
- {ormlambda-3.11.2/src/ormlambda/utils → ormlambda-3.34.0/src/ormlambda/util}/module_tree/__init__.py +0 -0
- {ormlambda-3.11.2/src/ormlambda/utils → ormlambda-3.34.0/src/ormlambda/util}/module_tree/dfs_traversal.py +0 -0
ormlambda-3.34.0/AUTHORS
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
ormlambda was created by Pablo hernandez.
|
2
|
+
|
3
|
+
Some files was originally written by other authors from sqlalchemy library and rewritten by Pablo Hernandez
|
4
|
+
|
5
|
+
Major contributing authors include:
|
6
|
+
|
7
|
+
- Pablo Hernandez
|
8
|
+
- Jason Kirtland
|
9
|
+
- Michael Trier
|
10
|
+
- Diana Clarke
|
11
|
+
- Gaetan de Menten
|
12
|
+
- Lele Gaifax
|
13
|
+
- Jonathan Ellis
|
14
|
+
- Gord Thompson
|
15
|
+
- Federico Caselli
|
16
|
+
- Philip Jenvey
|
17
|
+
- Rick Morrison
|
18
|
+
- Chris Withers
|
19
|
+
- Ants Aasma
|
20
|
+
- Sheila Allen
|
21
|
+
- Paul Johnston
|
22
|
+
- Tony Locke
|
23
|
+
- Hajime Nakagami
|
24
|
+
- Vraj Mohan
|
25
|
+
- Robert Leftwich
|
26
|
+
- Taavi Burns
|
27
|
+
- Jonathan Vanasco
|
28
|
+
- Jeff Widman
|
29
|
+
- Scott Dugas
|
30
|
+
- Dobes Vandermeer
|
31
|
+
- Ville Skytta
|
32
|
+
- Rodrigo Menezes
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: ormlambda
|
3
|
-
Version: 3.
|
3
|
+
Version: 3.34.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
|
@@ -316,7 +316,7 @@ res = AddressModel.count(Address.address_id, execute=True)
|
|
316
316
|
|
317
317
|
The `concat` method allows you to concatenate multiple columns or values into a single string. This is particularly useful for creating derived fields in your queries.
|
318
318
|
|
319
|
-
|
319
|
+
### Usage
|
320
320
|
|
321
321
|
```python
|
322
322
|
response = ORM(Address, db).where(Address.City.Country.country.regex(r"^Spain")).first(
|
@@ -347,6 +347,60 @@ As you can see in the response, the result is a dictionary where the keys are a
|
|
347
347
|
|
348
348
|
Another elegant approach to adjust the response and obtain an object is by using the `flavour` attribute. You can pass a callable object, which will be used to instantiate it with the returned data.
|
349
349
|
|
350
|
+
|
351
|
+
## 2. Group by
|
352
|
+
|
353
|
+
The `groupby` method is used to filter results based on aggregate functions.
|
354
|
+
|
355
|
+
### Usage
|
356
|
+
```python
|
357
|
+
from ormlambda import Column, ORM, create_engine
|
358
|
+
from test.config import DATABASE_URL
|
359
|
+
|
360
|
+
|
361
|
+
class Response(BaseModel):
|
362
|
+
district: str
|
363
|
+
count: int
|
364
|
+
|
365
|
+
engine= create_engine(DATABASE_URL)
|
366
|
+
model = ORM(Address,engine)
|
367
|
+
|
368
|
+
count_name = Column(column_name="count")
|
369
|
+
|
370
|
+
res = (
|
371
|
+
self.model
|
372
|
+
.groupby(Address.district)
|
373
|
+
.select(
|
374
|
+
(
|
375
|
+
Address.district,
|
376
|
+
self.model.count(Address.address),
|
377
|
+
),
|
378
|
+
flavour=Response,
|
379
|
+
)
|
380
|
+
)
|
381
|
+
```
|
382
|
+
|
383
|
+
## 3. Having
|
384
|
+
|
385
|
+
The `having` method is used to filter results based on aggregate functions. It is typically used in conjunction with `group by` clauses.
|
386
|
+
|
387
|
+
### Usage
|
388
|
+
```python
|
389
|
+
res = (
|
390
|
+
model
|
391
|
+
.groupby(Address.district)
|
392
|
+
.having(count_name > 4)
|
393
|
+
.select(
|
394
|
+
(
|
395
|
+
Address.district,
|
396
|
+
model.count(Address.address),
|
397
|
+
),
|
398
|
+
flavour=Response,
|
399
|
+
)
|
400
|
+
)
|
401
|
+
```
|
402
|
+
|
403
|
+
|
350
404
|
## Using BaseModel for Custom Responses (Pydantic)
|
351
405
|
|
352
406
|
You can utilize `BaseModel` from Pydantic to create structured response models. This allows you to define the expected structure of your data, ensuring type safety and validation.
|
@@ -391,14 +445,6 @@ print(select.city)
|
|
391
445
|
print(select.country)
|
392
446
|
```
|
393
447
|
|
394
|
-
|
395
|
-
<!-- ### 2. Having
|
396
|
-
|
397
|
-
The `having` method is used to filter results based on aggregate functions. It is typically used in conjunction with `group by` clauses.
|
398
|
-
|
399
|
-
#### Usage -->
|
400
|
-
|
401
|
-
|
402
448
|
## Combine aggregation method
|
403
449
|
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.
|
404
450
|
```python
|
@@ -302,7 +302,7 @@ res = AddressModel.count(Address.address_id, execute=True)
|
|
302
302
|
|
303
303
|
The `concat` method allows you to concatenate multiple columns or values into a single string. This is particularly useful for creating derived fields in your queries.
|
304
304
|
|
305
|
-
|
305
|
+
### Usage
|
306
306
|
|
307
307
|
```python
|
308
308
|
response = ORM(Address, db).where(Address.City.Country.country.regex(r"^Spain")).first(
|
@@ -333,6 +333,60 @@ As you can see in the response, the result is a dictionary where the keys are a
|
|
333
333
|
|
334
334
|
Another elegant approach to adjust the response and obtain an object is by using the `flavour` attribute. You can pass a callable object, which will be used to instantiate it with the returned data.
|
335
335
|
|
336
|
+
|
337
|
+
## 2. Group by
|
338
|
+
|
339
|
+
The `groupby` method is used to filter results based on aggregate functions.
|
340
|
+
|
341
|
+
### Usage
|
342
|
+
```python
|
343
|
+
from ormlambda import Column, ORM, create_engine
|
344
|
+
from test.config import DATABASE_URL
|
345
|
+
|
346
|
+
|
347
|
+
class Response(BaseModel):
|
348
|
+
district: str
|
349
|
+
count: int
|
350
|
+
|
351
|
+
engine= create_engine(DATABASE_URL)
|
352
|
+
model = ORM(Address,engine)
|
353
|
+
|
354
|
+
count_name = Column(column_name="count")
|
355
|
+
|
356
|
+
res = (
|
357
|
+
self.model
|
358
|
+
.groupby(Address.district)
|
359
|
+
.select(
|
360
|
+
(
|
361
|
+
Address.district,
|
362
|
+
self.model.count(Address.address),
|
363
|
+
),
|
364
|
+
flavour=Response,
|
365
|
+
)
|
366
|
+
)
|
367
|
+
```
|
368
|
+
|
369
|
+
## 3. Having
|
370
|
+
|
371
|
+
The `having` method is used to filter results based on aggregate functions. It is typically used in conjunction with `group by` clauses.
|
372
|
+
|
373
|
+
### Usage
|
374
|
+
```python
|
375
|
+
res = (
|
376
|
+
model
|
377
|
+
.groupby(Address.district)
|
378
|
+
.having(count_name > 4)
|
379
|
+
.select(
|
380
|
+
(
|
381
|
+
Address.district,
|
382
|
+
model.count(Address.address),
|
383
|
+
),
|
384
|
+
flavour=Response,
|
385
|
+
)
|
386
|
+
)
|
387
|
+
```
|
388
|
+
|
389
|
+
|
336
390
|
## Using BaseModel for Custom Responses (Pydantic)
|
337
391
|
|
338
392
|
You can utilize `BaseModel` from Pydantic to create structured response models. This allows you to define the expected structure of your data, ensuring type safety and validation.
|
@@ -377,14 +431,6 @@ print(select.city)
|
|
377
431
|
print(select.country)
|
378
432
|
```
|
379
433
|
|
380
|
-
|
381
|
-
<!-- ### 2. Having
|
382
|
-
|
383
|
-
The `having` method is used to filter results based on aggregate functions. It is typically used in conjunction with `group by` clauses.
|
384
|
-
|
385
|
-
#### Usage -->
|
386
|
-
|
387
|
-
|
388
434
|
## Combine aggregation method
|
389
435
|
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.
|
390
436
|
```python
|
@@ -3,7 +3,7 @@ line-length = 320
|
|
3
3
|
|
4
4
|
[tool.poetry]
|
5
5
|
name = "ormlambda"
|
6
|
-
version = "3.
|
6
|
+
version = "3.34.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"
|
@@ -20,6 +20,7 @@ pandas = "^2.2.2"
|
|
20
20
|
ruff = "^0.4.5"
|
21
21
|
parameterized = "^0.9.0"
|
22
22
|
pydantic = "^2.11.1"
|
23
|
+
sqlserver = "^0.0.17.1"
|
23
24
|
|
24
25
|
|
25
26
|
[build-system]
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import ormlambda.env # noqa: F401 Necesary to load all variables inside ormalambda.env
|
2
|
+
|
1
3
|
# region enums
|
2
4
|
from .common.enums import (
|
3
5
|
JoinType as JoinType,
|
@@ -21,4 +23,4 @@ from .model.base_model import (
|
|
21
23
|
ORM as ORM,
|
22
24
|
) # COMMENT: to avoid relative import we need to import BaseModel after import Table,Column, ForeignKey, IRepositoryBase and Disassembler
|
23
25
|
|
24
|
-
from .engine import create_engine, URL, make_url
|
26
|
+
from .engine import create_engine, URL, make_url # noqa: F401
|
@@ -1,24 +1,26 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
|
4
|
-
from typing import Optional, Type, TYPE_CHECKING, Callable, overload
|
5
|
-
|
4
|
+
from typing import ClassVar, Optional, Type, TYPE_CHECKING, Callable, overload, get_args
|
5
|
+
from types import NoneType
|
6
|
+
from ormlambda.caster.interfaces import ICaster
|
6
7
|
from ormlambda.common.global_checker import GlobalChecker
|
7
8
|
from ormlambda.sql.types import ColumnType
|
8
|
-
from ormlambda.
|
9
|
+
from ormlambda.caster import BaseCaster
|
10
|
+
from ormlambda.sql.sqltypes import TypeEngine
|
11
|
+
|
9
12
|
|
10
13
|
if TYPE_CHECKING:
|
11
14
|
from ormlambda.caster import BaseCaster
|
12
|
-
from ormlambda.repository import IRepositoryBase
|
13
15
|
|
14
16
|
|
15
|
-
|
17
|
+
class Caster(ICaster):
|
18
|
+
PLACEHOLDER: ClassVar[str] = "%s"
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
self._caster = RepositoryTemplateDict().get(repository).caster
|
20
|
+
@classmethod
|
21
|
+
def set_placeholder(cls, char: str) -> None:
|
22
|
+
cls.PLACEHOLDER = char
|
23
|
+
return None
|
22
24
|
|
23
25
|
@overload
|
24
26
|
def for_column[T, TProp](self, column: Callable[[T], TProp], instance: T) -> BaseCaster[TProp, Type[TProp]]: ...
|
@@ -36,7 +38,7 @@ class Caster:
|
|
36
38
|
column_type = column.dtype
|
37
39
|
value = instance[column]
|
38
40
|
|
39
|
-
return self.
|
41
|
+
return self.cast(value, column_type)
|
40
42
|
|
41
43
|
@overload
|
42
44
|
def for_value[TProp](self, value: TProp) -> BaseCaster[TProp, Type[TProp]]: ...
|
@@ -45,4 +47,19 @@ class Caster:
|
|
45
47
|
|
46
48
|
def for_value[TProp, TType](self, value: TProp, value_type: Optional[TType] = None) -> BaseCaster[TProp, TType]:
|
47
49
|
column_type = value_type if value_type else type(value)
|
48
|
-
return self.
|
50
|
+
return self.cast(value, column_type)
|
51
|
+
|
52
|
+
@classmethod
|
53
|
+
def cast[TProp, TType](cls, value: TProp, type_value: Optional[TypeEngine[TType]] = None) -> BaseCaster[TProp, TType]:
|
54
|
+
if len(args := get_args(type_value)) > 1:
|
55
|
+
args = [x for x in args if x != NoneType]
|
56
|
+
|
57
|
+
type_value = args[0]
|
58
|
+
|
59
|
+
if isinstance(type_value, TypeEngine):
|
60
|
+
column_type = type_value.python_type
|
61
|
+
elif not type_value:
|
62
|
+
column_type = type(value)
|
63
|
+
else:
|
64
|
+
column_type = type_value
|
65
|
+
return cls.CASTER_SELECTOR()[column_type](value, column_type)
|
@@ -0,0 +1,65 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
import typing as tp
|
3
|
+
from ormlambda import Table
|
4
|
+
|
5
|
+
from ormlambda.sql.clause_info import ClauseInfo, AggregateFunctionBase
|
6
|
+
from ormlambda.sql.clause_info.clause_info_context import ClauseContextType
|
7
|
+
from ormlambda import ForeignKey
|
8
|
+
|
9
|
+
from ormlambda.sql.types import AliasType, TableType, ColumnType
|
10
|
+
|
11
|
+
|
12
|
+
class ClauseInfoConverter[T, TProp](tp.Protocol):
|
13
|
+
@classmethod
|
14
|
+
def convert(cls, data: T, alias_table: AliasType[ColumnType[TProp]] = "{table}", context: ClauseContextType = None, **kwargs) -> list[ClauseInfo[T]]: ...
|
15
|
+
|
16
|
+
|
17
|
+
class ConvertFromAnyType(ClauseInfoConverter[None, None]):
|
18
|
+
@classmethod
|
19
|
+
def convert(cls, data: tp.Any, alias_table: AliasType = "{table}", context: ClauseContextType = None, **kwargs) -> list[ClauseInfo[None]]:
|
20
|
+
return [ClauseInfo[None](table=None, column=data, alias_table=alias_table, alias_clause=kwargs.get("alias", None), context=context, **kwargs)]
|
21
|
+
|
22
|
+
|
23
|
+
class ConvertFromForeignKey[LT: Table, RT: Table](ClauseInfoConverter[RT, None]):
|
24
|
+
@classmethod
|
25
|
+
def convert(cls, data: ForeignKey[LT, RT], alias_table=None, context: ClauseContextType = None, **kwargs) -> list[ClauseInfo[RT]]:
|
26
|
+
return ConvertFromTable[RT].convert(data.tright, data.get_alias(kwargs["dialect"]), context, **kwargs)
|
27
|
+
|
28
|
+
|
29
|
+
class ConvertFromColumn[TProp](ClauseInfoConverter[None, TProp]):
|
30
|
+
@classmethod
|
31
|
+
def convert(cls, data: ColumnType[TProp], alias_table: AliasType[ColumnType[TProp]] = "{table}", context: ClauseContextType = None, **kwargs) -> list[ClauseInfo[None]]:
|
32
|
+
# COMMENT: if the property belongs to the main class, the columnn name in not prefixed. This only done if the property comes from any join.
|
33
|
+
attributes = {
|
34
|
+
"table": data.table,
|
35
|
+
"column": data,
|
36
|
+
"alias_table": alias_table,
|
37
|
+
"alias_clause": "{table}_{column}",
|
38
|
+
"context": context,
|
39
|
+
}
|
40
|
+
attributes.update(**kwargs)
|
41
|
+
clause_info = ClauseInfo(**attributes)
|
42
|
+
return [clause_info]
|
43
|
+
|
44
|
+
|
45
|
+
class ConvertFromIAggregate(ClauseInfoConverter[None, None]):
|
46
|
+
@classmethod
|
47
|
+
def convert(cls, data: AggregateFunctionBase, alias_table=None, context: ClauseContextType = None, **kwargs) -> list[ClauseInfo[None]]:
|
48
|
+
return [data]
|
49
|
+
|
50
|
+
|
51
|
+
class ConvertFromTable[T: Table](ClauseInfoConverter[T, None]):
|
52
|
+
@classmethod
|
53
|
+
def convert(cls, data: T, alias_table: AliasType[ColumnType] = "{table}", context: ClauseContextType = None, **kwargs) -> list[ClauseInfo[T]]:
|
54
|
+
"""
|
55
|
+
if the data is Table, means that we want to retrieve all columns
|
56
|
+
"""
|
57
|
+
return cls._extract_all_clauses(data, alias_table, context, **kwargs)
|
58
|
+
|
59
|
+
@staticmethod
|
60
|
+
def _extract_all_clauses(table: TableType[T], alias_table: AliasType[ColumnType], context: ClauseContextType = None, **kwargs) -> list[ClauseInfo[TableType[T]]]:
|
61
|
+
# all columns
|
62
|
+
column_clauses = []
|
63
|
+
for column in table.get_columns():
|
64
|
+
column_clauses.extend(ConvertFromColumn.convert(column, alias_table=alias_table, context=context, **kwargs))
|
65
|
+
return column_clauses
|
{ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/abstract_classes/decomposition_query.py
RENAMED
@@ -1,6 +1,5 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
import typing as tp
|
3
|
-
import abc
|
4
3
|
from ormlambda import Table, Column
|
5
4
|
|
6
5
|
from ormlambda.common.interfaces import IDecompositionQuery, ICustomAlias
|
@@ -10,8 +9,15 @@ from ormlambda.sql.clause_info.clause_info_context import ClauseInfoContext, Cla
|
|
10
9
|
from ormlambda import ForeignKey
|
11
10
|
from ormlambda.common.global_checker import GlobalChecker
|
12
11
|
|
13
|
-
from ormlambda.sql.types import
|
14
|
-
|
12
|
+
from ormlambda.sql.types import TableType, ColumnType
|
13
|
+
from .clause_info_converter import (
|
14
|
+
ClauseInfoConverter,
|
15
|
+
ConvertFromAnyType,
|
16
|
+
ConvertFromForeignKey,
|
17
|
+
ConvertFromColumn,
|
18
|
+
ConvertFromIAggregate,
|
19
|
+
ConvertFromTable,
|
20
|
+
)
|
15
21
|
|
16
22
|
type TableTupleType[T, *Ts] = tuple[T:TableType, *Ts]
|
17
23
|
type ValueType = tp.Union[
|
@@ -21,68 +27,8 @@ type ValueType = tp.Union[
|
|
21
27
|
tp.Type[ICustomAlias],
|
22
28
|
]
|
23
29
|
|
24
|
-
|
25
|
-
|
26
|
-
@classmethod
|
27
|
-
@abc.abstractmethod
|
28
|
-
def convert(cls, data: T, alias_table: AliasType[ColumnType[TProp]] = "{table}", context: ClauseContextType = None) -> list[ClauseInfo[T]]: ...
|
29
|
-
|
30
|
-
|
31
|
-
class ConvertFromAnyType(ClauseInfoConverter[None, None]):
|
32
|
-
@classmethod
|
33
|
-
def convert(cls, data: tp.Any, alias_table: AliasType = "{table}", context: ClauseContextType = None) -> list[ClauseInfo[None]]:
|
34
|
-
return [
|
35
|
-
ClauseInfo[None](
|
36
|
-
table=None,
|
37
|
-
column=data,
|
38
|
-
alias_table=alias_table,
|
39
|
-
alias_clause=None,
|
40
|
-
context=context,
|
41
|
-
)
|
42
|
-
]
|
43
|
-
|
44
|
-
|
45
|
-
class ConvertFromForeignKey[LT: Table, RT: Table](ClauseInfoConverter[RT, None]):
|
46
|
-
@classmethod
|
47
|
-
def convert(cls, data: ForeignKey[LT, RT], alias_table=None, context: ClauseContextType = None) -> list[ClauseInfo[RT]]:
|
48
|
-
return ConvertFromTable[RT].convert(data.tright, data.alias, context)
|
49
|
-
|
50
|
-
|
51
|
-
class ConvertFromColumn[TProp](ClauseInfoConverter[None, TProp]):
|
52
|
-
@classmethod
|
53
|
-
def convert(cls, data: ColumnType[TProp], alias_table: AliasType[ColumnType[TProp]] = "{table}", context: ClauseContextType = None) -> list[ClauseInfo[None]]:
|
54
|
-
# COMMENT: if the property belongs to the main class, the columnn name in not prefixed. This only done if the property comes from any join.
|
55
|
-
clause_info = ClauseInfo[None](
|
56
|
-
table=data.table,
|
57
|
-
column=data,
|
58
|
-
alias_table=alias_table,
|
59
|
-
alias_clause="{table}_{column}",
|
60
|
-
context=context,
|
61
|
-
)
|
62
|
-
return [clause_info]
|
63
|
-
|
64
|
-
|
65
|
-
class ConvertFromIAggregate(ClauseInfoConverter[None, None]):
|
66
|
-
@classmethod
|
67
|
-
def convert(cls, data: AggregateFunctionBase, alias_table=None, context: ClauseContextType = None) -> list[ClauseInfo[None]]:
|
68
|
-
return [data]
|
69
|
-
|
70
|
-
|
71
|
-
class ConvertFromTable[T: Table](ClauseInfoConverter[T, None]):
|
72
|
-
@classmethod
|
73
|
-
def convert(cls, data: T, alias_table: AliasType[ColumnType] = "{table}", context: ClauseContextType = None) -> list[ClauseInfo[T]]:
|
74
|
-
"""
|
75
|
-
if the data is Table, means that we want to retrieve all columns
|
76
|
-
"""
|
77
|
-
return cls._extract_all_clauses(data, alias_table, context)
|
78
|
-
|
79
|
-
@staticmethod
|
80
|
-
def _extract_all_clauses(table: TableType[T], alias_table: AliasType[ColumnType], context: ClauseContextType = None) -> list[ClauseInfo[TableType[T]]]:
|
81
|
-
# all columns
|
82
|
-
column_clauses = []
|
83
|
-
for column in table.get_columns():
|
84
|
-
column_clauses.extend(ConvertFromColumn.convert(column, alias_table=alias_table, context=context))
|
85
|
-
return column_clauses
|
30
|
+
if tp.TYPE_CHECKING:
|
31
|
+
from ormlambda.dialects import Dialect
|
86
32
|
|
87
33
|
|
88
34
|
class DecompositionQueryBase[T: Table, *Ts](IDecompositionQuery[T, *Ts]):
|
@@ -93,9 +39,20 @@ class DecompositionQueryBase[T: Table, *Ts](IDecompositionQuery[T, *Ts]):
|
|
93
39
|
@tp.overload
|
94
40
|
def __init__(self, tables: tuple[TableType[T]], columns: tuple[ColumnType], alias_table: str, context: ClauseContextType = ...) -> None: ...
|
95
41
|
|
96
|
-
def __init__(
|
42
|
+
def __init__(
|
43
|
+
self,
|
44
|
+
tables: tuple[TableType[T]],
|
45
|
+
columns: tuple[ColumnType],
|
46
|
+
alias_table: str = "{table}",
|
47
|
+
*,
|
48
|
+
context: ClauseContextType = ClauseInfoContext(),
|
49
|
+
dialect: Dialect,
|
50
|
+
**kwargs,
|
51
|
+
) -> None:
|
52
|
+
self.kwargs = kwargs
|
97
53
|
self._tables: tuple[TableType[T]] = tables if isinstance(tables, tp.Iterable) else (tables,)
|
98
54
|
|
55
|
+
self._dialect = dialect
|
99
56
|
self._columns: tp.Callable[[T], tuple] = columns
|
100
57
|
self._all_clauses: list[ClauseInfo | AggregateFunctionBase] = []
|
101
58
|
self._context: ClauseContextType = context if context else ClauseInfoContext()
|
@@ -144,8 +101,10 @@ class DecompositionQueryBase[T: Table, *Ts](IDecompositionQuery[T, *Ts]):
|
|
144
101
|
Table: ConvertFromTable[T],
|
145
102
|
}
|
146
103
|
classConverter = next((converter for obj, converter in VALUE_TYPE_MAPPED.items() if validation(data, obj)), ConvertFromAnyType)
|
147
|
-
|
148
|
-
|
104
|
+
self.kwargs.setdefault("dialect", self._dialect)
|
105
|
+
if "dialect" not in self.kwargs:
|
106
|
+
raise ValueError("You must specified 'dialect' variable")
|
107
|
+
return classConverter.convert(data, alias_table=self._alias_table, context=self._context, **self.kwargs)
|
149
108
|
|
150
109
|
def __add_clause[TTable: TableType](self, clauses: list[ClauseInfo[TTable]] | ClauseInfo[TTable]) -> None:
|
151
110
|
if not isinstance(clauses, tp.Iterable):
|
{ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/abstract_classes/non_query_base.py
RENAMED
@@ -1,22 +1,26 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
from abc import abstractmethod
|
3
|
-
from typing import Any, Optional, Type,
|
3
|
+
from typing import Any, Optional, Type, TYPE_CHECKING
|
4
4
|
|
5
5
|
from ormlambda.common.interfaces.INonQueryCommand import INonQueryCommand
|
6
6
|
|
7
7
|
if TYPE_CHECKING:
|
8
|
-
from ormlambda.repository import
|
8
|
+
from ormlambda.repository import BaseRepository
|
9
|
+
from ormlambda.dialects import Dialect
|
9
10
|
from ormlambda import Table
|
11
|
+
from ormlambda.engine import Engine
|
10
12
|
|
11
13
|
|
12
|
-
class NonQueryBase[T: Type[Table], TRepo
|
14
|
+
class NonQueryBase[T: Type[Table], TRepo](INonQueryCommand):
|
13
15
|
__slots__: tuple[str, ...] = ("_model", "_repository", "_values", "_query")
|
14
16
|
|
15
|
-
def __init__(self, model: T, repository: TRepo) -> None:
|
17
|
+
def __init__(self, model: T, repository: TRepo, **kwargs) -> None:
|
16
18
|
self._model: T = model
|
17
|
-
self._repository: TRepo = repository
|
19
|
+
self._repository: BaseRepository[TRepo] = repository
|
18
20
|
self._values: list[tuple[Any]] = []
|
19
21
|
self._query: Optional[str] = None
|
22
|
+
self._dialect: Dialect = kwargs.get("dialect", None)
|
23
|
+
self._engine: Optional[Engine] = kwargs.get("engine", None)
|
20
24
|
|
21
25
|
@property
|
22
26
|
@abstractmethod
|
@@ -25,9 +29,7 @@ class NonQueryBase[T: Type[Table], TRepo: IRepositoryBase](INonQueryCommand):
|
|
25
29
|
@abstractmethod
|
26
30
|
def execute(self) -> None: ...
|
27
31
|
|
28
|
-
|
29
|
-
@override
|
30
|
-
def query(self) -> str:
|
32
|
+
def query(self, dialect: Dialect, **kwargs) -> str:
|
31
33
|
return self._query
|
32
34
|
|
33
35
|
@property
|
@@ -1,3 +1,4 @@
|
|
1
|
+
from __future__ import annotations
|
1
2
|
from abc import abstractmethod
|
2
3
|
from typing import TYPE_CHECKING
|
3
4
|
|
@@ -5,9 +6,10 @@ from ormlambda.common.interfaces import IQuery
|
|
5
6
|
|
6
7
|
if TYPE_CHECKING:
|
7
8
|
from ormlambda import Table
|
9
|
+
from ormlambda.dialects import Dialect
|
8
10
|
|
9
11
|
|
10
12
|
class QueryBase[T: Table](IQuery):
|
11
13
|
@property
|
12
14
|
@abstractmethod
|
13
|
-
def query(self) -> str: ...
|
15
|
+
def query(self, dialect: Dialect, **kwargs) -> str: ...
|
@@ -0,0 +1,50 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
import inspect
|
3
|
+
import typing as tp
|
4
|
+
|
5
|
+
|
6
|
+
if tp.TYPE_CHECKING:
|
7
|
+
from ormlambda.sql.clause_info import ClauseInfo
|
8
|
+
|
9
|
+
|
10
|
+
class UnmatchedLambdaParameterError(Exception):
|
11
|
+
def __init__(self, expected_params: int, function: tp.Callable[..., tp.Any], *args: object) -> None:
|
12
|
+
super().__init__(*args)
|
13
|
+
self.expected_params = expected_params
|
14
|
+
self.found_param: tuple[str, ...] = tuple(inspect.signature(function).parameters)
|
15
|
+
|
16
|
+
def __str__(self) -> str:
|
17
|
+
return f"Unmatched number of parameters in lambda function with the number of tables: Expected {self.expected_params} parameters but found {str(self.found_param)}."
|
18
|
+
|
19
|
+
|
20
|
+
class NotKeysInIAggregateError(Exception):
|
21
|
+
def __init__(self, match_regex: list[str], *args: object) -> None:
|
22
|
+
super().__init__(*args)
|
23
|
+
self._match_regex: list[str] = match_regex
|
24
|
+
|
25
|
+
def __str__(self) -> str:
|
26
|
+
return f"We cannot use placeholders in IAggregate class. You used {self._match_regex}"
|
27
|
+
|
28
|
+
|
29
|
+
class AggregateFunctionError[T](Exception):
|
30
|
+
def __init__(self, clause: ClauseInfo[T], *args):
|
31
|
+
self.clause = clause
|
32
|
+
super().__init__(*args)
|
33
|
+
|
34
|
+
def __str__(self):
|
35
|
+
agg_methods = self.__get_all_aggregate_method(self.clause)
|
36
|
+
return f"You cannot use aggregation method like '{agg_methods}' to return model objects. Try specifying 'flavour' attribute as 'dict'."
|
37
|
+
|
38
|
+
def __get_all_aggregate_method(self, clauses: list[ClauseInfo]) -> str:
|
39
|
+
"""
|
40
|
+
Get the class name of those classes that inherit from 'AggregateFunctionBase' class in order to create a better error message.
|
41
|
+
"""
|
42
|
+
from ormlambda.sql.clause_info import AggregateFunctionBase
|
43
|
+
|
44
|
+
res: set[str] = set()
|
45
|
+
if not isinstance(clauses, tp.Iterable):
|
46
|
+
return clauses.__class__.__name__
|
47
|
+
for clause in clauses:
|
48
|
+
if isinstance(clause, AggregateFunctionBase):
|
49
|
+
res.add(clause.__class__.__name__)
|
50
|
+
return ", ".join(res)
|
@@ -1,12 +1,16 @@
|
|
1
|
+
from __future__ import annotations
|
1
2
|
from abc import abstractmethod, ABC
|
3
|
+
from typing import TYPE_CHECKING
|
4
|
+
|
5
|
+
if TYPE_CHECKING:
|
6
|
+
from ormlambda.dialects import Dialect
|
2
7
|
|
3
8
|
|
4
9
|
class IQuery(ABC):
|
5
10
|
"""Interface to queries that retrieve any element such as select, limit, offset, where, group by, etc..."""
|
6
11
|
|
7
|
-
@property
|
8
12
|
@abstractmethod
|
9
|
-
def query(self) -> str: ...
|
13
|
+
def query(self, dialect: Dialect, **kwargs) -> str: ...
|
10
14
|
|
11
15
|
def __repr__(self) -> str:
|
12
16
|
return f"{IQuery.__name__}: {self.__class__.__name__}"
|
@@ -0,0 +1,39 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import Callable, Optional, Type, TYPE_CHECKING
|
3
|
+
from ormlambda import util
|
4
|
+
import importlib
|
5
|
+
|
6
|
+
if TYPE_CHECKING:
|
7
|
+
from .interface import Dialect
|
8
|
+
|
9
|
+
|
10
|
+
__all__ = ("mysql", "sqlite")
|
11
|
+
|
12
|
+
|
13
|
+
def _auto_fn(name: str) -> Optional[Callable[[], Type[Dialect]]]:
|
14
|
+
"""default dialect importer.
|
15
|
+
|
16
|
+
plugs into the :class:`.PluginLoader`
|
17
|
+
as a first-hit system.
|
18
|
+
|
19
|
+
"""
|
20
|
+
if "." in name:
|
21
|
+
dialect, driver = name.split(".")
|
22
|
+
else:
|
23
|
+
dialect = name
|
24
|
+
driver = "base"
|
25
|
+
|
26
|
+
try:
|
27
|
+
module = importlib.import_module(f"ormlambda.dialects.{dialect}")
|
28
|
+
|
29
|
+
except ImportError:
|
30
|
+
return None
|
31
|
+
|
32
|
+
if hasattr(module, driver):
|
33
|
+
module = getattr(module, driver)
|
34
|
+
return lambda: module.dialect
|
35
|
+
else:
|
36
|
+
return None
|
37
|
+
|
38
|
+
|
39
|
+
registry = util.PluginLoader("ormlambda.dialects", auto_fn=_auto_fn)
|