ormlambda 3.11.2__py3-none-any.whl → 3.34.0__py3-none-any.whl
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/__init__.py +3 -1
- ormlambda/caster/__init__.py +1 -1
- ormlambda/caster/caster.py +29 -12
- ormlambda/common/abstract_classes/clause_info_converter.py +65 -0
- ormlambda/common/abstract_classes/decomposition_query.py +27 -68
- ormlambda/common/abstract_classes/non_query_base.py +10 -8
- ormlambda/common/abstract_classes/query_base.py +3 -1
- ormlambda/common/errors/__init__.py +29 -0
- ormlambda/common/interfaces/ICustomAlias.py +1 -1
- ormlambda/common/interfaces/IQueryCommand.py +6 -2
- ormlambda/dialects/__init__.py +39 -0
- ormlambda/dialects/default/__init__.py +1 -0
- ormlambda/dialects/default/base.py +39 -0
- ormlambda/dialects/interface/__init__.py +1 -0
- ormlambda/dialects/interface/dialect.py +78 -0
- ormlambda/dialects/mysql/__init__.py +38 -0
- ormlambda/dialects/mysql/base.py +388 -0
- ormlambda/dialects/mysql/caster/caster.py +39 -0
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/__init__.py +1 -0
- ormlambda/dialects/mysql/caster/types/boolean.py +35 -0
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/bytes.py +7 -7
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/datetime.py +7 -7
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/float.py +7 -7
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/int.py +7 -7
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/iterable.py +7 -7
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/none.py +8 -7
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/point.py +4 -4
- ormlambda/{databases/my_sql → dialects/mysql}/caster/types/string.py +7 -7
- ormlambda/{databases/my_sql → dialects/mysql}/clauses/ST_AsText.py +8 -7
- ormlambda/{databases/my_sql → dialects/mysql}/clauses/ST_Contains.py +10 -5
- ormlambda/dialects/mysql/clauses/__init__.py +13 -0
- ormlambda/dialects/mysql/clauses/count.py +33 -0
- ormlambda/dialects/mysql/clauses/delete.py +9 -0
- ormlambda/dialects/mysql/clauses/group_by.py +17 -0
- ormlambda/dialects/mysql/clauses/having.py +12 -0
- ormlambda/dialects/mysql/clauses/insert.py +9 -0
- ormlambda/dialects/mysql/clauses/joins.py +14 -0
- ormlambda/dialects/mysql/clauses/limit.py +6 -0
- ormlambda/dialects/mysql/clauses/offset.py +6 -0
- ormlambda/dialects/mysql/clauses/order.py +8 -0
- ormlambda/dialects/mysql/clauses/update.py +8 -0
- ormlambda/dialects/mysql/clauses/upsert.py +9 -0
- ormlambda/dialects/mysql/clauses/where.py +7 -0
- ormlambda/dialects/mysql/mysqlconnector.py +46 -0
- ormlambda/dialects/mysql/repository/__init__.py +1 -0
- ormlambda/dialects/mysql/repository/repository.py +212 -0
- ormlambda/dialects/mysql/types.py +732 -0
- ormlambda/dialects/sqlite/__init__.py +5 -0
- ormlambda/dialects/sqlite/base.py +47 -0
- ormlambda/dialects/sqlite/pysqlite.py +32 -0
- ormlambda/engine/__init__.py +1 -0
- ormlambda/engine/base.py +77 -0
- ormlambda/engine/create.py +9 -23
- ormlambda/engine/url.py +34 -19
- ormlambda/env.py +30 -0
- ormlambda/errors.py +17 -0
- ormlambda/model/base_model.py +7 -9
- ormlambda/repository/base_repository.py +36 -5
- ormlambda/repository/interfaces/IRepositoryBase.py +119 -12
- ormlambda/repository/response.py +134 -0
- ormlambda/sql/clause_info/__init__.py +2 -1
- ormlambda/sql/clause_info/aggregate_function_base.py +96 -0
- ormlambda/sql/clause_info/clause_info.py +35 -115
- ormlambda/sql/clause_info/interface/IClauseInfo.py +37 -0
- ormlambda/sql/clause_info/interface/__init__.py +1 -0
- ormlambda/sql/clauses/__init__.py +14 -0
- ormlambda/{databases/my_sql → sql}/clauses/alias.py +23 -6
- ormlambda/{databases/my_sql → sql}/clauses/count.py +15 -1
- ormlambda/{databases/my_sql → sql}/clauses/delete.py +22 -7
- ormlambda/sql/clauses/group_by.py +30 -0
- ormlambda/{databases/my_sql → sql}/clauses/having.py +7 -2
- ormlambda/{databases/my_sql → sql}/clauses/insert.py +16 -9
- ormlambda/sql/clauses/interfaces/__init__.py +5 -0
- ormlambda/sql/clauses/join/__init__.py +1 -0
- ormlambda/{databases/my_sql → sql/clauses/join}/join_context.py +15 -7
- ormlambda/{databases/my_sql → sql}/clauses/joins.py +29 -19
- ormlambda/sql/clauses/limit.py +15 -0
- ormlambda/sql/clauses/offset.py +15 -0
- ormlambda/{databases/my_sql → sql}/clauses/order.py +14 -24
- ormlambda/{databases/my_sql → sql}/clauses/select.py +14 -13
- ormlambda/{databases/my_sql → sql}/clauses/update.py +24 -11
- ormlambda/{databases/my_sql → sql}/clauses/upsert.py +19 -10
- ormlambda/{databases/my_sql → sql}/clauses/where.py +28 -8
- ormlambda/sql/column/__init__.py +1 -0
- ormlambda/sql/{column.py → column/column.py} +85 -22
- ormlambda/sql/comparer.py +51 -37
- ormlambda/sql/compiler.py +668 -0
- ormlambda/sql/ddl.py +82 -0
- ormlambda/sql/elements.py +36 -0
- ormlambda/sql/foreign_key.py +61 -39
- ormlambda/{databases/my_sql → sql}/functions/concat.py +13 -5
- ormlambda/{databases/my_sql → sql}/functions/max.py +9 -4
- ormlambda/{databases/my_sql → sql}/functions/min.py +9 -13
- ormlambda/{databases/my_sql → sql}/functions/sum.py +8 -10
- ormlambda/sql/sqltypes.py +647 -0
- ormlambda/sql/table/__init__.py +1 -1
- ormlambda/sql/table/table.py +175 -0
- ormlambda/sql/table/table_constructor.py +1 -208
- ormlambda/sql/type_api.py +35 -0
- ormlambda/sql/types.py +3 -1
- ormlambda/sql/visitors.py +74 -0
- ormlambda/statements/__init__.py +1 -0
- ormlambda/statements/base_statement.py +34 -40
- ormlambda/statements/interfaces/IStatements.py +28 -21
- ormlambda/statements/query_builder.py +163 -0
- ormlambda/{databases/my_sql → statements}/statements.py +68 -210
- ormlambda/statements/types.py +2 -2
- ormlambda/types/__init__.py +24 -0
- ormlambda/types/metadata.py +42 -0
- ormlambda/util/__init__.py +87 -0
- ormlambda/{utils → util}/module_tree/dynamic_module.py +4 -3
- ormlambda/util/plugin_loader.py +32 -0
- ormlambda/util/typing.py +6 -0
- ormlambda-3.34.0.dist-info/AUTHORS +32 -0
- {ormlambda-3.11.2.dist-info → ormlambda-3.34.0.dist-info}/METADATA +56 -10
- ormlambda-3.34.0.dist-info/RECORD +152 -0
- ormlambda/components/__init__.py +0 -4
- ormlambda/components/delete/__init__.py +0 -2
- ormlambda/components/delete/abstract_delete.py +0 -17
- ormlambda/components/insert/__init__.py +0 -2
- ormlambda/components/insert/abstract_insert.py +0 -25
- ormlambda/components/select/__init__.py +0 -1
- ormlambda/components/update/__init__.py +0 -2
- ormlambda/components/update/abstract_update.py +0 -29
- ormlambda/components/upsert/__init__.py +0 -2
- ormlambda/components/upsert/abstract_upsert.py +0 -25
- ormlambda/databases/__init__.py +0 -5
- ormlambda/databases/my_sql/__init__.py +0 -4
- ormlambda/databases/my_sql/caster/caster.py +0 -39
- ormlambda/databases/my_sql/clauses/__init__.py +0 -20
- ormlambda/databases/my_sql/clauses/create_database.py +0 -35
- ormlambda/databases/my_sql/clauses/drop_database.py +0 -17
- ormlambda/databases/my_sql/clauses/drop_table.py +0 -23
- ormlambda/databases/my_sql/clauses/group_by.py +0 -31
- ormlambda/databases/my_sql/clauses/limit.py +0 -17
- ormlambda/databases/my_sql/clauses/offset.py +0 -17
- ormlambda/databases/my_sql/repository/__init__.py +0 -1
- ormlambda/databases/my_sql/repository/repository.py +0 -351
- ormlambda/engine/template.py +0 -47
- ormlambda/sql/dtypes.py +0 -94
- ormlambda/utils/__init__.py +0 -1
- ormlambda-3.11.2.dist-info/RECORD +0 -120
- /ormlambda/{databases/my_sql → dialects/mysql}/caster/__init__.py +0 -0
- /ormlambda/{databases/my_sql/types.py → dialects/mysql/repository/pool_types.py} +0 -0
- /ormlambda/{components/delete → sql/clauses/interfaces}/IDelete.py +0 -0
- /ormlambda/{components/insert → sql/clauses/interfaces}/IInsert.py +0 -0
- /ormlambda/{components/select → sql/clauses/interfaces}/ISelect.py +0 -0
- /ormlambda/{components/update → sql/clauses/interfaces}/IUpdate.py +0 -0
- /ormlambda/{components/upsert → sql/clauses/interfaces}/IUpsert.py +0 -0
- /ormlambda/{databases/my_sql → sql}/functions/__init__.py +0 -0
- /ormlambda/{utils → util}/module_tree/__init__.py +0 -0
- /ormlambda/{utils → util}/module_tree/dfs_traversal.py +0 -0
- {ormlambda-3.11.2.dist-info → ormlambda-3.34.0.dist-info}/LICENSE +0 -0
- {ormlambda-3.11.2.dist-info → ormlambda-3.34.0.dist-info}/WHEEL +0 -0
@@ -3,14 +3,25 @@ import typing as tp
|
|
3
3
|
from ormlambda.sql.comparer import Comparer
|
4
4
|
from ormlambda.sql.clause_info import AggregateFunctionBase
|
5
5
|
from ormlambda.sql.clause_info.clause_info_context import ClauseInfoContext, ClauseContextType
|
6
|
+
from ormlambda.sql.elements import ClauseElement
|
6
7
|
|
8
|
+
if tp.TYPE_CHECKING:
|
9
|
+
from ormlambda.dialects import Dialect
|
7
10
|
|
8
|
-
|
11
|
+
|
12
|
+
class Where(AggregateFunctionBase, ClauseElement):
|
9
13
|
"""
|
10
14
|
The purpose of this class is to create 'WHERE' condition queries properly.
|
11
15
|
"""
|
12
16
|
|
13
|
-
|
17
|
+
__visit_name__ = "where"
|
18
|
+
|
19
|
+
def __init__(
|
20
|
+
self,
|
21
|
+
*comparer: Comparer,
|
22
|
+
restrictive: bool = True,
|
23
|
+
context: ClauseContextType = None,
|
24
|
+
) -> None:
|
14
25
|
self._comparer: tuple[Comparer] = comparer
|
15
26
|
self._restrictive: bool = restrictive
|
16
27
|
self._context: ClauseContextType = context if context else ClauseInfoContext()
|
@@ -19,11 +30,16 @@ class Where(AggregateFunctionBase):
|
|
19
30
|
def FUNCTION_NAME() -> str:
|
20
31
|
return "WHERE"
|
21
32
|
|
22
|
-
|
23
|
-
def query(self) -> str:
|
33
|
+
def query(self, dialect: Dialect, **kwargs) -> str:
|
24
34
|
if isinstance(self._comparer, tp.Iterable):
|
25
35
|
context = ClauseInfoContext(table_context=self._context._table_context)
|
26
|
-
comparer = Comparer.join_comparers(
|
36
|
+
comparer = Comparer.join_comparers(
|
37
|
+
self._comparer,
|
38
|
+
restrictive=self._restrictive,
|
39
|
+
context=context,
|
40
|
+
dialect=dialect,
|
41
|
+
**kwargs,
|
42
|
+
)
|
27
43
|
else:
|
28
44
|
comparer = self._comparer
|
29
45
|
return f"{self.FUNCTION_NAME()} {comparer}"
|
@@ -33,13 +49,17 @@ class Where(AggregateFunctionBase):
|
|
33
49
|
return None
|
34
50
|
|
35
51
|
@classmethod
|
36
|
-
def join_condition(cls, wheres: tp.Iterable[Where], restrictive: bool, context: ClauseInfoContext) -> str:
|
52
|
+
def join_condition(cls, wheres: tp.Iterable[Where], restrictive: bool, context: ClauseInfoContext, dialect: Dialect = None) -> str:
|
37
53
|
if not isinstance(wheres, tp.Iterable):
|
38
54
|
wheres = (wheres,)
|
39
55
|
|
40
56
|
comparers: list[Comparer] = []
|
41
57
|
for where in wheres:
|
42
58
|
for c in where._comparer:
|
43
|
-
c.
|
59
|
+
if not c._context:
|
60
|
+
c._context = context
|
44
61
|
comparers.append(c)
|
45
|
-
return cls(*comparers, restrictive=restrictive, context=context).query
|
62
|
+
return cls(*comparers, restrictive=restrictive, context=context).query(dialect=dialect)
|
63
|
+
|
64
|
+
|
65
|
+
__all__ = ["Where"]
|
@@ -0,0 +1 @@
|
|
1
|
+
from .column import Column # noqa: F401
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
-
from typing import Iterable, Type, Optional, TYPE_CHECKING, overload
|
3
2
|
import abc
|
3
|
+
from typing import Annotated, Any, Iterable, Type, Optional, TYPE_CHECKING, get_type_hints, overload, get_origin, get_args
|
4
4
|
from ormlambda.sql.types import TableType, ComparerType, ColumnType
|
5
5
|
from ormlambda import ConditionType
|
6
6
|
|
@@ -8,6 +8,19 @@ if TYPE_CHECKING:
|
|
8
8
|
import re
|
9
9
|
from ormlambda import Table
|
10
10
|
from ormlambda.sql.comparer import Comparer, Regex, Like
|
11
|
+
from ormlambda.sql.type_api import TypeEngine
|
12
|
+
|
13
|
+
|
14
|
+
from ormlambda.types import (
|
15
|
+
# metadata
|
16
|
+
PrimaryKey,
|
17
|
+
AutoGenerated,
|
18
|
+
AutoIncrement,
|
19
|
+
Unique,
|
20
|
+
CheckTypes,
|
21
|
+
Default,
|
22
|
+
NotNull,
|
23
|
+
)
|
11
24
|
|
12
25
|
|
13
26
|
class Column[TProp]:
|
@@ -21,6 +34,9 @@ class Column[TProp]:
|
|
21
34
|
"is_auto_generated",
|
22
35
|
"is_auto_increment",
|
23
36
|
"is_unique",
|
37
|
+
"is_not_null",
|
38
|
+
"default_value",
|
39
|
+
"sql_type",
|
24
40
|
"__private_name",
|
25
41
|
"_check",
|
26
42
|
)
|
@@ -37,7 +53,9 @@ class Column[TProp]:
|
|
37
53
|
is_auto_generated: bool = False,
|
38
54
|
is_auto_increment: bool = False,
|
39
55
|
is_unique: bool = False,
|
56
|
+
is_not_null: bool = False,
|
40
57
|
check_types: bool = True,
|
58
|
+
default: Optional[Any] = None,
|
41
59
|
) -> None: ...
|
42
60
|
|
43
61
|
def __init__[T: Table](
|
@@ -48,8 +66,10 @@ class Column[TProp]:
|
|
48
66
|
is_auto_generated: bool = False,
|
49
67
|
is_auto_increment: bool = False,
|
50
68
|
is_unique: bool = False,
|
69
|
+
is_not_null: bool = False,
|
51
70
|
check_types: bool = True,
|
52
71
|
column_name: Optional[str] = None,
|
72
|
+
default: Optional[Any] = None,
|
53
73
|
) -> None:
|
54
74
|
if dtype is None and column_name is None:
|
55
75
|
raise AttributeError("You must specify either the 'dtype' or 'column_name' attribute.")
|
@@ -62,14 +82,17 @@ class Column[TProp]:
|
|
62
82
|
self.column_name: Optional[str] = column_name
|
63
83
|
self.__private_name: Optional[str] = None
|
64
84
|
self._check = check_types
|
85
|
+
self.default_value: TProp = default
|
86
|
+
self.sql_type: TypeEngine[TProp] = None
|
65
87
|
|
66
88
|
self.is_primary_key: bool = is_primary_key
|
67
89
|
self.is_auto_generated: bool = is_auto_generated
|
68
90
|
self.is_auto_increment: bool = is_auto_increment
|
69
91
|
self.is_unique: bool = is_unique
|
92
|
+
self.is_not_null: bool = is_not_null
|
70
93
|
|
71
94
|
def __repr__(self) -> str:
|
72
|
-
return f"{type(self).__name__}[{self.dtype.__name__}] => {self.column_name}"
|
95
|
+
return f"{type(self).__name__}[{self.dtype.__class__.__name__}] => {self.column_name}"
|
73
96
|
|
74
97
|
def __str__(self) -> str:
|
75
98
|
return self.table.__table_name__ + "." + self.column_name
|
@@ -79,6 +102,8 @@ class Column[TProp]:
|
|
79
102
|
self.column_name = name
|
80
103
|
self.__private_name = self.PRIVATE_CHAR + name
|
81
104
|
|
105
|
+
self._fill_from_annotations(owner, name)
|
106
|
+
|
82
107
|
def __get__(self, obj, objtype=None) -> ColumnType[TProp]:
|
83
108
|
if not obj:
|
84
109
|
return self
|
@@ -100,40 +125,78 @@ class Column[TProp]:
|
|
100
125
|
self.is_auto_generated,
|
101
126
|
self.is_auto_increment,
|
102
127
|
self.is_unique,
|
128
|
+
self.is_not_null,
|
103
129
|
)
|
104
130
|
)
|
105
131
|
|
132
|
+
def _fill_from_annotations[T: Table](self, obj: Type[T], name: str) -> None:
|
133
|
+
"""Read the metada when using Annotated typing class, and set the attributes accordingly"""
|
134
|
+
|
135
|
+
from ormlambda.sql.type_api import TypeEngine
|
136
|
+
|
137
|
+
annotations = get_type_hints(obj, include_extras=True)
|
138
|
+
if name in annotations:
|
139
|
+
annotation = annotations[name]
|
140
|
+
if get_origin(annotation) is Annotated:
|
141
|
+
dtype, *metadata = get_args(annotation)
|
142
|
+
|
143
|
+
if not self.dtype:
|
144
|
+
self.dtype = dtype
|
145
|
+
|
146
|
+
for meta in metadata:
|
147
|
+
if isinstance(meta, TypeEngine):
|
148
|
+
self.sql_type = meta
|
149
|
+
elif isinstance(meta, PrimaryKey):
|
150
|
+
self.is_primary_key = True
|
151
|
+
elif isinstance(meta, AutoGenerated):
|
152
|
+
self.is_auto_generated = True
|
153
|
+
elif isinstance(meta, AutoIncrement):
|
154
|
+
self.is_auto_increment = True
|
155
|
+
elif isinstance(meta, Unique):
|
156
|
+
self.is_unique = True
|
157
|
+
elif isinstance(meta, CheckTypes):
|
158
|
+
self._check = True
|
159
|
+
elif isinstance(meta, Default):
|
160
|
+
self.default_value = meta.value
|
161
|
+
self.is_auto_generated = True
|
162
|
+
elif isinstance(meta, NotNull):
|
163
|
+
self.is_not_null = True
|
164
|
+
return None
|
165
|
+
|
106
166
|
@abc.abstractmethod
|
107
|
-
def __comparer_creator
|
167
|
+
def __comparer_creator(self, other: ColumnType, compare: ComparerType) -> Comparer:
|
108
168
|
from ormlambda.sql.comparer import Comparer
|
109
169
|
|
110
|
-
return Comparer
|
170
|
+
return Comparer(self, other, compare)
|
171
|
+
|
172
|
+
def __eq__(self, other: ColumnType) -> Comparer:
|
173
|
+
return self.__comparer_creator(other, ConditionType.EQUAL.value)
|
111
174
|
|
112
|
-
def
|
113
|
-
return self.__comparer_creator(other, ConditionType.
|
175
|
+
def __ne__(self, other: ColumnType) -> Comparer:
|
176
|
+
return self.__comparer_creator(other, ConditionType.NOT_EQUAL.value)
|
114
177
|
|
115
|
-
def
|
116
|
-
return self.__comparer_creator(other, ConditionType.
|
178
|
+
def __lt__(self, other: ColumnType) -> Comparer:
|
179
|
+
return self.__comparer_creator(other, ConditionType.LESS_THAN.value)
|
117
180
|
|
118
|
-
def
|
119
|
-
return self.__comparer_creator(other, ConditionType.
|
181
|
+
def __le__(self, other: ColumnType) -> Comparer:
|
182
|
+
return self.__comparer_creator(other, ConditionType.LESS_THAN_OR_EQUAL.value)
|
120
183
|
|
121
|
-
def
|
122
|
-
return self.__comparer_creator(other, ConditionType.
|
184
|
+
def __gt__(self, other: ColumnType) -> Comparer:
|
185
|
+
return self.__comparer_creator(other, ConditionType.GREATER_THAN.value)
|
123
186
|
|
124
|
-
def
|
125
|
-
return self.__comparer_creator(other, ConditionType.
|
187
|
+
def __ge__(self, other: ColumnType) -> Comparer:
|
188
|
+
return self.__comparer_creator(other, ConditionType.GREATER_THAN_OR_EQUAL.value)
|
126
189
|
|
127
|
-
def
|
128
|
-
|
190
|
+
def contains(self, other: ColumnType) -> Comparer:
|
191
|
+
if not isinstance(other, tuple) and isinstance(other, Iterable):
|
192
|
+
other = tuple(other)
|
129
193
|
|
130
|
-
|
131
|
-
return self.__comparer_creator(other, ConditionType.IN.value, *args)
|
194
|
+
return self.__comparer_creator(other, ConditionType.IN.value)
|
132
195
|
|
133
|
-
def not_contains
|
134
|
-
return self.__comparer_creator(other, ConditionType.NOT_IN.value
|
196
|
+
def not_contains(self, other: ColumnType) -> Comparer:
|
197
|
+
return self.__comparer_creator(other, ConditionType.NOT_IN.value)
|
135
198
|
|
136
|
-
def regex
|
199
|
+
def regex(self, pattern: str, flags: Optional[re.RegexFlag | Iterable[re.RegexFlag]] = None) -> Regex:
|
137
200
|
from ormlambda.sql.comparer import Regex
|
138
201
|
|
139
202
|
if not isinstance(flags, Iterable):
|
@@ -145,7 +208,7 @@ class Column[TProp]:
|
|
145
208
|
flags=flags,
|
146
209
|
)
|
147
210
|
|
148
|
-
def like
|
211
|
+
def like(self, pattern: str) -> Like:
|
149
212
|
from ormlambda.sql.comparer import Like
|
150
213
|
|
151
214
|
return Like(self, pattern)
|
ormlambda/sql/comparer.py
CHANGED
@@ -8,10 +8,11 @@ from ormlambda.common.interfaces.IQueryCommand import IQuery
|
|
8
8
|
from ormlambda.sql.types import ConditionType, ComparerTypes
|
9
9
|
from ormlambda.sql.clause_info import ClauseInfo
|
10
10
|
from ormlambda import ConditionType as ConditionEnum
|
11
|
+
from ormlambda.sql.elements import Element
|
11
12
|
|
12
13
|
if tp.TYPE_CHECKING:
|
13
14
|
from ormlambda.sql.clause_info.clause_info_context import ClauseContextType
|
14
|
-
from ormlambda.
|
15
|
+
from ormlambda.dialects import Dialect
|
15
16
|
|
16
17
|
|
17
18
|
class ICleaner(abc.ABC):
|
@@ -45,75 +46,88 @@ class CleanValue:
|
|
45
46
|
return temp_name
|
46
47
|
|
47
48
|
|
48
|
-
class Comparer
|
49
|
+
class Comparer(Element, IQuery):
|
50
|
+
__visit_name__ = "comparer"
|
51
|
+
|
49
52
|
def __init__(
|
50
53
|
self,
|
51
|
-
left_condition: ConditionType
|
52
|
-
right_condition: ConditionType
|
54
|
+
left_condition: ConditionType,
|
55
|
+
right_condition: ConditionType,
|
53
56
|
compare: ComparerTypes,
|
54
57
|
context: ClauseContextType = None,
|
55
58
|
flags: tp.Optional[tp.Iterable[re.RegexFlag]] = None,
|
59
|
+
dialect: tp.Optional[Dialect] = None,
|
56
60
|
) -> None:
|
57
61
|
self._context: ClauseContextType = context
|
58
62
|
self._compare: ComparerTypes = compare
|
59
|
-
self._left_condition: Comparer
|
60
|
-
self._right_condition: Comparer
|
63
|
+
self._left_condition: Comparer | ClauseInfo = left_condition
|
64
|
+
self._right_condition: Comparer | ClauseInfo = right_condition
|
61
65
|
self._flags = flags
|
66
|
+
self._dialect = dialect
|
62
67
|
|
63
68
|
def set_context(self, context: ClauseContextType) -> None:
|
64
69
|
self._context = context
|
70
|
+
return None
|
71
|
+
|
72
|
+
def set_dialect(self, dialect: Dialect) -> None:
|
73
|
+
self._dialect = dialect
|
74
|
+
return None
|
65
75
|
|
66
76
|
def __repr__(self) -> str:
|
67
77
|
return f"{Comparer.__name__}: {self.query}"
|
68
78
|
|
69
|
-
def _create_clause_info
|
79
|
+
def _create_clause_info(self, cond: ConditionType, dialect: Dialect, **kw) -> Comparer | ClauseInfo:
|
70
80
|
from ormlambda import Column
|
71
81
|
|
72
82
|
if isinstance(cond, Comparer):
|
73
83
|
return cond
|
74
|
-
if isinstance(cond, Column)
|
75
|
-
|
84
|
+
table = None if not isinstance(cond, Column) else cond.table
|
85
|
+
|
76
86
|
# it a value that's not depend of any Table
|
77
|
-
return ClauseInfo(
|
87
|
+
return ClauseInfo(
|
88
|
+
table,
|
89
|
+
cond,
|
90
|
+
alias_clause=None,
|
91
|
+
context=self._context,
|
92
|
+
dialect=dialect,
|
93
|
+
**kw,
|
94
|
+
)
|
78
95
|
|
79
|
-
|
80
|
-
|
81
|
-
return self._create_clause_info(self._left_condition)
|
96
|
+
def left_condition(self, dialect: Dialect) -> Comparer | ClauseInfo:
|
97
|
+
return self._create_clause_info(self._left_condition, dialect=dialect)
|
82
98
|
|
83
|
-
|
84
|
-
|
85
|
-
return self._create_clause_info(self._right_condition)
|
99
|
+
def right_condition(self, dialect: Dialect) -> Comparer | ClauseInfo:
|
100
|
+
return self._create_clause_info(self._right_condition, dialect=dialect)
|
86
101
|
|
87
102
|
@property
|
88
103
|
def compare(self) -> ComparerTypes:
|
89
104
|
return self._compare
|
90
105
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
rcond = self.right_condition.query
|
106
|
+
def query(self, dialect: Dialect, **kwargs) -> str:
|
107
|
+
lcond = self.left_condition(dialect).query(dialect, **kwargs)
|
108
|
+
rcond = self.right_condition(dialect).query(dialect, **kwargs)
|
95
109
|
|
96
110
|
if self._flags:
|
97
111
|
rcond = CleanValue(rcond, self._flags).clean()
|
98
112
|
|
99
113
|
return f"{lcond} {self._compare} {rcond}"
|
100
114
|
|
101
|
-
def __and__(self, other: Comparer,
|
115
|
+
def __and__(self, other: Comparer, **kwargs) -> Comparer:
|
102
116
|
# Customize the behavior of '&'
|
103
|
-
return Comparer(self, other, "AND",
|
117
|
+
return Comparer(self, other, "AND", **kwargs)
|
104
118
|
|
105
|
-
def __or__(self, other: Comparer,
|
119
|
+
def __or__(self, other: Comparer, **kwargs) -> Comparer:
|
106
120
|
# Customize the behavior of '|'
|
107
|
-
return Comparer(self, other, "OR",
|
121
|
+
return Comparer(self, other, "OR", **kwargs)
|
108
122
|
|
109
123
|
@classmethod
|
110
|
-
def join_comparers(cls, comparers: list[Comparer], restrictive: bool = True, context: ClauseContextType = None) -> str:
|
124
|
+
def join_comparers(cls, comparers: list[Comparer], restrictive: bool = True, context: ClauseContextType = None, *, dialect) -> str:
|
111
125
|
if not isinstance(comparers, tp.Iterable):
|
112
126
|
raise ValueError(f"Excepted '{Comparer.__name__}' iterable not {type(comparers).__name__}")
|
113
127
|
if len(comparers) == 1:
|
114
128
|
comparer = comparers[0]
|
115
|
-
comparer.
|
116
|
-
return comparer.query
|
129
|
+
comparer._context = context
|
130
|
+
return comparer.query(dialect)
|
117
131
|
|
118
132
|
join_method = cls.__or__ if not restrictive else cls.__and__
|
119
133
|
|
@@ -121,19 +135,19 @@ class Comparer[LTable: Table, LProp, RTable: Table, RProp](IQuery):
|
|
121
135
|
for i in range(len(comparers) - 1):
|
122
136
|
if ini_comparer is None:
|
123
137
|
ini_comparer = comparers[i]
|
124
|
-
ini_comparer.
|
138
|
+
ini_comparer._context = context
|
125
139
|
right_comparer = comparers[i + 1]
|
126
|
-
right_comparer.
|
127
|
-
new_comparer = join_method(ini_comparer, right_comparer, context=context)
|
140
|
+
right_comparer._context = context
|
141
|
+
new_comparer = join_method(ini_comparer, right_comparer, context=context, dialect=dialect)
|
128
142
|
ini_comparer = new_comparer
|
129
|
-
return new_comparer.query
|
143
|
+
return new_comparer.query(dialect)
|
130
144
|
|
131
145
|
|
132
|
-
class Regex
|
146
|
+
class Regex(Comparer):
|
133
147
|
def __init__(
|
134
148
|
self,
|
135
|
-
left_condition: ConditionType
|
136
|
-
right_condition: ConditionType
|
149
|
+
left_condition: ConditionType,
|
150
|
+
right_condition: ConditionType,
|
137
151
|
context: ClauseContextType = None,
|
138
152
|
flags: tp.Optional[tp.Iterable[re.RegexFlag]] = None,
|
139
153
|
):
|
@@ -146,11 +160,11 @@ class Regex[LProp, RProp](Comparer[None, LProp, None, RProp]):
|
|
146
160
|
)
|
147
161
|
|
148
162
|
|
149
|
-
class Like
|
163
|
+
class Like(Comparer):
|
150
164
|
def __init__(
|
151
165
|
self,
|
152
|
-
left_condition: ConditionType
|
153
|
-
right_condition: ConditionType
|
166
|
+
left_condition: ConditionType,
|
167
|
+
right_condition: ConditionType,
|
154
168
|
context: ClauseContextType = None,
|
155
169
|
):
|
156
170
|
super().__init__(left_condition, right_condition, ConditionEnum.LIKE.value, context)
|