sqlspec 0.25.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 (199) hide show
  1. sqlspec/__init__.py +7 -15
  2. sqlspec/_serialization.py +256 -24
  3. sqlspec/_typing.py +71 -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 +69 -12
  8. sqlspec/adapters/adbc/data_dictionary.py +340 -0
  9. sqlspec/adapters/adbc/driver.py +266 -58
  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 +153 -0
  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 +88 -15
  17. sqlspec/adapters/aiosqlite/data_dictionary.py +149 -0
  18. sqlspec/adapters/aiosqlite/driver.py +143 -40
  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 +2 -2
  24. sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
  25. sqlspec/adapters/asyncmy/adk/store.py +493 -0
  26. sqlspec/adapters/asyncmy/config.py +68 -23
  27. sqlspec/adapters/asyncmy/data_dictionary.py +161 -0
  28. sqlspec/adapters/asyncmy/driver.py +313 -58
  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 +59 -35
  37. sqlspec/adapters/asyncpg/data_dictionary.py +173 -0
  38. sqlspec/adapters/asyncpg/driver.py +170 -25
  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 +27 -10
  45. sqlspec/adapters/bigquery/data_dictionary.py +149 -0
  46. sqlspec/adapters/bigquery/driver.py +368 -142
  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 +125 -0
  50. sqlspec/adapters/duckdb/_types.py +1 -1
  51. sqlspec/adapters/duckdb/adk/__init__.py +14 -0
  52. sqlspec/adapters/duckdb/adk/store.py +553 -0
  53. sqlspec/adapters/duckdb/config.py +80 -20
  54. sqlspec/adapters/duckdb/data_dictionary.py +163 -0
  55. sqlspec/adapters/duckdb/driver.py +167 -45
  56. sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
  57. sqlspec/adapters/duckdb/litestar/store.py +332 -0
  58. sqlspec/adapters/duckdb/pool.py +4 -4
  59. sqlspec/adapters/duckdb/type_converter.py +133 -0
  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 +122 -32
  65. sqlspec/adapters/oracledb/data_dictionary.py +509 -0
  66. sqlspec/adapters/oracledb/driver.py +353 -91
  67. sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
  68. sqlspec/adapters/oracledb/litestar/store.py +767 -0
  69. sqlspec/adapters/oracledb/migrations.py +348 -73
  70. sqlspec/adapters/oracledb/type_converter.py +207 -0
  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 +46 -17
  76. sqlspec/adapters/psqlpy/data_dictionary.py +172 -0
  77. sqlspec/adapters/psqlpy/driver.py +123 -209
  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 +102 -0
  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 +69 -35
  86. sqlspec/adapters/psycopg/data_dictionary.py +331 -0
  87. sqlspec/adapters/psycopg/driver.py +238 -81
  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 +87 -15
  96. sqlspec/adapters/sqlite/data_dictionary.py +149 -0
  97. sqlspec/adapters/sqlite/driver.py +137 -54
  98. sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
  99. sqlspec/adapters/sqlite/litestar/store.py +318 -0
  100. sqlspec/adapters/sqlite/pool.py +18 -9
  101. sqlspec/base.py +45 -26
  102. sqlspec/builder/__init__.py +73 -4
  103. sqlspec/builder/_base.py +162 -89
  104. sqlspec/builder/_column.py +62 -29
  105. sqlspec/builder/_ddl.py +180 -121
  106. sqlspec/builder/_delete.py +5 -4
  107. sqlspec/builder/_dml.py +388 -0
  108. sqlspec/{_sql.py → builder/_factory.py} +53 -94
  109. sqlspec/builder/_insert.py +32 -131
  110. sqlspec/builder/_join.py +375 -0
  111. sqlspec/builder/_merge.py +446 -11
  112. sqlspec/builder/_parsing_utils.py +111 -17
  113. sqlspec/builder/_select.py +1457 -24
  114. sqlspec/builder/_update.py +11 -42
  115. sqlspec/cli.py +307 -194
  116. sqlspec/config.py +252 -67
  117. sqlspec/core/__init__.py +5 -4
  118. sqlspec/core/cache.py +17 -17
  119. sqlspec/core/compiler.py +62 -9
  120. sqlspec/core/filters.py +37 -37
  121. sqlspec/core/hashing.py +9 -9
  122. sqlspec/core/parameters.py +83 -48
  123. sqlspec/core/result.py +102 -46
  124. sqlspec/core/splitter.py +16 -17
  125. sqlspec/core/statement.py +36 -30
  126. sqlspec/core/type_conversion.py +235 -0
  127. sqlspec/driver/__init__.py +7 -6
  128. sqlspec/driver/_async.py +188 -151
  129. sqlspec/driver/_common.py +285 -80
  130. sqlspec/driver/_sync.py +188 -152
  131. sqlspec/driver/mixins/_result_tools.py +20 -236
  132. sqlspec/driver/mixins/_sql_translator.py +4 -4
  133. sqlspec/exceptions.py +75 -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/__init__.py +4 -3
  153. sqlspec/migrations/base.py +302 -39
  154. sqlspec/migrations/commands.py +611 -144
  155. sqlspec/migrations/context.py +142 -0
  156. sqlspec/migrations/fix.py +199 -0
  157. sqlspec/migrations/loaders.py +68 -23
  158. sqlspec/migrations/runner.py +543 -107
  159. sqlspec/migrations/tracker.py +237 -21
  160. sqlspec/migrations/utils.py +51 -3
  161. sqlspec/migrations/validation.py +177 -0
  162. sqlspec/protocols.py +66 -36
  163. sqlspec/storage/_utils.py +98 -0
  164. sqlspec/storage/backends/fsspec.py +134 -106
  165. sqlspec/storage/backends/local.py +78 -51
  166. sqlspec/storage/backends/obstore.py +278 -162
  167. sqlspec/storage/registry.py +75 -39
  168. sqlspec/typing.py +16 -84
  169. sqlspec/utils/config_resolver.py +153 -0
  170. sqlspec/utils/correlation.py +4 -5
  171. sqlspec/utils/data_transformation.py +3 -2
  172. sqlspec/utils/deprecation.py +9 -8
  173. sqlspec/utils/fixtures.py +4 -4
  174. sqlspec/utils/logging.py +46 -6
  175. sqlspec/utils/module_loader.py +2 -2
  176. sqlspec/utils/schema.py +288 -0
  177. sqlspec/utils/serializers.py +50 -2
  178. sqlspec/utils/sync_tools.py +21 -17
  179. sqlspec/utils/text.py +1 -2
  180. sqlspec/utils/type_guards.py +111 -20
  181. sqlspec/utils/version.py +433 -0
  182. {sqlspec-0.25.0.dist-info → sqlspec-0.27.0.dist-info}/METADATA +40 -21
  183. sqlspec-0.27.0.dist-info/RECORD +207 -0
  184. sqlspec/builder/mixins/__init__.py +0 -55
  185. sqlspec/builder/mixins/_cte_and_set_ops.py +0 -254
  186. sqlspec/builder/mixins/_delete_operations.py +0 -50
  187. sqlspec/builder/mixins/_insert_operations.py +0 -282
  188. sqlspec/builder/mixins/_join_operations.py +0 -389
  189. sqlspec/builder/mixins/_merge_operations.py +0 -592
  190. sqlspec/builder/mixins/_order_limit_operations.py +0 -152
  191. sqlspec/builder/mixins/_pivot_operations.py +0 -157
  192. sqlspec/builder/mixins/_select_operations.py +0 -936
  193. sqlspec/builder/mixins/_update_operations.py +0 -218
  194. sqlspec/builder/mixins/_where_clause.py +0 -1304
  195. sqlspec-0.25.0.dist-info/RECORD +0 -139
  196. sqlspec-0.25.0.dist-info/licenses/NOTICE +0 -29
  197. {sqlspec-0.25.0.dist-info → sqlspec-0.27.0.dist-info}/WHEEL +0 -0
  198. {sqlspec-0.25.0.dist-info → sqlspec-0.27.0.dist-info}/entry_points.txt +0 -0
  199. {sqlspec-0.25.0.dist-info → sqlspec-0.27.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,207 @@
1
+ """Oracle-specific type conversion with LOB optimization.
2
+
3
+ Provides specialized type handling for Oracle databases, including
4
+ efficient LOB (Large Object) processing and JSON storage detection.
5
+ """
6
+
7
+ import array
8
+ import re
9
+ from datetime import datetime
10
+ from functools import lru_cache
11
+ from typing import Any, Final
12
+
13
+ from sqlspec.core.type_conversion import BaseTypeConverter
14
+ from sqlspec.typing import NUMPY_INSTALLED
15
+ from sqlspec.utils.sync_tools import ensure_async_
16
+
17
+ ORACLE_JSON_STORAGE_REGEX: Final[re.Pattern[str]] = re.compile(
18
+ r"^(?:"
19
+ r"(?P<json_type>JSON)|"
20
+ r"(?P<blob_oson>BLOB.*OSON)|"
21
+ r"(?P<blob_json>BLOB.*JSON)|"
22
+ r"(?P<clob_json>CLOB.*JSON)"
23
+ r")$",
24
+ re.IGNORECASE,
25
+ )
26
+
27
+ ORACLE_SPECIAL_CHARS: Final[frozenset[str]] = frozenset({"{", "[", "-", ":", "T", "."})
28
+
29
+
30
+ class OracleTypeConverter(BaseTypeConverter):
31
+ """Oracle-specific type conversion with LOB optimization.
32
+
33
+ Extends the base TypeDetector with Oracle-specific functionality
34
+ including streaming LOB support and JSON storage type detection.
35
+ Includes per-instance LRU cache for improved performance.
36
+ """
37
+
38
+ __slots__ = ("_convert_cache",)
39
+
40
+ def __init__(self, cache_size: int = 5000) -> None:
41
+ """Initialize converter with per-instance conversion cache.
42
+
43
+ Args:
44
+ cache_size: Maximum number of string values to cache (default: 5000)
45
+ """
46
+ super().__init__()
47
+
48
+ @lru_cache(maxsize=cache_size)
49
+ def _cached_convert(value: str) -> Any:
50
+ if not value or not any(c in value for c in ORACLE_SPECIAL_CHARS):
51
+ return value
52
+ detected_type = self.detect_type(value)
53
+ if detected_type:
54
+ return self.convert_value(value, detected_type)
55
+ return value
56
+
57
+ self._convert_cache = _cached_convert
58
+
59
+ def convert_if_detected(self, value: Any) -> Any:
60
+ """Convert string if special type detected (cached).
61
+
62
+ Args:
63
+ value: Value to potentially convert
64
+
65
+ Returns:
66
+ Converted value or original value
67
+ """
68
+ if not isinstance(value, str):
69
+ return value
70
+ return self._convert_cache(value)
71
+
72
+ async def process_lob(self, value: Any) -> Any:
73
+ """Process Oracle LOB objects efficiently.
74
+
75
+ Args:
76
+ value: Potential LOB object or regular value.
77
+
78
+ Returns:
79
+ LOB content if value is a LOB, original value otherwise.
80
+ """
81
+ if not hasattr(value, "read"):
82
+ return value
83
+
84
+ read_func = ensure_async_(value.read)
85
+ return await read_func()
86
+
87
+ def detect_json_storage_type(self, column_info: dict[str, Any]) -> bool:
88
+ """Detect if column stores JSON data.
89
+
90
+ Args:
91
+ column_info: Database column metadata.
92
+
93
+ Returns:
94
+ True if column is configured for JSON storage.
95
+ """
96
+ type_name = column_info.get("type_name", "").upper()
97
+ return bool(ORACLE_JSON_STORAGE_REGEX.match(type_name))
98
+
99
+ def format_datetime_for_oracle(self, dt: datetime) -> str:
100
+ """Format datetime for Oracle TO_DATE function.
101
+
102
+ Args:
103
+ dt: datetime object to format.
104
+
105
+ Returns:
106
+ Oracle TO_DATE SQL expression.
107
+ """
108
+ return f"TO_DATE('{dt.strftime('%Y-%m-%d %H:%M:%S')}', 'YYYY-MM-DD HH24:MI:SS')"
109
+
110
+ def handle_large_lob(self, lob_obj: Any, chunk_size: int = 1024 * 1024) -> bytes:
111
+ """Handle large LOB objects with streaming.
112
+
113
+ Args:
114
+ lob_obj: Oracle LOB object.
115
+ chunk_size: Size of chunks to read at a time.
116
+
117
+ Returns:
118
+ Complete LOB content as bytes.
119
+ """
120
+ if not hasattr(lob_obj, "read"):
121
+ return lob_obj if isinstance(lob_obj, bytes) else str(lob_obj).encode("utf-8")
122
+
123
+ chunks = []
124
+ while True:
125
+ chunk = lob_obj.read(chunk_size)
126
+ if not chunk:
127
+ break
128
+ chunks.append(chunk)
129
+
130
+ if not chunks:
131
+ return b""
132
+
133
+ return b"".join(chunks) if isinstance(chunks[0], bytes) else "".join(chunks).encode("utf-8")
134
+
135
+ def convert_oracle_value(self, value: Any, column_info: dict[str, Any]) -> Any:
136
+ """Convert Oracle-specific value with column context.
137
+
138
+ Args:
139
+ value: Value to convert.
140
+ column_info: Column metadata for context.
141
+
142
+ Returns:
143
+ Converted value appropriate for the column type.
144
+ """
145
+ if hasattr(value, "read"):
146
+ if self.detect_json_storage_type(column_info):
147
+ content = self.handle_large_lob(value)
148
+ content_str = content.decode("utf-8") if isinstance(content, bytes) else content
149
+ return self.convert_if_detected(content_str)
150
+ return self.handle_large_lob(value)
151
+
152
+ if isinstance(value, str):
153
+ return self.convert_if_detected(value)
154
+
155
+ return value
156
+
157
+ def convert_vector_to_numpy(self, value: Any) -> Any:
158
+ """Convert Oracle VECTOR to NumPy array.
159
+
160
+ Provides manual conversion API for users who need explicit control
161
+ over vector transformations or have disabled automatic handlers.
162
+
163
+ Args:
164
+ value: Oracle VECTOR value (array.array) or other value.
165
+
166
+ Returns:
167
+ NumPy ndarray if value is array.array and NumPy is installed,
168
+ otherwise original value.
169
+ """
170
+ if not NUMPY_INSTALLED:
171
+ return value
172
+
173
+ if isinstance(value, array.array):
174
+ from sqlspec.adapters.oracledb._numpy_handlers import numpy_converter_out
175
+
176
+ return numpy_converter_out(value)
177
+
178
+ return value
179
+
180
+ def convert_numpy_to_vector(self, value: Any) -> Any:
181
+ """Convert NumPy array to Oracle VECTOR format.
182
+
183
+ Provides manual conversion API for users who need explicit control
184
+ over vector transformations or have disabled automatic handlers.
185
+
186
+ Args:
187
+ value: NumPy ndarray or other value.
188
+
189
+ Returns:
190
+ array.array compatible with Oracle VECTOR if value is ndarray,
191
+ otherwise original value.
192
+
193
+ """
194
+ if not NUMPY_INSTALLED:
195
+ return value
196
+
197
+ import numpy as np
198
+
199
+ if isinstance(value, np.ndarray):
200
+ from sqlspec.adapters.oracledb._numpy_handlers import numpy_converter_in
201
+
202
+ return numpy_converter_in(value)
203
+
204
+ return value
205
+
206
+
207
+ __all__ = ("ORACLE_JSON_STORAGE_REGEX", "ORACLE_SPECIAL_CHARS", "OracleTypeConverter")
@@ -0,0 +1,44 @@
1
+ """Psqlpy pgvector type handlers for vector data type support.
2
+
3
+ Provides automatic conversion between NumPy arrays and PostgreSQL vector types
4
+ via pgvector-python library when integrated with psqlpy connection pool.
5
+
6
+ Note:
7
+ Full pgvector support for psqlpy is planned for a future release.
8
+ The driver_features infrastructure (enable_pgvector) has been implemented
9
+ to enable this feature when the underlying psqlpy library adds support for
10
+ custom type handlers on pool initialization.
11
+ """
12
+
13
+ import logging
14
+ from typing import TYPE_CHECKING
15
+
16
+ from sqlspec.typing import PGVECTOR_INSTALLED
17
+
18
+ if TYPE_CHECKING:
19
+ from psqlpy import Connection
20
+
21
+ __all__ = ("register_pgvector",)
22
+
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ def register_pgvector(connection: "Connection") -> None:
28
+ """Register pgvector type handlers on psqlpy connection.
29
+
30
+ Currently a placeholder for future implementation. The psqlpy library
31
+ does not yet expose a type handler registration API compatible with
32
+ pgvector's automatic conversion system.
33
+
34
+ Args:
35
+ connection: Psqlpy connection instance.
36
+
37
+ Note:
38
+ When psqlpy adds type handler support, this function will:
39
+ - Register pgvector extension on the connection
40
+ - Enable automatic NumPy array <-> PostgreSQL vector conversion
41
+ - Support vector similarity search operations
42
+ """
43
+ if not PGVECTOR_INSTALLED:
44
+ return
@@ -1,8 +1,9 @@
1
1
  from typing import TYPE_CHECKING
2
2
 
3
3
  if TYPE_CHECKING:
4
+ from typing import TypeAlias
5
+
4
6
  from psqlpy import Connection
5
- from typing_extensions import TypeAlias
6
7
 
7
8
  PsqlpyConnection: TypeAlias = Connection
8
9
  else:
@@ -0,0 +1,5 @@
1
+ """Psqlpy ADK store module."""
2
+
3
+ from sqlspec.adapters.psqlpy.adk.store import PsqlpyADKStore
4
+
5
+ __all__ = ("PsqlpyADKStore",)