sqlspec 0.16.1__cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.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.
Potentially problematic release.
This version of sqlspec might be problematic. Click here for more details.
- 51ff5a9eadfdefd49f98__mypyc.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/__init__.py +92 -0
- sqlspec/__main__.py +12 -0
- sqlspec/__metadata__.py +14 -0
- sqlspec/_serialization.py +77 -0
- sqlspec/_sql.py +1780 -0
- sqlspec/_typing.py +680 -0
- sqlspec/adapters/__init__.py +0 -0
- sqlspec/adapters/adbc/__init__.py +5 -0
- sqlspec/adapters/adbc/_types.py +12 -0
- sqlspec/adapters/adbc/config.py +361 -0
- sqlspec/adapters/adbc/driver.py +512 -0
- sqlspec/adapters/aiosqlite/__init__.py +19 -0
- sqlspec/adapters/aiosqlite/_types.py +13 -0
- sqlspec/adapters/aiosqlite/config.py +253 -0
- sqlspec/adapters/aiosqlite/driver.py +248 -0
- sqlspec/adapters/asyncmy/__init__.py +19 -0
- sqlspec/adapters/asyncmy/_types.py +12 -0
- sqlspec/adapters/asyncmy/config.py +180 -0
- sqlspec/adapters/asyncmy/driver.py +274 -0
- sqlspec/adapters/asyncpg/__init__.py +21 -0
- sqlspec/adapters/asyncpg/_types.py +17 -0
- sqlspec/adapters/asyncpg/config.py +229 -0
- sqlspec/adapters/asyncpg/driver.py +344 -0
- sqlspec/adapters/bigquery/__init__.py +18 -0
- sqlspec/adapters/bigquery/_types.py +12 -0
- sqlspec/adapters/bigquery/config.py +298 -0
- sqlspec/adapters/bigquery/driver.py +558 -0
- sqlspec/adapters/duckdb/__init__.py +22 -0
- sqlspec/adapters/duckdb/_types.py +12 -0
- sqlspec/adapters/duckdb/config.py +504 -0
- sqlspec/adapters/duckdb/driver.py +368 -0
- sqlspec/adapters/oracledb/__init__.py +32 -0
- sqlspec/adapters/oracledb/_types.py +14 -0
- sqlspec/adapters/oracledb/config.py +317 -0
- sqlspec/adapters/oracledb/driver.py +538 -0
- sqlspec/adapters/psqlpy/__init__.py +16 -0
- sqlspec/adapters/psqlpy/_types.py +11 -0
- sqlspec/adapters/psqlpy/config.py +214 -0
- sqlspec/adapters/psqlpy/driver.py +530 -0
- sqlspec/adapters/psycopg/__init__.py +32 -0
- sqlspec/adapters/psycopg/_types.py +17 -0
- sqlspec/adapters/psycopg/config.py +426 -0
- sqlspec/adapters/psycopg/driver.py +796 -0
- sqlspec/adapters/sqlite/__init__.py +15 -0
- sqlspec/adapters/sqlite/_types.py +11 -0
- sqlspec/adapters/sqlite/config.py +240 -0
- sqlspec/adapters/sqlite/driver.py +294 -0
- sqlspec/base.py +571 -0
- sqlspec/builder/__init__.py +62 -0
- sqlspec/builder/_base.py +473 -0
- sqlspec/builder/_column.py +320 -0
- sqlspec/builder/_ddl.py +1346 -0
- sqlspec/builder/_ddl_utils.py +103 -0
- sqlspec/builder/_delete.py +76 -0
- sqlspec/builder/_insert.py +256 -0
- sqlspec/builder/_merge.py +71 -0
- sqlspec/builder/_parsing_utils.py +140 -0
- sqlspec/builder/_select.py +170 -0
- sqlspec/builder/_update.py +188 -0
- sqlspec/builder/mixins/__init__.py +55 -0
- sqlspec/builder/mixins/_cte_and_set_ops.py +222 -0
- sqlspec/builder/mixins/_delete_operations.py +41 -0
- sqlspec/builder/mixins/_insert_operations.py +244 -0
- sqlspec/builder/mixins/_join_operations.py +122 -0
- sqlspec/builder/mixins/_merge_operations.py +476 -0
- sqlspec/builder/mixins/_order_limit_operations.py +135 -0
- sqlspec/builder/mixins/_pivot_operations.py +153 -0
- sqlspec/builder/mixins/_select_operations.py +603 -0
- sqlspec/builder/mixins/_update_operations.py +187 -0
- sqlspec/builder/mixins/_where_clause.py +621 -0
- sqlspec/cli.py +247 -0
- sqlspec/config.py +395 -0
- sqlspec/core/__init__.py +63 -0
- sqlspec/core/cache.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/cache.py +871 -0
- sqlspec/core/compiler.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/compiler.py +417 -0
- sqlspec/core/filters.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/filters.py +830 -0
- sqlspec/core/hashing.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/hashing.py +310 -0
- sqlspec/core/parameters.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters.py +1237 -0
- sqlspec/core/result.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/result.py +677 -0
- sqlspec/core/splitter.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/splitter.py +819 -0
- sqlspec/core/statement.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/core/statement.py +676 -0
- sqlspec/driver/__init__.py +19 -0
- sqlspec/driver/_async.py +502 -0
- sqlspec/driver/_common.py +631 -0
- sqlspec/driver/_sync.py +503 -0
- sqlspec/driver/mixins/__init__.py +6 -0
- sqlspec/driver/mixins/_result_tools.py +193 -0
- sqlspec/driver/mixins/_sql_translator.py +86 -0
- sqlspec/exceptions.py +193 -0
- sqlspec/extensions/__init__.py +0 -0
- sqlspec/extensions/aiosql/__init__.py +10 -0
- sqlspec/extensions/aiosql/adapter.py +461 -0
- sqlspec/extensions/litestar/__init__.py +6 -0
- sqlspec/extensions/litestar/_utils.py +52 -0
- sqlspec/extensions/litestar/cli.py +48 -0
- sqlspec/extensions/litestar/config.py +92 -0
- sqlspec/extensions/litestar/handlers.py +260 -0
- sqlspec/extensions/litestar/plugin.py +145 -0
- sqlspec/extensions/litestar/providers.py +454 -0
- sqlspec/loader.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/loader.py +760 -0
- sqlspec/migrations/__init__.py +35 -0
- sqlspec/migrations/base.py +414 -0
- sqlspec/migrations/commands.py +443 -0
- sqlspec/migrations/loaders.py +402 -0
- sqlspec/migrations/runner.py +213 -0
- sqlspec/migrations/tracker.py +140 -0
- sqlspec/migrations/utils.py +129 -0
- sqlspec/protocols.py +407 -0
- sqlspec/py.typed +0 -0
- sqlspec/storage/__init__.py +23 -0
- sqlspec/storage/backends/__init__.py +0 -0
- sqlspec/storage/backends/base.py +163 -0
- sqlspec/storage/backends/fsspec.py +386 -0
- sqlspec/storage/backends/obstore.py +459 -0
- sqlspec/storage/capabilities.py +102 -0
- sqlspec/storage/registry.py +239 -0
- sqlspec/typing.py +299 -0
- sqlspec/utils/__init__.py +3 -0
- sqlspec/utils/correlation.py +150 -0
- sqlspec/utils/deprecation.py +106 -0
- sqlspec/utils/fixtures.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/fixtures.py +58 -0
- sqlspec/utils/logging.py +127 -0
- sqlspec/utils/module_loader.py +89 -0
- sqlspec/utils/serializers.py +4 -0
- sqlspec/utils/singleton.py +32 -0
- sqlspec/utils/sync_tools.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/sync_tools.py +237 -0
- sqlspec/utils/text.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/text.py +96 -0
- sqlspec/utils/type_guards.cpython-39-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/type_guards.py +1139 -0
- sqlspec-0.16.1.dist-info/METADATA +365 -0
- sqlspec-0.16.1.dist-info/RECORD +148 -0
- sqlspec-0.16.1.dist-info/WHEEL +7 -0
- sqlspec-0.16.1.dist-info/entry_points.txt +2 -0
- sqlspec-0.16.1.dist-info/licenses/LICENSE +21 -0
- sqlspec-0.16.1.dist-info/licenses/NOTICE +29 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"""Pythonic column expressions for query building.
|
|
2
|
+
|
|
3
|
+
This module provides Column objects that support native Python operators
|
|
4
|
+
for building SQL conditions with type safety and parameter binding.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from collections.abc import Iterable
|
|
8
|
+
from typing import Any, Optional
|
|
9
|
+
|
|
10
|
+
from sqlglot import exp
|
|
11
|
+
|
|
12
|
+
from sqlspec.utils.type_guards import has_sql_method
|
|
13
|
+
|
|
14
|
+
__all__ = ("Column", "ColumnExpression", "FunctionColumn")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ColumnExpression:
|
|
18
|
+
"""Base class for column expressions that can be combined with operators."""
|
|
19
|
+
|
|
20
|
+
__slots__ = ("_expression",)
|
|
21
|
+
|
|
22
|
+
def __init__(self, expression: exp.Expression) -> None:
|
|
23
|
+
self._expression = expression
|
|
24
|
+
|
|
25
|
+
def __and__(self, other: "ColumnExpression") -> "ColumnExpression":
|
|
26
|
+
"""Combine with AND operator (&)."""
|
|
27
|
+
if not isinstance(other, ColumnExpression):
|
|
28
|
+
return NotImplemented
|
|
29
|
+
return ColumnExpression(exp.And(this=self._expression, expression=other._expression))
|
|
30
|
+
|
|
31
|
+
def __or__(self, other: "ColumnExpression") -> "ColumnExpression":
|
|
32
|
+
"""Combine with OR operator (|)."""
|
|
33
|
+
if not isinstance(other, ColumnExpression):
|
|
34
|
+
return NotImplemented
|
|
35
|
+
return ColumnExpression(exp.Or(this=self._expression, expression=other._expression))
|
|
36
|
+
|
|
37
|
+
def __invert__(self) -> "ColumnExpression":
|
|
38
|
+
"""Apply NOT operator (~)."""
|
|
39
|
+
return ColumnExpression(exp.Not(this=self._expression))
|
|
40
|
+
|
|
41
|
+
def __bool__(self) -> bool:
|
|
42
|
+
"""Prevent accidental use of 'and'/'or' keywords."""
|
|
43
|
+
msg = (
|
|
44
|
+
"Cannot use 'and'/'or' operators on ColumnExpression. "
|
|
45
|
+
"Use '&'/'|' operators instead. "
|
|
46
|
+
f"Expression: {self._expression.sql()}"
|
|
47
|
+
)
|
|
48
|
+
raise TypeError(msg)
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def sqlglot_expression(self) -> exp.Expression:
|
|
52
|
+
"""Get the underlying SQLGlot expression."""
|
|
53
|
+
return self._expression
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class Column:
|
|
57
|
+
"""Represents a database column with Python operator support."""
|
|
58
|
+
|
|
59
|
+
__slots__ = ("_expression", "name", "table")
|
|
60
|
+
|
|
61
|
+
def __init__(self, name: str, table: Optional[str] = None) -> None:
|
|
62
|
+
self.name = name
|
|
63
|
+
self.table = table
|
|
64
|
+
|
|
65
|
+
if table:
|
|
66
|
+
self._expression = exp.Column(this=exp.Identifier(this=name), table=exp.Identifier(this=table))
|
|
67
|
+
else:
|
|
68
|
+
self._expression = exp.Column(this=exp.Identifier(this=name))
|
|
69
|
+
|
|
70
|
+
def __eq__(self, other: object) -> ColumnExpression: # type: ignore[override]
|
|
71
|
+
"""Equal to (==)."""
|
|
72
|
+
if other is None:
|
|
73
|
+
return ColumnExpression(exp.Is(this=self._expression, expression=exp.Null()))
|
|
74
|
+
return ColumnExpression(exp.EQ(this=self._expression, expression=exp.convert(other)))
|
|
75
|
+
|
|
76
|
+
def __ne__(self, other: object) -> ColumnExpression: # type: ignore[override]
|
|
77
|
+
"""Not equal to (!=)."""
|
|
78
|
+
if other is None:
|
|
79
|
+
return ColumnExpression(exp.Not(this=exp.Is(this=self._expression, expression=exp.Null())))
|
|
80
|
+
return ColumnExpression(exp.NEQ(this=self._expression, expression=exp.convert(other)))
|
|
81
|
+
|
|
82
|
+
def __gt__(self, other: Any) -> ColumnExpression:
|
|
83
|
+
"""Greater than (>)."""
|
|
84
|
+
return ColumnExpression(exp.GT(this=self._expression, expression=exp.convert(other)))
|
|
85
|
+
|
|
86
|
+
def __ge__(self, other: Any) -> ColumnExpression:
|
|
87
|
+
"""Greater than or equal (>=)."""
|
|
88
|
+
return ColumnExpression(exp.GTE(this=self._expression, expression=exp.convert(other)))
|
|
89
|
+
|
|
90
|
+
def __lt__(self, other: Any) -> ColumnExpression:
|
|
91
|
+
"""Less than (<)."""
|
|
92
|
+
return ColumnExpression(exp.LT(this=self._expression, expression=exp.convert(other)))
|
|
93
|
+
|
|
94
|
+
def __le__(self, other: Any) -> ColumnExpression:
|
|
95
|
+
"""Less than or equal (<=)."""
|
|
96
|
+
return ColumnExpression(exp.LTE(this=self._expression, expression=exp.convert(other)))
|
|
97
|
+
|
|
98
|
+
def __invert__(self) -> ColumnExpression:
|
|
99
|
+
"""Apply NOT operator (~)."""
|
|
100
|
+
return ColumnExpression(exp.Not(this=self._expression))
|
|
101
|
+
|
|
102
|
+
def like(self, pattern: str, escape: Optional[str] = None) -> ColumnExpression:
|
|
103
|
+
"""SQL LIKE pattern matching."""
|
|
104
|
+
if escape:
|
|
105
|
+
like_expr = exp.Like(this=self._expression, expression=exp.convert(pattern), escape=exp.convert(escape))
|
|
106
|
+
else:
|
|
107
|
+
like_expr = exp.Like(this=self._expression, expression=exp.convert(pattern))
|
|
108
|
+
return ColumnExpression(like_expr)
|
|
109
|
+
|
|
110
|
+
def ilike(self, pattern: str) -> ColumnExpression:
|
|
111
|
+
"""Case-insensitive LIKE."""
|
|
112
|
+
return ColumnExpression(exp.ILike(this=self._expression, expression=exp.convert(pattern)))
|
|
113
|
+
|
|
114
|
+
def in_(self, values: Iterable[Any]) -> ColumnExpression:
|
|
115
|
+
"""SQL IN clause."""
|
|
116
|
+
converted_values = [exp.convert(v) for v in values]
|
|
117
|
+
return ColumnExpression(exp.In(this=self._expression, expressions=converted_values))
|
|
118
|
+
|
|
119
|
+
def not_in(self, values: Iterable[Any]) -> ColumnExpression:
|
|
120
|
+
"""SQL NOT IN clause."""
|
|
121
|
+
return ~self.in_(values)
|
|
122
|
+
|
|
123
|
+
def between(self, start: Any, end: Any) -> ColumnExpression:
|
|
124
|
+
"""SQL BETWEEN clause."""
|
|
125
|
+
return ColumnExpression(exp.Between(this=self._expression, low=exp.convert(start), high=exp.convert(end)))
|
|
126
|
+
|
|
127
|
+
def is_null(self) -> ColumnExpression:
|
|
128
|
+
"""SQL IS NULL."""
|
|
129
|
+
return ColumnExpression(exp.Is(this=self._expression, expression=exp.Null()))
|
|
130
|
+
|
|
131
|
+
def is_not_null(self) -> ColumnExpression:
|
|
132
|
+
"""SQL IS NOT NULL."""
|
|
133
|
+
return ColumnExpression(exp.Not(this=exp.Is(this=self._expression, expression=exp.Null())))
|
|
134
|
+
|
|
135
|
+
def not_like(self, pattern: str, escape: Optional[str] = None) -> ColumnExpression:
|
|
136
|
+
"""SQL NOT LIKE pattern matching."""
|
|
137
|
+
return ~self.like(pattern, escape)
|
|
138
|
+
|
|
139
|
+
def not_ilike(self, pattern: str) -> ColumnExpression:
|
|
140
|
+
"""Case-insensitive NOT LIKE."""
|
|
141
|
+
return ~self.ilike(pattern)
|
|
142
|
+
|
|
143
|
+
def any_(self, values: Iterable[Any]) -> ColumnExpression:
|
|
144
|
+
"""SQL = ANY(...) clause."""
|
|
145
|
+
converted_values = [exp.convert(v) for v in values]
|
|
146
|
+
return ColumnExpression(exp.EQ(this=self._expression, expression=exp.Any(expressions=converted_values)))
|
|
147
|
+
|
|
148
|
+
def not_any_(self, values: Iterable[Any]) -> ColumnExpression:
|
|
149
|
+
"""SQL <> ANY(...) clause."""
|
|
150
|
+
converted_values = [exp.convert(v) for v in values]
|
|
151
|
+
return ColumnExpression(exp.NEQ(this=self._expression, expression=exp.Any(expressions=converted_values)))
|
|
152
|
+
|
|
153
|
+
def lower(self) -> "FunctionColumn":
|
|
154
|
+
"""SQL LOWER() function."""
|
|
155
|
+
return FunctionColumn(exp.Lower(this=self._expression))
|
|
156
|
+
|
|
157
|
+
def upper(self) -> "FunctionColumn":
|
|
158
|
+
"""SQL UPPER() function."""
|
|
159
|
+
return FunctionColumn(exp.Upper(this=self._expression))
|
|
160
|
+
|
|
161
|
+
def length(self) -> "FunctionColumn":
|
|
162
|
+
"""SQL LENGTH() function."""
|
|
163
|
+
return FunctionColumn(exp.Length(this=self._expression))
|
|
164
|
+
|
|
165
|
+
def trim(self) -> "FunctionColumn":
|
|
166
|
+
"""SQL TRIM() function."""
|
|
167
|
+
return FunctionColumn(exp.Trim(this=self._expression))
|
|
168
|
+
|
|
169
|
+
def abs(self) -> "FunctionColumn":
|
|
170
|
+
"""SQL ABS() function."""
|
|
171
|
+
return FunctionColumn(exp.Abs(this=self._expression))
|
|
172
|
+
|
|
173
|
+
def round(self, decimals: int = 0) -> "FunctionColumn":
|
|
174
|
+
"""SQL ROUND() function."""
|
|
175
|
+
if decimals == 0:
|
|
176
|
+
return FunctionColumn(exp.Round(this=self._expression))
|
|
177
|
+
return FunctionColumn(exp.Round(this=self._expression, expression=exp.convert(decimals)))
|
|
178
|
+
|
|
179
|
+
def floor(self) -> "FunctionColumn":
|
|
180
|
+
"""SQL FLOOR() function."""
|
|
181
|
+
return FunctionColumn(exp.Floor(this=self._expression))
|
|
182
|
+
|
|
183
|
+
def ceil(self) -> "FunctionColumn":
|
|
184
|
+
"""SQL CEIL() function."""
|
|
185
|
+
return FunctionColumn(exp.Ceil(this=self._expression))
|
|
186
|
+
|
|
187
|
+
def substring(self, start: int, length: Optional[int] = None) -> "FunctionColumn":
|
|
188
|
+
"""SQL SUBSTRING() function."""
|
|
189
|
+
args = [exp.convert(start)]
|
|
190
|
+
if length is not None:
|
|
191
|
+
args.append(exp.convert(length))
|
|
192
|
+
return FunctionColumn(exp.Substring(this=self._expression, expressions=args))
|
|
193
|
+
|
|
194
|
+
def coalesce(self, *values: Any) -> "FunctionColumn":
|
|
195
|
+
"""SQL COALESCE() function."""
|
|
196
|
+
expressions = [self._expression] + [exp.convert(v) for v in values]
|
|
197
|
+
return FunctionColumn(exp.Coalesce(expressions=expressions))
|
|
198
|
+
|
|
199
|
+
def cast(self, data_type: str) -> "FunctionColumn":
|
|
200
|
+
"""SQL CAST() function."""
|
|
201
|
+
return FunctionColumn(exp.Cast(this=self._expression, to=exp.DataType.build(data_type)))
|
|
202
|
+
|
|
203
|
+
def count(self) -> "FunctionColumn":
|
|
204
|
+
"""SQL COUNT() function."""
|
|
205
|
+
return FunctionColumn(exp.Count(this=self._expression))
|
|
206
|
+
|
|
207
|
+
def sum(self) -> "FunctionColumn":
|
|
208
|
+
"""SQL SUM() function."""
|
|
209
|
+
return FunctionColumn(exp.Sum(this=self._expression))
|
|
210
|
+
|
|
211
|
+
def avg(self) -> "FunctionColumn":
|
|
212
|
+
"""SQL AVG() function."""
|
|
213
|
+
return FunctionColumn(exp.Avg(this=self._expression))
|
|
214
|
+
|
|
215
|
+
def min(self) -> "FunctionColumn":
|
|
216
|
+
"""SQL MIN() function."""
|
|
217
|
+
return FunctionColumn(exp.Min(this=self._expression))
|
|
218
|
+
|
|
219
|
+
def max(self) -> "FunctionColumn":
|
|
220
|
+
"""SQL MAX() function."""
|
|
221
|
+
return FunctionColumn(exp.Max(this=self._expression))
|
|
222
|
+
|
|
223
|
+
def count_distinct(self) -> "FunctionColumn":
|
|
224
|
+
"""SQL COUNT(DISTINCT column) function."""
|
|
225
|
+
return FunctionColumn(exp.Count(this=exp.Distinct(expressions=[self._expression])))
|
|
226
|
+
|
|
227
|
+
@staticmethod
|
|
228
|
+
def count_all() -> "FunctionColumn":
|
|
229
|
+
"""SQL COUNT(*) function."""
|
|
230
|
+
return FunctionColumn(exp.Count(this=exp.Star()))
|
|
231
|
+
|
|
232
|
+
def alias(self, alias_name: str) -> exp.Expression:
|
|
233
|
+
"""Create an aliased column expression."""
|
|
234
|
+
return exp.Alias(this=self._expression, alias=alias_name)
|
|
235
|
+
|
|
236
|
+
def asc(self) -> exp.Ordered:
|
|
237
|
+
"""Create an ASC ordering expression."""
|
|
238
|
+
return exp.Ordered(this=self._expression, desc=False)
|
|
239
|
+
|
|
240
|
+
def desc(self) -> exp.Ordered:
|
|
241
|
+
"""Create a DESC ordering expression."""
|
|
242
|
+
return exp.Ordered(this=self._expression, desc=True)
|
|
243
|
+
|
|
244
|
+
def __repr__(self) -> str:
|
|
245
|
+
if self.table:
|
|
246
|
+
return f"Column<{self.table}.{self.name}>"
|
|
247
|
+
return f"Column<{self.name}>"
|
|
248
|
+
|
|
249
|
+
def __hash__(self) -> int:
|
|
250
|
+
"""Hash based on table and column name."""
|
|
251
|
+
return hash((self.table, self.name))
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class FunctionColumn:
|
|
255
|
+
"""Represents the result of a SQL function call on a column."""
|
|
256
|
+
|
|
257
|
+
__slots__ = ("_expression",)
|
|
258
|
+
|
|
259
|
+
def __init__(self, expression: exp.Expression) -> None:
|
|
260
|
+
self._expression = expression
|
|
261
|
+
|
|
262
|
+
def __eq__(self, other: object) -> ColumnExpression: # type: ignore[override]
|
|
263
|
+
return ColumnExpression(exp.EQ(this=self._expression, expression=exp.convert(other)))
|
|
264
|
+
|
|
265
|
+
def __ne__(self, other: object) -> ColumnExpression: # type: ignore[override]
|
|
266
|
+
return ColumnExpression(exp.NEQ(this=self._expression, expression=exp.convert(other)))
|
|
267
|
+
|
|
268
|
+
def like(self, pattern: str) -> ColumnExpression:
|
|
269
|
+
return ColumnExpression(exp.Like(this=self._expression, expression=exp.convert(pattern)))
|
|
270
|
+
|
|
271
|
+
def ilike(self, pattern: str) -> ColumnExpression:
|
|
272
|
+
"""Case-insensitive LIKE."""
|
|
273
|
+
return ColumnExpression(exp.ILike(this=self._expression, expression=exp.convert(pattern)))
|
|
274
|
+
|
|
275
|
+
def in_(self, values: Iterable[Any]) -> ColumnExpression:
|
|
276
|
+
"""SQL IN clause."""
|
|
277
|
+
converted_values = [exp.convert(v) for v in values]
|
|
278
|
+
return ColumnExpression(exp.In(this=self._expression, expressions=converted_values))
|
|
279
|
+
|
|
280
|
+
def not_in_(self, values: Iterable[Any]) -> ColumnExpression:
|
|
281
|
+
"""SQL NOT IN clause."""
|
|
282
|
+
return ~self.in_(values)
|
|
283
|
+
|
|
284
|
+
def not_like(self, pattern: str) -> ColumnExpression:
|
|
285
|
+
"""SQL NOT LIKE."""
|
|
286
|
+
return ~self.like(pattern)
|
|
287
|
+
|
|
288
|
+
def not_ilike(self, pattern: str) -> ColumnExpression:
|
|
289
|
+
"""Case-insensitive NOT LIKE."""
|
|
290
|
+
return ~self.ilike(pattern)
|
|
291
|
+
|
|
292
|
+
def between(self, start: Any, end: Any) -> ColumnExpression:
|
|
293
|
+
"""SQL BETWEEN clause."""
|
|
294
|
+
return ColumnExpression(exp.Between(this=self._expression, low=exp.convert(start), high=exp.convert(end)))
|
|
295
|
+
|
|
296
|
+
def is_null(self) -> ColumnExpression:
|
|
297
|
+
"""SQL IS NULL."""
|
|
298
|
+
return ColumnExpression(exp.Is(this=self._expression, expression=exp.Null()))
|
|
299
|
+
|
|
300
|
+
def is_not_null(self) -> ColumnExpression:
|
|
301
|
+
"""SQL IS NOT NULL."""
|
|
302
|
+
return ColumnExpression(exp.Not(this=exp.Is(this=self._expression, expression=exp.Null())))
|
|
303
|
+
|
|
304
|
+
def any_(self, values: Iterable[Any]) -> ColumnExpression:
|
|
305
|
+
"""SQL = ANY(...) clause."""
|
|
306
|
+
converted_values = [exp.convert(v) for v in values]
|
|
307
|
+
return ColumnExpression(exp.EQ(this=self._expression, expression=exp.Any(expressions=converted_values)))
|
|
308
|
+
|
|
309
|
+
def not_any_(self, values: Iterable[Any]) -> ColumnExpression:
|
|
310
|
+
"""SQL <> ANY(...) clause."""
|
|
311
|
+
converted_values = [exp.convert(v) for v in values]
|
|
312
|
+
return ColumnExpression(exp.NEQ(this=self._expression, expression=exp.Any(expressions=converted_values)))
|
|
313
|
+
|
|
314
|
+
def alias(self, alias_name: str) -> exp.Expression:
|
|
315
|
+
"""Create an aliased function expression."""
|
|
316
|
+
return exp.Alias(this=self._expression, alias=alias_name)
|
|
317
|
+
|
|
318
|
+
def __hash__(self) -> int:
|
|
319
|
+
"""Hash based on the SQL expression."""
|
|
320
|
+
return hash(self._expression.sql() if has_sql_method(self._expression) else str(self._expression))
|