sqlspec 0.26.0__py3-none-any.whl → 0.27.0__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 (197) hide show
  1. sqlspec/__init__.py +7 -15
  2. sqlspec/_serialization.py +55 -25
  3. sqlspec/_typing.py +62 -52
  4. sqlspec/adapters/adbc/_types.py +1 -1
  5. sqlspec/adapters/adbc/adk/__init__.py +5 -0
  6. sqlspec/adapters/adbc/adk/store.py +870 -0
  7. sqlspec/adapters/adbc/config.py +62 -12
  8. sqlspec/adapters/adbc/data_dictionary.py +52 -2
  9. sqlspec/adapters/adbc/driver.py +144 -45
  10. sqlspec/adapters/adbc/litestar/__init__.py +5 -0
  11. sqlspec/adapters/adbc/litestar/store.py +504 -0
  12. sqlspec/adapters/adbc/type_converter.py +44 -50
  13. sqlspec/adapters/aiosqlite/_types.py +1 -1
  14. sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
  15. sqlspec/adapters/aiosqlite/adk/store.py +527 -0
  16. sqlspec/adapters/aiosqlite/config.py +86 -16
  17. sqlspec/adapters/aiosqlite/data_dictionary.py +34 -2
  18. sqlspec/adapters/aiosqlite/driver.py +127 -38
  19. sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
  20. sqlspec/adapters/aiosqlite/litestar/store.py +281 -0
  21. sqlspec/adapters/aiosqlite/pool.py +7 -7
  22. sqlspec/adapters/asyncmy/__init__.py +7 -1
  23. sqlspec/adapters/asyncmy/_types.py +1 -1
  24. sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
  25. sqlspec/adapters/asyncmy/adk/store.py +493 -0
  26. sqlspec/adapters/asyncmy/config.py +59 -17
  27. sqlspec/adapters/asyncmy/data_dictionary.py +41 -2
  28. sqlspec/adapters/asyncmy/driver.py +293 -62
  29. sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
  30. sqlspec/adapters/asyncmy/litestar/store.py +296 -0
  31. sqlspec/adapters/asyncpg/__init__.py +2 -1
  32. sqlspec/adapters/asyncpg/_type_handlers.py +71 -0
  33. sqlspec/adapters/asyncpg/_types.py +11 -7
  34. sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
  35. sqlspec/adapters/asyncpg/adk/store.py +450 -0
  36. sqlspec/adapters/asyncpg/config.py +57 -36
  37. sqlspec/adapters/asyncpg/data_dictionary.py +41 -2
  38. sqlspec/adapters/asyncpg/driver.py +153 -23
  39. sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
  40. sqlspec/adapters/asyncpg/litestar/store.py +253 -0
  41. sqlspec/adapters/bigquery/_types.py +1 -1
  42. sqlspec/adapters/bigquery/adk/__init__.py +5 -0
  43. sqlspec/adapters/bigquery/adk/store.py +576 -0
  44. sqlspec/adapters/bigquery/config.py +25 -11
  45. sqlspec/adapters/bigquery/data_dictionary.py +42 -2
  46. sqlspec/adapters/bigquery/driver.py +352 -144
  47. sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
  48. sqlspec/adapters/bigquery/litestar/store.py +327 -0
  49. sqlspec/adapters/bigquery/type_converter.py +55 -23
  50. sqlspec/adapters/duckdb/_types.py +2 -2
  51. sqlspec/adapters/duckdb/adk/__init__.py +14 -0
  52. sqlspec/adapters/duckdb/adk/store.py +553 -0
  53. sqlspec/adapters/duckdb/config.py +79 -21
  54. sqlspec/adapters/duckdb/data_dictionary.py +41 -2
  55. sqlspec/adapters/duckdb/driver.py +138 -43
  56. sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
  57. sqlspec/adapters/duckdb/litestar/store.py +332 -0
  58. sqlspec/adapters/duckdb/pool.py +5 -5
  59. sqlspec/adapters/duckdb/type_converter.py +51 -21
  60. sqlspec/adapters/oracledb/_numpy_handlers.py +133 -0
  61. sqlspec/adapters/oracledb/_types.py +20 -2
  62. sqlspec/adapters/oracledb/adk/__init__.py +5 -0
  63. sqlspec/adapters/oracledb/adk/store.py +1745 -0
  64. sqlspec/adapters/oracledb/config.py +120 -36
  65. sqlspec/adapters/oracledb/data_dictionary.py +87 -20
  66. sqlspec/adapters/oracledb/driver.py +292 -84
  67. sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
  68. sqlspec/adapters/oracledb/litestar/store.py +767 -0
  69. sqlspec/adapters/oracledb/migrations.py +316 -25
  70. sqlspec/adapters/oracledb/type_converter.py +91 -16
  71. sqlspec/adapters/psqlpy/_type_handlers.py +44 -0
  72. sqlspec/adapters/psqlpy/_types.py +2 -1
  73. sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
  74. sqlspec/adapters/psqlpy/adk/store.py +482 -0
  75. sqlspec/adapters/psqlpy/config.py +45 -19
  76. sqlspec/adapters/psqlpy/data_dictionary.py +41 -2
  77. sqlspec/adapters/psqlpy/driver.py +101 -31
  78. sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
  79. sqlspec/adapters/psqlpy/litestar/store.py +272 -0
  80. sqlspec/adapters/psqlpy/type_converter.py +40 -11
  81. sqlspec/adapters/psycopg/_type_handlers.py +80 -0
  82. sqlspec/adapters/psycopg/_types.py +2 -1
  83. sqlspec/adapters/psycopg/adk/__init__.py +5 -0
  84. sqlspec/adapters/psycopg/adk/store.py +944 -0
  85. sqlspec/adapters/psycopg/config.py +65 -37
  86. sqlspec/adapters/psycopg/data_dictionary.py +77 -3
  87. sqlspec/adapters/psycopg/driver.py +200 -78
  88. sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
  89. sqlspec/adapters/psycopg/litestar/store.py +554 -0
  90. sqlspec/adapters/sqlite/__init__.py +2 -1
  91. sqlspec/adapters/sqlite/_type_handlers.py +86 -0
  92. sqlspec/adapters/sqlite/_types.py +1 -1
  93. sqlspec/adapters/sqlite/adk/__init__.py +5 -0
  94. sqlspec/adapters/sqlite/adk/store.py +572 -0
  95. sqlspec/adapters/sqlite/config.py +85 -16
  96. sqlspec/adapters/sqlite/data_dictionary.py +34 -2
  97. sqlspec/adapters/sqlite/driver.py +120 -52
  98. sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
  99. sqlspec/adapters/sqlite/litestar/store.py +318 -0
  100. sqlspec/adapters/sqlite/pool.py +5 -5
  101. sqlspec/base.py +45 -26
  102. sqlspec/builder/__init__.py +73 -4
  103. sqlspec/builder/_base.py +91 -58
  104. sqlspec/builder/_column.py +5 -5
  105. sqlspec/builder/_ddl.py +98 -89
  106. sqlspec/builder/_delete.py +5 -4
  107. sqlspec/builder/_dml.py +388 -0
  108. sqlspec/{_sql.py → builder/_factory.py} +41 -44
  109. sqlspec/builder/_insert.py +5 -82
  110. sqlspec/builder/{mixins/_join_operations.py → _join.py} +145 -143
  111. sqlspec/builder/_merge.py +446 -11
  112. sqlspec/builder/_parsing_utils.py +9 -11
  113. sqlspec/builder/_select.py +1313 -25
  114. sqlspec/builder/_update.py +11 -42
  115. sqlspec/cli.py +76 -69
  116. sqlspec/config.py +231 -60
  117. sqlspec/core/__init__.py +5 -4
  118. sqlspec/core/cache.py +18 -18
  119. sqlspec/core/compiler.py +6 -8
  120. sqlspec/core/filters.py +37 -37
  121. sqlspec/core/hashing.py +9 -9
  122. sqlspec/core/parameters.py +76 -45
  123. sqlspec/core/result.py +102 -46
  124. sqlspec/core/splitter.py +16 -17
  125. sqlspec/core/statement.py +32 -31
  126. sqlspec/core/type_conversion.py +3 -2
  127. sqlspec/driver/__init__.py +1 -3
  128. sqlspec/driver/_async.py +95 -161
  129. sqlspec/driver/_common.py +133 -80
  130. sqlspec/driver/_sync.py +95 -162
  131. sqlspec/driver/mixins/_result_tools.py +20 -236
  132. sqlspec/driver/mixins/_sql_translator.py +4 -4
  133. sqlspec/exceptions.py +70 -7
  134. sqlspec/extensions/adk/__init__.py +53 -0
  135. sqlspec/extensions/adk/_types.py +51 -0
  136. sqlspec/extensions/adk/converters.py +172 -0
  137. sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +144 -0
  138. sqlspec/extensions/adk/migrations/__init__.py +0 -0
  139. sqlspec/extensions/adk/service.py +181 -0
  140. sqlspec/extensions/adk/store.py +536 -0
  141. sqlspec/extensions/aiosql/adapter.py +73 -53
  142. sqlspec/extensions/litestar/__init__.py +21 -4
  143. sqlspec/extensions/litestar/cli.py +54 -10
  144. sqlspec/extensions/litestar/config.py +59 -266
  145. sqlspec/extensions/litestar/handlers.py +46 -17
  146. sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
  147. sqlspec/extensions/litestar/migrations/__init__.py +3 -0
  148. sqlspec/extensions/litestar/plugin.py +324 -223
  149. sqlspec/extensions/litestar/providers.py +25 -25
  150. sqlspec/extensions/litestar/store.py +265 -0
  151. sqlspec/loader.py +30 -49
  152. sqlspec/migrations/base.py +200 -76
  153. sqlspec/migrations/commands.py +591 -62
  154. sqlspec/migrations/context.py +6 -9
  155. sqlspec/migrations/fix.py +199 -0
  156. sqlspec/migrations/loaders.py +47 -19
  157. sqlspec/migrations/runner.py +241 -75
  158. sqlspec/migrations/tracker.py +237 -21
  159. sqlspec/migrations/utils.py +51 -3
  160. sqlspec/migrations/validation.py +177 -0
  161. sqlspec/protocols.py +66 -36
  162. sqlspec/storage/_utils.py +98 -0
  163. sqlspec/storage/backends/fsspec.py +134 -106
  164. sqlspec/storage/backends/local.py +78 -51
  165. sqlspec/storage/backends/obstore.py +278 -162
  166. sqlspec/storage/registry.py +75 -39
  167. sqlspec/typing.py +14 -84
  168. sqlspec/utils/config_resolver.py +6 -6
  169. sqlspec/utils/correlation.py +4 -5
  170. sqlspec/utils/data_transformation.py +3 -2
  171. sqlspec/utils/deprecation.py +9 -8
  172. sqlspec/utils/fixtures.py +4 -4
  173. sqlspec/utils/logging.py +46 -6
  174. sqlspec/utils/module_loader.py +2 -2
  175. sqlspec/utils/schema.py +288 -0
  176. sqlspec/utils/serializers.py +3 -3
  177. sqlspec/utils/sync_tools.py +21 -17
  178. sqlspec/utils/text.py +1 -2
  179. sqlspec/utils/type_guards.py +111 -20
  180. sqlspec/utils/version.py +433 -0
  181. {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/METADATA +40 -21
  182. sqlspec-0.27.0.dist-info/RECORD +207 -0
  183. sqlspec/builder/mixins/__init__.py +0 -55
  184. sqlspec/builder/mixins/_cte_and_set_ops.py +0 -253
  185. sqlspec/builder/mixins/_delete_operations.py +0 -50
  186. sqlspec/builder/mixins/_insert_operations.py +0 -282
  187. sqlspec/builder/mixins/_merge_operations.py +0 -698
  188. sqlspec/builder/mixins/_order_limit_operations.py +0 -145
  189. sqlspec/builder/mixins/_pivot_operations.py +0 -157
  190. sqlspec/builder/mixins/_select_operations.py +0 -930
  191. sqlspec/builder/mixins/_update_operations.py +0 -199
  192. sqlspec/builder/mixins/_where_clause.py +0 -1298
  193. sqlspec-0.26.0.dist-info/RECORD +0 -157
  194. sqlspec-0.26.0.dist-info/licenses/NOTICE +0 -29
  195. {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/WHEEL +0 -0
  196. {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/entry_points.txt +0 -0
  197. {sqlspec-0.26.0.dist-info → sqlspec-0.27.0.dist-info}/licenses/LICENSE +0 -0
sqlspec/core/cache.py CHANGED
@@ -14,7 +14,7 @@ Components:
14
14
  import threading
15
15
  import time
16
16
  from dataclasses import dataclass
17
- from typing import TYPE_CHECKING, Any, Final, Optional, Union
17
+ from typing import TYPE_CHECKING, Any, Final, Optional
18
18
 
19
19
  from mypy_extensions import mypyc_attr
20
20
  from typing_extensions import TypeVar
@@ -173,8 +173,8 @@ class CacheNode:
173
173
  """
174
174
  self.key = key
175
175
  self.value = value
176
- self.prev: Optional[CacheNode] = None
177
- self.next: Optional[CacheNode] = None
176
+ self.prev: CacheNode | None = None
177
+ self.next: CacheNode | None = None
178
178
  self.timestamp = time.time()
179
179
  self.access_count = 1
180
180
 
@@ -190,7 +190,7 @@ class UnifiedCache:
190
190
 
191
191
  __slots__ = UNIFIED_CACHE_SLOTS
192
192
 
193
- def __init__(self, max_size: int = DEFAULT_MAX_SIZE, ttl_seconds: Optional[int] = DEFAULT_TTL_SECONDS) -> None:
193
+ def __init__(self, max_size: int = DEFAULT_MAX_SIZE, ttl_seconds: int | None = DEFAULT_TTL_SECONDS) -> None:
194
194
  """Initialize unified cache.
195
195
 
196
196
  Args:
@@ -208,7 +208,7 @@ class UnifiedCache:
208
208
  self._head.next = self._tail
209
209
  self._tail.prev = self._head
210
210
 
211
- def get(self, key: CacheKey) -> Optional[Any]:
211
+ def get(self, key: CacheKey) -> Any | None:
212
212
  """Get value from cache.
213
213
 
214
214
  Args:
@@ -275,7 +275,7 @@ class UnifiedCache:
275
275
  True if key was found and deleted, False otherwise
276
276
  """
277
277
  with self._lock:
278
- node: Optional[CacheNode] = self._cache.get(key)
278
+ node: CacheNode | None = self._cache.get(key)
279
279
  if node is None:
280
280
  return False
281
281
 
@@ -306,7 +306,7 @@ class UnifiedCache:
306
306
  def _add_to_head(self, node: CacheNode) -> None:
307
307
  """Add node to head of list."""
308
308
  node.prev = self._head
309
- head_next: Optional[CacheNode] = self._head.next
309
+ head_next: CacheNode | None = self._head.next
310
310
  node.next = head_next
311
311
  if head_next is not None:
312
312
  head_next.prev = node
@@ -314,8 +314,8 @@ class UnifiedCache:
314
314
 
315
315
  def _remove_node(self, node: CacheNode) -> None:
316
316
  """Remove node from linked list."""
317
- node_prev: Optional[CacheNode] = node.prev
318
- node_next: Optional[CacheNode] = node.next
317
+ node_prev: CacheNode | None = node.prev
318
+ node_next: CacheNode | None = node.next
319
319
  if node_prev is not None:
320
320
  node_prev.next = node_next
321
321
  if node_next is not None:
@@ -341,7 +341,7 @@ class UnifiedCache:
341
341
  return not (ttl is not None and time.time() - node.timestamp > ttl)
342
342
 
343
343
 
344
- _default_cache: Optional[UnifiedCache] = None
344
+ _default_cache: UnifiedCache | None = None
345
345
  _cache_lock = threading.Lock()
346
346
 
347
347
 
@@ -381,7 +381,7 @@ def get_cache_statistics() -> dict[str, CacheStats]:
381
381
  return stats
382
382
 
383
383
 
384
- _global_cache_config: "Optional[CacheConfig]" = None
384
+ _global_cache_config: "CacheConfig | None" = None
385
385
 
386
386
 
387
387
  @mypyc_attr(allow_interpreted_subclasses=False)
@@ -558,7 +558,7 @@ class CachedStatement:
558
558
  """
559
559
 
560
560
  compiled_sql: str
561
- parameters: Optional[Union[tuple[Any, ...], dict[str, Any]]] # None allowed for static script compilation
561
+ parameters: tuple[Any, ...] | dict[str, Any] | None # None allowed for static script compilation
562
562
  expression: Optional["exp.Expression"]
563
563
 
564
564
  def get_parameters_view(self) -> "ParametersView":
@@ -572,7 +572,7 @@ class CachedStatement:
572
572
  return ParametersView(list(self.parameters), {})
573
573
 
574
574
 
575
- def create_cache_key(level: str, key: str, dialect: Optional[str] = None) -> str:
575
+ def create_cache_key(level: str, key: str, dialect: str | None = None) -> str:
576
576
  """Create optimized cache key using string concatenation.
577
577
 
578
578
  Args:
@@ -592,7 +592,7 @@ class MultiLevelCache:
592
592
 
593
593
  __slots__ = ("_cache",)
594
594
 
595
- def __init__(self, max_size: int = DEFAULT_MAX_SIZE, ttl_seconds: Optional[int] = DEFAULT_TTL_SECONDS) -> None:
595
+ def __init__(self, max_size: int = DEFAULT_MAX_SIZE, ttl_seconds: int | None = DEFAULT_TTL_SECONDS) -> None:
596
596
  """Initialize multi-level cache.
597
597
 
598
598
  Args:
@@ -601,7 +601,7 @@ class MultiLevelCache:
601
601
  """
602
602
  self._cache = UnifiedCache(max_size, ttl_seconds)
603
603
 
604
- def get(self, level: str, key: str, dialect: Optional[str] = None) -> Optional[Any]:
604
+ def get(self, level: str, key: str, dialect: str | None = None) -> Any | None:
605
605
  """Get value from cache with level and dialect namespace.
606
606
 
607
607
  Args:
@@ -616,7 +616,7 @@ class MultiLevelCache:
616
616
  cache_key = CacheKey((full_key,))
617
617
  return self._cache.get(cache_key)
618
618
 
619
- def put(self, level: str, key: str, value: Any, dialect: Optional[str] = None) -> None:
619
+ def put(self, level: str, key: str, value: Any, dialect: str | None = None) -> None:
620
620
  """Put value in cache with level and dialect namespace.
621
621
 
622
622
  Args:
@@ -629,7 +629,7 @@ class MultiLevelCache:
629
629
  cache_key = CacheKey((full_key,))
630
630
  self._cache.put(cache_key, value)
631
631
 
632
- def delete(self, level: str, key: str, dialect: Optional[str] = None) -> bool:
632
+ def delete(self, level: str, key: str, dialect: str | None = None) -> bool:
633
633
  """Delete entry from cache.
634
634
 
635
635
  Args:
@@ -653,7 +653,7 @@ class MultiLevelCache:
653
653
  return self._cache.get_stats()
654
654
 
655
655
 
656
- _multi_level_cache: Optional[MultiLevelCache] = None
656
+ _multi_level_cache: MultiLevelCache | None = None
657
657
 
658
658
 
659
659
  def get_cache() -> MultiLevelCache:
sqlspec/core/compiler.py CHANGED
@@ -8,16 +8,15 @@ Components:
8
8
 
9
9
  import hashlib
10
10
  from collections import OrderedDict
11
- from typing import TYPE_CHECKING, Any, Optional
11
+ from typing import TYPE_CHECKING, Any, Literal, Optional
12
12
 
13
13
  import sqlglot
14
14
  from mypy_extensions import mypyc_attr
15
15
  from sqlglot import expressions as exp
16
16
  from sqlglot.errors import ParseError
17
- from typing_extensions import Literal
18
17
 
18
+ import sqlspec.exceptions
19
19
  from sqlspec.core.parameters import ParameterProcessor
20
- from sqlspec.exceptions import SQLSpecError
21
20
  from sqlspec.utils.logging import get_logger
22
21
 
23
22
  if TYPE_CHECKING:
@@ -85,7 +84,7 @@ class CompiledSQL:
85
84
  execution_parameters: Any,
86
85
  operation_type: "OperationType",
87
86
  expression: Optional["exp.Expression"] = None,
88
- parameter_style: Optional[str] = None,
87
+ parameter_style: str | None = None,
89
88
  supports_many: bool = False,
90
89
  parameter_casts: Optional["dict[int, str]"] = None,
91
90
  ) -> None:
@@ -107,7 +106,7 @@ class CompiledSQL:
107
106
  self.parameter_style = parameter_style
108
107
  self.supports_many = supports_many
109
108
  self.parameter_casts = parameter_casts or {}
110
- self._hash: Optional[int] = None
109
+ self._hash: int | None = None
111
110
 
112
111
  def __hash__(self) -> int:
113
112
  """Cached hash value."""
@@ -274,8 +273,7 @@ class SQLProcessor:
274
273
  parameter_casts=parameter_casts,
275
274
  )
276
275
 
277
- except SQLSpecError:
278
- # Re-raise SQLSpecError (validation errors, parameter mismatches) - these should fail hard
276
+ except sqlspec.exceptions.SQLSpecError:
279
277
  raise
280
278
  except Exception as e:
281
279
  logger.warning("Compilation failed, using fallback: %s", e)
@@ -382,7 +380,7 @@ class SQLProcessor:
382
380
  return cast_positions
383
381
 
384
382
  def _apply_final_transformations(
385
- self, expression: "Optional[exp.Expression]", sql: str, parameters: Any, dialect_str: "Optional[str]"
383
+ self, expression: "exp.Expression | None", sql: str, parameters: Any, dialect_str: "str | None"
386
384
  ) -> "tuple[str, Any]":
387
385
  """Apply final transformations.
388
386
 
sqlspec/core/filters.py CHANGED
@@ -23,11 +23,11 @@ from abc import ABC, abstractmethod
23
23
  from collections import abc
24
24
  from collections.abc import Sequence
25
25
  from datetime import datetime
26
- from typing import TYPE_CHECKING, Any, Generic, Literal, Optional, Union
26
+ from typing import TYPE_CHECKING, Any, Generic, Literal, TypeAlias
27
27
 
28
28
  import sqlglot
29
29
  from sqlglot import exp
30
- from typing_extensions import TypeAlias, TypeVar
30
+ from typing_extensions import TypeVar
31
31
 
32
32
  if TYPE_CHECKING:
33
33
  from sqlglot.expressions import Condition
@@ -125,7 +125,7 @@ class BeforeAfterFilter(StatementFilter):
125
125
 
126
126
  __slots__ = ("_after", "_before", "_field_name")
127
127
 
128
- def __init__(self, field_name: str, before: Optional[datetime] = None, after: Optional[datetime] = None) -> None:
128
+ def __init__(self, field_name: str, before: datetime | None = None, after: datetime | None = None) -> None:
129
129
  self._field_name = field_name
130
130
  self._before = before
131
131
  self._after = after
@@ -135,11 +135,11 @@ class BeforeAfterFilter(StatementFilter):
135
135
  return self._field_name
136
136
 
137
137
  @property
138
- def before(self) -> Optional[datetime]:
138
+ def before(self) -> datetime | None:
139
139
  return self._before
140
140
 
141
141
  @property
142
- def after(self) -> Optional[datetime]:
142
+ def after(self) -> datetime | None:
143
143
  return self._after
144
144
 
145
145
  def get_param_names(self) -> list[str]:
@@ -206,7 +206,7 @@ class OnBeforeAfterFilter(StatementFilter):
206
206
  __slots__ = ("_field_name", "_on_or_after", "_on_or_before")
207
207
 
208
208
  def __init__(
209
- self, field_name: str, on_or_before: Optional[datetime] = None, on_or_after: Optional[datetime] = None
209
+ self, field_name: str, on_or_before: datetime | None = None, on_or_after: datetime | None = None
210
210
  ) -> None:
211
211
  self._field_name = field_name
212
212
  self._on_or_before = on_or_before
@@ -217,11 +217,11 @@ class OnBeforeAfterFilter(StatementFilter):
217
217
  return self._field_name
218
218
 
219
219
  @property
220
- def on_or_before(self) -> Optional[datetime]:
220
+ def on_or_before(self) -> datetime | None:
221
221
  return self._on_or_before
222
222
 
223
223
  @property
224
- def on_or_after(self) -> Optional[datetime]:
224
+ def on_or_after(self) -> datetime | None:
225
225
  return self._on_or_after
226
226
 
227
227
  def get_param_names(self) -> list[str]:
@@ -298,7 +298,7 @@ class InCollectionFilter(InAnyFilter[T]):
298
298
 
299
299
  __slots__ = ("_field_name", "_values")
300
300
 
301
- def __init__(self, field_name: str, values: Optional[abc.Collection[T]] = None) -> None:
301
+ def __init__(self, field_name: str, values: abc.Collection[T] | None = None) -> None:
302
302
  self._field_name = field_name
303
303
  self._values = values
304
304
 
@@ -307,7 +307,7 @@ class InCollectionFilter(InAnyFilter[T]):
307
307
  return self._field_name
308
308
 
309
309
  @property
310
- def values(self) -> Optional[abc.Collection[T]]:
310
+ def values(self) -> abc.Collection[T] | None:
311
311
  return self._values
312
312
 
313
313
  def get_param_names(self) -> list[str]:
@@ -340,7 +340,7 @@ class InCollectionFilter(InAnyFilter[T]):
340
340
 
341
341
  result = statement.where(exp.In(this=exp.column(self.field_name), expressions=placeholder_expressions))
342
342
 
343
- for resolved_name, value in zip(resolved_names, self.values):
343
+ for resolved_name, value in zip(resolved_names, self.values, strict=False):
344
344
  result = result.add_named_parameter(resolved_name, value)
345
345
  return result
346
346
 
@@ -358,7 +358,7 @@ class NotInCollectionFilter(InAnyFilter[T]):
358
358
 
359
359
  __slots__ = ("_field_name", "_values")
360
360
 
361
- def __init__(self, field_name: str, values: Optional[abc.Collection[T]] = None) -> None:
361
+ def __init__(self, field_name: str, values: abc.Collection[T] | None = None) -> None:
362
362
  self._field_name = field_name
363
363
  self._values = values
364
364
 
@@ -367,7 +367,7 @@ class NotInCollectionFilter(InAnyFilter[T]):
367
367
  return self._field_name
368
368
 
369
369
  @property
370
- def values(self) -> Optional[abc.Collection[T]]:
370
+ def values(self) -> abc.Collection[T] | None:
371
371
  return self._values
372
372
 
373
373
  def get_param_names(self) -> list[str]:
@@ -400,7 +400,7 @@ class NotInCollectionFilter(InAnyFilter[T]):
400
400
  exp.Not(this=exp.In(this=exp.column(self.field_name), expressions=placeholder_expressions))
401
401
  )
402
402
 
403
- for resolved_name, value in zip(resolved_names, self.values):
403
+ for resolved_name, value in zip(resolved_names, self.values, strict=False):
404
404
  result = result.add_named_parameter(resolved_name, value)
405
405
  return result
406
406
 
@@ -418,7 +418,7 @@ class AnyCollectionFilter(InAnyFilter[T]):
418
418
 
419
419
  __slots__ = ("_field_name", "_values")
420
420
 
421
- def __init__(self, field_name: str, values: Optional[abc.Collection[T]] = None) -> None:
421
+ def __init__(self, field_name: str, values: abc.Collection[T] | None = None) -> None:
422
422
  self._field_name = field_name
423
423
  self._values = values
424
424
 
@@ -427,7 +427,7 @@ class AnyCollectionFilter(InAnyFilter[T]):
427
427
  return self._field_name
428
428
 
429
429
  @property
430
- def values(self) -> Optional[abc.Collection[T]]:
430
+ def values(self) -> abc.Collection[T] | None:
431
431
  return self._values
432
432
 
433
433
  def get_param_names(self) -> list[str]:
@@ -461,7 +461,7 @@ class AnyCollectionFilter(InAnyFilter[T]):
461
461
  array_expr = exp.Array(expressions=placeholder_expressions)
462
462
  result = statement.where(exp.EQ(this=exp.column(self.field_name), expression=exp.Any(this=array_expr)))
463
463
 
464
- for resolved_name, value in zip(resolved_names, self.values):
464
+ for resolved_name, value in zip(resolved_names, self.values, strict=False):
465
465
  result = result.add_named_parameter(resolved_name, value)
466
466
  return result
467
467
 
@@ -479,7 +479,7 @@ class NotAnyCollectionFilter(InAnyFilter[T]):
479
479
 
480
480
  __slots__ = ("_field_name", "_values")
481
481
 
482
- def __init__(self, field_name: str, values: Optional[abc.Collection[T]] = None) -> None:
482
+ def __init__(self, field_name: str, values: abc.Collection[T] | None = None) -> None:
483
483
  self._field_name = field_name
484
484
  self._values = values
485
485
 
@@ -488,7 +488,7 @@ class NotAnyCollectionFilter(InAnyFilter[T]):
488
488
  return self._field_name
489
489
 
490
490
  @property
491
- def values(self) -> Optional[abc.Collection[T]]:
491
+ def values(self) -> abc.Collection[T] | None:
492
492
  return self._values
493
493
 
494
494
  def get_param_names(self) -> list[str]:
@@ -520,7 +520,7 @@ class NotAnyCollectionFilter(InAnyFilter[T]):
520
520
  condition = exp.EQ(this=exp.column(self.field_name), expression=exp.Any(this=array_expr))
521
521
  result = statement.where(exp.Not(this=condition))
522
522
 
523
- for resolved_name, value in zip(resolved_names, self.values):
523
+ for resolved_name, value in zip(resolved_names, self.values, strict=False):
524
524
  result = result.add_named_parameter(resolved_name, value)
525
525
  return result
526
526
 
@@ -650,13 +650,13 @@ class SearchFilter(StatementFilter):
650
650
 
651
651
  __slots__ = ("_field_name", "_ignore_case", "_value")
652
652
 
653
- def __init__(self, field_name: Union[str, set[str]], value: str, ignore_case: Optional[bool] = False) -> None:
653
+ def __init__(self, field_name: str | set[str], value: str, ignore_case: bool | None = False) -> None:
654
654
  self._field_name = field_name
655
655
  self._value = value
656
656
  self._ignore_case = ignore_case
657
657
 
658
658
  @property
659
- def field_name(self) -> Union[str, set[str]]:
659
+ def field_name(self) -> str | set[str]:
660
660
  return self._field_name
661
661
 
662
662
  @property
@@ -664,10 +664,10 @@ class SearchFilter(StatementFilter):
664
664
  return self._value
665
665
 
666
666
  @property
667
- def ignore_case(self) -> Optional[bool]:
667
+ def ignore_case(self) -> bool | None:
668
668
  return self._ignore_case
669
669
 
670
- def get_param_name(self) -> Optional[str]:
670
+ def get_param_name(self) -> str | None:
671
671
  """Get parameter name without storing it."""
672
672
  if not self.value:
673
673
  return None
@@ -726,7 +726,7 @@ class NotInSearchFilter(SearchFilter):
726
726
  Constructs WHERE field_name NOT LIKE '%value%' clauses.
727
727
  """
728
728
 
729
- def get_param_name(self) -> Optional[str]:
729
+ def get_param_name(self) -> str | None:
730
730
  """Get parameter name without storing it."""
731
731
  if not self.value:
732
732
  return None
@@ -817,18 +817,18 @@ def apply_filter(statement: "SQL", filter_obj: StatementFilter) -> "SQL":
817
817
  return filter_obj.append_to_statement(statement)
818
818
 
819
819
 
820
- FilterTypes: TypeAlias = Union[
821
- BeforeAfterFilter,
822
- OnBeforeAfterFilter,
823
- InCollectionFilter[Any],
824
- LimitOffsetFilter,
825
- OrderByFilter,
826
- SearchFilter,
827
- NotInCollectionFilter[Any],
828
- NotInSearchFilter,
829
- AnyCollectionFilter[Any],
830
- NotAnyCollectionFilter[Any],
831
- ]
820
+ FilterTypes: TypeAlias = (
821
+ BeforeAfterFilter
822
+ | OnBeforeAfterFilter
823
+ | InCollectionFilter[Any]
824
+ | LimitOffsetFilter
825
+ | OrderByFilter
826
+ | SearchFilter
827
+ | NotInCollectionFilter[Any]
828
+ | NotInSearchFilter
829
+ | AnyCollectionFilter[Any]
830
+ | NotAnyCollectionFilter[Any]
831
+ )
832
832
 
833
833
 
834
834
  def create_filters(filters: "list[StatementFilter]") -> tuple["StatementFilter", ...]:
sqlspec/core/hashing.py CHANGED
@@ -4,7 +4,7 @@ Provides hashing functions for SQL statements, expressions, parameters,
4
4
  filters, and AST sub-expressions.
5
5
  """
6
6
 
7
- from typing import TYPE_CHECKING, Any, Optional
7
+ from typing import TYPE_CHECKING, Any
8
8
 
9
9
  from sqlglot import exp
10
10
 
@@ -23,7 +23,7 @@ __all__ = (
23
23
  )
24
24
 
25
25
 
26
- def hash_expression(expr: Optional[exp.Expression], _seen: Optional[set[int]] = None) -> int:
26
+ def hash_expression(expr: exp.Expression | None, _seen: set[int] | None = None) -> int:
27
27
  """Generate hash from AST structure.
28
28
 
29
29
  Args:
@@ -77,9 +77,9 @@ def _hash_value(value: Any, _seen: set[int]) -> int:
77
77
 
78
78
 
79
79
  def hash_parameters(
80
- positional_parameters: Optional[list[Any]] = None,
81
- named_parameters: Optional[dict[str, Any]] = None,
82
- original_parameters: Optional[Any] = None,
80
+ positional_parameters: list[Any] | None = None,
81
+ named_parameters: dict[str, Any] | None = None,
82
+ original_parameters: Any | None = None,
83
83
  ) -> int:
84
84
  """Generate hash for SQL parameters.
85
85
 
@@ -148,7 +148,7 @@ def _hash_filter_value(value: Any) -> int:
148
148
  return hash(repr(value))
149
149
 
150
150
 
151
- def hash_filters(filters: Optional[list["StatementFilter"]] = None) -> int:
151
+ def hash_filters(filters: list["StatementFilter"] | None = None) -> int:
152
152
  """Generate hash for statement filters.
153
153
 
154
154
  Args:
@@ -208,7 +208,7 @@ def hash_sql_statement(statement: "SQL") -> str:
208
208
  return f"sql:{hash(tuple(state_components))}"
209
209
 
210
210
 
211
- def hash_expression_node(node: exp.Expression, include_children: bool = True, dialect: Optional[str] = None) -> str:
211
+ def hash_expression_node(node: exp.Expression, include_children: bool = True, dialect: str | None = None) -> str:
212
212
  """Generate cache key for an expression node.
213
213
 
214
214
  Args:
@@ -235,8 +235,8 @@ def hash_expression_node(node: exp.Expression, include_children: bool = True, di
235
235
  def hash_optimized_expression(
236
236
  expr: exp.Expression,
237
237
  dialect: str,
238
- schema: Optional[dict[str, Any]] = None,
239
- optimizer_settings: Optional[dict[str, Any]] = None,
238
+ schema: dict[str, Any] | None = None,
239
+ optimizer_settings: dict[str, Any] | None = None,
240
240
  ) -> str:
241
241
  """Generate cache key for optimized expressions.
242
242