sqlspec 0.11.1__py3-none-any.whl → 0.12.1__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.

Files changed (155) hide show
  1. sqlspec/__init__.py +16 -3
  2. sqlspec/_serialization.py +3 -10
  3. sqlspec/_sql.py +1147 -0
  4. sqlspec/_typing.py +343 -41
  5. sqlspec/adapters/adbc/__init__.py +2 -6
  6. sqlspec/adapters/adbc/config.py +474 -149
  7. sqlspec/adapters/adbc/driver.py +330 -621
  8. sqlspec/adapters/aiosqlite/__init__.py +2 -6
  9. sqlspec/adapters/aiosqlite/config.py +143 -57
  10. sqlspec/adapters/aiosqlite/driver.py +269 -431
  11. sqlspec/adapters/asyncmy/__init__.py +3 -8
  12. sqlspec/adapters/asyncmy/config.py +247 -202
  13. sqlspec/adapters/asyncmy/driver.py +218 -436
  14. sqlspec/adapters/asyncpg/__init__.py +4 -7
  15. sqlspec/adapters/asyncpg/config.py +329 -176
  16. sqlspec/adapters/asyncpg/driver.py +417 -487
  17. sqlspec/adapters/bigquery/__init__.py +2 -2
  18. sqlspec/adapters/bigquery/config.py +407 -0
  19. sqlspec/adapters/bigquery/driver.py +600 -553
  20. sqlspec/adapters/duckdb/__init__.py +4 -1
  21. sqlspec/adapters/duckdb/config.py +432 -321
  22. sqlspec/adapters/duckdb/driver.py +392 -406
  23. sqlspec/adapters/oracledb/__init__.py +3 -8
  24. sqlspec/adapters/oracledb/config.py +625 -0
  25. sqlspec/adapters/oracledb/driver.py +548 -921
  26. sqlspec/adapters/psqlpy/__init__.py +4 -7
  27. sqlspec/adapters/psqlpy/config.py +372 -203
  28. sqlspec/adapters/psqlpy/driver.py +197 -533
  29. sqlspec/adapters/psycopg/__init__.py +3 -8
  30. sqlspec/adapters/psycopg/config.py +725 -0
  31. sqlspec/adapters/psycopg/driver.py +734 -694
  32. sqlspec/adapters/sqlite/__init__.py +2 -6
  33. sqlspec/adapters/sqlite/config.py +146 -81
  34. sqlspec/adapters/sqlite/driver.py +242 -405
  35. sqlspec/base.py +220 -784
  36. sqlspec/config.py +354 -0
  37. sqlspec/driver/__init__.py +22 -0
  38. sqlspec/driver/_async.py +252 -0
  39. sqlspec/driver/_common.py +338 -0
  40. sqlspec/driver/_sync.py +261 -0
  41. sqlspec/driver/mixins/__init__.py +17 -0
  42. sqlspec/driver/mixins/_pipeline.py +523 -0
  43. sqlspec/driver/mixins/_result_utils.py +122 -0
  44. sqlspec/driver/mixins/_sql_translator.py +35 -0
  45. sqlspec/driver/mixins/_storage.py +993 -0
  46. sqlspec/driver/mixins/_type_coercion.py +131 -0
  47. sqlspec/exceptions.py +299 -7
  48. sqlspec/extensions/aiosql/__init__.py +10 -0
  49. sqlspec/extensions/aiosql/adapter.py +474 -0
  50. sqlspec/extensions/litestar/__init__.py +1 -6
  51. sqlspec/extensions/litestar/_utils.py +1 -5
  52. sqlspec/extensions/litestar/config.py +5 -6
  53. sqlspec/extensions/litestar/handlers.py +13 -12
  54. sqlspec/extensions/litestar/plugin.py +22 -24
  55. sqlspec/extensions/litestar/providers.py +37 -55
  56. sqlspec/loader.py +528 -0
  57. sqlspec/service/__init__.py +3 -0
  58. sqlspec/service/base.py +24 -0
  59. sqlspec/service/pagination.py +26 -0
  60. sqlspec/statement/__init__.py +21 -0
  61. sqlspec/statement/builder/__init__.py +54 -0
  62. sqlspec/statement/builder/_ddl_utils.py +119 -0
  63. sqlspec/statement/builder/_parsing_utils.py +135 -0
  64. sqlspec/statement/builder/base.py +328 -0
  65. sqlspec/statement/builder/ddl.py +1379 -0
  66. sqlspec/statement/builder/delete.py +80 -0
  67. sqlspec/statement/builder/insert.py +274 -0
  68. sqlspec/statement/builder/merge.py +95 -0
  69. sqlspec/statement/builder/mixins/__init__.py +65 -0
  70. sqlspec/statement/builder/mixins/_aggregate_functions.py +151 -0
  71. sqlspec/statement/builder/mixins/_case_builder.py +91 -0
  72. sqlspec/statement/builder/mixins/_common_table_expr.py +91 -0
  73. sqlspec/statement/builder/mixins/_delete_from.py +34 -0
  74. sqlspec/statement/builder/mixins/_from.py +61 -0
  75. sqlspec/statement/builder/mixins/_group_by.py +119 -0
  76. sqlspec/statement/builder/mixins/_having.py +35 -0
  77. sqlspec/statement/builder/mixins/_insert_from_select.py +48 -0
  78. sqlspec/statement/builder/mixins/_insert_into.py +36 -0
  79. sqlspec/statement/builder/mixins/_insert_values.py +69 -0
  80. sqlspec/statement/builder/mixins/_join.py +110 -0
  81. sqlspec/statement/builder/mixins/_limit_offset.py +53 -0
  82. sqlspec/statement/builder/mixins/_merge_clauses.py +405 -0
  83. sqlspec/statement/builder/mixins/_order_by.py +46 -0
  84. sqlspec/statement/builder/mixins/_pivot.py +82 -0
  85. sqlspec/statement/builder/mixins/_returning.py +37 -0
  86. sqlspec/statement/builder/mixins/_select_columns.py +60 -0
  87. sqlspec/statement/builder/mixins/_set_ops.py +122 -0
  88. sqlspec/statement/builder/mixins/_unpivot.py +80 -0
  89. sqlspec/statement/builder/mixins/_update_from.py +54 -0
  90. sqlspec/statement/builder/mixins/_update_set.py +91 -0
  91. sqlspec/statement/builder/mixins/_update_table.py +29 -0
  92. sqlspec/statement/builder/mixins/_where.py +374 -0
  93. sqlspec/statement/builder/mixins/_window_functions.py +86 -0
  94. sqlspec/statement/builder/protocols.py +20 -0
  95. sqlspec/statement/builder/select.py +206 -0
  96. sqlspec/statement/builder/update.py +178 -0
  97. sqlspec/statement/filters.py +571 -0
  98. sqlspec/statement/parameters.py +736 -0
  99. sqlspec/statement/pipelines/__init__.py +67 -0
  100. sqlspec/statement/pipelines/analyzers/__init__.py +9 -0
  101. sqlspec/statement/pipelines/analyzers/_analyzer.py +649 -0
  102. sqlspec/statement/pipelines/base.py +315 -0
  103. sqlspec/statement/pipelines/context.py +119 -0
  104. sqlspec/statement/pipelines/result_types.py +41 -0
  105. sqlspec/statement/pipelines/transformers/__init__.py +8 -0
  106. sqlspec/statement/pipelines/transformers/_expression_simplifier.py +256 -0
  107. sqlspec/statement/pipelines/transformers/_literal_parameterizer.py +623 -0
  108. sqlspec/statement/pipelines/transformers/_remove_comments.py +66 -0
  109. sqlspec/statement/pipelines/transformers/_remove_hints.py +81 -0
  110. sqlspec/statement/pipelines/validators/__init__.py +23 -0
  111. sqlspec/statement/pipelines/validators/_dml_safety.py +275 -0
  112. sqlspec/statement/pipelines/validators/_parameter_style.py +297 -0
  113. sqlspec/statement/pipelines/validators/_performance.py +703 -0
  114. sqlspec/statement/pipelines/validators/_security.py +990 -0
  115. sqlspec/statement/pipelines/validators/base.py +67 -0
  116. sqlspec/statement/result.py +527 -0
  117. sqlspec/statement/splitter.py +701 -0
  118. sqlspec/statement/sql.py +1198 -0
  119. sqlspec/storage/__init__.py +15 -0
  120. sqlspec/storage/backends/__init__.py +0 -0
  121. sqlspec/storage/backends/base.py +166 -0
  122. sqlspec/storage/backends/fsspec.py +315 -0
  123. sqlspec/storage/backends/obstore.py +464 -0
  124. sqlspec/storage/protocol.py +170 -0
  125. sqlspec/storage/registry.py +315 -0
  126. sqlspec/typing.py +157 -36
  127. sqlspec/utils/correlation.py +155 -0
  128. sqlspec/utils/deprecation.py +3 -6
  129. sqlspec/utils/fixtures.py +6 -11
  130. sqlspec/utils/logging.py +135 -0
  131. sqlspec/utils/module_loader.py +45 -43
  132. sqlspec/utils/serializers.py +4 -0
  133. sqlspec/utils/singleton.py +6 -8
  134. sqlspec/utils/sync_tools.py +15 -27
  135. sqlspec/utils/text.py +58 -26
  136. {sqlspec-0.11.1.dist-info → sqlspec-0.12.1.dist-info}/METADATA +97 -26
  137. sqlspec-0.12.1.dist-info/RECORD +145 -0
  138. sqlspec/adapters/bigquery/config/__init__.py +0 -3
  139. sqlspec/adapters/bigquery/config/_common.py +0 -40
  140. sqlspec/adapters/bigquery/config/_sync.py +0 -87
  141. sqlspec/adapters/oracledb/config/__init__.py +0 -9
  142. sqlspec/adapters/oracledb/config/_asyncio.py +0 -186
  143. sqlspec/adapters/oracledb/config/_common.py +0 -131
  144. sqlspec/adapters/oracledb/config/_sync.py +0 -186
  145. sqlspec/adapters/psycopg/config/__init__.py +0 -19
  146. sqlspec/adapters/psycopg/config/_async.py +0 -169
  147. sqlspec/adapters/psycopg/config/_common.py +0 -56
  148. sqlspec/adapters/psycopg/config/_sync.py +0 -168
  149. sqlspec/filters.py +0 -331
  150. sqlspec/mixins.py +0 -305
  151. sqlspec/statement.py +0 -378
  152. sqlspec-0.11.1.dist-info/RECORD +0 -69
  153. {sqlspec-0.11.1.dist-info → sqlspec-0.12.1.dist-info}/WHEEL +0 -0
  154. {sqlspec-0.11.1.dist-info → sqlspec-0.12.1.dist-info}/licenses/LICENSE +0 -0
  155. {sqlspec-0.11.1.dist-info → sqlspec-0.12.1.dist-info}/licenses/NOTICE +0 -0
sqlspec/statement.py DELETED
@@ -1,378 +0,0 @@
1
- # ruff: noqa: RUF100, PLR6301, PLR0912, PLR0915, C901, PLR0911, PLR0914, N806
2
- import logging
3
- from collections.abc import Sequence
4
- from dataclasses import dataclass, field
5
- from typing import (
6
- TYPE_CHECKING,
7
- Any,
8
- Optional,
9
- Union,
10
- )
11
-
12
- import sqlglot
13
- from sqlglot import exp
14
-
15
- from sqlspec.exceptions import ParameterStyleMismatchError, SQLParsingError
16
- from sqlspec.typing import StatementParameterType
17
-
18
- if TYPE_CHECKING:
19
- from sqlspec.filters import StatementFilter
20
-
21
- __all__ = ("SQLStatement",)
22
-
23
- logger = logging.getLogger("sqlspec")
24
-
25
-
26
- @dataclass()
27
- class SQLStatement:
28
- """An immutable representation of a SQL statement with its parameters.
29
-
30
- This class encapsulates the SQL statement and its parameters, providing
31
- a clean interface for parameter binding and SQL statement formatting.
32
- """
33
-
34
- sql: str
35
- """The raw SQL statement."""
36
- parameters: Optional[StatementParameterType] = None
37
- """The parameters for the SQL statement."""
38
- kwargs: Optional[dict[str, Any]] = None
39
- """Keyword arguments passed for parameter binding."""
40
- dialect: Optional[str] = None
41
- """SQL dialect to use for parsing. If not provided, sqlglot will try to auto-detect."""
42
-
43
- _merged_parameters: Optional[Union[StatementParameterType, dict[str, Any]]] = field(default=None, init=False)
44
- _parsed_expression: Optional[exp.Expression] = field(default=None, init=False)
45
- _param_counter: int = field(default=0, init=False)
46
-
47
- def __post_init__(self) -> None:
48
- """Merge parameters and kwargs after initialization."""
49
- merged_params = self.parameters
50
-
51
- if self.kwargs:
52
- if merged_params is None:
53
- merged_params = self.kwargs
54
- elif isinstance(merged_params, dict):
55
- # Merge kwargs into parameters dict, kwargs take precedence
56
- merged_params = {**merged_params, **self.kwargs}
57
- else:
58
- # If parameters is sequence or scalar, kwargs replace it
59
- # Consider adding a warning here if this behavior is surprising
60
- merged_params = self.kwargs
61
-
62
- self._merged_parameters = merged_params
63
-
64
- def process(
65
- self,
66
- ) -> "tuple[str, Optional[Union[tuple[Any, ...], list[Any], dict[str, Any]]], Optional[exp.Expression]]":
67
- """Process the SQL statement and merged parameters for execution.
68
-
69
- This method validates the parameters against the SQL statement using sqlglot
70
- parsing but returns the *original* SQL string, the merged parameters,
71
- and the parsed sqlglot expression if successful.
72
- The actual formatting of SQL placeholders and parameter structures for the
73
- DBAPI driver is delegated to the specific adapter.
74
-
75
- Returns:
76
- A tuple containing the *original* SQL string, the merged/validated
77
- parameters (dict, tuple, list, or None), and the parsed sqlglot expression
78
- (or None if parsing failed).
79
-
80
- Raises:
81
- SQLParsingError: If the SQL statement contains parameter placeholders
82
- but no parameters were provided, or if parsing fails unexpectedly.
83
- """
84
- # Parse the SQL to find expected parameters
85
- try:
86
- expression = self._parse_sql()
87
- # Find all parameter expressions (:name, ?, @name, $1, etc.)
88
- # These are nodes that sqlglot considers as bind parameters.
89
- all_sqlglot_placeholders = list(expression.find_all(exp.Placeholder, exp.Parameter))
90
- except SQLParsingError as e:
91
- logger.debug(
92
- "SQL parsing failed during validation: %s. Returning original SQL and parameters for adapter.", e
93
- )
94
- self._parsed_expression = None
95
- return self.sql, self._merged_parameters, None
96
-
97
- if self._merged_parameters is None:
98
- # If no parameters were provided, but the parsed SQL expects them, raise an error.
99
- if all_sqlglot_placeholders:
100
- placeholder_types_desc = []
101
- for p_node in all_sqlglot_placeholders:
102
- if isinstance(p_node, exp.Parameter) and p_node.name:
103
- placeholder_types_desc.append(f"named (e.g., :{p_node.name}, @{p_node.name})")
104
- elif (
105
- isinstance(p_node, exp.Placeholder)
106
- and p_node.this
107
- and not isinstance(p_node.this, (exp.Identifier, exp.Literal))
108
- and not str(p_node.this).isdigit()
109
- ):
110
- placeholder_types_desc.append(f"named (e.g., :{p_node.this})")
111
- elif isinstance(p_node, exp.Parameter) and p_node.name and p_node.name.isdigit():
112
- placeholder_types_desc.append("positional (e.g., $1, :1)")
113
- elif isinstance(p_node, exp.Placeholder) and p_node.this is None:
114
- placeholder_types_desc.append("positional (?)")
115
- desc_str = ", ".join(sorted(set(placeholder_types_desc))) or "unknown"
116
- msg = f"SQL statement contains {desc_str} parameter placeholders, but no parameters were provided. SQL: {self.sql}"
117
- raise SQLParsingError(msg)
118
- return self.sql, None, self._parsed_expression
119
-
120
- # Validate provided parameters against parsed SQL parameters
121
- if isinstance(self._merged_parameters, dict):
122
- self._validate_dict_params(all_sqlglot_placeholders, self._merged_parameters)
123
- elif isinstance(self._merged_parameters, (tuple, list)):
124
- self._validate_sequence_params(all_sqlglot_placeholders, self._merged_parameters)
125
- else: # Scalar parameter
126
- self._validate_scalar_param(all_sqlglot_placeholders, self._merged_parameters)
127
-
128
- # Return the original SQL and the merged parameters for the adapter to process
129
- return self.sql, self._merged_parameters, self._parsed_expression
130
-
131
- def _parse_sql(self) -> exp.Expression:
132
- """Parse the SQL using sqlglot.
133
-
134
- Raises:
135
- SQLParsingError: If the SQL statement cannot be parsed.
136
-
137
- Returns:
138
- The parsed SQL expression.
139
- """
140
- try:
141
- if not self.sql.strip():
142
- self._parsed_expression = exp.Select()
143
- return self._parsed_expression
144
- # Use the provided dialect if available, otherwise sqlglot will try to auto-detect
145
- self._parsed_expression = sqlglot.parse_one(self.sql, dialect=self.dialect)
146
- if self._parsed_expression is None:
147
- self._parsed_expression = exp.Select() # type: ignore[unreachable]
148
- except Exception as e:
149
- msg = f"Failed to parse SQL for validation: {e!s}\nSQL: {self.sql}"
150
- self._parsed_expression = None
151
- raise SQLParsingError(msg) from e
152
- else:
153
- return self._parsed_expression
154
-
155
- def _validate_dict_params(
156
- self, all_sqlglot_placeholders: Sequence[exp.Expression], parameter_dict: dict[str, Any]
157
- ) -> None:
158
- sqlglot_named_params: dict[str, Union[exp.Parameter, exp.Placeholder]] = {}
159
- has_positional_qmark = False
160
-
161
- for p_node in all_sqlglot_placeholders:
162
- if (
163
- isinstance(p_node, exp.Parameter) and p_node.name and not p_node.name.isdigit()
164
- ): # @name, $name (non-numeric)
165
- sqlglot_named_params[p_node.name] = p_node
166
- elif (
167
- isinstance(p_node, exp.Placeholder)
168
- and p_node.this
169
- and not isinstance(p_node.this, (exp.Identifier, exp.Literal))
170
- and not str(p_node.this).isdigit()
171
- ): # :name
172
- sqlglot_named_params[str(p_node.this)] = p_node
173
- elif isinstance(p_node, exp.Placeholder) and p_node.this is None: # ?
174
- has_positional_qmark = True
175
- # Ignores numeric placeholders like $1, :1 for dict validation for now
176
-
177
- if has_positional_qmark:
178
- msg = f"Dictionary parameters provided, but found unnamed placeholders ('?') in SQL: {self.sql}"
179
- raise ParameterStyleMismatchError(msg)
180
-
181
- if not sqlglot_named_params and parameter_dict:
182
- msg = f"Dictionary parameters provided, but no named placeholders (e.g., ':name', '$name', '@name') found by sqlglot in SQL: {self.sql}"
183
- raise ParameterStyleMismatchError(msg)
184
-
185
- missing_keys = set(sqlglot_named_params.keys()) - set(parameter_dict.keys())
186
- if missing_keys:
187
- msg = f"Named parameters found in SQL by sqlglot but not provided: {missing_keys}. SQL: {self.sql}"
188
- raise SQLParsingError(msg)
189
-
190
- def _validate_sequence_params(
191
- self,
192
- all_sqlglot_placeholders: Sequence[exp.Expression],
193
- params: Union[tuple[Any, ...], list[Any]],
194
- ) -> None:
195
- sqlglot_named_param_names = [] # For detecting named params
196
- sqlglot_positional_count = 0 # For counting ?, $1, :1 etc.
197
-
198
- for p_node in all_sqlglot_placeholders:
199
- if isinstance(p_node, exp.Parameter) and p_node.name and not p_node.name.isdigit(): # @name, $name
200
- sqlglot_named_param_names.append(p_node.name)
201
- elif (
202
- isinstance(p_node, exp.Placeholder)
203
- and p_node.this
204
- and not isinstance(p_node.this, (exp.Identifier, exp.Literal))
205
- and not str(p_node.this).isdigit()
206
- ): # :name
207
- sqlglot_named_param_names.append(str(p_node.this))
208
- elif isinstance(p_node, exp.Placeholder) and p_node.this is None: # ?
209
- sqlglot_positional_count += 1
210
- elif isinstance(p_node, exp.Parameter) and ( # noqa: PLR0916
211
- (p_node.name and p_node.name.isdigit())
212
- or (
213
- not p_node.name
214
- and p_node.this
215
- and isinstance(p_node.this, (str, exp.Identifier, exp.Literal))
216
- and str(p_node.this).isdigit()
217
- )
218
- ):
219
- # $1, :1 style (parsed as Parameter with name="1" or this="1" or this=Identifier(this="1") or this=Literal(this=1))
220
- sqlglot_positional_count += 1
221
- elif (
222
- isinstance(p_node, exp.Placeholder) and p_node.this and str(p_node.this).isdigit()
223
- ): # :1 style (Placeholder with this="1")
224
- sqlglot_positional_count += 1
225
-
226
- if sqlglot_named_param_names:
227
- msg = f"Sequence parameters provided, but found named placeholders ({', '.join(sorted(set(sqlglot_named_param_names)))}) in SQL: {self.sql}"
228
- raise ParameterStyleMismatchError(msg)
229
-
230
- actual_count_provided = len(params)
231
-
232
- if sqlglot_positional_count != actual_count_provided:
233
- msg = (
234
- f"Parameter count mismatch. SQL expects {sqlglot_positional_count} (sqlglot) positional "
235
- f"parameters, but {actual_count_provided} were provided. SQL: {self.sql}"
236
- )
237
- raise SQLParsingError(msg)
238
-
239
- def _validate_scalar_param(self, all_sqlglot_placeholders: Sequence[exp.Expression], param_value: Any) -> None:
240
- """Validates a single scalar parameter against parsed SQL parameters."""
241
- self._validate_sequence_params(
242
- all_sqlglot_placeholders, (param_value,)
243
- ) # Treat scalar as a single-element sequence
244
-
245
- def get_expression(self) -> exp.Expression:
246
- """Get the parsed SQLglot expression, parsing if necessary.
247
-
248
- Returns:
249
- The SQLglot expression.
250
- """
251
- if self._parsed_expression is None:
252
- self._parse_sql()
253
- if self._parsed_expression is None: # Still None after parsing attempt
254
- return exp.Select() # Return an empty SELECT as fallback
255
- return self._parsed_expression
256
-
257
- def generate_param_name(self, base_name: str) -> str:
258
- """Generates a unique parameter name.
259
-
260
- Args:
261
- base_name: The base name for the parameter.
262
-
263
- Returns:
264
- The generated parameter name.
265
- """
266
- self._param_counter += 1
267
- safe_base_name = "".join(c if c.isalnum() else "_" for c in base_name if c.isalnum() or c == "_")
268
- return f"param_{safe_base_name}_{self._param_counter}"
269
-
270
- def add_condition(self, condition: exp.Condition, params: Optional[dict[str, Any]] = None) -> None:
271
- """Adds a condition to the WHERE clause of the query.
272
-
273
- Args:
274
- condition: The condition to add to the WHERE clause.
275
- params: The parameters to add to the statement parameters.
276
- """
277
- expression = self.get_expression()
278
- if not isinstance(expression, (exp.Select, exp.Update, exp.Delete)):
279
- return # Cannot add WHERE to some expressions
280
-
281
- # Update the expression
282
- expression.where(condition, copy=False)
283
-
284
- # Update the parameters
285
- if params:
286
- if self._merged_parameters is None:
287
- self._merged_parameters = params
288
- elif isinstance(self._merged_parameters, dict):
289
- self._merged_parameters.update(params)
290
- else:
291
- # Convert to dict if not already
292
- self._merged_parameters = params
293
-
294
- # Update the SQL string
295
- self.sql = expression.sql(dialect=self.dialect)
296
-
297
- def add_order_by(self, field_name: str, direction: str = "asc") -> None:
298
- """Adds an ORDER BY clause.
299
-
300
- Args:
301
- field_name: The name of the field to order by.
302
- direction: The direction to order by ("asc" or "desc").
303
- """
304
- expression = self.get_expression()
305
- if not isinstance(expression, exp.Select):
306
- return
307
-
308
- expression.order_by(exp.Ordered(this=exp.column(field_name), desc=direction.lower() == "desc"), copy=False)
309
- self.sql = expression.sql(dialect=self.dialect)
310
-
311
- def add_limit(self, limit_val: int, param_name: Optional[str] = None) -> None:
312
- """Adds a LIMIT clause.
313
-
314
- Args:
315
- limit_val: The value for the LIMIT clause.
316
- param_name: Optional name for the parameter.
317
- """
318
- expression = self.get_expression()
319
- if not isinstance(expression, exp.Select):
320
- return
321
-
322
- if param_name:
323
- expression.limit(exp.Placeholder(this=param_name), copy=False)
324
- if self._merged_parameters is None:
325
- self._merged_parameters = {param_name: limit_val}
326
- elif isinstance(self._merged_parameters, dict):
327
- self._merged_parameters[param_name] = limit_val
328
- else:
329
- expression.limit(exp.Literal.number(limit_val), copy=False)
330
-
331
- self.sql = expression.sql(dialect=self.dialect)
332
-
333
- def add_offset(self, offset_val: int, param_name: Optional[str] = None) -> None:
334
- """Adds an OFFSET clause.
335
-
336
- Args:
337
- offset_val: The value for the OFFSET clause.
338
- param_name: Optional name for the parameter.
339
- """
340
- expression = self.get_expression()
341
- if not isinstance(expression, exp.Select):
342
- return
343
-
344
- if param_name:
345
- expression.offset(exp.Placeholder(this=param_name), copy=False)
346
- if self._merged_parameters is None:
347
- self._merged_parameters = {param_name: offset_val}
348
- elif isinstance(self._merged_parameters, dict):
349
- self._merged_parameters[param_name] = offset_val
350
- else:
351
- expression.offset(exp.Literal.number(offset_val), copy=False)
352
-
353
- self.sql = expression.sql(dialect=self.dialect)
354
-
355
- def apply_filter(self, filter_obj: "StatementFilter") -> "SQLStatement":
356
- """Apply a statement filter to this statement.
357
-
358
- Args:
359
- filter_obj: The filter to apply.
360
-
361
- Returns:
362
- The modified statement.
363
- """
364
- from sqlspec.filters import apply_filter
365
-
366
- return apply_filter(self, filter_obj)
367
-
368
- def to_sql(self, dialect: Optional[str] = None) -> str:
369
- """Generate SQL string using the specified dialect.
370
-
371
- Args:
372
- dialect: SQL dialect to use for SQL generation. If None, uses the statement's dialect.
373
-
374
- Returns:
375
- SQL string in the specified dialect.
376
- """
377
- expression = self.get_expression()
378
- return expression.sql(dialect=dialect or self.dialect)
@@ -1,69 +0,0 @@
1
- sqlspec/__init__.py,sha256=Dl1QOZAK21--ORQcRn15n4YPFklFMe2-Lb7TWWq_WQE,338
2
- sqlspec/__metadata__.py,sha256=hNP3wXvtk8fQVPKGjRLpZ9mP-gaPJqzrmgm3UqpDIXQ,460
3
- sqlspec/_serialization.py,sha256=tSwWwFImlYviC6ARdXRz0Bp4QXbCdc8cKGgZr33OglY,2657
4
- sqlspec/_typing.py,sha256=a8QTy3oqdUfjrA6Iu4PxfQcUf9DuG9pZcalcevM_xIU,7037
5
- sqlspec/base.py,sha256=sKN8t3tpq6p2wriBcNn8YPwb3tSXubNVm4J5GRZOpN0,33689
6
- sqlspec/exceptions.py,sha256=WnA56CdDSSdOjA5UE4jnfXXtrfClgwjCRxT-id0eVAo,4302
7
- sqlspec/filters.py,sha256=oLC5a0__i1B91OwNLCm_shoUsqxA3sqHlwJB6cA61JQ,12037
8
- sqlspec/mixins.py,sha256=q_N5HBcfA-gETtP3zQn8gd7CNB86fqaenx2tlBqIIZI,10552
9
- sqlspec/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- sqlspec/statement.py,sha256=LNagGHKt-ixjom5WW5VLRzT9YIJC0lOfvwnn41Zz-fw,16433
11
- sqlspec/typing.py,sha256=XAQpyOPAcHzlGScY3DCxIfiaQpfbFP4PntIgvYdcLwk,16313
12
- sqlspec/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- sqlspec/adapters/adbc/__init__.py,sha256=Ih0mdciGyhmOlqmz4uiByj7mEaqvP4upRjYhlUNopAQ,193
14
- sqlspec/adapters/adbc/config.py,sha256=yayt62Mx789_B7Xo8DrlWCyeXclFchL4OxUxZIFnh9I,9646
15
- sqlspec/adapters/adbc/driver.py,sha256=XI0xJRYZ7uordzR7Vpt3BRTH1DLpRZn7ZXC5-GUZAZc,28631
16
- sqlspec/adapters/aiosqlite/__init__.py,sha256=CndH49GREnHuIB-jY1XAxVlLwZTvKNuk8XJu9jiiM7A,233
17
- sqlspec/adapters/aiosqlite/config.py,sha256=tE-DnjKbdy5FaqqRyA1q3s06rMSAglt0HkhO2oWQT2w,4603
18
- sqlspec/adapters/aiosqlite/driver.py,sha256=bwJOV-iqqn5FS4LZK6Wjt-jH0y922XCIoFqINziXFs0,17045
19
- sqlspec/adapters/asyncmy/__init__.py,sha256=7jQFc0WOgc58XPeIiDgX9a95scMa6PuFgGXQaxG33nI,291
20
- sqlspec/adapters/asyncmy/config.py,sha256=5ILV46FWjc9Cy46aMuhinpfc70b_708h9ubHj9HRCmE,9412
21
- sqlspec/adapters/asyncmy/driver.py,sha256=ZXZt8ixuD74UvU5D-v4nrRHH_wU8apPzbROPma8Jm-k,17472
22
- sqlspec/adapters/asyncpg/__init__.py,sha256=iR-vJYxImcw5hLaDgMqPLLRxW_vOYylEpemSg5G4dP4,261
23
- sqlspec/adapters/asyncpg/config.py,sha256=cuQ_cCQ6xtqluaNO5Ax9vqZ-4JZoaUR31-QE6xAVbns,10011
24
- sqlspec/adapters/asyncpg/driver.py,sha256=5FJDA0tVJYtsQK4Y9XpmiDwPtdjnyRkSAMk8MwVdKZ0,21197
25
- sqlspec/adapters/bigquery/__init__.py,sha256=8kcl0_tnvnk8omVKnAljIY9n2XVnzkPRCfhfedGO0m4,264
26
- sqlspec/adapters/bigquery/driver.py,sha256=BLD9EyKdbo85LZs6l7MMw5OE_n7dLlBtclM1kKIQlvM,23494
27
- sqlspec/adapters/bigquery/config/__init__.py,sha256=4ij4LAS-kIt-vOK8KetewVoYN90i1RV_BjtowKWDIs0,150
28
- sqlspec/adapters/bigquery/config/_common.py,sha256=LSbBC302-Ewx8XHTRzYR-tInMYywVW9I6UcL8cO7-HQ,1901
29
- sqlspec/adapters/bigquery/config/_sync.py,sha256=oglaEErXuce1TnE2wj5KrfFLkScRGFYAoOTCVV5BFcw,3323
30
- sqlspec/adapters/duckdb/__init__.py,sha256=GMSHigyHgtaJKu751kE_Sxl5Ry4hnQOnFUSIeLSg1qs,209
31
- sqlspec/adapters/duckdb/config.py,sha256=b-Ev7UnpguC12CJSxK9DDqcPw0R2dZUZXaVIePf_EEg,15700
32
- sqlspec/adapters/duckdb/driver.py,sha256=uMIsa6ipMmL8on1Q4vPfxbem6s7uq5_-PLCqFifFvzE,16096
33
- sqlspec/adapters/oracledb/__init__.py,sha256=vVe8cXZJLFvBA6LPx4NzGRLdOeRugzRjz92UYjb0lC0,521
34
- sqlspec/adapters/oracledb/driver.py,sha256=UsYa3Z0lM4w39PVgL0edDRkO35M7Rha2NxcvCLv5NR8,38755
35
- sqlspec/adapters/oracledb/config/__init__.py,sha256=emx5jWXqw3ifoW-m_tNI7sTz_duq2vRkubc0J2QqEQ4,306
36
- sqlspec/adapters/oracledb/config/_asyncio.py,sha256=k0wGr4FflFR03jUSgrw-4LC4mYtRlyH9gnbbBXNcMRM,7310
37
- sqlspec/adapters/oracledb/config/_common.py,sha256=UJZL2DQQZM3uOn1E1A_gnsB8nX3-yCDXGd66PDI29_s,5691
38
- sqlspec/adapters/oracledb/config/_sync.py,sha256=nm5FnrRG1ScrNviw3MR_40Vq8WJCXX5mJGtHhhRTPb0,7055
39
- sqlspec/adapters/psqlpy/__init__.py,sha256=K8UlQrKfbCZmxGAaT4CHzQvdwGPxPLB9TDOHJgkESFc,251
40
- sqlspec/adapters/psqlpy/config.py,sha256=qssXcu_Nd6o_X8QU1i61sAXwi9FiTApWxiTRU0gyBhk,10205
41
- sqlspec/adapters/psqlpy/driver.py,sha256=7CG3vGjOjbmjOjW2Zd0yf73WHIRU0tNtj4YoPQ4fNFs,21325
42
- sqlspec/adapters/psycopg/__init__.py,sha256=xmFWHSB6hwPNQS1wpBmAczJThABmhRv2PDNKqaMFX3E,535
43
- sqlspec/adapters/psycopg/driver.py,sha256=ADzb482mbxBwmSt4WmADev2RmwRtDPSMA4uepLMx0-M,27519
44
- sqlspec/adapters/psycopg/config/__init__.py,sha256=hUmtNkSma4M-Y66B-l1gh601Lx7FVYVhU0BWo9ssdJo,570
45
- sqlspec/adapters/psycopg/config/_async.py,sha256=oKitbfpsJVLhMnbMUmICQub3rBzVZ5n9lwsU_ZvB45s,6661
46
- sqlspec/adapters/psycopg/config/_common.py,sha256=UqqvqPE9zlSO9G_Gh6fI190cHfCDG98S0GaznGAHpdU,2181
47
- sqlspec/adapters/psycopg/config/_sync.py,sha256=GYPgE7jfb15gbVdTWRoGGS3B7hauN8wk61CW6Bdrjcs,6512
48
- sqlspec/adapters/sqlite/__init__.py,sha256=N8VL4Y850OOt63qz-Yvu6rIaCXiziASmn_qDY5tsRuA,209
49
- sqlspec/adapters/sqlite/config.py,sha256=lGz0G-JFd7dZLhbUrITn9V-ipbhlekwNUr0bXEzM-8k,4498
50
- sqlspec/adapters/sqlite/driver.py,sha256=e-EmOrr91TWNvmHuvAq58qI_eyhwL20EwprRu3YlQds,14889
51
- sqlspec/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
- sqlspec/extensions/litestar/__init__.py,sha256=ifiR2AXv3m4iDncA2XsVsgk8NnEjcEKxjK2jhFe6A-8,262
53
- sqlspec/extensions/litestar/_utils.py,sha256=UgwFxqLnjDw9S8G0H24DP2GsbMGas81W1lfhfTY68m8,1969
54
- sqlspec/extensions/litestar/config.py,sha256=Lz5_NqZ-XDXvaLh7fsPqxvuSDJ1JLJg1XUqbC-PdZPU,4666
55
- sqlspec/extensions/litestar/handlers.py,sha256=3RJJ5rCEQCbmrhDhkz9Tp03UxqPYhyL8PYR7WKyvuP8,10372
56
- sqlspec/extensions/litestar/plugin.py,sha256=0isCQ_VFC33_xyRf1Zcb2oWYbZpjFTg-OOZ2EGwTV5M,5175
57
- sqlspec/extensions/litestar/providers.py,sha256=dwdw7o0jfhDGNbwgabx41dROQ3HCgA0cdXNhWsJPVuw,21805
58
- sqlspec/utils/__init__.py,sha256=_Ya8IZuc2cZIstXr_xjgnSfxICXHXvu5mfWsi2USDrw,183
59
- sqlspec/utils/deprecation.py,sha256=4pwGxoQYI3dAc3L1lh4tszZG6e2jp5m4e0ICk8SJx5M,3886
60
- sqlspec/utils/fixtures.py,sha256=ni51rAuen6S1wuSi1kUwn6Qh25B-XrewPEsjV8G4gQ0,2029
61
- sqlspec/utils/module_loader.py,sha256=tmMy9JcTTQETcwT8Wt8adCIuqr4zinQnPbCiBJ6JTSQ,2703
62
- sqlspec/utils/singleton.py,sha256=YsHuo8_blPRQJRvXnjWXa8-Y-TO5V7jFGRwql-rNpO0,1363
63
- sqlspec/utils/sync_tools.py,sha256=IRzgLMvdkYIwPGUG_EBYGwoOiBBmQSaphwaGachkV4M,9146
64
- sqlspec/utils/text.py,sha256=-RlwmGjXtfD_ZkqIesZTHAPi46xg-uqlpVKDMcNwFrU,3539
65
- sqlspec-0.11.1.dist-info/METADATA,sha256=o1D1jHZ58W2Xz6DNlEapfqAA7Nr1PWGZmAK7qwurucg,14467
66
- sqlspec-0.11.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
67
- sqlspec-0.11.1.dist-info/licenses/LICENSE,sha256=MdujfZ6l5HuLz4mElxlu049itenOR3gnhN1_Nd3nVcM,1078
68
- sqlspec-0.11.1.dist-info/licenses/NOTICE,sha256=Lyir8ozXWov7CyYS4huVaOCNrtgL17P-bNV-5daLntQ,1634
69
- sqlspec-0.11.1.dist-info/RECORD,,