sqlspec 0.16.2__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 +1782 -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 +421 -0
- sqlspec/builder/_merge.py +71 -0
- sqlspec/builder/_parsing_utils.py +164 -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 +149 -0
- sqlspec/builder/mixins/_merge_operations.py +562 -0
- 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 +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.2.dist-info/METADATA +365 -0
- sqlspec-0.16.2.dist-info/RECORD +148 -0
- sqlspec-0.16.2.dist-info/WHEEL +7 -0
- sqlspec-0.16.2.dist-info/entry_points.txt +2 -0
- sqlspec-0.16.2.dist-info/licenses/LICENSE +21 -0
- sqlspec-0.16.2.dist-info/licenses/NOTICE +29 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""Pivot and Unpivot operations mixins for SQL builders."""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Optional, Union, cast
|
|
4
|
+
|
|
5
|
+
from mypy_extensions import trait
|
|
6
|
+
from sqlglot import exp
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from sqlglot.dialects.dialect import DialectType
|
|
10
|
+
|
|
11
|
+
from sqlspec.builder._select import Select
|
|
12
|
+
|
|
13
|
+
__all__ = ("PivotClauseMixin", "UnpivotClauseMixin")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@trait
|
|
17
|
+
class PivotClauseMixin:
|
|
18
|
+
"""Mixin class to add PIVOT functionality to a Select."""
|
|
19
|
+
|
|
20
|
+
__slots__ = ()
|
|
21
|
+
# Type annotation for PyRight - this will be provided by the base class
|
|
22
|
+
_expression: Optional[exp.Expression]
|
|
23
|
+
|
|
24
|
+
dialect: "DialectType" = None
|
|
25
|
+
|
|
26
|
+
def pivot(
|
|
27
|
+
self: "PivotClauseMixin",
|
|
28
|
+
aggregate_function: Union[str, exp.Expression],
|
|
29
|
+
aggregate_column: Union[str, exp.Expression],
|
|
30
|
+
pivot_column: Union[str, exp.Expression],
|
|
31
|
+
pivot_values: list[Union[str, int, float, exp.Expression]],
|
|
32
|
+
alias: Optional[str] = None,
|
|
33
|
+
) -> "Select":
|
|
34
|
+
"""Adds a PIVOT clause to the SELECT statement.
|
|
35
|
+
|
|
36
|
+
Example:
|
|
37
|
+
`query.pivot(aggregate_function="SUM", aggregate_column="Sales", pivot_column="Quarter", pivot_values=["Q1", "Q2", "Q3", "Q4"], alias="PivotTable")`
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
aggregate_function: The aggregate function to use (e.g., "SUM", "AVG").
|
|
41
|
+
aggregate_column: The column to be aggregated.
|
|
42
|
+
pivot_column: The column whose unique values will become new column headers.
|
|
43
|
+
pivot_values: A list of specific values from the pivot_column to be turned into columns.
|
|
44
|
+
alias: Optional alias for the pivoted table/subquery.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
The SelectBuilder instance for chaining.
|
|
48
|
+
"""
|
|
49
|
+
current_expr = self._expression
|
|
50
|
+
if not isinstance(current_expr, exp.Select):
|
|
51
|
+
msg = "Pivot can only be applied to a Select expression managed by SelectBuilder."
|
|
52
|
+
raise TypeError(msg)
|
|
53
|
+
|
|
54
|
+
agg_func_name = aggregate_function if isinstance(aggregate_function, str) else aggregate_function.name
|
|
55
|
+
agg_col_expr = exp.column(aggregate_column) if isinstance(aggregate_column, str) else aggregate_column
|
|
56
|
+
pivot_col_expr = exp.column(pivot_column) if isinstance(pivot_column, str) else pivot_column
|
|
57
|
+
|
|
58
|
+
pivot_agg_expr = exp.func(agg_func_name, agg_col_expr)
|
|
59
|
+
|
|
60
|
+
pivot_value_exprs: list[exp.Expression] = []
|
|
61
|
+
for val in pivot_values:
|
|
62
|
+
if isinstance(val, exp.Expression):
|
|
63
|
+
pivot_value_exprs.append(val)
|
|
64
|
+
elif isinstance(val, (str, int, float)):
|
|
65
|
+
pivot_value_exprs.append(exp.convert(val))
|
|
66
|
+
else:
|
|
67
|
+
pivot_value_exprs.append(exp.convert(str(val)))
|
|
68
|
+
|
|
69
|
+
in_expr = exp.In(this=pivot_col_expr, expressions=pivot_value_exprs)
|
|
70
|
+
|
|
71
|
+
pivot_node = exp.Pivot(expressions=[pivot_agg_expr], fields=[in_expr], unpivot=False)
|
|
72
|
+
|
|
73
|
+
if alias:
|
|
74
|
+
pivot_node.set("alias", exp.TableAlias(this=exp.to_identifier(alias)))
|
|
75
|
+
|
|
76
|
+
from_clause = current_expr.args.get("from")
|
|
77
|
+
if from_clause and isinstance(from_clause, exp.From):
|
|
78
|
+
table = from_clause.this
|
|
79
|
+
if isinstance(table, exp.Table):
|
|
80
|
+
existing_pivots = table.args.get("pivots", [])
|
|
81
|
+
existing_pivots.append(pivot_node)
|
|
82
|
+
table.set("pivots", existing_pivots)
|
|
83
|
+
|
|
84
|
+
return cast("Select", self)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@trait
|
|
88
|
+
class UnpivotClauseMixin:
|
|
89
|
+
"""Mixin class to add UNPIVOT functionality to a Select."""
|
|
90
|
+
|
|
91
|
+
__slots__ = ()
|
|
92
|
+
# Type annotation for PyRight - this will be provided by the base class
|
|
93
|
+
_expression: Optional[exp.Expression]
|
|
94
|
+
|
|
95
|
+
dialect: "DialectType" = None
|
|
96
|
+
|
|
97
|
+
def unpivot(
|
|
98
|
+
self: "UnpivotClauseMixin",
|
|
99
|
+
value_column_name: str,
|
|
100
|
+
name_column_name: str,
|
|
101
|
+
columns_to_unpivot: list[Union[str, exp.Expression]],
|
|
102
|
+
alias: Optional[str] = None,
|
|
103
|
+
) -> "Select":
|
|
104
|
+
"""Adds an UNPIVOT clause to the SELECT statement.
|
|
105
|
+
|
|
106
|
+
Example:
|
|
107
|
+
`query.unpivot(value_column_name="Sales", name_column_name="Quarter", columns_to_unpivot=["Q1Sales", "Q2Sales"], alias="UnpivotTable")`
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
value_column_name: The name for the new column that will hold the values from the unpivoted columns.
|
|
111
|
+
name_column_name: The name for the new column that will hold the names of the original unpivoted columns.
|
|
112
|
+
columns_to_unpivot: A list of columns to be unpivoted into rows.
|
|
113
|
+
alias: Optional alias for the unpivoted table/subquery.
|
|
114
|
+
|
|
115
|
+
Raises:
|
|
116
|
+
TypeError: If the current expression is not a Select expression.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
The Select instance for chaining.
|
|
120
|
+
"""
|
|
121
|
+
current_expr = self._expression
|
|
122
|
+
if not isinstance(current_expr, exp.Select):
|
|
123
|
+
msg = "Unpivot can only be applied to a Select expression managed by Select."
|
|
124
|
+
raise TypeError(msg)
|
|
125
|
+
|
|
126
|
+
value_col_ident = exp.to_identifier(value_column_name)
|
|
127
|
+
name_col_ident = exp.to_identifier(name_column_name)
|
|
128
|
+
|
|
129
|
+
unpivot_cols_exprs: list[exp.Expression] = []
|
|
130
|
+
for col_name_or_expr in columns_to_unpivot:
|
|
131
|
+
if isinstance(col_name_or_expr, exp.Expression):
|
|
132
|
+
unpivot_cols_exprs.append(col_name_or_expr)
|
|
133
|
+
elif isinstance(col_name_or_expr, str):
|
|
134
|
+
unpivot_cols_exprs.append(exp.column(col_name_or_expr))
|
|
135
|
+
else:
|
|
136
|
+
unpivot_cols_exprs.append(exp.column(str(col_name_or_expr)))
|
|
137
|
+
|
|
138
|
+
in_expr = exp.In(this=name_col_ident, expressions=unpivot_cols_exprs)
|
|
139
|
+
|
|
140
|
+
unpivot_node = exp.Pivot(expressions=[value_col_ident], fields=[in_expr], unpivot=True)
|
|
141
|
+
|
|
142
|
+
if alias:
|
|
143
|
+
unpivot_node.set("alias", exp.TableAlias(this=exp.to_identifier(alias)))
|
|
144
|
+
|
|
145
|
+
from_clause = current_expr.args.get("from")
|
|
146
|
+
if from_clause and isinstance(from_clause, exp.From):
|
|
147
|
+
table = from_clause.this
|
|
148
|
+
if isinstance(table, exp.Table):
|
|
149
|
+
existing_pivots = table.args.get("pivots", [])
|
|
150
|
+
existing_pivots.append(unpivot_node)
|
|
151
|
+
table.set("pivots", existing_pivots)
|
|
152
|
+
|
|
153
|
+
return cast("Select", self)
|