ormlambda 4.4.0__tar.gz → 4.4.4__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 (151) hide show
  1. {ormlambda-4.4.0 → ormlambda-4.4.4}/PKG-INFO +1 -1
  2. {ormlambda-4.4.0 → ormlambda-4.4.4}/pyproject.toml +20 -4
  3. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/__init__.py +12 -0
  4. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/common/__init__.py +1 -0
  5. ormlambda-4.4.4/src/ormlambda/common/constants.py +1 -0
  6. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/common/enums/union_type.py +1 -1
  7. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/common/errors/__init__.py +43 -1
  8. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/common/global_checker.py +1 -1
  9. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/base.py +30 -15
  10. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/caster.py +3 -1
  11. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/types/__init__.py +1 -1
  12. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/types/json.py +1 -0
  13. ormlambda-4.4.4/src/ormlambda/dialects/mysql/repository/__init__.py +1 -0
  14. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/repository/response.py +13 -3
  15. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clause_info/clause_info.py +31 -10
  16. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clauses/alias.py +1 -1
  17. ormlambda-4.4.4/src/ormlambda/sql/clauses/delete.py +25 -0
  18. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clauses/insert.py +1 -1
  19. ormlambda-4.4.4/src/ormlambda/sql/clauses/update.py +26 -0
  20. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clauses/where.py +0 -1
  21. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/column/column.py +38 -50
  22. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/column/column_proxy.py +4 -0
  23. {ormlambda-4.4.0/src/ormlambda/types → ormlambda-4.4.4/src/ormlambda/sql/column}/metadata.py +10 -7
  24. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/interface/__init__.py +1 -3
  25. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/sqltypes.py +17 -2
  26. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/table/fields.py +4 -6
  27. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/table/table.py +34 -1
  28. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/type_api.py +8 -4
  29. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/statements/interfaces/IStatements.py +20 -8
  30. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/statements/query_builder.py +25 -21
  31. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/statements/statements.py +19 -22
  32. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/statements/types.py +1 -1
  33. ormlambda-4.4.4/src/ormlambda/util/__init__.py +50 -0
  34. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/util/langhelpers.py +1 -1
  35. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/util/preloaded.py +2 -1
  36. ormlambda-4.4.0/src/ormlambda/dialects/mysql/repository/__init__.py +0 -1
  37. ormlambda-4.4.0/src/ormlambda/errors.py +0 -26
  38. ormlambda-4.4.0/src/ormlambda/sql/clauses/delete.py +0 -21
  39. ormlambda-4.4.0/src/ormlambda/sql/clauses/update.py +0 -23
  40. ormlambda-4.4.0/src/ormlambda/types/__init__.py +0 -24
  41. ormlambda-4.4.0/src/ormlambda/util/__init__.py +0 -9
  42. {ormlambda-4.4.0 → ormlambda-4.4.4}/AUTHORS +0 -0
  43. {ormlambda-4.4.0 → ormlambda-4.4.4}/LICENSE +0 -0
  44. {ormlambda-4.4.0 → ormlambda-4.4.4}/README.md +0 -0
  45. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/caster/__init__.py +0 -0
  46. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/caster/base_caster.py +0 -0
  47. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/caster/caster.py +0 -0
  48. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/caster/interfaces/ICaster.py +0 -0
  49. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/caster/interfaces/__init__.py +0 -0
  50. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/common/enums/__init__.py +0 -0
  51. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/common/enums/condition_types.py +0 -0
  52. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/common/enums/join_type.py +0 -0
  53. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/common/enums/order_type.py +0 -0
  54. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/common/interfaces/IJoinSelector.py +0 -0
  55. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/common/interfaces/IQueryCommand.py +0 -0
  56. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/common/interfaces/__init__.py +0 -0
  57. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/__init__.py +0 -0
  58. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/default/__init__.py +0 -0
  59. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/default/base.py +0 -0
  60. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/__init__.py +0 -0
  61. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/__init__.py +0 -0
  62. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/types/boolean.py +0 -0
  63. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/types/bytes.py +0 -0
  64. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/types/date.py +0 -0
  65. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/types/datetime.py +0 -0
  66. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/types/decimal.py +0 -0
  67. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/types/float.py +0 -0
  68. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/types/int.py +0 -0
  69. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/types/iterable.py +0 -0
  70. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/types/none.py +0 -0
  71. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/types/point.py +0 -0
  72. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/caster/types/string.py +0 -0
  73. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/clauses/ST_AsText.py +0 -0
  74. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/clauses/ST_Contains.py +0 -0
  75. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/clauses/__init__.py +0 -0
  76. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/mysqlconnector.py +0 -0
  77. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/repository/pool_types.py +0 -0
  78. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/repository/repository.py +0 -0
  79. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/mysql/types.py +0 -0
  80. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/sqlite/__init__.py +0 -0
  81. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/sqlite/base.py +0 -0
  82. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/dialects/sqlite/pysqlite.py +0 -0
  83. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/engine/__init__.py +0 -0
  84. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/engine/base.py +0 -0
  85. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/engine/create.py +0 -0
  86. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/engine/url.py +0 -0
  87. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/engine/utils.py +0 -0
  88. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/env.py +0 -0
  89. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/model/__init__.py +0 -0
  90. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/model/base_model.py +0 -0
  91. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/repository/__init__.py +0 -0
  92. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/repository/base_repository.py +0 -0
  93. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/repository/interfaces/IDatabaseConnection.py +0 -0
  94. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/repository/interfaces/IRepositoryBase.py +0 -0
  95. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/repository/interfaces/__init__.py +0 -0
  96. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/__init__.py +0 -0
  97. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clause_info/__init__.py +0 -0
  98. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clause_info/interface/IClauseInfo.py +0 -0
  99. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clause_info/interface/__init__.py +0 -0
  100. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clauses/__init__.py +0 -0
  101. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clauses/group_by.py +0 -0
  102. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clauses/having.py +0 -0
  103. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clauses/join/__init__.py +0 -0
  104. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clauses/join/join_context.py +0 -0
  105. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clauses/joins.py +0 -0
  106. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clauses/limit.py +0 -0
  107. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clauses/offset.py +0 -0
  108. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clauses/order.py +0 -0
  109. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clauses/select.py +0 -0
  110. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/clauses/upsert.py +0 -0
  111. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/column/__init__.py +0 -0
  112. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/column_table_proxy.py +0 -0
  113. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/comparer.py +0 -0
  114. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/compiler.py +0 -0
  115. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/context/__init__.py +0 -0
  116. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/ddl.py +0 -0
  117. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/elements.py +0 -0
  118. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/foreign_key.py +0 -0
  119. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/__init__.py +0 -0
  120. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/aggregate/__init__.py +0 -0
  121. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/aggregate/avg.py +0 -0
  122. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/aggregate/concat.py +0 -0
  123. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/aggregate/count.py +0 -0
  124. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/aggregate/max.py +0 -0
  125. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/aggregate/min.py +0 -0
  126. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/aggregate/sum.py +0 -0
  127. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/base.py +0 -0
  128. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/datetime/__init__.py +0 -0
  129. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/mathematical/__init__.py +0 -0
  130. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/mathematical/abs.py +0 -0
  131. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/mathematical/ceil.py +0 -0
  132. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/mathematical/floor.py +0 -0
  133. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/mathematical/mod.py +0 -0
  134. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/mathematical/pow.py +0 -0
  135. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/mathematical/rand.py +0 -0
  136. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/mathematical/round.py +0 -0
  137. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/mathematical/sqrt.py +0 -0
  138. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/mathematical/truncate.py +0 -0
  139. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/functions/string/__init__.py +0 -0
  140. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/table/__init__.py +0 -0
  141. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/table/table_constructor.py +0 -0
  142. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/table/table_proxy.py +0 -0
  143. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/types.py +0 -0
  144. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/sql/visitors.py +0 -0
  145. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/statements/__init__.py +0 -0
  146. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/statements/base_statement.py +0 -0
  147. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/statements/interfaces/__init__.py +0 -0
  148. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/util/module_tree/__init__.py +0 -0
  149. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/util/module_tree/dfs_traversal.py +0 -0
  150. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/util/module_tree/dynamic_module.py +0 -0
  151. {ormlambda-4.4.0 → ormlambda-4.4.4}/src/ormlambda/util/typing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ormlambda
3
- Version: 4.4.0
3
+ Version: 4.4.4
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
@@ -1,9 +1,6 @@
1
- [tool.ruff]
2
- line-length = 320
3
-
4
1
  [tool.poetry]
5
2
  name = "ormlambda"
6
- version = "4.4.0"
3
+ version = "4.4.4"
7
4
  description = "ORM designed to interact with the database (currently with MySQL) using lambda functions and nested functions"
8
5
  authors = ["p-hzamora <p.hzamora@icloud.com>"]
9
6
  readme = "README.md"
@@ -21,8 +18,27 @@ ruff = "^0.4.5"
21
18
  parameterized = "^0.9.0"
22
19
  pydantic = "^2.11.1"
23
20
  sqlserver = "^0.0.17.1"
21
+ pytest = "^8.4.2"
22
+
23
+ [tool.ruff]
24
+ line-length = 320
24
25
 
26
+ [tool.pytest.ini_options]
27
+ testpaths = ["src/test"]
28
+ python_files = ["test_*.py"]
29
+ python_classes = ["Test*"]
30
+ python_functions = ["test_*"]
31
+ addopts = [
32
+ "-v", # verbose output
33
+ "--strict-markers", # error on unknown markers
34
+ "--tb=short", # shorter traceback format
35
+ ]
36
+
37
+ markers = [
38
+ "slow: Slow test (deselect with '-m \"not slow\"')",
39
+ ]
25
40
 
26
41
  [build-system]
27
42
  requires = ["poetry-core"]
28
43
  build-backend = "poetry.core.masonry.api"
44
+
@@ -80,4 +80,16 @@ from .sql import functions as functions
80
80
  from .sql.functions import * # noqa: F403
81
81
  from . import util as _util
82
82
 
83
+
84
+ from .sql.column.metadata import PrimaryKey as PrimaryKey
85
+ from .sql.column.metadata import AutoGenerated as AutoGenerated
86
+ from .sql.column.metadata import AutoIncrement as AutoIncrement
87
+ from .sql.column.metadata import Unique as Unique
88
+ from .sql.column.metadata import CheckTypes as CheckTypes
89
+ from .sql.column.metadata import Default as Default
90
+ from .sql.column.metadata import NotNull as NotNull
91
+
92
+ from ormlambda.statements.interfaces import IStatements as IStatements
93
+ from ormlambda.engine import Engine as Engine
94
+
83
95
  _util.import_prefix("ormlambda")
@@ -1 +1,2 @@
1
1
  from .global_checker import GlobalChecker as GlobalChecker
2
+ from .constants import DOT as DOT
@@ -0,0 +1 @@
1
+ DOT = '.'
@@ -6,4 +6,4 @@ class UnionEnum(str, enum.Enum):
6
6
  OR = "OR"
7
7
 
8
8
  def __str__(self):
9
- return super().__str__()
9
+ return super().__str__()
@@ -6,6 +6,7 @@ from ormlambda import util
6
6
 
7
7
  if tp.TYPE_CHECKING:
8
8
  from ormlambda.sql.clause_info import ClauseInfo
9
+ from ormlambda.sql import Column
9
10
 
10
11
 
11
12
  class UnmatchedLambdaParameterError(Exception):
@@ -42,7 +43,7 @@ class FunctionFunctionError[T](Exception):
42
43
  Get the class name of those classes that inherit from 'IFunction' class in order to create a better error message.
43
44
  """
44
45
 
45
- IFunction = util.preloaded.sql_functions.IFunction
46
+ IFunction = util.preloaded.sql_functions.IFunction
46
47
  res: set[str] = set()
47
48
  if not isinstance(clauses, tp.Iterable):
48
49
  return clauses.__class__.__name__
@@ -58,3 +59,44 @@ class NotCallableError(ValueError):
58
59
 
59
60
  def __str__(self) -> str:
60
61
  return f"You must provide a function or callable to proceed with the query creation. Passed '{self.args[0].__class__.__name__}' "
62
+
63
+
64
+ class CompileError(Exception):
65
+ """Exception raised for errors in the compilation process."""
66
+
67
+ def __init__(self, message):
68
+ super().__init__(message)
69
+ self.message = message
70
+
71
+ def __str__(self):
72
+ return f"CompileError: {self.message}"
73
+
74
+
75
+ class NoSuchModuleError(Exception):
76
+ """Raised when a dynamically-loaded module (usually a database dialect)
77
+ of a particular name cannot be located."""
78
+
79
+ def __str__(self):
80
+ return f"NoSuchModuleError: {self.args[0]}"
81
+
82
+
83
+ class DuplicatedClauseNameError(Exception):
84
+ def __init__(self, names: tuple[str], **kw):
85
+ self.names = names
86
+ super().__init__(**kw)
87
+
88
+ def __str__(self):
89
+ return f"Some clauses has the same alias. {self.names}\nTry wrapping the clause with the 'Alias' class first or setting 'avoid_duplicates' param as 'True'"
90
+
91
+
92
+ class ColumnError(ValueError):
93
+ def __init__(self, column: Column, *args):
94
+ super().__init__(*args)
95
+ self.column = column
96
+ self.clause: str = ""
97
+
98
+ def set_clause(self, value: str) -> None:
99
+ self.clause = value
100
+
101
+ def __str__(self):
102
+ return f"The column '{self.column.column_name}' does not exist. Check the name you used inside of '{self.clause}' clause."
@@ -29,7 +29,7 @@ class GlobalChecker[T: TableProxy]:
29
29
  try:
30
30
  table_proxy = TableProxy(table)
31
31
 
32
- if not callable(lambda_func):
32
+ if not callable(lambda_func):
33
33
  raise NotCallableError(lambda_func)
34
34
 
35
35
  if isinstance(lambda_func, Iterable):
@@ -101,6 +101,9 @@ class MySQLCompiler(compiler.SQLCompiler):
101
101
  render_table_with_column_in_update_from = True
102
102
  """Overridden from base SQLCompiler value"""
103
103
 
104
+ def visit_table(self, table: Table):
105
+ return ClauseInfo(table=table, dialect=self.dialect).query(dialect=self.dialect)
106
+
104
107
  def visit_table_proxy(self, table: TableProxy, **kw) -> str:
105
108
  param = {
106
109
  "table": None,
@@ -167,7 +170,7 @@ class MySQLCompiler(compiler.SQLCompiler):
167
170
 
168
171
  return f"{lcond} {comparer.compare} {rcond}"
169
172
 
170
- def visit_where(self, where: Where) -> str:
173
+ def visit_where(self, where: Where, sep: str = " ", **kw) -> str:
171
174
  assert (n := len(where.comparers)) == len(where.restrictive)
172
175
 
173
176
  if not where.comparers:
@@ -178,17 +181,17 @@ class MySQLCompiler(compiler.SQLCompiler):
178
181
  for i in range(n):
179
182
  comp = where.comparers[i]
180
183
 
181
- string = comp.compile(self.dialect).string
184
+ string = comp.compile(self.dialect, **kw).string
182
185
 
183
186
  condition = f"({string})" if isinstance(comp, ComparerCluster) else string
184
187
 
185
- union = f" {where.restrictive[i + 1]} " if i != n - 1 else ""
188
+ union = f" {where.restrictive[i + 1]}{sep}" if i != n - 1 else ""
186
189
 
187
190
  condition += union
188
191
  cond.append(condition)
189
- return f" WHERE {"".join(cond)}"
192
+ return f"WHERE{sep}{''.join(cond)}"
190
193
 
191
- def visit_having(self, having: Having) -> str:
194
+ def visit_having(self, having: Having, sep: str = " ", **kw) -> str:
192
195
  assert (n := len(having.comparers)) == len(having.restrictive)
193
196
 
194
197
  if not having.comparers:
@@ -199,15 +202,15 @@ class MySQLCompiler(compiler.SQLCompiler):
199
202
  for i in range(n):
200
203
  comp = having.comparers[i]
201
204
 
202
- string = comp.compile(self.dialect).string
205
+ string = comp.compile(self.dialect, **kw).string
203
206
 
204
207
  condition = f"({string})" if isinstance(comp, ComparerCluster) else string
205
208
 
206
- union = f" {having.restrictive[i + 1]} " if i != n - 1 else ""
209
+ union = f" {having.restrictive[i + 1]}{sep}" if i != n - 1 else ""
207
210
 
208
211
  condition += union
209
212
  cond.append(condition)
210
- return f" HAVING {"".join(cond)}"
213
+ return f"HAVING{sep}{''.join(cond)}"
211
214
 
212
215
  def visit_join(self, join: JoinSelector) -> str:
213
216
  rt = join.rcon.table
@@ -226,7 +229,7 @@ class MySQLCompiler(compiler.SQLCompiler):
226
229
  ]
227
230
  return " ".join([x for x in list_ if x is not None])
228
231
 
229
- def visit_select(self, select: Select):
232
+ def visit_select(self, select: Select, sep: str = " ", **kw):
230
233
  params = {}
231
234
 
232
235
  # COMMENT: when passing alias into 'select' method, we gonna replace the current aliases of columns with the generic one.
@@ -236,15 +239,15 @@ class MySQLCompiler(compiler.SQLCompiler):
236
239
  elif select.alias:
237
240
  params["alias_clause"] = select.alias
238
241
 
239
- columns = ClauseInfo.join_clauses(select.columns, ",", dialect=self.dialect, **params)
242
+ columns = ClauseInfo.join_clauses(select.columns, sep, dialect=self.dialect, **params)
243
+
240
244
  from_ = ClauseInfo(
241
245
  select._table,
242
246
  None,
243
- alias_table=select._alias_table,
244
247
  dialect=self.dialect,
245
248
  ).query(self.dialect)
246
249
 
247
- return f"SELECT {columns} FROM {from_}"
250
+ return f"SELECT{sep}{columns}{sep}FROM {from_}"
248
251
 
249
252
  def visit_group_by(self, groupby: GroupBy):
250
253
  column = ", ".join(x.compile(self.dialect, alias_clause=None).string for x in groupby.column)
@@ -320,11 +323,18 @@ class MySQLCompiler(compiler.SQLCompiler):
320
323
  unknown_rows = f"({', '.join(wildcards)})" # The number of "%s" must match the dict 'dicc_0' length
321
324
 
322
325
  insert.cleaned_values = [tuple(x) for x in col_values]
323
- query = f"INSERT INTO {insert.table.__table_name__} {f'({join_cols})'} VALUES {unknown_rows}"
326
+ query = f"INSERT INTO {self.visit_table(insert.table)} {f'({join_cols})'} VALUES {unknown_rows}"
324
327
  return query
325
328
 
326
329
  def visit_delete(self, delete: Delete, **kw) -> str:
327
- return f"DELETE FROM {delete.table.__table_name__}"
330
+ query = f"DELETE FROM {self.visit_table(delete.table)}"
331
+
332
+ if delete.where.comparers:
333
+ # COMMENT: We need to change the Where.restrictive due to if we use more than one where, we want to use "OR" instead "AND"
334
+ for x in range(len(delete.where.restrictive)):
335
+ delete.where.restrictive[x] = "OR"
336
+ query += " " + delete.where.compile(self.dialect).string
337
+ return query
328
338
 
329
339
  def visit_upsert(self, upsert: Upsert, **kw) -> str:
330
340
  """
@@ -436,6 +446,11 @@ class MySQLCompiler(compiler.SQLCompiler):
436
446
  set_query: str = ",".join(["=".join(col_data) for col_data in col_names])
437
447
 
438
448
  query = f"UPDATE {update.table.__table_name__} SET {set_query}"
449
+
450
+ if update.where.comparers:
451
+ where_string = update.where.compile(self.dialect).string
452
+
453
+ query += " " + where_string
439
454
  update.cleaned_values = tuple(update.cleaned_values)
440
455
  return query
441
456
 
@@ -568,7 +583,7 @@ class MySQLCompiler(compiler.SQLCompiler):
568
583
 
569
584
  class MySQLDDLCompiler(compiler.DDLCompiler):
570
585
  def get_column_specification(self, column: Column, **kwargs):
571
- colspec = column.column_name + " " + self.dialect.type_compiler_instance.process(column.dbtype)
586
+ colspec = column.column_name + " " + self.dialect.type_compiler_instance.process(column.dtype)
572
587
  default = self.get_column_default_string(column)
573
588
  if default is not None:
574
589
  colspec += " DEFAULT " + default
@@ -1,4 +1,5 @@
1
1
  from __future__ import annotations
2
+ from typing import Union
2
3
  from ormlambda.caster.caster import Caster
3
4
 
4
5
 
@@ -41,5 +42,6 @@ class MySQLCaster(Caster):
41
42
  list: IterableCaster,
42
43
  bool: BooleanCaster,
43
44
  Decimal: DecimalCaster,
44
- dict:JsonCaster
45
+ dict: JsonCaster,
46
+ Union[list | dict]: JsonCaster,
45
47
  }
@@ -9,4 +9,4 @@ from .iterable import IterableCaster as IterableCaster
9
9
  from .boolean import BooleanCaster as BooleanCaster
10
10
  from .date import DateCaster as DateCaster
11
11
  from .decimal import DecimalCaster as DecimalCaster
12
- from .json import JsonCaster as JsonCaster
12
+ from .json import JsonCaster as JsonCaster
@@ -2,6 +2,7 @@ from typing import Optional
2
2
  from ormlambda.caster import BaseCaster, Caster
3
3
  import json
4
4
 
5
+
5
6
  class JsonCaster[TType](BaseCaster[dict, TType]):
6
7
  def __init__(self, value: dict, type_value: TType):
7
8
  super().__init__(value, type_value)
@@ -0,0 +1 @@
1
+ from .repository import MySQLRepository # noqa: F401
@@ -5,8 +5,10 @@ import shapely as shp
5
5
 
6
6
  # Custom libraries
7
7
  from ormlambda.sql.clauses import Alias
8
+ from ormlambda import ColumnProxy
8
9
 
9
10
  if TYPE_CHECKING:
11
+ from ormlambda.sql.types import SelectCol
10
12
  from ormlambda.sql.clause_info import ClauseInfo
11
13
  from ormlambda import Table
12
14
  from ormlambda.sql.clauses import Select
@@ -69,12 +71,11 @@ class Response[TFlavour, *Ts]:
69
71
  nonlocal data
70
72
  result = []
71
73
  for value in data:
72
- if len(value) ==1:
74
+ if len(value) == 1:
73
75
  result.append(value[0])
74
76
  continue
75
77
  result.append(value)
76
78
 
77
-
78
79
  return result
79
80
 
80
81
  def _set(**kwargs) -> list[set]:
@@ -130,7 +131,7 @@ class Response[TFlavour, *Ts]:
130
131
  for i, data in enumerate(row):
131
132
  alias = self._columns[i]
132
133
  clause = self._select[alias]
133
- dtype = clause.dtype if hasattr(clause, "dtype") else None
134
+ dtype = self.get_python_type(clause)
134
135
  parse_data = self._caster.for_value(data, value_type=dtype).from_database
135
136
  new_row.append(parse_data)
136
137
  new_row = tuple(new_row)
@@ -146,3 +147,12 @@ class Response[TFlavour, *Ts]:
146
147
  return False
147
148
 
148
149
  return clause_info.dtype is shp.Point
150
+
151
+ @staticmethod
152
+ def get_python_type[T](value: SelectCol) -> Type[T]:
153
+ if isinstance(value, ColumnProxy):
154
+ return value.dtype.python_type
155
+
156
+ if hasattr(value, "dtype"):
157
+ return value.dtype
158
+ return None
@@ -4,9 +4,9 @@ import typing as tp
4
4
  import re
5
5
 
6
6
  from ormlambda.sql.types import ASTERISK
7
- from ormlambda.errors import DuplicatedClauseNameError
7
+ from ormlambda.common.errors import DuplicatedClauseNameError
8
8
  from .interface import IClauseInfo
9
- from ormlambda.common import GlobalChecker
9
+ from ormlambda.common import GlobalChecker, DOT
10
10
  from ormlambda import util
11
11
 
12
12
 
@@ -46,6 +46,8 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
46
46
  def __init__(self, table: TableType[T], preserve_context: tp.Optional[bool] = ...): ...
47
47
  @tp.overload
48
48
  def __init__[TProp](self, table: TableType[T], dtype: tp.Optional[TProp] = ...): ...
49
+ @tp.overload
50
+ def __init__(self, table: TableType[T], literal: bool = ...): ...
49
51
 
50
52
  @tp.overload
51
53
  def __init__(self, dialect: Dialect, *args, **kwargs): ...
@@ -122,8 +124,10 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
122
124
  @property
123
125
  def alias_table(self) -> tp.Optional[str]:
124
126
  alias = self._alias_table
127
+
125
128
  return self._alias_resolver(alias)
126
129
 
130
+
127
131
  # TODOL [ ]: if we using this setter, we don't update the _context with the new value. Study if it's necessary
128
132
  @alias_table.setter
129
133
  def alias_table(self, value: str) -> str:
@@ -146,7 +150,7 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
146
150
  return self._dtype
147
151
 
148
152
  if self.is_column(self._column):
149
- return self._column.dtype
153
+ return self._column.dtype.python_type
150
154
 
151
155
  if isinstance(self._column, type):
152
156
  return self._column
@@ -185,7 +189,8 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
185
189
  # When passing the Table itself without 'column'
186
190
  if self.table and not self._column:
187
191
  if not self._alias_table:
188
- return self.table.__table_name__
192
+ return self.join_db_and_table(self.table)
193
+
189
194
  alias_table = self.alias_table
190
195
  return self.concat_alias_and_column(self.table.__table_name__, alias_table)
191
196
 
@@ -193,6 +198,20 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
193
198
  return self._get_all_columns(dialect)
194
199
  return self._join_table_and_column(self._column, dialect)
195
200
 
201
+ @classmethod
202
+ def join_db_and_table(cls, table: str| Table, table_name: tp.Optional[str] = None) -> str:
203
+ table_name = table.__table_name__ if (not table_name and hasattr(table,"__table_name__")) else table_name
204
+
205
+ db = table.__db_name__ if hasattr(table,"__db_name__") else None
206
+
207
+ wrapped_table = cls.wrapped_with_quotes(table_name)
208
+
209
+ if db:
210
+ wrapped_db = cls.wrapped_with_quotes(db)
211
+ return f"{wrapped_db}{DOT}{wrapped_table}"
212
+
213
+ return wrapped_table
214
+
196
215
  @util.preload_module("ormlambda.sql")
197
216
  def _join_table_and_column[TProp](self, column: ColumnType[TProp], dialect: Dialect) -> str:
198
217
  ColumnProxy = util.preloaded.sql_column.ColumnProxy
@@ -200,15 +219,17 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
200
219
  caster = dialect.caster()
201
220
 
202
221
  if self.alias_table:
203
- table = self.wrapped_with_quotes(self.alias_table)
222
+ col = column.table if hasattr(column, "table") else column
223
+ table = self.join_db_and_table(col, self.alias_table)
204
224
  elif isinstance(column, ColumnProxy):
205
- table = self.wrapped_with_quotes(column.get_table_chain())
225
+ table_name: str = column.get_table_chain()
226
+ table = self.join_db_and_table(column.table, table_name)
206
227
  else:
207
228
  table = self.table.__table_name__
208
229
 
209
230
  column: str = self._column_resolver(column)
210
231
 
211
- table_column = f"{table}.{column}"
232
+ table_column = f"{table}{DOT}{column}"
212
233
 
213
234
  dtype = str if self.is_table(self.dtype) else self.dtype
214
235
  wrapped_column = caster.for_value(table_column, dtype).wildcard_to_select(table_column)
@@ -309,7 +330,7 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
309
330
 
310
331
  @util.preload_module("ormlambda.sql.clauses")
311
332
  @staticmethod
312
- def join_clauses(clauses: list[ColumnProxy], chr: str = ",", *, dialect: Dialect, **kw) -> str:
333
+ def join_clauses(clauses: list[ColumnProxy], chr: str = " ", *, dialect: Dialect, **kw) -> str:
313
334
  IComparer = util.preloaded.sql_comparer.IComparer
314
335
 
315
336
  raise_alias_duplicated = False
@@ -345,7 +366,7 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
345
366
 
346
367
  if raise_alias_duplicated:
347
368
  raise DuplicatedClauseNameError(tuple(alias for alias, number in all_aliases.items() if number > 1))
348
- return f"{chr} ".join(queries)
369
+ return f",{chr}".join(queries)
349
370
 
350
371
  @staticmethod
351
372
  def wrapped_with_quotes(
@@ -375,7 +396,7 @@ class ClauseInfo[T: Table](IClauseInfo[T]):
375
396
  def is_table(data: ColumnType | Table | ForeignKey) -> bool:
376
397
  Table = util.preloaded.sql_table.Table
377
398
  TableProxy = util.preloaded.sql_table.TableProxy
378
-
399
+
379
400
  return isinstance(data, type) and issubclass(data, Table | TableProxy)
380
401
 
381
402
  @util.preload_module("ormlambda.sql")
@@ -46,7 +46,7 @@ class ComparerAlias(IComparer):
46
46
  return self.comparer.join
47
47
 
48
48
  def compile(self, dialect=None, **kw):
49
- return cast(ClauseElement,self.comparer).compile(dialect, **kw)
49
+ return cast(ClauseElement, self.comparer).compile(dialect, **kw)
50
50
 
51
51
 
52
52
  __all__ = ["Alias"]
@@ -0,0 +1,25 @@
1
+ from __future__ import annotations
2
+ from typing import Iterable, overload, TYPE_CHECKING
3
+ from ormlambda.sql.elements import ClauseElement
4
+ from ormlambda import Table
5
+
6
+ if TYPE_CHECKING:
7
+ from ormlambda.sql.clauses import Where
8
+
9
+
10
+ class Delete[T: Table](ClauseElement):
11
+ __visit_name__ = "delete"
12
+
13
+ @overload
14
+ def __init__(self, table: T, where: Where, values: T) -> None: ...
15
+ @overload
16
+ def __init__(self, table: T, where: Where, values: Iterable[T]) -> None: ...
17
+
18
+ def __init__(self, table: T, where: Where, values) -> None:
19
+ self.values: Table | Iterable[Table] = values
20
+ self.table = table
21
+ self.cleaned_values = []
22
+ self.where = where
23
+
24
+
25
+ __all__ = ["Delete"]
@@ -16,7 +16,7 @@ class Insert[T: Table](ClauseElement):
16
16
  def __init__(self, values: T) -> None: ...
17
17
 
18
18
  def __init__(self, values: T | list[T]) -> None:
19
- self.values:Iterable[T] = values if isinstance(values, Iterable) else (values,)
19
+ self.values: Iterable[T] = values if isinstance(values, Iterable) else (values,)
20
20
  self.table = type(self.values[0])
21
21
 
22
22
  self.cleaned_values = []
@@ -0,0 +1,26 @@
1
+ from __future__ import annotations
2
+ from typing import Iterable, Type, overload, Any, TYPE_CHECKING
3
+
4
+ from ormlambda import Table
5
+ from ormlambda.sql.elements import ClauseElement
6
+
7
+ if TYPE_CHECKING:
8
+ from ormlambda.sql.clauses import Where
9
+
10
+
11
+ class Update[T: Type[Table]](ClauseElement):
12
+ __visit_name__ = "update"
13
+
14
+ @overload
15
+ def __init__(self, model: T, where: Where, values: dict[str, Any]) -> None: ...
16
+ @overload
17
+ def __init__(self, model: T, where: Where, values: Iterable[dict[str, Any]]) -> None: ...
18
+
19
+ def __init__(self, model: T, where: Where, values) -> None:
20
+ self.values: Iterable[dict[str, Any]] = values if isinstance(values, Iterable) else (values,)
21
+ self.table: Table = model
22
+ self.cleaned_values = []
23
+ self.where: Where = where
24
+
25
+
26
+ __all__ = ["Update"]
@@ -38,5 +38,4 @@ class Where(ClauseElement):
38
38
  return None
39
39
 
40
40
 
41
-
42
41
  __all__ = ["Where"]