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.
Files changed (183) hide show
  1. ormlambda-3.34.0/AUTHORS +32 -0
  2. {ormlambda-3.11.2 → ormlambda-3.34.0}/PKG-INFO +56 -10
  3. {ormlambda-3.11.2 → ormlambda-3.34.0}/README.md +55 -9
  4. {ormlambda-3.11.2 → ormlambda-3.34.0}/pyproject.toml +2 -1
  5. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/__init__.py +3 -1
  6. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/caster/__init__.py +1 -1
  7. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/caster/caster.py +29 -12
  8. ormlambda-3.34.0/src/ormlambda/common/abstract_classes/clause_info_converter.py +65 -0
  9. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/abstract_classes/decomposition_query.py +27 -68
  10. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/abstract_classes/non_query_base.py +10 -8
  11. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/abstract_classes/query_base.py +3 -1
  12. ormlambda-3.34.0/src/ormlambda/common/errors/__init__.py +50 -0
  13. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/interfaces/ICustomAlias.py +1 -1
  14. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/interfaces/IQueryCommand.py +6 -2
  15. ormlambda-3.34.0/src/ormlambda/dialects/__init__.py +39 -0
  16. ormlambda-3.34.0/src/ormlambda/dialects/default/__init__.py +1 -0
  17. ormlambda-3.34.0/src/ormlambda/dialects/default/base.py +39 -0
  18. ormlambda-3.34.0/src/ormlambda/dialects/interface/__init__.py +1 -0
  19. ormlambda-3.34.0/src/ormlambda/dialects/interface/dialect.py +78 -0
  20. ormlambda-3.34.0/src/ormlambda/dialects/mysql/__init__.py +38 -0
  21. ormlambda-3.34.0/src/ormlambda/dialects/mysql/base.py +388 -0
  22. ormlambda-3.34.0/src/ormlambda/dialects/mysql/caster/caster.py +39 -0
  23. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/__init__.py +1 -0
  24. ormlambda-3.34.0/src/ormlambda/dialects/mysql/caster/types/boolean.py +35 -0
  25. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/bytes.py +7 -7
  26. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/datetime.py +7 -7
  27. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/float.py +7 -7
  28. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/int.py +7 -7
  29. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/iterable.py +7 -7
  30. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/none.py +8 -7
  31. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/point.py +4 -4
  32. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/types/string.py +7 -7
  33. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/clauses/ST_AsText.py +8 -7
  34. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/clauses/ST_Contains.py +10 -5
  35. ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/__init__.py +13 -0
  36. ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/count.py +33 -0
  37. ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/delete.py +9 -0
  38. ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/group_by.py +17 -0
  39. ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/having.py +12 -0
  40. ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/insert.py +9 -0
  41. ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/joins.py +14 -0
  42. ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/limit.py +6 -0
  43. ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/offset.py +6 -0
  44. ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/order.py +8 -0
  45. ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/update.py +8 -0
  46. ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/upsert.py +9 -0
  47. ormlambda-3.34.0/src/ormlambda/dialects/mysql/clauses/where.py +7 -0
  48. ormlambda-3.34.0/src/ormlambda/dialects/mysql/mysqlconnector.py +46 -0
  49. ormlambda-3.34.0/src/ormlambda/dialects/mysql/repository/__init__.py +1 -0
  50. ormlambda-3.34.0/src/ormlambda/dialects/mysql/repository/repository.py +212 -0
  51. ormlambda-3.34.0/src/ormlambda/dialects/mysql/types.py +732 -0
  52. ormlambda-3.34.0/src/ormlambda/dialects/sqlite/__init__.py +5 -0
  53. ormlambda-3.34.0/src/ormlambda/dialects/sqlite/base.py +47 -0
  54. ormlambda-3.34.0/src/ormlambda/dialects/sqlite/pysqlite.py +32 -0
  55. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/engine/__init__.py +1 -0
  56. ormlambda-3.34.0/src/ormlambda/engine/base.py +77 -0
  57. ormlambda-3.34.0/src/ormlambda/engine/create.py +21 -0
  58. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/engine/url.py +34 -19
  59. ormlambda-3.34.0/src/ormlambda/env.py +30 -0
  60. ormlambda-3.34.0/src/ormlambda/errors.py +17 -0
  61. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/model/base_model.py +7 -9
  62. ormlambda-3.34.0/src/ormlambda/repository/base_repository.py +44 -0
  63. ormlambda-3.34.0/src/ormlambda/repository/interfaces/IRepositoryBase.py +149 -0
  64. ormlambda-3.34.0/src/ormlambda/repository/response.py +134 -0
  65. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/clause_info/__init__.py +2 -1
  66. ormlambda-3.34.0/src/ormlambda/sql/clause_info/aggregate_function_base.py +96 -0
  67. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/clause_info/clause_info.py +35 -115
  68. ormlambda-3.34.0/src/ormlambda/sql/clause_info/interface/IClauseInfo.py +37 -0
  69. ormlambda-3.34.0/src/ormlambda/sql/clause_info/interface/__init__.py +2 -0
  70. ormlambda-3.34.0/src/ormlambda/sql/clauses/__init__.py +14 -0
  71. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/alias.py +23 -6
  72. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/count.py +15 -1
  73. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/delete.py +22 -7
  74. ormlambda-3.34.0/src/ormlambda/sql/clauses/group_by.py +30 -0
  75. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/having.py +7 -2
  76. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/insert.py +16 -9
  77. ormlambda-3.34.0/src/ormlambda/sql/clauses/interfaces/__init__.py +5 -0
  78. ormlambda-3.34.0/src/ormlambda/sql/clauses/join/__init__.py +1 -0
  79. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql/clauses/join}/join_context.py +15 -7
  80. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/joins.py +29 -19
  81. ormlambda-3.34.0/src/ormlambda/sql/clauses/limit.py +15 -0
  82. ormlambda-3.34.0/src/ormlambda/sql/clauses/offset.py +15 -0
  83. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/order.py +14 -24
  84. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/select.py +14 -13
  85. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/update.py +24 -11
  86. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/upsert.py +19 -10
  87. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/clauses/where.py +28 -8
  88. ormlambda-3.34.0/src/ormlambda/sql/column/__init__.py +1 -0
  89. {ormlambda-3.11.2/src/ormlambda/sql → ormlambda-3.34.0/src/ormlambda/sql/column}/column.py +85 -22
  90. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/comparer.py +51 -37
  91. ormlambda-3.34.0/src/ormlambda/sql/compiler.py +668 -0
  92. ormlambda-3.34.0/src/ormlambda/sql/ddl.py +82 -0
  93. ormlambda-3.34.0/src/ormlambda/sql/elements.py +36 -0
  94. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/foreign_key.py +61 -39
  95. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/functions/concat.py +13 -5
  96. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/functions/max.py +9 -4
  97. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/functions/min.py +9 -13
  98. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/functions/sum.py +8 -10
  99. ormlambda-3.34.0/src/ormlambda/sql/sqltypes.py +647 -0
  100. ormlambda-3.34.0/src/ormlambda/sql/table/__init__.py +1 -0
  101. ormlambda-3.11.2/src/ormlambda/sql/table/table_constructor.py → ormlambda-3.34.0/src/ormlambda/sql/table/table.py +13 -88
  102. ormlambda-3.34.0/src/ormlambda/sql/table/table_constructor.py +43 -0
  103. ormlambda-3.34.0/src/ormlambda/sql/type_api.py +35 -0
  104. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/types.py +3 -1
  105. ormlambda-3.34.0/src/ormlambda/sql/visitors.py +74 -0
  106. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/statements/__init__.py +1 -0
  107. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/statements/base_statement.py +34 -40
  108. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/statements/interfaces/IStatements.py +28 -21
  109. ormlambda-3.34.0/src/ormlambda/statements/query_builder.py +163 -0
  110. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/statements}/statements.py +68 -210
  111. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/statements/types.py +2 -2
  112. ormlambda-3.34.0/src/ormlambda/types/__init__.py +24 -0
  113. ormlambda-3.34.0/src/ormlambda/types/metadata.py +42 -0
  114. ormlambda-3.34.0/src/ormlambda/util/__init__.py +87 -0
  115. {ormlambda-3.11.2/src/ormlambda/utils → ormlambda-3.34.0/src/ormlambda/util}/module_tree/dynamic_module.py +4 -3
  116. ormlambda-3.34.0/src/ormlambda/util/plugin_loader.py +32 -0
  117. ormlambda-3.34.0/src/ormlambda/util/typing.py +6 -0
  118. ormlambda-3.11.2/src/ormlambda/common/errors/__init__.py +0 -21
  119. ormlambda-3.11.2/src/ormlambda/components/__init__.py +0 -4
  120. ormlambda-3.11.2/src/ormlambda/components/delete/__init__.py +0 -2
  121. ormlambda-3.11.2/src/ormlambda/components/delete/abstract_delete.py +0 -17
  122. ormlambda-3.11.2/src/ormlambda/components/insert/__init__.py +0 -2
  123. ormlambda-3.11.2/src/ormlambda/components/insert/abstract_insert.py +0 -25
  124. ormlambda-3.11.2/src/ormlambda/components/select/__init__.py +0 -1
  125. ormlambda-3.11.2/src/ormlambda/components/update/__init__.py +0 -2
  126. ormlambda-3.11.2/src/ormlambda/components/update/abstract_update.py +0 -29
  127. ormlambda-3.11.2/src/ormlambda/components/upsert/__init__.py +0 -2
  128. ormlambda-3.11.2/src/ormlambda/components/upsert/abstract_upsert.py +0 -25
  129. ormlambda-3.11.2/src/ormlambda/databases/__init__.py +0 -5
  130. ormlambda-3.11.2/src/ormlambda/databases/my_sql/__init__.py +0 -4
  131. ormlambda-3.11.2/src/ormlambda/databases/my_sql/caster/caster.py +0 -39
  132. ormlambda-3.11.2/src/ormlambda/databases/my_sql/clauses/__init__.py +0 -20
  133. ormlambda-3.11.2/src/ormlambda/databases/my_sql/clauses/create_database.py +0 -35
  134. ormlambda-3.11.2/src/ormlambda/databases/my_sql/clauses/drop_database.py +0 -17
  135. ormlambda-3.11.2/src/ormlambda/databases/my_sql/clauses/drop_table.py +0 -23
  136. ormlambda-3.11.2/src/ormlambda/databases/my_sql/clauses/group_by.py +0 -31
  137. ormlambda-3.11.2/src/ormlambda/databases/my_sql/clauses/limit.py +0 -17
  138. ormlambda-3.11.2/src/ormlambda/databases/my_sql/clauses/offset.py +0 -17
  139. ormlambda-3.11.2/src/ormlambda/databases/my_sql/repository/__init__.py +0 -1
  140. ormlambda-3.11.2/src/ormlambda/databases/my_sql/repository/repository.py +0 -351
  141. ormlambda-3.11.2/src/ormlambda/engine/create.py +0 -35
  142. ormlambda-3.11.2/src/ormlambda/engine/template.py +0 -47
  143. ormlambda-3.11.2/src/ormlambda/repository/base_repository.py +0 -13
  144. ormlambda-3.11.2/src/ormlambda/repository/interfaces/IRepositoryBase.py +0 -42
  145. ormlambda-3.11.2/src/ormlambda/sql/clause_info/interface/__init__.py +0 -1
  146. ormlambda-3.11.2/src/ormlambda/sql/dtypes.py +0 -94
  147. ormlambda-3.11.2/src/ormlambda/sql/table/__init__.py +0 -1
  148. ormlambda-3.11.2/src/ormlambda/utils/__init__.py +0 -1
  149. {ormlambda-3.11.2 → ormlambda-3.34.0}/LICENSE +0 -0
  150. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/caster/base_caster.py +0 -0
  151. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/caster/interfaces/ICaster.py +0 -0
  152. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/caster/interfaces/__init__.py +0 -0
  153. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/__init__.py +0 -0
  154. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/abstract_classes/__init__.py +0 -0
  155. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/enums/__init__.py +0 -0
  156. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/enums/condition_types.py +0 -0
  157. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/enums/join_type.py +0 -0
  158. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/global_checker.py +0 -0
  159. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/interfaces/IDecompositionQuery.py +0 -0
  160. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/interfaces/IJoinSelector.py +0 -0
  161. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/interfaces/INonQueryCommand.py +0 -0
  162. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/common/interfaces/__init__.py +0 -0
  163. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/dialects/mysql}/caster/__init__.py +0 -0
  164. /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
  165. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/engine/utils.py +0 -0
  166. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/model/__init__.py +0 -0
  167. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/repository/__init__.py +0 -0
  168. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/repository/interfaces/IDatabaseConnection.py +0 -0
  169. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/repository/interfaces/__init__.py +0 -0
  170. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/__init__.py +0 -0
  171. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/clause_info/clause_info_context.py +0 -0
  172. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/clause_info/interface/IAggregate.py +0 -0
  173. {ormlambda-3.11.2/src/ormlambda/components/delete → ormlambda-3.34.0/src/ormlambda/sql/clauses/interfaces}/IDelete.py +0 -0
  174. {ormlambda-3.11.2/src/ormlambda/components/insert → ormlambda-3.34.0/src/ormlambda/sql/clauses/interfaces}/IInsert.py +0 -0
  175. {ormlambda-3.11.2/src/ormlambda/components/select → ormlambda-3.34.0/src/ormlambda/sql/clauses/interfaces}/ISelect.py +0 -0
  176. {ormlambda-3.11.2/src/ormlambda/components/update → ormlambda-3.34.0/src/ormlambda/sql/clauses/interfaces}/IUpdate.py +0 -0
  177. {ormlambda-3.11.2/src/ormlambda/components/upsert → ormlambda-3.34.0/src/ormlambda/sql/clauses/interfaces}/IUpsert.py +0 -0
  178. {ormlambda-3.11.2/src/ormlambda/databases/my_sql → ormlambda-3.34.0/src/ormlambda/sql}/functions/__init__.py +0 -0
  179. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/interfaces/__init__.py +0 -0
  180. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/sql/table/fields.py +0 -0
  181. {ormlambda-3.11.2 → ormlambda-3.34.0}/src/ormlambda/statements/interfaces/__init__.py +0 -0
  182. {ormlambda-3.11.2/src/ormlambda/utils → ormlambda-3.34.0/src/ormlambda/util}/module_tree/__init__.py +0 -0
  183. {ormlambda-3.11.2/src/ormlambda/utils → ormlambda-3.34.0/src/ormlambda/util}/module_tree/dfs_traversal.py +0 -0
@@ -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.11.2
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
- #### Usage
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
- #### Usage
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.11.2"
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 # noqa: F401
26
+ from .engine import create_engine, URL, make_url # noqa: F401
@@ -1,3 +1,3 @@
1
1
  from .base_caster import BaseCaster # noqa: F401
2
- from .caster import Caster, PLACEHOLDER # noqa: F401
2
+ from .caster import Caster # noqa: F401
3
3
  from .interfaces import ICaster # 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.engine.template import RepositoryTemplateDict
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
- PLACEHOLDER: str = "%s"
17
+ class Caster(ICaster):
18
+ PLACEHOLDER: ClassVar[str] = "%s"
16
19
 
17
-
18
- class Caster:
19
- def __init__(self, repository: IRepositoryBase):
20
- self._repository: IRepositoryBase = repository
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._caster.cast(value, column_type)
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._caster.cast(value, column_type)
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
@@ -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 AliasType, TableType, ColumnType
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
- class ClauseInfoConverter[T, TProp](abc.ABC):
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__(self, tables: tuple[TableType[T]], columns: tuple[ColumnType], alias_table: str = "{table}", *, context: ClauseContextType = ClauseInfoContext()) -> None:
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
- return classConverter.convert(data, alias_table=self._alias_table, context=self._context)
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):
@@ -1,22 +1,26 @@
1
1
  from __future__ import annotations
2
2
  from abc import abstractmethod
3
- from typing import Any, Optional, Type, override, TYPE_CHECKING
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 IRepositoryBase
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: IRepositoryBase](INonQueryCommand):
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
- @property
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,4 +1,4 @@
1
- from ormlambda.common.interfaces import IDecompositionQuery
1
+ # from ormlambda.common.interfaces import IDecompositionQuery
2
2
 
3
3
 
4
4
  class ICustomAlias[T, *Ts]: ...
@@ -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)