sqlspec 0.13.1__py3-none-any.whl → 0.16.2__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.
Potentially problematic release.
This version of sqlspec might be problematic. Click here for more details.
- sqlspec/__init__.py +71 -8
- sqlspec/__main__.py +12 -0
- sqlspec/__metadata__.py +1 -3
- sqlspec/_serialization.py +1 -2
- sqlspec/_sql.py +930 -136
- sqlspec/_typing.py +278 -142
- sqlspec/adapters/adbc/__init__.py +4 -3
- sqlspec/adapters/adbc/_types.py +12 -0
- sqlspec/adapters/adbc/config.py +116 -285
- sqlspec/adapters/adbc/driver.py +462 -340
- sqlspec/adapters/aiosqlite/__init__.py +18 -3
- sqlspec/adapters/aiosqlite/_types.py +13 -0
- sqlspec/adapters/aiosqlite/config.py +202 -150
- sqlspec/adapters/aiosqlite/driver.py +226 -247
- sqlspec/adapters/asyncmy/__init__.py +18 -3
- sqlspec/adapters/asyncmy/_types.py +12 -0
- sqlspec/adapters/asyncmy/config.py +80 -199
- sqlspec/adapters/asyncmy/driver.py +257 -215
- sqlspec/adapters/asyncpg/__init__.py +19 -4
- sqlspec/adapters/asyncpg/_types.py +17 -0
- sqlspec/adapters/asyncpg/config.py +81 -214
- sqlspec/adapters/asyncpg/driver.py +284 -359
- sqlspec/adapters/bigquery/__init__.py +17 -3
- sqlspec/adapters/bigquery/_types.py +12 -0
- sqlspec/adapters/bigquery/config.py +191 -299
- sqlspec/adapters/bigquery/driver.py +474 -634
- sqlspec/adapters/duckdb/__init__.py +14 -3
- sqlspec/adapters/duckdb/_types.py +12 -0
- sqlspec/adapters/duckdb/config.py +414 -397
- sqlspec/adapters/duckdb/driver.py +342 -393
- sqlspec/adapters/oracledb/__init__.py +19 -5
- sqlspec/adapters/oracledb/_types.py +14 -0
- sqlspec/adapters/oracledb/config.py +123 -458
- sqlspec/adapters/oracledb/driver.py +505 -531
- sqlspec/adapters/psqlpy/__init__.py +13 -3
- sqlspec/adapters/psqlpy/_types.py +11 -0
- sqlspec/adapters/psqlpy/config.py +93 -307
- sqlspec/adapters/psqlpy/driver.py +504 -213
- sqlspec/adapters/psycopg/__init__.py +19 -5
- sqlspec/adapters/psycopg/_types.py +17 -0
- sqlspec/adapters/psycopg/config.py +143 -472
- sqlspec/adapters/psycopg/driver.py +704 -825
- sqlspec/adapters/sqlite/__init__.py +14 -3
- sqlspec/adapters/sqlite/_types.py +11 -0
- sqlspec/adapters/sqlite/config.py +208 -142
- sqlspec/adapters/sqlite/driver.py +263 -278
- sqlspec/base.py +105 -9
- sqlspec/{statement/builder → builder}/__init__.py +12 -14
- sqlspec/{statement/builder/base.py → builder/_base.py} +184 -86
- sqlspec/{statement/builder/column.py → builder/_column.py} +97 -60
- sqlspec/{statement/builder/ddl.py → builder/_ddl.py} +61 -131
- sqlspec/{statement/builder → builder}/_ddl_utils.py +4 -10
- sqlspec/{statement/builder/delete.py → builder/_delete.py} +10 -30
- sqlspec/builder/_insert.py +421 -0
- sqlspec/builder/_merge.py +71 -0
- sqlspec/{statement/builder → builder}/_parsing_utils.py +49 -26
- sqlspec/builder/_select.py +170 -0
- sqlspec/{statement/builder/update.py → builder/_update.py} +16 -20
- sqlspec/builder/mixins/__init__.py +55 -0
- sqlspec/builder/mixins/_cte_and_set_ops.py +222 -0
- sqlspec/{statement/builder/mixins/_delete_from.py → builder/mixins/_delete_operations.py} +8 -1
- sqlspec/builder/mixins/_insert_operations.py +244 -0
- sqlspec/{statement/builder/mixins/_join.py → builder/mixins/_join_operations.py} +45 -13
- sqlspec/{statement/builder/mixins/_merge_clauses.py → builder/mixins/_merge_operations.py} +188 -30
- sqlspec/builder/mixins/_order_limit_operations.py +135 -0
- sqlspec/builder/mixins/_pivot_operations.py +153 -0
- sqlspec/builder/mixins/_select_operations.py +604 -0
- sqlspec/builder/mixins/_update_operations.py +202 -0
- sqlspec/builder/mixins/_where_clause.py +644 -0
- sqlspec/cli.py +247 -0
- sqlspec/config.py +183 -138
- sqlspec/core/__init__.py +63 -0
- sqlspec/core/cache.py +871 -0
- sqlspec/core/compiler.py +417 -0
- sqlspec/core/filters.py +830 -0
- sqlspec/core/hashing.py +310 -0
- sqlspec/core/parameters.py +1237 -0
- sqlspec/core/result.py +677 -0
- sqlspec/{statement → core}/splitter.py +321 -191
- sqlspec/core/statement.py +676 -0
- sqlspec/driver/__init__.py +7 -10
- sqlspec/driver/_async.py +422 -163
- sqlspec/driver/_common.py +545 -287
- sqlspec/driver/_sync.py +426 -160
- sqlspec/driver/mixins/__init__.py +2 -13
- sqlspec/driver/mixins/_result_tools.py +193 -0
- sqlspec/driver/mixins/_sql_translator.py +65 -14
- sqlspec/exceptions.py +5 -252
- sqlspec/extensions/aiosql/adapter.py +93 -96
- sqlspec/extensions/litestar/__init__.py +2 -1
- sqlspec/extensions/litestar/cli.py +48 -0
- sqlspec/extensions/litestar/config.py +0 -1
- sqlspec/extensions/litestar/handlers.py +15 -26
- sqlspec/extensions/litestar/plugin.py +21 -16
- sqlspec/extensions/litestar/providers.py +17 -52
- sqlspec/loader.py +423 -104
- 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 +51 -186
- sqlspec/storage/__init__.py +1 -1
- sqlspec/storage/backends/base.py +37 -40
- sqlspec/storage/backends/fsspec.py +136 -112
- sqlspec/storage/backends/obstore.py +138 -160
- sqlspec/storage/capabilities.py +5 -4
- sqlspec/storage/registry.py +57 -106
- sqlspec/typing.py +136 -115
- sqlspec/utils/__init__.py +2 -2
- sqlspec/utils/correlation.py +0 -3
- sqlspec/utils/deprecation.py +6 -6
- sqlspec/utils/fixtures.py +6 -6
- sqlspec/utils/logging.py +0 -2
- sqlspec/utils/module_loader.py +7 -12
- sqlspec/utils/singleton.py +0 -1
- sqlspec/utils/sync_tools.py +17 -38
- sqlspec/utils/text.py +12 -51
- sqlspec/utils/type_guards.py +482 -235
- {sqlspec-0.13.1.dist-info → sqlspec-0.16.2.dist-info}/METADATA +7 -2
- sqlspec-0.16.2.dist-info/RECORD +134 -0
- sqlspec-0.16.2.dist-info/entry_points.txt +2 -0
- sqlspec/driver/connection.py +0 -207
- sqlspec/driver/mixins/_csv_writer.py +0 -91
- sqlspec/driver/mixins/_pipeline.py +0 -512
- sqlspec/driver/mixins/_result_utils.py +0 -140
- sqlspec/driver/mixins/_storage.py +0 -926
- sqlspec/driver/mixins/_type_coercion.py +0 -130
- sqlspec/driver/parameters.py +0 -138
- sqlspec/service/__init__.py +0 -4
- sqlspec/service/_util.py +0 -147
- sqlspec/service/base.py +0 -1131
- sqlspec/service/pagination.py +0 -26
- sqlspec/statement/__init__.py +0 -21
- sqlspec/statement/builder/insert.py +0 -288
- sqlspec/statement/builder/merge.py +0 -95
- sqlspec/statement/builder/mixins/__init__.py +0 -65
- sqlspec/statement/builder/mixins/_aggregate_functions.py +0 -250
- sqlspec/statement/builder/mixins/_case_builder.py +0 -91
- sqlspec/statement/builder/mixins/_common_table_expr.py +0 -90
- sqlspec/statement/builder/mixins/_from.py +0 -63
- sqlspec/statement/builder/mixins/_group_by.py +0 -118
- sqlspec/statement/builder/mixins/_having.py +0 -35
- sqlspec/statement/builder/mixins/_insert_from_select.py +0 -47
- sqlspec/statement/builder/mixins/_insert_into.py +0 -36
- sqlspec/statement/builder/mixins/_insert_values.py +0 -67
- sqlspec/statement/builder/mixins/_limit_offset.py +0 -53
- sqlspec/statement/builder/mixins/_order_by.py +0 -46
- sqlspec/statement/builder/mixins/_pivot.py +0 -79
- sqlspec/statement/builder/mixins/_returning.py +0 -37
- sqlspec/statement/builder/mixins/_select_columns.py +0 -61
- sqlspec/statement/builder/mixins/_set_ops.py +0 -122
- sqlspec/statement/builder/mixins/_unpivot.py +0 -77
- sqlspec/statement/builder/mixins/_update_from.py +0 -55
- sqlspec/statement/builder/mixins/_update_set.py +0 -94
- sqlspec/statement/builder/mixins/_update_table.py +0 -29
- sqlspec/statement/builder/mixins/_where.py +0 -401
- sqlspec/statement/builder/mixins/_window_functions.py +0 -86
- sqlspec/statement/builder/select.py +0 -221
- sqlspec/statement/filters.py +0 -596
- sqlspec/statement/parameter_manager.py +0 -220
- sqlspec/statement/parameters.py +0 -867
- sqlspec/statement/pipelines/__init__.py +0 -210
- sqlspec/statement/pipelines/analyzers/__init__.py +0 -9
- sqlspec/statement/pipelines/analyzers/_analyzer.py +0 -646
- sqlspec/statement/pipelines/context.py +0 -115
- sqlspec/statement/pipelines/transformers/__init__.py +0 -7
- sqlspec/statement/pipelines/transformers/_expression_simplifier.py +0 -88
- sqlspec/statement/pipelines/transformers/_literal_parameterizer.py +0 -1247
- sqlspec/statement/pipelines/transformers/_remove_comments_and_hints.py +0 -76
- sqlspec/statement/pipelines/validators/__init__.py +0 -23
- sqlspec/statement/pipelines/validators/_dml_safety.py +0 -290
- sqlspec/statement/pipelines/validators/_parameter_style.py +0 -370
- sqlspec/statement/pipelines/validators/_performance.py +0 -718
- sqlspec/statement/pipelines/validators/_security.py +0 -967
- sqlspec/statement/result.py +0 -435
- sqlspec/statement/sql.py +0 -1704
- sqlspec/statement/sql_compiler.py +0 -140
- sqlspec/utils/cached_property.py +0 -25
- sqlspec-0.13.1.dist-info/RECORD +0 -150
- {sqlspec-0.13.1.dist-info → sqlspec-0.16.2.dist-info}/WHEEL +0 -0
- {sqlspec-0.13.1.dist-info → sqlspec-0.16.2.dist-info}/licenses/LICENSE +0 -0
- {sqlspec-0.13.1.dist-info → sqlspec-0.16.2.dist-info}/licenses/NOTICE +0 -0
|
@@ -17,103 +17,104 @@ __all__ = ("Column", "ColumnExpression", "FunctionColumn")
|
|
|
17
17
|
class ColumnExpression:
|
|
18
18
|
"""Base class for column expressions that can be combined with operators."""
|
|
19
19
|
|
|
20
|
+
__slots__ = ("_expression",)
|
|
21
|
+
|
|
20
22
|
def __init__(self, expression: exp.Expression) -> None:
|
|
21
|
-
self.
|
|
23
|
+
self._expression = expression
|
|
22
24
|
|
|
23
25
|
def __and__(self, other: "ColumnExpression") -> "ColumnExpression":
|
|
24
26
|
"""Combine with AND operator (&)."""
|
|
25
27
|
if not isinstance(other, ColumnExpression):
|
|
26
28
|
return NotImplemented
|
|
27
|
-
return ColumnExpression(exp.And(this=self.
|
|
29
|
+
return ColumnExpression(exp.And(this=self._expression, expression=other._expression))
|
|
28
30
|
|
|
29
31
|
def __or__(self, other: "ColumnExpression") -> "ColumnExpression":
|
|
30
32
|
"""Combine with OR operator (|)."""
|
|
31
33
|
if not isinstance(other, ColumnExpression):
|
|
32
34
|
return NotImplemented
|
|
33
|
-
return ColumnExpression(exp.Or(this=self.
|
|
35
|
+
return ColumnExpression(exp.Or(this=self._expression, expression=other._expression))
|
|
34
36
|
|
|
35
37
|
def __invert__(self) -> "ColumnExpression":
|
|
36
38
|
"""Apply NOT operator (~)."""
|
|
37
|
-
return ColumnExpression(exp.Not(this=self.
|
|
39
|
+
return ColumnExpression(exp.Not(this=self._expression))
|
|
38
40
|
|
|
39
41
|
def __bool__(self) -> bool:
|
|
40
42
|
"""Prevent accidental use of 'and'/'or' keywords."""
|
|
41
43
|
msg = (
|
|
42
44
|
"Cannot use 'and'/'or' operators on ColumnExpression. "
|
|
43
45
|
"Use '&'/'|' operators instead. "
|
|
44
|
-
f"Expression: {self.
|
|
46
|
+
f"Expression: {self._expression.sql()}"
|
|
45
47
|
)
|
|
46
48
|
raise TypeError(msg)
|
|
47
49
|
|
|
48
50
|
@property
|
|
49
51
|
def sqlglot_expression(self) -> exp.Expression:
|
|
50
52
|
"""Get the underlying SQLGlot expression."""
|
|
51
|
-
return self.
|
|
53
|
+
return self._expression
|
|
52
54
|
|
|
53
55
|
|
|
54
56
|
class Column:
|
|
55
57
|
"""Represents a database column with Python operator support."""
|
|
56
58
|
|
|
59
|
+
__slots__ = ("_expression", "name", "table")
|
|
60
|
+
|
|
57
61
|
def __init__(self, name: str, table: Optional[str] = None) -> None:
|
|
58
62
|
self.name = name
|
|
59
63
|
self.table = table
|
|
60
64
|
|
|
61
|
-
# Create SQLGlot column expression
|
|
62
65
|
if table:
|
|
63
|
-
self.
|
|
66
|
+
self._expression = exp.Column(this=exp.Identifier(this=name), table=exp.Identifier(this=table))
|
|
64
67
|
else:
|
|
65
|
-
self.
|
|
68
|
+
self._expression = exp.Column(this=exp.Identifier(this=name))
|
|
66
69
|
|
|
67
|
-
# Comparison operators
|
|
68
70
|
def __eq__(self, other: object) -> ColumnExpression: # type: ignore[override]
|
|
69
71
|
"""Equal to (==)."""
|
|
70
72
|
if other is None:
|
|
71
|
-
return ColumnExpression(exp.Is(this=self.
|
|
72
|
-
return ColumnExpression(exp.EQ(this=self.
|
|
73
|
+
return ColumnExpression(exp.Is(this=self._expression, expression=exp.Null()))
|
|
74
|
+
return ColumnExpression(exp.EQ(this=self._expression, expression=exp.convert(other)))
|
|
73
75
|
|
|
74
76
|
def __ne__(self, other: object) -> ColumnExpression: # type: ignore[override]
|
|
75
77
|
"""Not equal to (!=)."""
|
|
76
78
|
if other is None:
|
|
77
|
-
return ColumnExpression(exp.Not(this=exp.Is(this=self.
|
|
78
|
-
return ColumnExpression(exp.NEQ(this=self.
|
|
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)))
|
|
79
81
|
|
|
80
82
|
def __gt__(self, other: Any) -> ColumnExpression:
|
|
81
83
|
"""Greater than (>)."""
|
|
82
|
-
return ColumnExpression(exp.GT(this=self.
|
|
84
|
+
return ColumnExpression(exp.GT(this=self._expression, expression=exp.convert(other)))
|
|
83
85
|
|
|
84
86
|
def __ge__(self, other: Any) -> ColumnExpression:
|
|
85
87
|
"""Greater than or equal (>=)."""
|
|
86
|
-
return ColumnExpression(exp.GTE(this=self.
|
|
88
|
+
return ColumnExpression(exp.GTE(this=self._expression, expression=exp.convert(other)))
|
|
87
89
|
|
|
88
90
|
def __lt__(self, other: Any) -> ColumnExpression:
|
|
89
91
|
"""Less than (<)."""
|
|
90
|
-
return ColumnExpression(exp.LT(this=self.
|
|
92
|
+
return ColumnExpression(exp.LT(this=self._expression, expression=exp.convert(other)))
|
|
91
93
|
|
|
92
94
|
def __le__(self, other: Any) -> ColumnExpression:
|
|
93
95
|
"""Less than or equal (<=)."""
|
|
94
|
-
return ColumnExpression(exp.LTE(this=self.
|
|
96
|
+
return ColumnExpression(exp.LTE(this=self._expression, expression=exp.convert(other)))
|
|
95
97
|
|
|
96
98
|
def __invert__(self) -> ColumnExpression:
|
|
97
99
|
"""Apply NOT operator (~)."""
|
|
98
|
-
return ColumnExpression(exp.Not(this=self.
|
|
100
|
+
return ColumnExpression(exp.Not(this=self._expression))
|
|
99
101
|
|
|
100
|
-
# SQL-specific methods
|
|
101
102
|
def like(self, pattern: str, escape: Optional[str] = None) -> ColumnExpression:
|
|
102
103
|
"""SQL LIKE pattern matching."""
|
|
103
104
|
if escape:
|
|
104
|
-
like_expr = exp.Like(this=self.
|
|
105
|
+
like_expr = exp.Like(this=self._expression, expression=exp.convert(pattern), escape=exp.convert(escape))
|
|
105
106
|
else:
|
|
106
|
-
like_expr = exp.Like(this=self.
|
|
107
|
+
like_expr = exp.Like(this=self._expression, expression=exp.convert(pattern))
|
|
107
108
|
return ColumnExpression(like_expr)
|
|
108
109
|
|
|
109
110
|
def ilike(self, pattern: str) -> ColumnExpression:
|
|
110
111
|
"""Case-insensitive LIKE."""
|
|
111
|
-
return ColumnExpression(exp.ILike(this=self.
|
|
112
|
+
return ColumnExpression(exp.ILike(this=self._expression, expression=exp.convert(pattern)))
|
|
112
113
|
|
|
113
114
|
def in_(self, values: Iterable[Any]) -> ColumnExpression:
|
|
114
115
|
"""SQL IN clause."""
|
|
115
116
|
converted_values = [exp.convert(v) for v in values]
|
|
116
|
-
return ColumnExpression(exp.In(this=self.
|
|
117
|
+
return ColumnExpression(exp.In(this=self._expression, expressions=converted_values))
|
|
117
118
|
|
|
118
119
|
def not_in(self, values: Iterable[Any]) -> ColumnExpression:
|
|
119
120
|
"""SQL NOT IN clause."""
|
|
@@ -121,15 +122,15 @@ class Column:
|
|
|
121
122
|
|
|
122
123
|
def between(self, start: Any, end: Any) -> ColumnExpression:
|
|
123
124
|
"""SQL BETWEEN clause."""
|
|
124
|
-
return ColumnExpression(exp.Between(this=self.
|
|
125
|
+
return ColumnExpression(exp.Between(this=self._expression, low=exp.convert(start), high=exp.convert(end)))
|
|
125
126
|
|
|
126
127
|
def is_null(self) -> ColumnExpression:
|
|
127
128
|
"""SQL IS NULL."""
|
|
128
|
-
return ColumnExpression(exp.Is(this=self.
|
|
129
|
+
return ColumnExpression(exp.Is(this=self._expression, expression=exp.Null()))
|
|
129
130
|
|
|
130
131
|
def is_not_null(self) -> ColumnExpression:
|
|
131
132
|
"""SQL IS NOT NULL."""
|
|
132
|
-
return ColumnExpression(exp.Not(this=exp.Is(this=self.
|
|
133
|
+
return ColumnExpression(exp.Not(this=exp.Is(this=self._expression, expression=exp.Null())))
|
|
133
134
|
|
|
134
135
|
def not_like(self, pattern: str, escape: Optional[str] = None) -> ColumnExpression:
|
|
135
136
|
"""SQL NOT LIKE pattern matching."""
|
|
@@ -142,67 +143,103 @@ class Column:
|
|
|
142
143
|
def any_(self, values: Iterable[Any]) -> ColumnExpression:
|
|
143
144
|
"""SQL = ANY(...) clause."""
|
|
144
145
|
converted_values = [exp.convert(v) for v in values]
|
|
145
|
-
return ColumnExpression(exp.EQ(this=self.
|
|
146
|
+
return ColumnExpression(exp.EQ(this=self._expression, expression=exp.Any(expressions=converted_values)))
|
|
146
147
|
|
|
147
148
|
def not_any_(self, values: Iterable[Any]) -> ColumnExpression:
|
|
148
149
|
"""SQL <> ANY(...) clause."""
|
|
149
150
|
converted_values = [exp.convert(v) for v in values]
|
|
150
|
-
return ColumnExpression(exp.NEQ(this=self.
|
|
151
|
+
return ColumnExpression(exp.NEQ(this=self._expression, expression=exp.Any(expressions=converted_values)))
|
|
151
152
|
|
|
152
|
-
# SQL Functions
|
|
153
153
|
def lower(self) -> "FunctionColumn":
|
|
154
154
|
"""SQL LOWER() function."""
|
|
155
|
-
return FunctionColumn(exp.Lower(this=self.
|
|
155
|
+
return FunctionColumn(exp.Lower(this=self._expression))
|
|
156
156
|
|
|
157
157
|
def upper(self) -> "FunctionColumn":
|
|
158
158
|
"""SQL UPPER() function."""
|
|
159
|
-
return FunctionColumn(exp.Upper(this=self.
|
|
159
|
+
return FunctionColumn(exp.Upper(this=self._expression))
|
|
160
160
|
|
|
161
161
|
def length(self) -> "FunctionColumn":
|
|
162
162
|
"""SQL LENGTH() function."""
|
|
163
|
-
return FunctionColumn(exp.Length(this=self.
|
|
163
|
+
return FunctionColumn(exp.Length(this=self._expression))
|
|
164
164
|
|
|
165
165
|
def trim(self) -> "FunctionColumn":
|
|
166
166
|
"""SQL TRIM() function."""
|
|
167
|
-
return FunctionColumn(exp.Trim(this=self.
|
|
167
|
+
return FunctionColumn(exp.Trim(this=self._expression))
|
|
168
168
|
|
|
169
169
|
def abs(self) -> "FunctionColumn":
|
|
170
170
|
"""SQL ABS() function."""
|
|
171
|
-
return FunctionColumn(exp.Abs(this=self.
|
|
171
|
+
return FunctionColumn(exp.Abs(this=self._expression))
|
|
172
172
|
|
|
173
173
|
def round(self, decimals: int = 0) -> "FunctionColumn":
|
|
174
174
|
"""SQL ROUND() function."""
|
|
175
175
|
if decimals == 0:
|
|
176
|
-
return FunctionColumn(exp.Round(this=self.
|
|
177
|
-
return FunctionColumn(exp.Round(this=self.
|
|
176
|
+
return FunctionColumn(exp.Round(this=self._expression))
|
|
177
|
+
return FunctionColumn(exp.Round(this=self._expression, expression=exp.convert(decimals)))
|
|
178
178
|
|
|
179
179
|
def floor(self) -> "FunctionColumn":
|
|
180
180
|
"""SQL FLOOR() function."""
|
|
181
|
-
return FunctionColumn(exp.Floor(this=self.
|
|
181
|
+
return FunctionColumn(exp.Floor(this=self._expression))
|
|
182
182
|
|
|
183
183
|
def ceil(self) -> "FunctionColumn":
|
|
184
184
|
"""SQL CEIL() function."""
|
|
185
|
-
return FunctionColumn(exp.Ceil(this=self.
|
|
185
|
+
return FunctionColumn(exp.Ceil(this=self._expression))
|
|
186
186
|
|
|
187
187
|
def substring(self, start: int, length: Optional[int] = None) -> "FunctionColumn":
|
|
188
188
|
"""SQL SUBSTRING() function."""
|
|
189
|
-
args = [exp.
|
|
189
|
+
args = [exp.convert(start)]
|
|
190
190
|
if length is not None:
|
|
191
|
-
args.append(exp.
|
|
192
|
-
return FunctionColumn(exp.Substring(this=self.
|
|
191
|
+
args.append(exp.convert(length))
|
|
192
|
+
return FunctionColumn(exp.Substring(this=self._expression, expressions=args))
|
|
193
193
|
|
|
194
194
|
def coalesce(self, *values: Any) -> "FunctionColumn":
|
|
195
195
|
"""SQL COALESCE() function."""
|
|
196
|
-
expressions = [self.
|
|
196
|
+
expressions = [self._expression] + [exp.convert(v) for v in values]
|
|
197
197
|
return FunctionColumn(exp.Coalesce(expressions=expressions))
|
|
198
198
|
|
|
199
199
|
def cast(self, data_type: str) -> "FunctionColumn":
|
|
200
200
|
"""SQL CAST() function."""
|
|
201
|
-
return FunctionColumn(exp.Cast(this=self.
|
|
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()))
|
|
202
231
|
|
|
203
232
|
def alias(self, alias_name: str) -> exp.Expression:
|
|
204
233
|
"""Create an aliased column expression."""
|
|
205
|
-
return exp.Alias(this=self.
|
|
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)
|
|
206
243
|
|
|
207
244
|
def __repr__(self) -> str:
|
|
208
245
|
if self.table:
|
|
@@ -217,26 +254,28 @@ class Column:
|
|
|
217
254
|
class FunctionColumn:
|
|
218
255
|
"""Represents the result of a SQL function call on a column."""
|
|
219
256
|
|
|
257
|
+
__slots__ = ("_expression",)
|
|
258
|
+
|
|
220
259
|
def __init__(self, expression: exp.Expression) -> None:
|
|
221
|
-
self.
|
|
260
|
+
self._expression = expression
|
|
222
261
|
|
|
223
262
|
def __eq__(self, other: object) -> ColumnExpression: # type: ignore[override]
|
|
224
|
-
return ColumnExpression(exp.EQ(this=self.
|
|
263
|
+
return ColumnExpression(exp.EQ(this=self._expression, expression=exp.convert(other)))
|
|
225
264
|
|
|
226
265
|
def __ne__(self, other: object) -> ColumnExpression: # type: ignore[override]
|
|
227
|
-
return ColumnExpression(exp.NEQ(this=self.
|
|
266
|
+
return ColumnExpression(exp.NEQ(this=self._expression, expression=exp.convert(other)))
|
|
228
267
|
|
|
229
268
|
def like(self, pattern: str) -> ColumnExpression:
|
|
230
|
-
return ColumnExpression(exp.Like(this=self.
|
|
269
|
+
return ColumnExpression(exp.Like(this=self._expression, expression=exp.convert(pattern)))
|
|
231
270
|
|
|
232
271
|
def ilike(self, pattern: str) -> ColumnExpression:
|
|
233
272
|
"""Case-insensitive LIKE."""
|
|
234
|
-
return ColumnExpression(exp.ILike(this=self.
|
|
273
|
+
return ColumnExpression(exp.ILike(this=self._expression, expression=exp.convert(pattern)))
|
|
235
274
|
|
|
236
275
|
def in_(self, values: Iterable[Any]) -> ColumnExpression:
|
|
237
276
|
"""SQL IN clause."""
|
|
238
277
|
converted_values = [exp.convert(v) for v in values]
|
|
239
|
-
return ColumnExpression(exp.In(this=self.
|
|
278
|
+
return ColumnExpression(exp.In(this=self._expression, expressions=converted_values))
|
|
240
279
|
|
|
241
280
|
def not_in_(self, values: Iterable[Any]) -> ColumnExpression:
|
|
242
281
|
"""SQL NOT IN clause."""
|
|
@@ -252,32 +291,30 @@ class FunctionColumn:
|
|
|
252
291
|
|
|
253
292
|
def between(self, start: Any, end: Any) -> ColumnExpression:
|
|
254
293
|
"""SQL BETWEEN clause."""
|
|
255
|
-
return ColumnExpression(exp.Between(this=self.
|
|
294
|
+
return ColumnExpression(exp.Between(this=self._expression, low=exp.convert(start), high=exp.convert(end)))
|
|
256
295
|
|
|
257
296
|
def is_null(self) -> ColumnExpression:
|
|
258
297
|
"""SQL IS NULL."""
|
|
259
|
-
return ColumnExpression(exp.Is(this=self.
|
|
298
|
+
return ColumnExpression(exp.Is(this=self._expression, expression=exp.Null()))
|
|
260
299
|
|
|
261
300
|
def is_not_null(self) -> ColumnExpression:
|
|
262
301
|
"""SQL IS NOT NULL."""
|
|
263
|
-
return ColumnExpression(exp.Not(this=exp.Is(this=self.
|
|
302
|
+
return ColumnExpression(exp.Not(this=exp.Is(this=self._expression, expression=exp.Null())))
|
|
264
303
|
|
|
265
304
|
def any_(self, values: Iterable[Any]) -> ColumnExpression:
|
|
266
305
|
"""SQL = ANY(...) clause."""
|
|
267
306
|
converted_values = [exp.convert(v) for v in values]
|
|
268
|
-
return ColumnExpression(exp.EQ(this=self.
|
|
307
|
+
return ColumnExpression(exp.EQ(this=self._expression, expression=exp.Any(expressions=converted_values)))
|
|
269
308
|
|
|
270
309
|
def not_any_(self, values: Iterable[Any]) -> ColumnExpression:
|
|
271
310
|
"""SQL <> ANY(...) clause."""
|
|
272
311
|
converted_values = [exp.convert(v) for v in values]
|
|
273
|
-
return ColumnExpression(exp.NEQ(this=self.
|
|
312
|
+
return ColumnExpression(exp.NEQ(this=self._expression, expression=exp.Any(expressions=converted_values)))
|
|
274
313
|
|
|
275
314
|
def alias(self, alias_name: str) -> exp.Expression:
|
|
276
315
|
"""Create an aliased function expression."""
|
|
277
|
-
return exp.Alias(this=self.
|
|
278
|
-
|
|
279
|
-
# Add other operators as needed...
|
|
316
|
+
return exp.Alias(this=self._expression, alias=alias_name)
|
|
280
317
|
|
|
281
318
|
def __hash__(self) -> int:
|
|
282
319
|
"""Hash based on the SQL expression."""
|
|
283
|
-
return hash(self.
|
|
320
|
+
return hash(self._expression.sql() if has_sql_method(self._expression) else str(self._expression))
|