sqlspec 0.16.0__cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.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.

Files changed (148) hide show
  1. 51ff5a9eadfdefd49f98__mypyc.cpython-311-x86_64-linux-gnu.so +0 -0
  2. sqlspec/__init__.py +92 -0
  3. sqlspec/__main__.py +12 -0
  4. sqlspec/__metadata__.py +14 -0
  5. sqlspec/_serialization.py +77 -0
  6. sqlspec/_sql.py +1347 -0
  7. sqlspec/_typing.py +680 -0
  8. sqlspec/adapters/__init__.py +0 -0
  9. sqlspec/adapters/adbc/__init__.py +5 -0
  10. sqlspec/adapters/adbc/_types.py +12 -0
  11. sqlspec/adapters/adbc/config.py +361 -0
  12. sqlspec/adapters/adbc/driver.py +512 -0
  13. sqlspec/adapters/aiosqlite/__init__.py +19 -0
  14. sqlspec/adapters/aiosqlite/_types.py +13 -0
  15. sqlspec/adapters/aiosqlite/config.py +253 -0
  16. sqlspec/adapters/aiosqlite/driver.py +248 -0
  17. sqlspec/adapters/asyncmy/__init__.py +19 -0
  18. sqlspec/adapters/asyncmy/_types.py +12 -0
  19. sqlspec/adapters/asyncmy/config.py +180 -0
  20. sqlspec/adapters/asyncmy/driver.py +274 -0
  21. sqlspec/adapters/asyncpg/__init__.py +21 -0
  22. sqlspec/adapters/asyncpg/_types.py +17 -0
  23. sqlspec/adapters/asyncpg/config.py +229 -0
  24. sqlspec/adapters/asyncpg/driver.py +344 -0
  25. sqlspec/adapters/bigquery/__init__.py +18 -0
  26. sqlspec/adapters/bigquery/_types.py +12 -0
  27. sqlspec/adapters/bigquery/config.py +298 -0
  28. sqlspec/adapters/bigquery/driver.py +558 -0
  29. sqlspec/adapters/duckdb/__init__.py +22 -0
  30. sqlspec/adapters/duckdb/_types.py +12 -0
  31. sqlspec/adapters/duckdb/config.py +504 -0
  32. sqlspec/adapters/duckdb/driver.py +368 -0
  33. sqlspec/adapters/oracledb/__init__.py +32 -0
  34. sqlspec/adapters/oracledb/_types.py +14 -0
  35. sqlspec/adapters/oracledb/config.py +317 -0
  36. sqlspec/adapters/oracledb/driver.py +538 -0
  37. sqlspec/adapters/psqlpy/__init__.py +16 -0
  38. sqlspec/adapters/psqlpy/_types.py +11 -0
  39. sqlspec/adapters/psqlpy/config.py +214 -0
  40. sqlspec/adapters/psqlpy/driver.py +530 -0
  41. sqlspec/adapters/psycopg/__init__.py +32 -0
  42. sqlspec/adapters/psycopg/_types.py +17 -0
  43. sqlspec/adapters/psycopg/config.py +426 -0
  44. sqlspec/adapters/psycopg/driver.py +796 -0
  45. sqlspec/adapters/sqlite/__init__.py +15 -0
  46. sqlspec/adapters/sqlite/_types.py +11 -0
  47. sqlspec/adapters/sqlite/config.py +240 -0
  48. sqlspec/adapters/sqlite/driver.py +294 -0
  49. sqlspec/base.py +571 -0
  50. sqlspec/builder/__init__.py +62 -0
  51. sqlspec/builder/_base.py +440 -0
  52. sqlspec/builder/_column.py +324 -0
  53. sqlspec/builder/_ddl.py +1383 -0
  54. sqlspec/builder/_ddl_utils.py +104 -0
  55. sqlspec/builder/_delete.py +77 -0
  56. sqlspec/builder/_insert.py +241 -0
  57. sqlspec/builder/_merge.py +56 -0
  58. sqlspec/builder/_parsing_utils.py +140 -0
  59. sqlspec/builder/_select.py +174 -0
  60. sqlspec/builder/_update.py +186 -0
  61. sqlspec/builder/mixins/__init__.py +55 -0
  62. sqlspec/builder/mixins/_cte_and_set_ops.py +195 -0
  63. sqlspec/builder/mixins/_delete_operations.py +36 -0
  64. sqlspec/builder/mixins/_insert_operations.py +152 -0
  65. sqlspec/builder/mixins/_join_operations.py +115 -0
  66. sqlspec/builder/mixins/_merge_operations.py +416 -0
  67. sqlspec/builder/mixins/_order_limit_operations.py +123 -0
  68. sqlspec/builder/mixins/_pivot_operations.py +144 -0
  69. sqlspec/builder/mixins/_select_operations.py +599 -0
  70. sqlspec/builder/mixins/_update_operations.py +164 -0
  71. sqlspec/builder/mixins/_where_clause.py +609 -0
  72. sqlspec/cli.py +247 -0
  73. sqlspec/config.py +395 -0
  74. sqlspec/core/__init__.py +63 -0
  75. sqlspec/core/cache.cpython-311-x86_64-linux-gnu.so +0 -0
  76. sqlspec/core/cache.py +873 -0
  77. sqlspec/core/compiler.cpython-311-x86_64-linux-gnu.so +0 -0
  78. sqlspec/core/compiler.py +396 -0
  79. sqlspec/core/filters.cpython-311-x86_64-linux-gnu.so +0 -0
  80. sqlspec/core/filters.py +830 -0
  81. sqlspec/core/hashing.cpython-311-x86_64-linux-gnu.so +0 -0
  82. sqlspec/core/hashing.py +310 -0
  83. sqlspec/core/parameters.cpython-311-x86_64-linux-gnu.so +0 -0
  84. sqlspec/core/parameters.py +1209 -0
  85. sqlspec/core/result.cpython-311-x86_64-linux-gnu.so +0 -0
  86. sqlspec/core/result.py +664 -0
  87. sqlspec/core/splitter.cpython-311-x86_64-linux-gnu.so +0 -0
  88. sqlspec/core/splitter.py +819 -0
  89. sqlspec/core/statement.cpython-311-x86_64-linux-gnu.so +0 -0
  90. sqlspec/core/statement.py +666 -0
  91. sqlspec/driver/__init__.py +19 -0
  92. sqlspec/driver/_async.py +472 -0
  93. sqlspec/driver/_common.py +612 -0
  94. sqlspec/driver/_sync.py +473 -0
  95. sqlspec/driver/mixins/__init__.py +6 -0
  96. sqlspec/driver/mixins/_result_tools.py +164 -0
  97. sqlspec/driver/mixins/_sql_translator.py +36 -0
  98. sqlspec/exceptions.py +193 -0
  99. sqlspec/extensions/__init__.py +0 -0
  100. sqlspec/extensions/aiosql/__init__.py +10 -0
  101. sqlspec/extensions/aiosql/adapter.py +461 -0
  102. sqlspec/extensions/litestar/__init__.py +6 -0
  103. sqlspec/extensions/litestar/_utils.py +52 -0
  104. sqlspec/extensions/litestar/cli.py +48 -0
  105. sqlspec/extensions/litestar/config.py +92 -0
  106. sqlspec/extensions/litestar/handlers.py +260 -0
  107. sqlspec/extensions/litestar/plugin.py +145 -0
  108. sqlspec/extensions/litestar/providers.py +454 -0
  109. sqlspec/loader.cpython-311-x86_64-linux-gnu.so +0 -0
  110. sqlspec/loader.py +760 -0
  111. sqlspec/migrations/__init__.py +35 -0
  112. sqlspec/migrations/base.py +414 -0
  113. sqlspec/migrations/commands.py +443 -0
  114. sqlspec/migrations/loaders.py +402 -0
  115. sqlspec/migrations/runner.py +213 -0
  116. sqlspec/migrations/tracker.py +140 -0
  117. sqlspec/migrations/utils.py +129 -0
  118. sqlspec/protocols.py +400 -0
  119. sqlspec/py.typed +0 -0
  120. sqlspec/storage/__init__.py +23 -0
  121. sqlspec/storage/backends/__init__.py +0 -0
  122. sqlspec/storage/backends/base.py +163 -0
  123. sqlspec/storage/backends/fsspec.py +386 -0
  124. sqlspec/storage/backends/obstore.py +459 -0
  125. sqlspec/storage/capabilities.py +102 -0
  126. sqlspec/storage/registry.py +239 -0
  127. sqlspec/typing.py +299 -0
  128. sqlspec/utils/__init__.py +3 -0
  129. sqlspec/utils/correlation.py +150 -0
  130. sqlspec/utils/deprecation.py +106 -0
  131. sqlspec/utils/fixtures.cpython-311-x86_64-linux-gnu.so +0 -0
  132. sqlspec/utils/fixtures.py +58 -0
  133. sqlspec/utils/logging.py +127 -0
  134. sqlspec/utils/module_loader.py +89 -0
  135. sqlspec/utils/serializers.py +4 -0
  136. sqlspec/utils/singleton.py +32 -0
  137. sqlspec/utils/sync_tools.cpython-311-x86_64-linux-gnu.so +0 -0
  138. sqlspec/utils/sync_tools.py +237 -0
  139. sqlspec/utils/text.cpython-311-x86_64-linux-gnu.so +0 -0
  140. sqlspec/utils/text.py +96 -0
  141. sqlspec/utils/type_guards.cpython-311-x86_64-linux-gnu.so +0 -0
  142. sqlspec/utils/type_guards.py +1135 -0
  143. sqlspec-0.16.0.dist-info/METADATA +365 -0
  144. sqlspec-0.16.0.dist-info/RECORD +148 -0
  145. sqlspec-0.16.0.dist-info/WHEEL +4 -0
  146. sqlspec-0.16.0.dist-info/entry_points.txt +2 -0
  147. sqlspec-0.16.0.dist-info/licenses/LICENSE +21 -0
  148. sqlspec-0.16.0.dist-info/licenses/NOTICE +29 -0
@@ -0,0 +1,123 @@
1
+ """Order, Limit, Offset and Returning operations mixins for SQL builders."""
2
+
3
+ from typing import TYPE_CHECKING, Optional, Union, cast
4
+
5
+ from sqlglot import exp
6
+ from typing_extensions import Self
7
+
8
+ from sqlspec.builder._parsing_utils import parse_order_expression
9
+ from sqlspec.exceptions import SQLBuilderError
10
+
11
+ if TYPE_CHECKING:
12
+ from sqlspec.protocols import SQLBuilderProtocol
13
+
14
+ __all__ = ("LimitOffsetClauseMixin", "OrderByClauseMixin", "ReturningClauseMixin")
15
+
16
+
17
+ class OrderByClauseMixin:
18
+ """Mixin providing ORDER BY clause."""
19
+
20
+ _expression: Optional[exp.Expression] = None
21
+
22
+ def order_by(self, *items: Union[str, exp.Ordered], desc: bool = False) -> Self:
23
+ """Add ORDER BY clause.
24
+
25
+ Args:
26
+ *items: Columns to order by. Can be strings (column names) or sqlglot.exp.Ordered instances for specific directions (e.g., exp.column("name").desc()).
27
+ desc: Whether to order in descending order (applies to all items if they are strings).
28
+
29
+ Raises:
30
+ SQLBuilderError: If the current expression is not a SELECT statement or if the item type is unsupported.
31
+
32
+ Returns:
33
+ The current builder instance for method chaining.
34
+ """
35
+ builder = cast("SQLBuilderProtocol", self)
36
+ if not isinstance(builder._expression, exp.Select):
37
+ msg = "ORDER BY is only supported for SELECT statements."
38
+ raise SQLBuilderError(msg)
39
+
40
+ current_expr = builder._expression
41
+ for item in items:
42
+ if isinstance(item, str):
43
+ order_item = parse_order_expression(item)
44
+ if desc:
45
+ order_item = order_item.desc()
46
+ else:
47
+ order_item = item
48
+ current_expr = current_expr.order_by(order_item, copy=False)
49
+ builder._expression = current_expr
50
+ return cast("Self", builder)
51
+
52
+
53
+ class LimitOffsetClauseMixin:
54
+ """Mixin providing LIMIT and OFFSET clauses."""
55
+
56
+ _expression: Optional[exp.Expression] = None
57
+
58
+ def limit(self, value: int) -> Self:
59
+ """Add LIMIT clause.
60
+
61
+ Args:
62
+ value: The maximum number of rows to return.
63
+
64
+ Raises:
65
+ SQLBuilderError: If the current expression is not a SELECT statement.
66
+
67
+ Returns:
68
+ The current builder instance for method chaining.
69
+ """
70
+ builder = cast("SQLBuilderProtocol", self)
71
+ if not isinstance(builder._expression, exp.Select):
72
+ msg = "LIMIT is only supported for SELECT statements."
73
+ raise SQLBuilderError(msg)
74
+ builder._expression = builder._expression.limit(exp.convert(value), copy=False)
75
+ return cast("Self", builder)
76
+
77
+ def offset(self, value: int) -> Self:
78
+ """Add OFFSET clause.
79
+
80
+ Args:
81
+ value: The number of rows to skip before starting to return rows.
82
+
83
+ Raises:
84
+ SQLBuilderError: If the current expression is not a SELECT statement.
85
+
86
+ Returns:
87
+ The current builder instance for method chaining.
88
+ """
89
+ builder = cast("SQLBuilderProtocol", self)
90
+ if not isinstance(builder._expression, exp.Select):
91
+ msg = "OFFSET is only supported for SELECT statements."
92
+ raise SQLBuilderError(msg)
93
+ builder._expression = builder._expression.offset(exp.convert(value), copy=False)
94
+ return cast("Self", builder)
95
+
96
+
97
+ class ReturningClauseMixin:
98
+ """Mixin providing RETURNING clause."""
99
+
100
+ _expression: Optional[exp.Expression] = None
101
+
102
+ def returning(self, *columns: Union[str, exp.Expression]) -> Self:
103
+ """Add RETURNING clause to the statement.
104
+
105
+ Args:
106
+ *columns: Columns to return. Can be strings or sqlglot expressions.
107
+
108
+ Raises:
109
+ SQLBuilderError: If the current expression is not INSERT, UPDATE, or DELETE.
110
+
111
+ Returns:
112
+ The current builder instance for method chaining.
113
+ """
114
+ if self._expression is None:
115
+ msg = "Cannot add RETURNING: expression is not initialized."
116
+ raise SQLBuilderError(msg)
117
+ valid_types = (exp.Insert, exp.Update, exp.Delete)
118
+ if not isinstance(self._expression, valid_types):
119
+ msg = "RETURNING is only supported for INSERT, UPDATE, and DELETE statements."
120
+ raise SQLBuilderError(msg)
121
+ returning_exprs = [exp.column(c) if isinstance(c, str) else c for c in columns]
122
+ self._expression.set("returning", exp.Returning(expressions=returning_exprs))
123
+ return self
@@ -0,0 +1,144 @@
1
+ """Pivot and Unpivot operations mixins for SQL builders."""
2
+
3
+ from typing import TYPE_CHECKING, Optional, Union, cast
4
+
5
+ from sqlglot import exp
6
+
7
+ if TYPE_CHECKING:
8
+ from sqlglot.dialects.dialect import DialectType
9
+
10
+ from sqlspec.builder._select import Select
11
+
12
+ __all__ = ("PivotClauseMixin", "UnpivotClauseMixin")
13
+
14
+
15
+ class PivotClauseMixin:
16
+ """Mixin class to add PIVOT functionality to a Select."""
17
+
18
+ _expression: "Optional[exp.Expression]" = None
19
+ dialect: "DialectType" = None
20
+
21
+ def pivot(
22
+ self: "PivotClauseMixin",
23
+ aggregate_function: Union[str, exp.Expression],
24
+ aggregate_column: Union[str, exp.Expression],
25
+ pivot_column: Union[str, exp.Expression],
26
+ pivot_values: list[Union[str, int, float, exp.Expression]],
27
+ alias: Optional[str] = None,
28
+ ) -> "Select":
29
+ """Adds a PIVOT clause to the SELECT statement.
30
+
31
+ Example:
32
+ `query.pivot(aggregate_function="SUM", aggregate_column="Sales", pivot_column="Quarter", pivot_values=["Q1", "Q2", "Q3", "Q4"], alias="PivotTable")`
33
+
34
+ Args:
35
+ aggregate_function: The aggregate function to use (e.g., "SUM", "AVG").
36
+ aggregate_column: The column to be aggregated.
37
+ pivot_column: The column whose unique values will become new column headers.
38
+ pivot_values: A list of specific values from the pivot_column to be turned into columns.
39
+ alias: Optional alias for the pivoted table/subquery.
40
+
41
+ Returns:
42
+ The SelectBuilder instance for chaining.
43
+ """
44
+ current_expr = self._expression
45
+ if not isinstance(current_expr, exp.Select):
46
+ msg = "Pivot can only be applied to a Select expression managed by SelectBuilder."
47
+ raise TypeError(msg)
48
+
49
+ agg_func_name = aggregate_function if isinstance(aggregate_function, str) else aggregate_function.name
50
+ agg_col_expr = exp.column(aggregate_column) if isinstance(aggregate_column, str) else aggregate_column
51
+ pivot_col_expr = exp.column(pivot_column) if isinstance(pivot_column, str) else pivot_column
52
+
53
+ pivot_agg_expr = exp.func(agg_func_name, agg_col_expr)
54
+
55
+ pivot_value_exprs: list[exp.Expression] = []
56
+ for val in pivot_values:
57
+ if isinstance(val, exp.Expression):
58
+ pivot_value_exprs.append(val)
59
+ elif isinstance(val, (str, int, float)):
60
+ pivot_value_exprs.append(exp.convert(val))
61
+ else:
62
+ pivot_value_exprs.append(exp.convert(str(val)))
63
+
64
+ in_expr = exp.In(this=pivot_col_expr, expressions=pivot_value_exprs)
65
+
66
+ pivot_node = exp.Pivot(expressions=[pivot_agg_expr], fields=[in_expr], unpivot=False)
67
+
68
+ if alias:
69
+ pivot_node.set("alias", exp.TableAlias(this=exp.to_identifier(alias)))
70
+
71
+ from_clause = current_expr.args.get("from")
72
+ if from_clause and isinstance(from_clause, exp.From):
73
+ table = from_clause.this
74
+ if isinstance(table, exp.Table):
75
+ existing_pivots = table.args.get("pivots", [])
76
+ existing_pivots.append(pivot_node)
77
+ table.set("pivots", existing_pivots)
78
+
79
+ return cast("Select", self)
80
+
81
+
82
+ class UnpivotClauseMixin:
83
+ """Mixin class to add UNPIVOT functionality to a Select."""
84
+
85
+ _expression: "Optional[exp.Expression]" = None
86
+ dialect: "DialectType" = None
87
+
88
+ def unpivot(
89
+ self: "UnpivotClauseMixin",
90
+ value_column_name: str,
91
+ name_column_name: str,
92
+ columns_to_unpivot: list[Union[str, exp.Expression]],
93
+ alias: Optional[str] = None,
94
+ ) -> "Select":
95
+ """Adds an UNPIVOT clause to the SELECT statement.
96
+
97
+ Example:
98
+ `query.unpivot(value_column_name="Sales", name_column_name="Quarter", columns_to_unpivot=["Q1Sales", "Q2Sales"], alias="UnpivotTable")`
99
+
100
+ Args:
101
+ value_column_name: The name for the new column that will hold the values from the unpivoted columns.
102
+ name_column_name: The name for the new column that will hold the names of the original unpivoted columns.
103
+ columns_to_unpivot: A list of columns to be unpivoted into rows.
104
+ alias: Optional alias for the unpivoted table/subquery.
105
+
106
+ Raises:
107
+ TypeError: If the current expression is not a Select expression.
108
+
109
+ Returns:
110
+ The Select instance for chaining.
111
+ """
112
+ current_expr = self._expression
113
+ if not isinstance(current_expr, exp.Select):
114
+ msg = "Unpivot can only be applied to a Select expression managed by Select."
115
+ raise TypeError(msg)
116
+
117
+ value_col_ident = exp.to_identifier(value_column_name)
118
+ name_col_ident = exp.to_identifier(name_column_name)
119
+
120
+ unpivot_cols_exprs: list[exp.Expression] = []
121
+ for col_name_or_expr in columns_to_unpivot:
122
+ if isinstance(col_name_or_expr, exp.Expression):
123
+ unpivot_cols_exprs.append(col_name_or_expr)
124
+ elif isinstance(col_name_or_expr, str):
125
+ unpivot_cols_exprs.append(exp.column(col_name_or_expr))
126
+ else:
127
+ unpivot_cols_exprs.append(exp.column(str(col_name_or_expr)))
128
+
129
+ in_expr = exp.In(this=name_col_ident, expressions=unpivot_cols_exprs)
130
+
131
+ unpivot_node = exp.Pivot(expressions=[value_col_ident], fields=[in_expr], unpivot=True)
132
+
133
+ if alias:
134
+ unpivot_node.set("alias", exp.TableAlias(this=exp.to_identifier(alias)))
135
+
136
+ from_clause = current_expr.args.get("from")
137
+ if from_clause and isinstance(from_clause, exp.From):
138
+ table = from_clause.this
139
+ if isinstance(table, exp.Table):
140
+ existing_pivots = table.args.get("pivots", [])
141
+ existing_pivots.append(unpivot_node)
142
+ table.set("pivots", existing_pivots)
143
+
144
+ return cast("Select", self)