sqlspec 0.36.0__cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (531) hide show
  1. ac8f31065839703b4e70__mypyc.cpython-310-aarch64-linux-gnu.so +0 -0
  2. sqlspec/__init__.py +140 -0
  3. sqlspec/__main__.py +12 -0
  4. sqlspec/__metadata__.py +14 -0
  5. sqlspec/_serialization.py +315 -0
  6. sqlspec/_typing.py +700 -0
  7. sqlspec/adapters/__init__.py +0 -0
  8. sqlspec/adapters/adbc/__init__.py +5 -0
  9. sqlspec/adapters/adbc/_typing.py +82 -0
  10. sqlspec/adapters/adbc/adk/__init__.py +5 -0
  11. sqlspec/adapters/adbc/adk/store.py +1273 -0
  12. sqlspec/adapters/adbc/config.py +295 -0
  13. sqlspec/adapters/adbc/core.cpython-310-aarch64-linux-gnu.so +0 -0
  14. sqlspec/adapters/adbc/core.py +735 -0
  15. sqlspec/adapters/adbc/data_dictionary.py +334 -0
  16. sqlspec/adapters/adbc/driver.py +529 -0
  17. sqlspec/adapters/adbc/events/__init__.py +5 -0
  18. sqlspec/adapters/adbc/events/store.py +285 -0
  19. sqlspec/adapters/adbc/litestar/__init__.py +5 -0
  20. sqlspec/adapters/adbc/litestar/store.py +502 -0
  21. sqlspec/adapters/adbc/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  22. sqlspec/adapters/adbc/type_converter.py +140 -0
  23. sqlspec/adapters/aiosqlite/__init__.py +25 -0
  24. sqlspec/adapters/aiosqlite/_typing.py +82 -0
  25. sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
  26. sqlspec/adapters/aiosqlite/adk/store.py +818 -0
  27. sqlspec/adapters/aiosqlite/config.py +334 -0
  28. sqlspec/adapters/aiosqlite/core.cpython-310-aarch64-linux-gnu.so +0 -0
  29. sqlspec/adapters/aiosqlite/core.py +315 -0
  30. sqlspec/adapters/aiosqlite/data_dictionary.py +208 -0
  31. sqlspec/adapters/aiosqlite/driver.py +313 -0
  32. sqlspec/adapters/aiosqlite/events/__init__.py +5 -0
  33. sqlspec/adapters/aiosqlite/events/store.py +20 -0
  34. sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
  35. sqlspec/adapters/aiosqlite/litestar/store.py +279 -0
  36. sqlspec/adapters/aiosqlite/pool.py +533 -0
  37. sqlspec/adapters/asyncmy/__init__.py +21 -0
  38. sqlspec/adapters/asyncmy/_typing.py +87 -0
  39. sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
  40. sqlspec/adapters/asyncmy/adk/store.py +703 -0
  41. sqlspec/adapters/asyncmy/config.py +302 -0
  42. sqlspec/adapters/asyncmy/core.cpython-310-aarch64-linux-gnu.so +0 -0
  43. sqlspec/adapters/asyncmy/core.py +360 -0
  44. sqlspec/adapters/asyncmy/data_dictionary.py +124 -0
  45. sqlspec/adapters/asyncmy/driver.py +383 -0
  46. sqlspec/adapters/asyncmy/events/__init__.py +5 -0
  47. sqlspec/adapters/asyncmy/events/store.py +104 -0
  48. sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
  49. sqlspec/adapters/asyncmy/litestar/store.py +296 -0
  50. sqlspec/adapters/asyncpg/__init__.py +19 -0
  51. sqlspec/adapters/asyncpg/_typing.py +88 -0
  52. sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
  53. sqlspec/adapters/asyncpg/adk/store.py +748 -0
  54. sqlspec/adapters/asyncpg/config.py +569 -0
  55. sqlspec/adapters/asyncpg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  56. sqlspec/adapters/asyncpg/core.py +367 -0
  57. sqlspec/adapters/asyncpg/data_dictionary.py +162 -0
  58. sqlspec/adapters/asyncpg/driver.py +487 -0
  59. sqlspec/adapters/asyncpg/events/__init__.py +6 -0
  60. sqlspec/adapters/asyncpg/events/backend.py +286 -0
  61. sqlspec/adapters/asyncpg/events/store.py +40 -0
  62. sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
  63. sqlspec/adapters/asyncpg/litestar/store.py +251 -0
  64. sqlspec/adapters/bigquery/__init__.py +14 -0
  65. sqlspec/adapters/bigquery/_typing.py +86 -0
  66. sqlspec/adapters/bigquery/adk/__init__.py +5 -0
  67. sqlspec/adapters/bigquery/adk/store.py +827 -0
  68. sqlspec/adapters/bigquery/config.py +353 -0
  69. sqlspec/adapters/bigquery/core.cpython-310-aarch64-linux-gnu.so +0 -0
  70. sqlspec/adapters/bigquery/core.py +715 -0
  71. sqlspec/adapters/bigquery/data_dictionary.py +128 -0
  72. sqlspec/adapters/bigquery/driver.py +548 -0
  73. sqlspec/adapters/bigquery/events/__init__.py +5 -0
  74. sqlspec/adapters/bigquery/events/store.py +139 -0
  75. sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
  76. sqlspec/adapters/bigquery/litestar/store.py +325 -0
  77. sqlspec/adapters/bigquery/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  78. sqlspec/adapters/bigquery/type_converter.py +107 -0
  79. sqlspec/adapters/cockroach_asyncpg/__init__.py +24 -0
  80. sqlspec/adapters/cockroach_asyncpg/_typing.py +72 -0
  81. sqlspec/adapters/cockroach_asyncpg/adk/__init__.py +3 -0
  82. sqlspec/adapters/cockroach_asyncpg/adk/store.py +410 -0
  83. sqlspec/adapters/cockroach_asyncpg/config.py +238 -0
  84. sqlspec/adapters/cockroach_asyncpg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  85. sqlspec/adapters/cockroach_asyncpg/core.py +55 -0
  86. sqlspec/adapters/cockroach_asyncpg/data_dictionary.py +107 -0
  87. sqlspec/adapters/cockroach_asyncpg/driver.py +144 -0
  88. sqlspec/adapters/cockroach_asyncpg/events/__init__.py +3 -0
  89. sqlspec/adapters/cockroach_asyncpg/events/store.py +20 -0
  90. sqlspec/adapters/cockroach_asyncpg/litestar/__init__.py +3 -0
  91. sqlspec/adapters/cockroach_asyncpg/litestar/store.py +142 -0
  92. sqlspec/adapters/cockroach_psycopg/__init__.py +38 -0
  93. sqlspec/adapters/cockroach_psycopg/_typing.py +129 -0
  94. sqlspec/adapters/cockroach_psycopg/adk/__init__.py +13 -0
  95. sqlspec/adapters/cockroach_psycopg/adk/store.py +868 -0
  96. sqlspec/adapters/cockroach_psycopg/config.py +484 -0
  97. sqlspec/adapters/cockroach_psycopg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  98. sqlspec/adapters/cockroach_psycopg/core.py +63 -0
  99. sqlspec/adapters/cockroach_psycopg/data_dictionary.py +215 -0
  100. sqlspec/adapters/cockroach_psycopg/driver.py +284 -0
  101. sqlspec/adapters/cockroach_psycopg/events/__init__.py +6 -0
  102. sqlspec/adapters/cockroach_psycopg/events/store.py +34 -0
  103. sqlspec/adapters/cockroach_psycopg/litestar/__init__.py +3 -0
  104. sqlspec/adapters/cockroach_psycopg/litestar/store.py +325 -0
  105. sqlspec/adapters/duckdb/__init__.py +25 -0
  106. sqlspec/adapters/duckdb/_typing.py +81 -0
  107. sqlspec/adapters/duckdb/adk/__init__.py +14 -0
  108. sqlspec/adapters/duckdb/adk/store.py +850 -0
  109. sqlspec/adapters/duckdb/config.py +463 -0
  110. sqlspec/adapters/duckdb/core.cpython-310-aarch64-linux-gnu.so +0 -0
  111. sqlspec/adapters/duckdb/core.py +257 -0
  112. sqlspec/adapters/duckdb/data_dictionary.py +140 -0
  113. sqlspec/adapters/duckdb/driver.py +430 -0
  114. sqlspec/adapters/duckdb/events/__init__.py +5 -0
  115. sqlspec/adapters/duckdb/events/store.py +57 -0
  116. sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
  117. sqlspec/adapters/duckdb/litestar/store.py +330 -0
  118. sqlspec/adapters/duckdb/pool.py +293 -0
  119. sqlspec/adapters/duckdb/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  120. sqlspec/adapters/duckdb/type_converter.py +118 -0
  121. sqlspec/adapters/mock/__init__.py +72 -0
  122. sqlspec/adapters/mock/_typing.py +147 -0
  123. sqlspec/adapters/mock/config.py +483 -0
  124. sqlspec/adapters/mock/core.py +319 -0
  125. sqlspec/adapters/mock/data_dictionary.py +366 -0
  126. sqlspec/adapters/mock/driver.py +721 -0
  127. sqlspec/adapters/mysqlconnector/__init__.py +36 -0
  128. sqlspec/adapters/mysqlconnector/_typing.py +141 -0
  129. sqlspec/adapters/mysqlconnector/adk/__init__.py +15 -0
  130. sqlspec/adapters/mysqlconnector/adk/store.py +1060 -0
  131. sqlspec/adapters/mysqlconnector/config.py +394 -0
  132. sqlspec/adapters/mysqlconnector/core.cpython-310-aarch64-linux-gnu.so +0 -0
  133. sqlspec/adapters/mysqlconnector/core.py +303 -0
  134. sqlspec/adapters/mysqlconnector/data_dictionary.py +235 -0
  135. sqlspec/adapters/mysqlconnector/driver.py +483 -0
  136. sqlspec/adapters/mysqlconnector/events/__init__.py +8 -0
  137. sqlspec/adapters/mysqlconnector/events/store.py +98 -0
  138. sqlspec/adapters/mysqlconnector/litestar/__init__.py +5 -0
  139. sqlspec/adapters/mysqlconnector/litestar/store.py +426 -0
  140. sqlspec/adapters/oracledb/__init__.py +60 -0
  141. sqlspec/adapters/oracledb/_numpy_handlers.py +141 -0
  142. sqlspec/adapters/oracledb/_typing.py +182 -0
  143. sqlspec/adapters/oracledb/_uuid_handlers.py +166 -0
  144. sqlspec/adapters/oracledb/adk/__init__.py +10 -0
  145. sqlspec/adapters/oracledb/adk/store.py +2369 -0
  146. sqlspec/adapters/oracledb/config.py +550 -0
  147. sqlspec/adapters/oracledb/core.cpython-310-aarch64-linux-gnu.so +0 -0
  148. sqlspec/adapters/oracledb/core.py +543 -0
  149. sqlspec/adapters/oracledb/data_dictionary.py +536 -0
  150. sqlspec/adapters/oracledb/driver.py +1229 -0
  151. sqlspec/adapters/oracledb/events/__init__.py +16 -0
  152. sqlspec/adapters/oracledb/events/backend.py +347 -0
  153. sqlspec/adapters/oracledb/events/store.py +420 -0
  154. sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
  155. sqlspec/adapters/oracledb/litestar/store.py +781 -0
  156. sqlspec/adapters/oracledb/migrations.py +535 -0
  157. sqlspec/adapters/oracledb/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  158. sqlspec/adapters/oracledb/type_converter.py +211 -0
  159. sqlspec/adapters/psqlpy/__init__.py +17 -0
  160. sqlspec/adapters/psqlpy/_typing.py +79 -0
  161. sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
  162. sqlspec/adapters/psqlpy/adk/store.py +766 -0
  163. sqlspec/adapters/psqlpy/config.py +304 -0
  164. sqlspec/adapters/psqlpy/core.cpython-310-aarch64-linux-gnu.so +0 -0
  165. sqlspec/adapters/psqlpy/core.py +480 -0
  166. sqlspec/adapters/psqlpy/data_dictionary.py +126 -0
  167. sqlspec/adapters/psqlpy/driver.py +438 -0
  168. sqlspec/adapters/psqlpy/events/__init__.py +6 -0
  169. sqlspec/adapters/psqlpy/events/backend.py +310 -0
  170. sqlspec/adapters/psqlpy/events/store.py +20 -0
  171. sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
  172. sqlspec/adapters/psqlpy/litestar/store.py +270 -0
  173. sqlspec/adapters/psqlpy/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  174. sqlspec/adapters/psqlpy/type_converter.py +113 -0
  175. sqlspec/adapters/psycopg/__init__.py +32 -0
  176. sqlspec/adapters/psycopg/_typing.py +164 -0
  177. sqlspec/adapters/psycopg/adk/__init__.py +10 -0
  178. sqlspec/adapters/psycopg/adk/store.py +1387 -0
  179. sqlspec/adapters/psycopg/config.py +576 -0
  180. sqlspec/adapters/psycopg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  181. sqlspec/adapters/psycopg/core.py +450 -0
  182. sqlspec/adapters/psycopg/data_dictionary.py +289 -0
  183. sqlspec/adapters/psycopg/driver.py +975 -0
  184. sqlspec/adapters/psycopg/events/__init__.py +20 -0
  185. sqlspec/adapters/psycopg/events/backend.py +458 -0
  186. sqlspec/adapters/psycopg/events/store.py +42 -0
  187. sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
  188. sqlspec/adapters/psycopg/litestar/store.py +552 -0
  189. sqlspec/adapters/psycopg/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  190. sqlspec/adapters/psycopg/type_converter.py +93 -0
  191. sqlspec/adapters/pymysql/__init__.py +21 -0
  192. sqlspec/adapters/pymysql/_typing.py +71 -0
  193. sqlspec/adapters/pymysql/adk/__init__.py +5 -0
  194. sqlspec/adapters/pymysql/adk/store.py +540 -0
  195. sqlspec/adapters/pymysql/config.py +195 -0
  196. sqlspec/adapters/pymysql/core.cpython-310-aarch64-linux-gnu.so +0 -0
  197. sqlspec/adapters/pymysql/core.py +299 -0
  198. sqlspec/adapters/pymysql/data_dictionary.py +122 -0
  199. sqlspec/adapters/pymysql/driver.py +259 -0
  200. sqlspec/adapters/pymysql/events/__init__.py +5 -0
  201. sqlspec/adapters/pymysql/events/store.py +50 -0
  202. sqlspec/adapters/pymysql/litestar/__init__.py +5 -0
  203. sqlspec/adapters/pymysql/litestar/store.py +232 -0
  204. sqlspec/adapters/pymysql/pool.py +137 -0
  205. sqlspec/adapters/spanner/__init__.py +40 -0
  206. sqlspec/adapters/spanner/_typing.py +86 -0
  207. sqlspec/adapters/spanner/adk/__init__.py +5 -0
  208. sqlspec/adapters/spanner/adk/store.py +732 -0
  209. sqlspec/adapters/spanner/config.py +352 -0
  210. sqlspec/adapters/spanner/core.cpython-310-aarch64-linux-gnu.so +0 -0
  211. sqlspec/adapters/spanner/core.py +188 -0
  212. sqlspec/adapters/spanner/data_dictionary.py +120 -0
  213. sqlspec/adapters/spanner/dialect/__init__.py +6 -0
  214. sqlspec/adapters/spanner/dialect/_spangres.py +57 -0
  215. sqlspec/adapters/spanner/dialect/_spanner.py +130 -0
  216. sqlspec/adapters/spanner/driver.py +373 -0
  217. sqlspec/adapters/spanner/events/__init__.py +5 -0
  218. sqlspec/adapters/spanner/events/store.py +187 -0
  219. sqlspec/adapters/spanner/litestar/__init__.py +5 -0
  220. sqlspec/adapters/spanner/litestar/store.py +291 -0
  221. sqlspec/adapters/spanner/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  222. sqlspec/adapters/spanner/type_converter.py +331 -0
  223. sqlspec/adapters/sqlite/__init__.py +19 -0
  224. sqlspec/adapters/sqlite/_typing.py +80 -0
  225. sqlspec/adapters/sqlite/adk/__init__.py +5 -0
  226. sqlspec/adapters/sqlite/adk/store.py +958 -0
  227. sqlspec/adapters/sqlite/config.py +280 -0
  228. sqlspec/adapters/sqlite/core.cpython-310-aarch64-linux-gnu.so +0 -0
  229. sqlspec/adapters/sqlite/core.py +312 -0
  230. sqlspec/adapters/sqlite/data_dictionary.py +202 -0
  231. sqlspec/adapters/sqlite/driver.py +359 -0
  232. sqlspec/adapters/sqlite/events/__init__.py +5 -0
  233. sqlspec/adapters/sqlite/events/store.py +20 -0
  234. sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
  235. sqlspec/adapters/sqlite/litestar/store.py +316 -0
  236. sqlspec/adapters/sqlite/pool.py +198 -0
  237. sqlspec/adapters/sqlite/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  238. sqlspec/adapters/sqlite/type_converter.py +114 -0
  239. sqlspec/base.py +747 -0
  240. sqlspec/builder/__init__.py +179 -0
  241. sqlspec/builder/_base.cpython-310-aarch64-linux-gnu.so +0 -0
  242. sqlspec/builder/_base.py +1022 -0
  243. sqlspec/builder/_column.cpython-310-aarch64-linux-gnu.so +0 -0
  244. sqlspec/builder/_column.py +521 -0
  245. sqlspec/builder/_ddl.cpython-310-aarch64-linux-gnu.so +0 -0
  246. sqlspec/builder/_ddl.py +1642 -0
  247. sqlspec/builder/_delete.cpython-310-aarch64-linux-gnu.so +0 -0
  248. sqlspec/builder/_delete.py +95 -0
  249. sqlspec/builder/_dml.cpython-310-aarch64-linux-gnu.so +0 -0
  250. sqlspec/builder/_dml.py +365 -0
  251. sqlspec/builder/_explain.cpython-310-aarch64-linux-gnu.so +0 -0
  252. sqlspec/builder/_explain.py +579 -0
  253. sqlspec/builder/_expression_wrappers.cpython-310-aarch64-linux-gnu.so +0 -0
  254. sqlspec/builder/_expression_wrappers.py +46 -0
  255. sqlspec/builder/_factory.cpython-310-aarch64-linux-gnu.so +0 -0
  256. sqlspec/builder/_factory.py +1697 -0
  257. sqlspec/builder/_insert.cpython-310-aarch64-linux-gnu.so +0 -0
  258. sqlspec/builder/_insert.py +328 -0
  259. sqlspec/builder/_join.cpython-310-aarch64-linux-gnu.so +0 -0
  260. sqlspec/builder/_join.py +499 -0
  261. sqlspec/builder/_merge.cpython-310-aarch64-linux-gnu.so +0 -0
  262. sqlspec/builder/_merge.py +821 -0
  263. sqlspec/builder/_parsing_utils.cpython-310-aarch64-linux-gnu.so +0 -0
  264. sqlspec/builder/_parsing_utils.py +297 -0
  265. sqlspec/builder/_select.cpython-310-aarch64-linux-gnu.so +0 -0
  266. sqlspec/builder/_select.py +1660 -0
  267. sqlspec/builder/_temporal.cpython-310-aarch64-linux-gnu.so +0 -0
  268. sqlspec/builder/_temporal.py +139 -0
  269. sqlspec/builder/_update.cpython-310-aarch64-linux-gnu.so +0 -0
  270. sqlspec/builder/_update.py +173 -0
  271. sqlspec/builder/_vector_expressions.py +267 -0
  272. sqlspec/cli.py +911 -0
  273. sqlspec/config.py +1755 -0
  274. sqlspec/core/__init__.py +374 -0
  275. sqlspec/core/_correlation.cpython-310-aarch64-linux-gnu.so +0 -0
  276. sqlspec/core/_correlation.py +176 -0
  277. sqlspec/core/cache.cpython-310-aarch64-linux-gnu.so +0 -0
  278. sqlspec/core/cache.py +1069 -0
  279. sqlspec/core/compiler.cpython-310-aarch64-linux-gnu.so +0 -0
  280. sqlspec/core/compiler.py +954 -0
  281. sqlspec/core/explain.cpython-310-aarch64-linux-gnu.so +0 -0
  282. sqlspec/core/explain.py +275 -0
  283. sqlspec/core/filters.cpython-310-aarch64-linux-gnu.so +0 -0
  284. sqlspec/core/filters.py +952 -0
  285. sqlspec/core/hashing.cpython-310-aarch64-linux-gnu.so +0 -0
  286. sqlspec/core/hashing.py +262 -0
  287. sqlspec/core/metrics.cpython-310-aarch64-linux-gnu.so +0 -0
  288. sqlspec/core/metrics.py +83 -0
  289. sqlspec/core/parameters/__init__.py +71 -0
  290. sqlspec/core/parameters/_alignment.cpython-310-aarch64-linux-gnu.so +0 -0
  291. sqlspec/core/parameters/_alignment.py +270 -0
  292. sqlspec/core/parameters/_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  293. sqlspec/core/parameters/_converter.py +543 -0
  294. sqlspec/core/parameters/_processor.cpython-310-aarch64-linux-gnu.so +0 -0
  295. sqlspec/core/parameters/_processor.py +505 -0
  296. sqlspec/core/parameters/_registry.cpython-310-aarch64-linux-gnu.so +0 -0
  297. sqlspec/core/parameters/_registry.py +206 -0
  298. sqlspec/core/parameters/_transformers.cpython-310-aarch64-linux-gnu.so +0 -0
  299. sqlspec/core/parameters/_transformers.py +292 -0
  300. sqlspec/core/parameters/_types.cpython-310-aarch64-linux-gnu.so +0 -0
  301. sqlspec/core/parameters/_types.py +499 -0
  302. sqlspec/core/parameters/_validator.cpython-310-aarch64-linux-gnu.so +0 -0
  303. sqlspec/core/parameters/_validator.py +180 -0
  304. sqlspec/core/pipeline.cpython-310-aarch64-linux-gnu.so +0 -0
  305. sqlspec/core/pipeline.py +319 -0
  306. sqlspec/core/query_modifiers.cpython-310-aarch64-linux-gnu.so +0 -0
  307. sqlspec/core/query_modifiers.py +437 -0
  308. sqlspec/core/result/__init__.py +23 -0
  309. sqlspec/core/result/_base.cpython-310-aarch64-linux-gnu.so +0 -0
  310. sqlspec/core/result/_base.py +1121 -0
  311. sqlspec/core/result/_io.cpython-310-aarch64-linux-gnu.so +0 -0
  312. sqlspec/core/result/_io.py +28 -0
  313. sqlspec/core/splitter.cpython-310-aarch64-linux-gnu.so +0 -0
  314. sqlspec/core/splitter.py +966 -0
  315. sqlspec/core/stack.cpython-310-aarch64-linux-gnu.so +0 -0
  316. sqlspec/core/stack.py +163 -0
  317. sqlspec/core/statement.cpython-310-aarch64-linux-gnu.so +0 -0
  318. sqlspec/core/statement.py +1503 -0
  319. sqlspec/core/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  320. sqlspec/core/type_converter.py +339 -0
  321. sqlspec/data_dictionary/__init__.py +22 -0
  322. sqlspec/data_dictionary/_loader.py +123 -0
  323. sqlspec/data_dictionary/_registry.cpython-310-aarch64-linux-gnu.so +0 -0
  324. sqlspec/data_dictionary/_registry.py +74 -0
  325. sqlspec/data_dictionary/_types.cpython-310-aarch64-linux-gnu.so +0 -0
  326. sqlspec/data_dictionary/_types.py +121 -0
  327. sqlspec/data_dictionary/dialects/__init__.py +21 -0
  328. sqlspec/data_dictionary/dialects/bigquery.cpython-310-aarch64-linux-gnu.so +0 -0
  329. sqlspec/data_dictionary/dialects/bigquery.py +49 -0
  330. sqlspec/data_dictionary/dialects/cockroachdb.cpython-310-aarch64-linux-gnu.so +0 -0
  331. sqlspec/data_dictionary/dialects/cockroachdb.py +43 -0
  332. sqlspec/data_dictionary/dialects/duckdb.cpython-310-aarch64-linux-gnu.so +0 -0
  333. sqlspec/data_dictionary/dialects/duckdb.py +47 -0
  334. sqlspec/data_dictionary/dialects/mysql.cpython-310-aarch64-linux-gnu.so +0 -0
  335. sqlspec/data_dictionary/dialects/mysql.py +42 -0
  336. sqlspec/data_dictionary/dialects/oracle.cpython-310-aarch64-linux-gnu.so +0 -0
  337. sqlspec/data_dictionary/dialects/oracle.py +34 -0
  338. sqlspec/data_dictionary/dialects/postgres.cpython-310-aarch64-linux-gnu.so +0 -0
  339. sqlspec/data_dictionary/dialects/postgres.py +46 -0
  340. sqlspec/data_dictionary/dialects/spanner.cpython-310-aarch64-linux-gnu.so +0 -0
  341. sqlspec/data_dictionary/dialects/spanner.py +37 -0
  342. sqlspec/data_dictionary/dialects/sqlite.cpython-310-aarch64-linux-gnu.so +0 -0
  343. sqlspec/data_dictionary/dialects/sqlite.py +42 -0
  344. sqlspec/data_dictionary/sql/.gitkeep +0 -0
  345. sqlspec/data_dictionary/sql/bigquery/columns.sql +23 -0
  346. sqlspec/data_dictionary/sql/bigquery/foreign_keys.sql +34 -0
  347. sqlspec/data_dictionary/sql/bigquery/indexes.sql +19 -0
  348. sqlspec/data_dictionary/sql/bigquery/tables.sql +33 -0
  349. sqlspec/data_dictionary/sql/bigquery/version.sql +3 -0
  350. sqlspec/data_dictionary/sql/cockroachdb/columns.sql +34 -0
  351. sqlspec/data_dictionary/sql/cockroachdb/foreign_keys.sql +40 -0
  352. sqlspec/data_dictionary/sql/cockroachdb/indexes.sql +32 -0
  353. sqlspec/data_dictionary/sql/cockroachdb/tables.sql +44 -0
  354. sqlspec/data_dictionary/sql/cockroachdb/version.sql +3 -0
  355. sqlspec/data_dictionary/sql/duckdb/columns.sql +23 -0
  356. sqlspec/data_dictionary/sql/duckdb/foreign_keys.sql +36 -0
  357. sqlspec/data_dictionary/sql/duckdb/indexes.sql +19 -0
  358. sqlspec/data_dictionary/sql/duckdb/tables.sql +38 -0
  359. sqlspec/data_dictionary/sql/duckdb/version.sql +3 -0
  360. sqlspec/data_dictionary/sql/mysql/columns.sql +23 -0
  361. sqlspec/data_dictionary/sql/mysql/foreign_keys.sql +28 -0
  362. sqlspec/data_dictionary/sql/mysql/indexes.sql +26 -0
  363. sqlspec/data_dictionary/sql/mysql/tables.sql +33 -0
  364. sqlspec/data_dictionary/sql/mysql/version.sql +3 -0
  365. sqlspec/data_dictionary/sql/oracle/columns.sql +23 -0
  366. sqlspec/data_dictionary/sql/oracle/foreign_keys.sql +48 -0
  367. sqlspec/data_dictionary/sql/oracle/indexes.sql +44 -0
  368. sqlspec/data_dictionary/sql/oracle/tables.sql +25 -0
  369. sqlspec/data_dictionary/sql/oracle/version.sql +20 -0
  370. sqlspec/data_dictionary/sql/postgres/columns.sql +34 -0
  371. sqlspec/data_dictionary/sql/postgres/foreign_keys.sql +40 -0
  372. sqlspec/data_dictionary/sql/postgres/indexes.sql +56 -0
  373. sqlspec/data_dictionary/sql/postgres/tables.sql +44 -0
  374. sqlspec/data_dictionary/sql/postgres/version.sql +3 -0
  375. sqlspec/data_dictionary/sql/spanner/columns.sql +23 -0
  376. sqlspec/data_dictionary/sql/spanner/foreign_keys.sql +70 -0
  377. sqlspec/data_dictionary/sql/spanner/indexes.sql +30 -0
  378. sqlspec/data_dictionary/sql/spanner/tables.sql +9 -0
  379. sqlspec/data_dictionary/sql/spanner/version.sql +3 -0
  380. sqlspec/data_dictionary/sql/sqlite/columns.sql +23 -0
  381. sqlspec/data_dictionary/sql/sqlite/foreign_keys.sql +22 -0
  382. sqlspec/data_dictionary/sql/sqlite/indexes.sql +7 -0
  383. sqlspec/data_dictionary/sql/sqlite/tables.sql +28 -0
  384. sqlspec/data_dictionary/sql/sqlite/version.sql +3 -0
  385. sqlspec/driver/__init__.py +32 -0
  386. sqlspec/driver/_async.cpython-310-aarch64-linux-gnu.so +0 -0
  387. sqlspec/driver/_async.py +1737 -0
  388. sqlspec/driver/_common.cpython-310-aarch64-linux-gnu.so +0 -0
  389. sqlspec/driver/_common.py +1478 -0
  390. sqlspec/driver/_sql_helpers.cpython-310-aarch64-linux-gnu.so +0 -0
  391. sqlspec/driver/_sql_helpers.py +148 -0
  392. sqlspec/driver/_storage_helpers.cpython-310-aarch64-linux-gnu.so +0 -0
  393. sqlspec/driver/_storage_helpers.py +144 -0
  394. sqlspec/driver/_sync.cpython-310-aarch64-linux-gnu.so +0 -0
  395. sqlspec/driver/_sync.py +1710 -0
  396. sqlspec/exceptions.py +338 -0
  397. sqlspec/extensions/__init__.py +0 -0
  398. sqlspec/extensions/adk/__init__.py +70 -0
  399. sqlspec/extensions/adk/_types.py +51 -0
  400. sqlspec/extensions/adk/converters.py +172 -0
  401. sqlspec/extensions/adk/memory/__init__.py +69 -0
  402. sqlspec/extensions/adk/memory/_types.py +30 -0
  403. sqlspec/extensions/adk/memory/converters.py +149 -0
  404. sqlspec/extensions/adk/memory/service.py +217 -0
  405. sqlspec/extensions/adk/memory/store.py +569 -0
  406. sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +246 -0
  407. sqlspec/extensions/adk/migrations/__init__.py +0 -0
  408. sqlspec/extensions/adk/service.py +225 -0
  409. sqlspec/extensions/adk/store.py +567 -0
  410. sqlspec/extensions/events/__init__.py +51 -0
  411. sqlspec/extensions/events/_channel.py +703 -0
  412. sqlspec/extensions/events/_hints.py +45 -0
  413. sqlspec/extensions/events/_models.py +23 -0
  414. sqlspec/extensions/events/_payload.py +69 -0
  415. sqlspec/extensions/events/_protocols.py +134 -0
  416. sqlspec/extensions/events/_queue.py +461 -0
  417. sqlspec/extensions/events/_store.py +209 -0
  418. sqlspec/extensions/events/migrations/0001_create_event_queue.py +59 -0
  419. sqlspec/extensions/events/migrations/__init__.py +3 -0
  420. sqlspec/extensions/fastapi/__init__.py +19 -0
  421. sqlspec/extensions/fastapi/extension.py +351 -0
  422. sqlspec/extensions/fastapi/providers.py +607 -0
  423. sqlspec/extensions/flask/__init__.py +37 -0
  424. sqlspec/extensions/flask/_state.py +76 -0
  425. sqlspec/extensions/flask/_utils.py +71 -0
  426. sqlspec/extensions/flask/extension.py +519 -0
  427. sqlspec/extensions/litestar/__init__.py +28 -0
  428. sqlspec/extensions/litestar/_utils.py +52 -0
  429. sqlspec/extensions/litestar/channels.py +165 -0
  430. sqlspec/extensions/litestar/cli.py +102 -0
  431. sqlspec/extensions/litestar/config.py +90 -0
  432. sqlspec/extensions/litestar/handlers.py +316 -0
  433. sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
  434. sqlspec/extensions/litestar/migrations/__init__.py +3 -0
  435. sqlspec/extensions/litestar/plugin.py +671 -0
  436. sqlspec/extensions/litestar/providers.py +526 -0
  437. sqlspec/extensions/litestar/store.py +296 -0
  438. sqlspec/extensions/otel/__init__.py +58 -0
  439. sqlspec/extensions/prometheus/__init__.py +113 -0
  440. sqlspec/extensions/starlette/__init__.py +19 -0
  441. sqlspec/extensions/starlette/_state.py +30 -0
  442. sqlspec/extensions/starlette/_utils.py +96 -0
  443. sqlspec/extensions/starlette/extension.py +346 -0
  444. sqlspec/extensions/starlette/middleware.py +235 -0
  445. sqlspec/loader.cpython-310-aarch64-linux-gnu.so +0 -0
  446. sqlspec/loader.py +702 -0
  447. sqlspec/migrations/__init__.py +36 -0
  448. sqlspec/migrations/base.py +731 -0
  449. sqlspec/migrations/commands.py +1232 -0
  450. sqlspec/migrations/context.py +157 -0
  451. sqlspec/migrations/fix.py +204 -0
  452. sqlspec/migrations/loaders.py +443 -0
  453. sqlspec/migrations/runner.py +1172 -0
  454. sqlspec/migrations/templates.py +234 -0
  455. sqlspec/migrations/tracker.py +611 -0
  456. sqlspec/migrations/utils.py +256 -0
  457. sqlspec/migrations/validation.py +207 -0
  458. sqlspec/migrations/version.py +446 -0
  459. sqlspec/observability/__init__.py +55 -0
  460. sqlspec/observability/_common.cpython-310-aarch64-linux-gnu.so +0 -0
  461. sqlspec/observability/_common.py +77 -0
  462. sqlspec/observability/_config.cpython-310-aarch64-linux-gnu.so +0 -0
  463. sqlspec/observability/_config.py +348 -0
  464. sqlspec/observability/_diagnostics.cpython-310-aarch64-linux-gnu.so +0 -0
  465. sqlspec/observability/_diagnostics.py +74 -0
  466. sqlspec/observability/_dispatcher.cpython-310-aarch64-linux-gnu.so +0 -0
  467. sqlspec/observability/_dispatcher.py +152 -0
  468. sqlspec/observability/_formatters/__init__.py +13 -0
  469. sqlspec/observability/_formatters/_aws.cpython-310-aarch64-linux-gnu.so +0 -0
  470. sqlspec/observability/_formatters/_aws.py +102 -0
  471. sqlspec/observability/_formatters/_azure.cpython-310-aarch64-linux-gnu.so +0 -0
  472. sqlspec/observability/_formatters/_azure.py +96 -0
  473. sqlspec/observability/_formatters/_base.cpython-310-aarch64-linux-gnu.so +0 -0
  474. sqlspec/observability/_formatters/_base.py +57 -0
  475. sqlspec/observability/_formatters/_gcp.cpython-310-aarch64-linux-gnu.so +0 -0
  476. sqlspec/observability/_formatters/_gcp.py +131 -0
  477. sqlspec/observability/_formatting.py +58 -0
  478. sqlspec/observability/_observer.cpython-310-aarch64-linux-gnu.so +0 -0
  479. sqlspec/observability/_observer.py +357 -0
  480. sqlspec/observability/_runtime.cpython-310-aarch64-linux-gnu.so +0 -0
  481. sqlspec/observability/_runtime.py +420 -0
  482. sqlspec/observability/_sampling.cpython-310-aarch64-linux-gnu.so +0 -0
  483. sqlspec/observability/_sampling.py +188 -0
  484. sqlspec/observability/_spans.cpython-310-aarch64-linux-gnu.so +0 -0
  485. sqlspec/observability/_spans.py +161 -0
  486. sqlspec/protocols.py +916 -0
  487. sqlspec/py.typed +0 -0
  488. sqlspec/storage/__init__.py +48 -0
  489. sqlspec/storage/_utils.py +104 -0
  490. sqlspec/storage/backends/__init__.py +1 -0
  491. sqlspec/storage/backends/base.py +253 -0
  492. sqlspec/storage/backends/fsspec.py +529 -0
  493. sqlspec/storage/backends/local.py +441 -0
  494. sqlspec/storage/backends/obstore.py +916 -0
  495. sqlspec/storage/errors.py +104 -0
  496. sqlspec/storage/pipeline.py +582 -0
  497. sqlspec/storage/registry.py +301 -0
  498. sqlspec/typing.py +395 -0
  499. sqlspec/utils/__init__.py +7 -0
  500. sqlspec/utils/arrow_helpers.py +318 -0
  501. sqlspec/utils/config_tools.py +332 -0
  502. sqlspec/utils/correlation.cpython-310-aarch64-linux-gnu.so +0 -0
  503. sqlspec/utils/correlation.py +134 -0
  504. sqlspec/utils/deprecation.py +190 -0
  505. sqlspec/utils/fixtures.cpython-310-aarch64-linux-gnu.so +0 -0
  506. sqlspec/utils/fixtures.py +258 -0
  507. sqlspec/utils/logging.py +222 -0
  508. sqlspec/utils/module_loader.py +306 -0
  509. sqlspec/utils/portal.cpython-310-aarch64-linux-gnu.so +0 -0
  510. sqlspec/utils/portal.py +375 -0
  511. sqlspec/utils/schema.cpython-310-aarch64-linux-gnu.so +0 -0
  512. sqlspec/utils/schema.py +485 -0
  513. sqlspec/utils/serializers.cpython-310-aarch64-linux-gnu.so +0 -0
  514. sqlspec/utils/serializers.py +408 -0
  515. sqlspec/utils/singleton.cpython-310-aarch64-linux-gnu.so +0 -0
  516. sqlspec/utils/singleton.py +41 -0
  517. sqlspec/utils/sync_tools.cpython-310-aarch64-linux-gnu.so +0 -0
  518. sqlspec/utils/sync_tools.py +311 -0
  519. sqlspec/utils/text.cpython-310-aarch64-linux-gnu.so +0 -0
  520. sqlspec/utils/text.py +108 -0
  521. sqlspec/utils/type_converters.cpython-310-aarch64-linux-gnu.so +0 -0
  522. sqlspec/utils/type_converters.py +128 -0
  523. sqlspec/utils/type_guards.cpython-310-aarch64-linux-gnu.so +0 -0
  524. sqlspec/utils/type_guards.py +1360 -0
  525. sqlspec/utils/uuids.cpython-310-aarch64-linux-gnu.so +0 -0
  526. sqlspec/utils/uuids.py +225 -0
  527. sqlspec-0.36.0.dist-info/METADATA +205 -0
  528. sqlspec-0.36.0.dist-info/RECORD +531 -0
  529. sqlspec-0.36.0.dist-info/WHEEL +7 -0
  530. sqlspec-0.36.0.dist-info/entry_points.txt +2 -0
  531. sqlspec-0.36.0.dist-info/licenses/LICENSE +21 -0
sqlspec/config.py ADDED
@@ -0,0 +1,1755 @@
1
+ from abc import ABC, abstractmethod
2
+ from collections.abc import Callable
3
+ from inspect import Signature, signature
4
+ from pathlib import Path
5
+ from typing import TYPE_CHECKING, Any, ClassVar, Generic, Literal, TypeAlias, TypeVar, cast
6
+
7
+ from typing_extensions import NotRequired, TypedDict
8
+
9
+ from sqlspec.core import ParameterStyle, ParameterStyleConfig, StatementConfig
10
+ from sqlspec.exceptions import MissingDependencyError
11
+ from sqlspec.extensions.events import EventRuntimeHints
12
+ from sqlspec.loader import SQLFileLoader
13
+ from sqlspec.migrations import AsyncMigrationTracker, SyncMigrationTracker, create_migration_commands
14
+ from sqlspec.observability import ObservabilityConfig, ObservabilityRuntime
15
+ from sqlspec.utils.logging import get_logger
16
+ from sqlspec.utils.module_loader import ensure_pyarrow
17
+
18
+ if TYPE_CHECKING:
19
+ from collections.abc import Awaitable
20
+ from contextlib import AbstractAsyncContextManager, AbstractContextManager
21
+
22
+ from sqlspec.driver import AsyncDriverAdapterBase, SyncDriverAdapterBase
23
+ from sqlspec.migrations.commands import AsyncMigrationCommands, SyncMigrationCommands
24
+ from sqlspec.storage import StorageCapabilities
25
+
26
+
27
+ __all__ = (
28
+ "ADKConfig",
29
+ "AsyncConfigT",
30
+ "AsyncDatabaseConfig",
31
+ "ConfigT",
32
+ "DatabaseConfigProtocol",
33
+ "DriverT",
34
+ "EventsConfig",
35
+ "ExtensionConfigs",
36
+ "FastAPIConfig",
37
+ "FlaskConfig",
38
+ "LifecycleConfig",
39
+ "LitestarConfig",
40
+ "MigrationConfig",
41
+ "NoPoolAsyncConfig",
42
+ "NoPoolSyncConfig",
43
+ "OpenTelemetryConfig",
44
+ "PrometheusConfig",
45
+ "StarletteConfig",
46
+ "SyncConfigT",
47
+ "SyncDatabaseConfig",
48
+ )
49
+
50
+ AsyncConfigT = TypeVar("AsyncConfigT", bound="AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any]")
51
+ SyncConfigT = TypeVar("SyncConfigT", bound="SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any]")
52
+ ConfigT = TypeVar(
53
+ "ConfigT",
54
+ bound="AsyncDatabaseConfig[Any, Any, Any] | NoPoolAsyncConfig[Any, Any] | SyncDatabaseConfig[Any, Any, Any] | NoPoolSyncConfig[Any, Any]",
55
+ )
56
+
57
+ ConnectionT = TypeVar("ConnectionT")
58
+ PoolT = TypeVar("PoolT")
59
+ DriverT = TypeVar("DriverT", bound="SyncDriverAdapterBase | AsyncDriverAdapterBase")
60
+
61
+ logger = get_logger("sqlspec.config")
62
+
63
+ DRIVER_FEATURE_LIFECYCLE_HOOKS: dict[str, str | None] = {
64
+ "on_connection_create": "connection",
65
+ "on_connection_destroy": "connection",
66
+ "on_pool_create": "pool",
67
+ "on_pool_destroy": "pool",
68
+ "on_session_start": "session",
69
+ "on_session_end": "session",
70
+ }
71
+
72
+
73
+ class _DriverFeatureHookWrapper:
74
+ __slots__ = ("_callback", "_context_key", "_expects_argument")
75
+
76
+ def __init__(self, callback: "Callable[..., Any]", context_key: "str | None", expects_argument: bool) -> None:
77
+ self._callback = callback
78
+ self._context_key = context_key
79
+ self._expects_argument = expects_argument
80
+
81
+ def __call__(self, context: "dict[str, Any]") -> None:
82
+ if not self._expects_argument:
83
+ self._callback()
84
+ return
85
+ if self._context_key is None:
86
+ self._callback(context)
87
+ return
88
+ self._callback(context.get(self._context_key))
89
+
90
+
91
+ class LifecycleConfig(TypedDict):
92
+ """Lifecycle hooks for database adapters.
93
+
94
+ Each hook accepts a list of callables to support multiple handlers.
95
+ """
96
+
97
+ on_connection_create: NotRequired[list[Callable[[Any], None]]]
98
+ on_connection_destroy: NotRequired[list[Callable[[Any], None]]]
99
+ on_pool_create: NotRequired[list[Callable[[Any], None]]]
100
+ on_pool_destroy: NotRequired[list[Callable[[Any], None]]]
101
+ on_session_start: NotRequired[list[Callable[[Any], None]]]
102
+ on_session_end: NotRequired[list[Callable[[Any], None]]]
103
+ on_query_start: NotRequired[list[Callable[[str, dict[str, Any]], None]]]
104
+ on_query_complete: NotRequired[list[Callable[[str, dict[str, Any], Any], None]]]
105
+ on_error: NotRequired[list[Callable[[Exception, str, dict[str, Any]], None]]]
106
+
107
+
108
+ class MigrationConfig(TypedDict):
109
+ """Configuration options for database migrations.
110
+
111
+ All fields are optional with default values.
112
+ """
113
+
114
+ script_location: NotRequired["str | Path"]
115
+ """Path to the migrations directory. Accepts string or Path object. Defaults to 'migrations'."""
116
+
117
+ version_table_name: NotRequired[str]
118
+ """Name of the table used to track applied migrations. Defaults to 'sqlspec_migrations'."""
119
+
120
+ project_root: NotRequired[str]
121
+ """Path to the project root directory. Used for relative path resolution."""
122
+
123
+ enabled: NotRequired[bool]
124
+ """Whether this configuration should be included in CLI operations. Defaults to True."""
125
+
126
+ auto_sync: NotRequired[bool]
127
+ """Enable automatic version reconciliation during upgrade. When enabled (default), SQLSpec automatically updates database tracking when migrations are renamed from timestamp to sequential format. Defaults to True."""
128
+
129
+ strict_ordering: NotRequired[bool]
130
+ """Enforce strict migration ordering. When enabled, prevents out-of-order migrations from being applied. Defaults to False."""
131
+
132
+ include_extensions: NotRequired["list[str]"]
133
+ """List of extension names whose migrations should be included. Extension migrations maintain separate versioning and are prefixed with 'ext_{name}_'.
134
+
135
+ Note: Extensions with migration support (litestar, adk, events) are auto-included when
136
+ their settings are present in ``extension_config``. Use ``exclude_extensions`` to opt out.
137
+ """
138
+
139
+ exclude_extensions: NotRequired["list[str]"]
140
+ """List of extension names to exclude from automatic migration inclusion.
141
+
142
+ When an extension is configured in ``extension_config``, its migrations are automatically
143
+ included. Use this to prevent that for specific extensions:
144
+
145
+ Example:
146
+ migration_config={
147
+ "exclude_extensions": ["events"] # Use ephemeral listen_notify, skip queue table
148
+ }
149
+ """
150
+
151
+ transactional: NotRequired[bool]
152
+ """Wrap migrations in transactions when supported. When enabled (default for adapters that support it), each migration runs in a transaction that is committed on success or rolled back on failure. This prevents partial migrations from leaving the database in an inconsistent state. Requires adapter support for transactional DDL. Defaults to True for PostgreSQL, SQLite, and DuckDB; False for MySQL, Oracle, and BigQuery. Individual migrations can override this with a '-- transactional: false' comment."""
153
+
154
+
155
+ class FlaskConfig(TypedDict):
156
+ """Configuration options for Flask SQLSpec extension.
157
+
158
+ All fields are optional with sensible defaults. Use in extension_config["flask"]:
159
+
160
+ Example:
161
+ from sqlspec.adapters.asyncpg import AsyncpgConfig
162
+
163
+ config = AsyncpgConfig(
164
+ connection_config={"dsn": "postgresql://localhost/mydb"},
165
+ extension_config={
166
+ "flask": {
167
+ "commit_mode": "autocommit",
168
+ "session_key": "db"
169
+ }
170
+ }
171
+ )
172
+
173
+ Notes:
174
+ This TypedDict provides type safety for extension config.
175
+ Flask extension uses g object for request-scoped storage.
176
+ """
177
+
178
+ connection_key: NotRequired[str]
179
+ """Key for storing connection in Flask g object. Default: auto-generated from session_key."""
180
+
181
+ session_key: NotRequired[str]
182
+ """Key for accessing session via plugin.get_session(). Default: 'db_session'."""
183
+
184
+ commit_mode: NotRequired[Literal["manual", "autocommit", "autocommit_include_redirect"]]
185
+ """Transaction commit mode. Default: 'manual'.
186
+ - manual: No automatic commits, user handles explicitly
187
+ - autocommit: Commits on 2xx status, rollback otherwise
188
+ - autocommit_include_redirect: Commits on 2xx-3xx status, rollback otherwise
189
+ """
190
+
191
+ extra_commit_statuses: NotRequired[set[int]]
192
+ """Additional HTTP status codes that trigger commit. Default: None."""
193
+
194
+ extra_rollback_statuses: NotRequired[set[int]]
195
+ """Additional HTTP status codes that trigger rollback. Default: None."""
196
+
197
+ disable_di: NotRequired[bool]
198
+ """Disable built-in dependency injection. Default: False.
199
+ When True, the Flask extension will not register request hooks for managing
200
+ database connections and sessions. Users are responsible for managing the
201
+ database lifecycle manually via their own DI solution.
202
+ """
203
+
204
+
205
+ class LitestarConfig(TypedDict):
206
+ """Configuration options for Litestar SQLSpec plugin.
207
+
208
+ All fields are optional with sensible defaults.
209
+ """
210
+
211
+ session_table: NotRequired["bool | str"]
212
+ """Enable session table for server-side session storage.
213
+
214
+ - ``True``: Use default table name ('litestar_session')
215
+ - ``"custom_name"``: Use custom table name
216
+
217
+ When set, litestar extension migrations are auto-included to create the session table.
218
+ If you're only using litestar for DI/connection management (not session storage),
219
+ leave this unset to skip the migrations.
220
+ """
221
+
222
+ connection_key: NotRequired[str]
223
+ """Key for storing connection in ASGI scope. Default: 'db_connection'"""
224
+
225
+ pool_key: NotRequired[str]
226
+ """Key for storing connection pool in application state. Default: 'db_pool'"""
227
+
228
+ session_key: NotRequired[str]
229
+ """Key for storing session in ASGI scope. Default: 'db_session'"""
230
+
231
+ commit_mode: NotRequired[Literal["manual", "autocommit", "autocommit_include_redirect"]]
232
+ """Transaction commit mode. Default: 'manual'"""
233
+
234
+ enable_correlation_middleware: NotRequired[bool]
235
+ """Enable request correlation ID middleware. Default: True"""
236
+
237
+ correlation_header: NotRequired[str]
238
+ """HTTP header to read the request correlation ID from when middleware is enabled. Default: ``X-Request-ID``"""
239
+
240
+ extra_commit_statuses: NotRequired[set[int]]
241
+ """Additional HTTP status codes that trigger commit. Default: set()"""
242
+
243
+ extra_rollback_statuses: NotRequired[set[int]]
244
+ """Additional HTTP status codes that trigger rollback. Default: set()"""
245
+
246
+ disable_di: NotRequired[bool]
247
+ """Disable built-in dependency injection. Default: False.
248
+ When True, the Litestar plugin will not register dependency providers for managing
249
+ database connections, pools, and sessions. Users are responsible for managing the
250
+ database lifecycle manually via their own DI solution.
251
+ """
252
+
253
+
254
+ class StarletteConfig(TypedDict):
255
+ """Configuration options for Starlette and FastAPI extensions.
256
+
257
+ All fields are optional with sensible defaults. Use in extension_config["starlette"]:
258
+
259
+ Example:
260
+ from sqlspec.adapters.asyncpg import AsyncpgConfig
261
+
262
+ config = AsyncpgConfig(
263
+ connection_config={"dsn": "postgresql://localhost/mydb"},
264
+ extension_config={
265
+ "starlette": {
266
+ "commit_mode": "autocommit",
267
+ "session_key": "db"
268
+ }
269
+ }
270
+ )
271
+
272
+ Notes:
273
+ Both Starlette and FastAPI extensions use the "starlette" key.
274
+ This TypedDict provides type safety for extension config.
275
+ """
276
+
277
+ connection_key: NotRequired[str]
278
+ """Key for storing connection in request.state. Default: 'db_connection'"""
279
+
280
+ pool_key: NotRequired[str]
281
+ """Key for storing connection pool in app.state. Default: 'db_pool'"""
282
+
283
+ session_key: NotRequired[str]
284
+ """Key for storing session in request.state. Default: 'db_session'"""
285
+
286
+ commit_mode: NotRequired[Literal["manual", "autocommit", "autocommit_include_redirect"]]
287
+ """Transaction commit mode. Default: 'manual'
288
+
289
+ - manual: No automatic commit/rollback
290
+ - autocommit: Commit on 2xx, rollback otherwise
291
+ - autocommit_include_redirect: Commit on 2xx-3xx, rollback otherwise
292
+ """
293
+
294
+ extra_commit_statuses: NotRequired[set[int]]
295
+ """Additional HTTP status codes that trigger commit. Default: set()
296
+
297
+ Example:
298
+ extra_commit_statuses={201, 202}
299
+ """
300
+
301
+ extra_rollback_statuses: NotRequired[set[int]]
302
+ """Additional HTTP status codes that trigger rollback. Default: set()
303
+
304
+ Example:
305
+ extra_rollback_statuses={409}
306
+ """
307
+
308
+ disable_di: NotRequired[bool]
309
+ """Disable built-in dependency injection. Default: False.
310
+ When True, the Starlette/FastAPI extension will not add middleware for managing
311
+ database connections and sessions. Users are responsible for managing the
312
+ database lifecycle manually via their own DI solution.
313
+ """
314
+
315
+
316
+ class FastAPIConfig(StarletteConfig):
317
+ """Configuration options for FastAPI SQLSpec extension.
318
+
319
+ All fields are optional with sensible defaults. Use in extension_config["fastapi"]:
320
+
321
+ Example:
322
+ from sqlspec.adapters.asyncpg import AsyncpgConfig
323
+
324
+ config = AsyncpgConfig(
325
+ connection_config={"dsn": "postgresql://localhost/mydb"},
326
+ extension_config={
327
+ "fastapi": {
328
+ "commit_mode": "autocommit",
329
+ "session_key": "db"
330
+ }
331
+ }
332
+ """
333
+
334
+
335
+ class ADKConfig(TypedDict):
336
+ """Configuration options for ADK session and memory store extension.
337
+
338
+ All fields are optional with sensible defaults. Use in extension_config["adk"]:
339
+
340
+ Configuration supports three deployment scenarios:
341
+ 1. SQLSpec manages everything (runtime + migrations)
342
+ 2. SQLSpec runtime only (external migration tools like Alembic/Flyway)
343
+ 3. Selective features (sessions OR memory, not both)
344
+
345
+ Example:
346
+ from sqlspec.adapters.asyncpg import AsyncpgConfig
347
+
348
+ config = AsyncpgConfig(
349
+ connection_config={"dsn": "postgresql://localhost/mydb"},
350
+ extension_config={
351
+ "adk": {
352
+ "session_table": "my_sessions",
353
+ "events_table": "my_events",
354
+ "memory_table": "my_memories",
355
+ "memory_use_fts": True,
356
+ "owner_id_column": "tenant_id INTEGER REFERENCES tenants(id)"
357
+ }
358
+ }
359
+ )
360
+
361
+ Notes:
362
+ This TypedDict provides type safety for extension config but is not required.
363
+ You can use plain dicts as well.
364
+ """
365
+
366
+ enable_sessions: NotRequired[bool]
367
+ """Enable session store at runtime. Default: True.
368
+
369
+ When False: session service unavailable, session store operations disabled.
370
+ Independent of migration control - can use externally-managed tables.
371
+ """
372
+
373
+ enable_memory: NotRequired[bool]
374
+ """Enable memory store at runtime. Default: True.
375
+
376
+ When False: memory service unavailable, memory store operations disabled.
377
+ Independent of migration control - can use externally-managed tables.
378
+ """
379
+
380
+ include_sessions_migration: NotRequired[bool]
381
+ """Include session tables in SQLSpec migrations. Default: True.
382
+
383
+ When False: session migration DDL skipped (use external migration tools).
384
+ Decoupled from enable_sessions - allows external table management with SQLSpec runtime.
385
+ """
386
+
387
+ include_memory_migration: NotRequired[bool]
388
+ """Include memory tables in SQLSpec migrations. Default: True.
389
+
390
+ When False: memory migration DDL skipped (use external migration tools).
391
+ Decoupled from enable_memory - allows external table management with SQLSpec runtime.
392
+ """
393
+
394
+ session_table: NotRequired[str]
395
+ """Name of the sessions table. Default: 'adk_sessions'
396
+
397
+ Examples:
398
+ "agent_sessions"
399
+ "my_app_sessions"
400
+ "tenant_acme_sessions"
401
+ """
402
+
403
+ events_table: NotRequired[str]
404
+ """Name of the events table. Default: 'adk_events'
405
+
406
+ Examples:
407
+ "agent_events"
408
+ "my_app_events"
409
+ "tenant_acme_events"
410
+ """
411
+
412
+ memory_table: NotRequired[str]
413
+ """Name of the memory entries table. Default: 'adk_memory_entries'
414
+
415
+ Examples:
416
+ "agent_memories"
417
+ "my_app_memories"
418
+ "tenant_acme_memories"
419
+ """
420
+
421
+ memory_use_fts: NotRequired[bool]
422
+ """Enable full-text search when supported. Default: False.
423
+
424
+ When True, adapters will use their native FTS capabilities where available:
425
+ - PostgreSQL: to_tsvector/to_tsquery with GIN index
426
+ - SQLite: FTS5 virtual table
427
+ - DuckDB: FTS extension with match_bm25
428
+ - Oracle: CONTAINS() with CTXSYS.CONTEXT index
429
+ - BigQuery: SEARCH() function (requires search index)
430
+ - Spanner: TOKENIZE_FULLTEXT with search index
431
+ - MySQL: MATCH...AGAINST with FULLTEXT index
432
+
433
+ When False, adapters use simple LIKE/ILIKE queries (works without indexes).
434
+ """
435
+
436
+ memory_max_results: NotRequired[int]
437
+ """Maximum number of results for memory search queries. Default: 20.
438
+
439
+ Limits the number of memory entries returned by search_memory().
440
+ Can be overridden per-query via the limit parameter.
441
+ """
442
+
443
+ owner_id_column: NotRequired[str]
444
+ """Optional owner ID column definition to link sessions/memories to a user, tenant, team, or other entity.
445
+
446
+ Format: "column_name TYPE [NOT NULL] REFERENCES table(column) [options...]"
447
+
448
+ The entire definition is passed through to DDL verbatim. We only parse
449
+ the column name (first word) for use in INSERT/SELECT statements.
450
+
451
+ This column is added to both session and memory tables for consistent
452
+ multi-tenant isolation.
453
+
454
+ Supports:
455
+ - Foreign key constraints: REFERENCES table(column)
456
+ - Nullable or NOT NULL
457
+ - CASCADE options: ON DELETE CASCADE, ON UPDATE CASCADE
458
+ - Dialect-specific options (DEFERRABLE, ENABLE VALIDATE, etc.)
459
+ - Plain columns without FK (just extra column storage)
460
+
461
+ Examples:
462
+ PostgreSQL with UUID FK:
463
+ "account_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE"
464
+
465
+ MySQL with BIGINT FK:
466
+ "user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE RESTRICT"
467
+
468
+ Oracle with NUMBER FK:
469
+ "user_id NUMBER(10) REFERENCES users(id) ENABLE VALIDATE"
470
+
471
+ SQLite with INTEGER FK:
472
+ "tenant_id INTEGER NOT NULL REFERENCES tenants(id)"
473
+
474
+ Nullable FK (optional relationship):
475
+ "workspace_id UUID REFERENCES workspaces(id) ON DELETE SET NULL"
476
+
477
+ No FK (just extra column):
478
+ "organization_name VARCHAR(128) NOT NULL"
479
+
480
+ Deferred constraint (PostgreSQL):
481
+ "user_id UUID REFERENCES users(id) DEFERRABLE INITIALLY DEFERRED"
482
+
483
+ Notes:
484
+ - Column name (first word) is extracted for INSERT/SELECT queries
485
+ - Rest of definition is passed through to CREATE TABLE DDL
486
+ - Database validates the DDL syntax (fail-fast on errors)
487
+ - Works with all database dialects (PostgreSQL, MySQL, SQLite, Oracle, etc.)
488
+ """
489
+
490
+ in_memory: NotRequired[bool]
491
+ """Enable in-memory table storage (Oracle-specific). Default: False.
492
+
493
+ When enabled, tables are created with the INMEMORY clause for Oracle Database,
494
+ which stores table data in columnar format in memory for faster query performance.
495
+
496
+ This is an Oracle-specific feature that requires:
497
+ - Oracle Database 12.1.0.2 or higher
498
+ - Database In-Memory option license (Enterprise Edition)
499
+ - Sufficient INMEMORY_SIZE configured in the database instance
500
+
501
+ Other database adapters ignore this setting.
502
+
503
+ Examples:
504
+ Oracle with in-memory enabled:
505
+ config = OracleAsyncConfig(
506
+ connection_config={"dsn": "oracle://..."},
507
+ extension_config={
508
+ "adk": {
509
+ "in_memory": True
510
+ }
511
+ }
512
+ )
513
+
514
+ Notes:
515
+ - Improves query performance for analytics (10-100x faster)
516
+ - Tables created with INMEMORY clause
517
+ - Requires Oracle Database In-Memory option license
518
+ - Ignored by non-Oracle adapters
519
+ """
520
+
521
+ shard_count: NotRequired[int]
522
+ """Optional hash shard count for session/event tables to reduce hotspotting.
523
+
524
+ When set (>1), adapters that support computed shard columns will create a
525
+ generated shard_id using MOD(FARM_FINGERPRINT(primary_key), shard_count) and
526
+ include it in the primary key and filters. Ignored by adapters that do not
527
+ support computed shards.
528
+ """
529
+
530
+ session_table_options: NotRequired[str]
531
+ """Adapter-specific table OPTIONS/clauses for the sessions table.
532
+
533
+ Passed verbatim when supported (e.g., Spanner columnar/tiered storage). Ignored by
534
+ adapters without table OPTIONS support.
535
+ """
536
+
537
+ events_table_options: NotRequired[str]
538
+ """Adapter-specific table OPTIONS/clauses for the events table."""
539
+
540
+ memory_table_options: NotRequired[str]
541
+ """Adapter-specific table OPTIONS/clauses for the memory table."""
542
+
543
+ expires_index_options: NotRequired[str]
544
+ """Adapter-specific options for the expires/index used in ADK stores."""
545
+
546
+
547
+ class EventsConfig(TypedDict):
548
+ """Configuration options for the events extension.
549
+
550
+ Use in ``extension_config["events"]``.
551
+ """
552
+
553
+ backend: NotRequired[Literal["listen_notify", "table_queue", "listen_notify_durable", "advanced_queue"]]
554
+ """Backend implementation. PostgreSQL adapters default to 'listen_notify', others to 'table_queue'.
555
+
556
+ - listen_notify: Real-time PostgreSQL LISTEN/NOTIFY (ephemeral)
557
+ - table_queue: Durable table-backed queue with retries (all adapters)
558
+ - listen_notify_durable: Hybrid combining both (PostgreSQL only)
559
+ - advanced_queue: Oracle Advanced Queueing
560
+ """
561
+
562
+ queue_table: NotRequired[str]
563
+ """Name of the fallback queue table. Defaults to 'sqlspec_event_queue'."""
564
+
565
+ lease_seconds: NotRequired[int]
566
+ """Lease duration for claimed events before they can be retried. Defaults to 30 seconds."""
567
+
568
+ retention_seconds: NotRequired[int]
569
+ """Retention window for acknowledged events before cleanup. Defaults to 86400 (24 hours)."""
570
+
571
+ poll_interval: NotRequired[float]
572
+ """Default poll interval in seconds for event consumers. Defaults to 1.0."""
573
+
574
+ select_for_update: NotRequired[bool]
575
+ """Use SELECT FOR UPDATE locking when claiming events. Defaults to False."""
576
+
577
+ skip_locked: NotRequired[bool]
578
+ """Use SKIP LOCKED for non-blocking event claims. Defaults to False."""
579
+
580
+ json_passthrough: NotRequired[bool]
581
+ """Skip JSON encoding/decoding for payloads. Defaults to False."""
582
+
583
+ in_memory: NotRequired[bool]
584
+ """Enable Oracle INMEMORY clause for the queue table. Ignored by other adapters. Defaults to False.
585
+
586
+ Note: To skip events migrations (e.g., when using ephemeral 'listen_notify' backend),
587
+ use ``migration_config={"exclude_extensions": ["events"]}``.
588
+ """
589
+
590
+
591
+ class OpenTelemetryConfig(TypedDict):
592
+ """Configuration options for OpenTelemetry integration.
593
+
594
+ Use in ``extension_config["otel"]``.
595
+ """
596
+
597
+ enabled: NotRequired[bool]
598
+ """Enable the extension. Default: True."""
599
+
600
+ enable_spans: NotRequired[bool]
601
+ """Enable span emission (set False to disable while keeping other settings)."""
602
+
603
+ resource_attributes: NotRequired[dict[str, Any]]
604
+ """Additional resource attributes passed to the tracer provider factory."""
605
+
606
+ tracer_provider: NotRequired[Any]
607
+ """Tracer provider instance to reuse. Mutually exclusive with ``tracer_provider_factory``."""
608
+
609
+ tracer_provider_factory: NotRequired[Callable[[], Any]]
610
+ """Factory returning a tracer provider. Invoked lazily when spans are needed."""
611
+
612
+
613
+ class PrometheusConfig(TypedDict):
614
+ """Configuration options for Prometheus metrics.
615
+
616
+ Use in ``extension_config["prometheus"]``.
617
+ """
618
+
619
+ enabled: NotRequired[bool]
620
+ """Enable the extension. Default: True."""
621
+
622
+ namespace: NotRequired[str]
623
+ """Prometheus metric namespace. Default: ``"sqlspec"``."""
624
+
625
+ subsystem: NotRequired[str]
626
+ """Prometheus metric subsystem. Default: ``"driver"``."""
627
+
628
+ registry: NotRequired[Any]
629
+ """Custom Prometheus registry (defaults to the global registry)."""
630
+
631
+ label_names: NotRequired[tuple[str, ...]]
632
+ """Labels applied to metrics. Default: ("driver", "operation")."""
633
+
634
+ duration_buckets: NotRequired[tuple[float, ...]]
635
+ """Histogram buckets for query duration (seconds)."""
636
+
637
+
638
+ ExtensionConfigs: TypeAlias = dict[
639
+ str,
640
+ dict[str, Any]
641
+ | LitestarConfig
642
+ | FastAPIConfig
643
+ | StarletteConfig
644
+ | FlaskConfig
645
+ | ADKConfig
646
+ | EventsConfig
647
+ | OpenTelemetryConfig
648
+ | PrometheusConfig,
649
+ ]
650
+
651
+
652
+ class DatabaseConfigProtocol(ABC, Generic[ConnectionT, PoolT, DriverT]):
653
+ """Protocol defining the interface for database configurations."""
654
+
655
+ __slots__ = (
656
+ "_migration_commands",
657
+ "_migration_loader",
658
+ "_observability_runtime",
659
+ "_storage_capabilities",
660
+ "bind_key",
661
+ "connection_instance",
662
+ "driver_features",
663
+ "extension_config",
664
+ "migration_config",
665
+ "observability_config",
666
+ "statement_config",
667
+ )
668
+
669
+ _migration_loader: "SQLFileLoader"
670
+ _migration_commands: "SyncMigrationCommands[Any] | AsyncMigrationCommands[Any]"
671
+ driver_type: "ClassVar[type[Any]]"
672
+ connection_type: "ClassVar[type[Any]]"
673
+ is_async: "ClassVar[bool]" = False
674
+ supports_connection_pooling: "ClassVar[bool]" = False
675
+ supports_transactional_ddl: "ClassVar[bool]" = False
676
+ supports_native_arrow_import: "ClassVar[bool]" = False
677
+ supports_native_arrow_export: "ClassVar[bool]" = False
678
+ supports_native_parquet_import: "ClassVar[bool]" = False
679
+ supports_native_parquet_export: "ClassVar[bool]" = False
680
+ requires_staging_for_load: "ClassVar[bool]" = False
681
+ staging_protocols: "ClassVar[tuple[str, ...]]" = ()
682
+ default_storage_profile: "ClassVar[str | None]" = None
683
+ storage_partition_strategies: "ClassVar[tuple[str, ...]]" = ("fixed",)
684
+ bind_key: "str | None"
685
+ statement_config: "StatementConfig"
686
+ connection_instance: "PoolT | None"
687
+ migration_config: "dict[str, Any] | MigrationConfig"
688
+ extension_config: "ExtensionConfigs"
689
+ driver_features: "dict[str, Any]"
690
+ _storage_capabilities: "StorageCapabilities | None"
691
+ observability_config: "ObservabilityConfig | None"
692
+ _observability_runtime: "ObservabilityRuntime | None"
693
+
694
+ def __hash__(self) -> int:
695
+ return id(self)
696
+
697
+ def __eq__(self, other: object) -> bool:
698
+ if not isinstance(other, type(self)):
699
+ return False
700
+ return bool(
701
+ self.connection_instance == other.connection_instance and self.migration_config == other.migration_config
702
+ )
703
+
704
+ def __repr__(self) -> str:
705
+ parts = ", ".join([
706
+ f"connection_instance={self.connection_instance!r}",
707
+ f"migration_config={self.migration_config!r}",
708
+ ])
709
+ return f"{type(self).__name__}({parts})"
710
+
711
+ def storage_capabilities(self) -> "StorageCapabilities":
712
+ """Return cached storage capabilities for this configuration."""
713
+
714
+ if self._storage_capabilities is None:
715
+ self._storage_capabilities = self._build_storage_capabilities()
716
+ return cast("StorageCapabilities", dict(self._storage_capabilities))
717
+
718
+ def reset_storage_capabilities_cache(self) -> None:
719
+ """Clear the cached capability snapshot."""
720
+
721
+ self._storage_capabilities = None
722
+
723
+ def _ensure_extension_migrations(self) -> None:
724
+ """Auto-include extension migrations when extension_config has them configured.
725
+
726
+ Extensions with migration support are automatically included in
727
+ ``migration_config["include_extensions"]`` based on their settings:
728
+
729
+ - **litestar**: Only when ``session_table`` is set (for session storage)
730
+ - **adk**: When any adk settings are present
731
+ - **events**: When any events settings are present
732
+
733
+ Use ``exclude_extensions`` to opt out of auto-inclusion.
734
+ """
735
+ extension_settings = cast("dict[str, Any]", self.extension_config)
736
+ migration_config = cast("dict[str, Any]", self.migration_config)
737
+
738
+ exclude_extensions = migration_config.get("exclude_extensions", [])
739
+ if isinstance(exclude_extensions, tuple):
740
+ exclude_extensions = list(exclude_extensions) # pyright: ignore
741
+
742
+ extensions_to_add: list[str] = []
743
+
744
+ litestar_settings = extension_settings.get("litestar")
745
+ if (
746
+ litestar_settings is not None
747
+ and "session_table" in litestar_settings
748
+ and "litestar" not in exclude_extensions
749
+ ):
750
+ extensions_to_add.append("litestar")
751
+
752
+ adk_settings = extension_settings.get("adk")
753
+ if adk_settings is not None and "adk" not in exclude_extensions:
754
+ extensions_to_add.append("adk")
755
+
756
+ events_settings = extension_settings.get("events")
757
+ if events_settings is not None and "events" not in exclude_extensions:
758
+ extensions_to_add.append("events")
759
+
760
+ if not extensions_to_add:
761
+ return
762
+
763
+ include_extensions = migration_config.get("include_extensions")
764
+ if include_extensions is None:
765
+ include_list: list[str] = []
766
+ migration_config["include_extensions"] = include_list
767
+ elif isinstance(include_extensions, tuple):
768
+ include_list = list(include_extensions) # pyright: ignore
769
+ migration_config["include_extensions"] = include_list
770
+ else:
771
+ include_list = cast("list[str]", include_extensions)
772
+
773
+ for ext in extensions_to_add:
774
+ if ext not in include_list:
775
+ include_list.append(ext)
776
+
777
+ def get_event_runtime_hints(self) -> "EventRuntimeHints":
778
+ """Return default event runtime hints for this configuration."""
779
+
780
+ return EventRuntimeHints()
781
+
782
+ def _build_storage_capabilities(self) -> "StorageCapabilities":
783
+ arrow_dependency_needed = self.supports_native_arrow_export or self.supports_native_arrow_import
784
+ parquet_dependency_needed = self.supports_native_parquet_export or self.supports_native_parquet_import
785
+
786
+ arrow_dependency_ready = self._dependency_available(ensure_pyarrow) if arrow_dependency_needed else False
787
+ parquet_dependency_ready = self._dependency_available(ensure_pyarrow) if parquet_dependency_needed else False
788
+
789
+ capabilities: StorageCapabilities = {
790
+ "arrow_export_enabled": bool(self.supports_native_arrow_export and arrow_dependency_ready),
791
+ "arrow_import_enabled": bool(self.supports_native_arrow_import and arrow_dependency_ready),
792
+ "parquet_export_enabled": bool(self.supports_native_parquet_export and parquet_dependency_ready),
793
+ "parquet_import_enabled": bool(self.supports_native_parquet_import and parquet_dependency_ready),
794
+ "requires_staging_for_load": self.requires_staging_for_load,
795
+ "staging_protocols": list(self.staging_protocols),
796
+ "partition_strategies": list(self.storage_partition_strategies),
797
+ }
798
+ if self.default_storage_profile is not None:
799
+ capabilities["default_storage_profile"] = self.default_storage_profile
800
+ return capabilities
801
+
802
+ def _init_observability(self, observability_config: "ObservabilityConfig | None" = None) -> None:
803
+ """Initialize observability attributes for the configuration."""
804
+
805
+ self.observability_config = observability_config
806
+ self._observability_runtime = None
807
+
808
+ def _configure_observability_extensions(self) -> None:
809
+ """Apply extension_config hooks (otel/prometheus) to ObservabilityConfig."""
810
+
811
+ config_map = cast("dict[str, Any]", self.extension_config)
812
+ if not config_map:
813
+ return
814
+ updated = self.observability_config
815
+
816
+ otel_config = cast("OpenTelemetryConfig | None", config_map.get("otel"))
817
+ if otel_config and otel_config.get("enabled", True):
818
+ from sqlspec.extensions import otel as otel_extension
819
+
820
+ updated = otel_extension.enable_tracing(
821
+ base_config=updated,
822
+ resource_attributes=otel_config.get("resource_attributes"),
823
+ tracer_provider=otel_config.get("tracer_provider"),
824
+ tracer_provider_factory=otel_config.get("tracer_provider_factory"),
825
+ enable_spans=otel_config.get("enable_spans", True),
826
+ )
827
+
828
+ prom_config = cast("PrometheusConfig | None", config_map.get("prometheus"))
829
+ if prom_config and prom_config.get("enabled", True):
830
+ from sqlspec.extensions import prometheus as prometheus_extension
831
+
832
+ label_names = tuple(prom_config.get("label_names", ("driver", "operation")))
833
+ duration_buckets = prom_config.get("duration_buckets")
834
+ if duration_buckets is not None:
835
+ duration_buckets = tuple(duration_buckets)
836
+
837
+ updated = prometheus_extension.enable_metrics(
838
+ base_config=updated,
839
+ namespace=prom_config.get("namespace", "sqlspec"),
840
+ subsystem=prom_config.get("subsystem", "driver"),
841
+ registry=prom_config.get("registry"),
842
+ label_names=label_names,
843
+ duration_buckets=duration_buckets,
844
+ )
845
+
846
+ if updated is not self.observability_config:
847
+ self.observability_config = updated
848
+
849
+ def _promote_driver_feature_hooks(self) -> None:
850
+ lifecycle_hooks: dict[str, list[Callable[[dict[str, Any]], None]]] = {}
851
+
852
+ for hook_name, context_key in DRIVER_FEATURE_LIFECYCLE_HOOKS.items():
853
+ callback = self.driver_features.pop(hook_name, None)
854
+ if callback is None:
855
+ continue
856
+ callbacks = callback if isinstance(callback, (list, tuple)) else (callback,) # pyright: ignore
857
+ wrapped_callbacks = [self._wrap_driver_feature_hook(cb, context_key) for cb in callbacks] # pyright: ignore
858
+ lifecycle_hooks.setdefault(hook_name, []).extend(wrapped_callbacks)
859
+
860
+ if not lifecycle_hooks:
861
+ return
862
+
863
+ lifecycle_config = cast("LifecycleConfig", lifecycle_hooks)
864
+ override = ObservabilityConfig(lifecycle=lifecycle_config)
865
+ if self.observability_config is None:
866
+ self.observability_config = override
867
+ else:
868
+ self.observability_config = ObservabilityConfig.merge(self.observability_config, override)
869
+
870
+ @staticmethod
871
+ def _wrap_driver_feature_hook(
872
+ callback: Callable[..., Any], context_key: str | None
873
+ ) -> Callable[[dict[str, Any]], None]:
874
+ try:
875
+ hook_signature: Signature = signature(callback)
876
+ except (TypeError, ValueError): # pragma: no cover - builtins without signatures
877
+ hook_signature = Signature()
878
+
879
+ positional_params = [
880
+ param
881
+ for param in hook_signature.parameters.values()
882
+ if param.kind in {param.POSITIONAL_ONLY, param.POSITIONAL_OR_KEYWORD} and param.default is param.empty
883
+ ]
884
+ expects_argument = bool(positional_params)
885
+
886
+ return _DriverFeatureHookWrapper(callback, context_key, expects_argument)
887
+
888
+ def attach_observability(self, registry_config: "ObservabilityConfig | None") -> None:
889
+ """Attach merged observability runtime composed from registry and adapter overrides."""
890
+ merged = ObservabilityConfig.merge(registry_config, self.observability_config)
891
+ self._observability_runtime = ObservabilityRuntime(
892
+ merged, bind_key=self.bind_key, config_name=type(self).__name__
893
+ )
894
+
895
+ def get_observability_runtime(self) -> "ObservabilityRuntime":
896
+ """Return the attached runtime, creating a disabled instance when missing."""
897
+
898
+ if self._observability_runtime is None:
899
+ self.attach_observability(None)
900
+ assert self._observability_runtime is not None
901
+ return self._observability_runtime
902
+
903
+ def _prepare_driver(self, driver: DriverT) -> DriverT:
904
+ """Attach observability runtime to driver instances before returning them."""
905
+
906
+ driver.attach_observability(self.get_observability_runtime())
907
+ return driver
908
+
909
+ @staticmethod
910
+ def _dependency_available(checker: "Callable[[], None]") -> bool:
911
+ try:
912
+ checker()
913
+ except MissingDependencyError:
914
+ return False
915
+ return True
916
+
917
+ @abstractmethod
918
+ def create_connection(self) -> "ConnectionT | Awaitable[ConnectionT]":
919
+ """Create and return a new database connection."""
920
+ raise NotImplementedError
921
+
922
+ @abstractmethod
923
+ def provide_connection(
924
+ self, *args: Any, **kwargs: Any
925
+ ) -> "AbstractContextManager[ConnectionT] | AbstractAsyncContextManager[ConnectionT]":
926
+ """Provide a database connection context manager."""
927
+ raise NotImplementedError
928
+
929
+ @abstractmethod
930
+ def provide_session(
931
+ self, *args: Any, **kwargs: Any
932
+ ) -> "AbstractContextManager[DriverT] | AbstractAsyncContextManager[DriverT]":
933
+ """Provide a database session context manager."""
934
+ raise NotImplementedError
935
+
936
+ @abstractmethod
937
+ def create_pool(self) -> "PoolT | Awaitable[PoolT]":
938
+ """Create and return connection pool."""
939
+ raise NotImplementedError
940
+
941
+ @abstractmethod
942
+ def close_pool(self) -> "Awaitable[None] | None":
943
+ """Terminate the connection pool."""
944
+ raise NotImplementedError
945
+
946
+ @abstractmethod
947
+ def provide_pool(
948
+ self, *args: Any, **kwargs: Any
949
+ ) -> "PoolT | Awaitable[PoolT] | AbstractContextManager[PoolT] | AbstractAsyncContextManager[PoolT]":
950
+ """Provide pool instance."""
951
+ raise NotImplementedError
952
+
953
+ def get_signature_namespace(self) -> "dict[str, Any]":
954
+ """Get the signature namespace for this database configuration.
955
+
956
+ Returns a dictionary of type names to objects (classes, functions, or
957
+ other callables) that should be registered with Litestar's signature
958
+ namespace to prevent serialization attempts on database-specific
959
+ structures.
960
+
961
+ Returns:
962
+ Dictionary mapping type names to objects.
963
+ """
964
+ return {}
965
+
966
+ def _initialize_migration_components(self) -> None:
967
+ """Initialize migration loader and migration command helpers."""
968
+ runtime = self.get_observability_runtime()
969
+ self._migration_loader = SQLFileLoader(runtime=runtime)
970
+ self._migration_commands = create_migration_commands(self) # pyright: ignore
971
+
972
+ def _ensure_migration_loader(self) -> "SQLFileLoader":
973
+ """Get the migration SQL loader and auto-load files if needed.
974
+
975
+ Returns:
976
+ SQLFileLoader instance for migration files.
977
+ """
978
+ migration_config = self.migration_config or {}
979
+ script_location = migration_config.get("script_location", "migrations")
980
+
981
+ migration_path = Path(script_location)
982
+ if migration_path.exists() and not self._migration_loader.list_files():
983
+ self._migration_loader.load_sql(migration_path)
984
+ logger.debug("Auto-loaded migration SQL files from %s", migration_path)
985
+
986
+ return self._migration_loader
987
+
988
+ def _ensure_migration_commands(self) -> "SyncMigrationCommands[Any] | AsyncMigrationCommands[Any]":
989
+ """Get the migration commands instance.
990
+
991
+ Returns:
992
+ MigrationCommands instance for this config.
993
+ """
994
+ return self._migration_commands
995
+
996
+ def get_migration_loader(self) -> "SQLFileLoader":
997
+ """Get the SQL loader for migration files.
998
+
999
+ Provides access to migration SQL files loaded from the configured
1000
+ script_location directory. Files are loaded lazily on first access.
1001
+
1002
+ Returns:
1003
+ SQLFileLoader instance with migration files loaded.
1004
+ """
1005
+ return self._ensure_migration_loader()
1006
+
1007
+ def load_migration_sql_files(self, *paths: "str | Path") -> None:
1008
+ """Load additional migration SQL files from specified paths.
1009
+
1010
+ Args:
1011
+ *paths: One or more file paths or directory paths to load migration SQL files from.
1012
+ """
1013
+
1014
+ loader = self._ensure_migration_loader()
1015
+ for path in paths:
1016
+ path_obj = Path(path)
1017
+ if path_obj.exists():
1018
+ loader.load_sql(path_obj)
1019
+ logger.debug("Loaded migration SQL files from %s", path_obj)
1020
+ else:
1021
+ logger.warning("Migration path does not exist: %s", path_obj)
1022
+
1023
+ def get_migration_commands(self) -> "SyncMigrationCommands[Any] | AsyncMigrationCommands[Any]":
1024
+ """Get migration commands for this configuration.
1025
+
1026
+ Returns:
1027
+ MigrationCommands instance configured for this database.
1028
+ """
1029
+ return self._ensure_migration_commands()
1030
+
1031
+ @abstractmethod
1032
+ def migrate_up(
1033
+ self, revision: str = "head", allow_missing: bool = False, auto_sync: bool = True, dry_run: bool = False
1034
+ ) -> "Awaitable[None] | None":
1035
+ """Apply database migrations up to specified revision.
1036
+
1037
+ Args:
1038
+ revision: Target revision or "head" for latest. Defaults to "head".
1039
+ allow_missing: Allow out-of-order migrations. Defaults to False.
1040
+ auto_sync: Auto-reconcile renamed migrations. Defaults to True.
1041
+ dry_run: Show what would be done without applying. Defaults to False.
1042
+ """
1043
+ raise NotImplementedError
1044
+
1045
+ @abstractmethod
1046
+ def migrate_down(self, revision: str = "-1", *, dry_run: bool = False) -> "Awaitable[None] | None":
1047
+ """Apply database migrations down to specified revision.
1048
+
1049
+ Args:
1050
+ revision: Target revision, "-1" for one step back, or "base" for all migrations. Defaults to "-1".
1051
+ dry_run: Show what would be done without applying. Defaults to False.
1052
+ """
1053
+ raise NotImplementedError
1054
+
1055
+ @abstractmethod
1056
+ def get_current_migration(self, verbose: bool = False) -> "Awaitable[str | None] | str | None":
1057
+ """Get the current migration version.
1058
+
1059
+ Args:
1060
+ verbose: Whether to show detailed migration history. Defaults to False.
1061
+
1062
+ Returns:
1063
+ Current migration version or None if no migrations applied.
1064
+ """
1065
+ raise NotImplementedError
1066
+
1067
+ @abstractmethod
1068
+ def create_migration(self, message: str, file_type: str = "sql") -> "Awaitable[None] | None":
1069
+ """Create a new migration file.
1070
+
1071
+ Args:
1072
+ message: Description for the migration.
1073
+ file_type: Type of migration file to create ('sql' or 'py'). Defaults to 'sql'.
1074
+ """
1075
+ raise NotImplementedError
1076
+
1077
+ @abstractmethod
1078
+ def init_migrations(self, directory: "str | None" = None, package: bool = True) -> "Awaitable[None] | None":
1079
+ """Initialize migration directory structure.
1080
+
1081
+ Args:
1082
+ directory: Directory to initialize migrations in. Uses script_location from migration_config if not provided.
1083
+ package: Whether to create __init__.py file. Defaults to True.
1084
+ """
1085
+ raise NotImplementedError
1086
+
1087
+ @abstractmethod
1088
+ def stamp_migration(self, revision: str) -> "Awaitable[None] | None":
1089
+ """Mark database as being at a specific revision without running migrations.
1090
+
1091
+ Args:
1092
+ revision: The revision to stamp.
1093
+ """
1094
+ raise NotImplementedError
1095
+
1096
+ @abstractmethod
1097
+ def fix_migrations(
1098
+ self, dry_run: bool = False, update_database: bool = True, yes: bool = False
1099
+ ) -> "Awaitable[None] | None":
1100
+ """Convert timestamp migrations to sequential format.
1101
+
1102
+ Implements hybrid versioning workflow where development uses timestamps
1103
+ and production uses sequential numbers. Creates backup before changes
1104
+ and provides rollback on errors.
1105
+
1106
+ Args:
1107
+ dry_run: Preview changes without applying. Defaults to False.
1108
+ update_database: Update migration records in database. Defaults to True.
1109
+ yes: Skip confirmation prompt. Defaults to False.
1110
+ """
1111
+ raise NotImplementedError
1112
+
1113
+
1114
+ class NoPoolSyncConfig(DatabaseConfigProtocol[ConnectionT, None, DriverT]):
1115
+ """Base class for sync database configurations that do not implement a pool."""
1116
+
1117
+ __slots__ = ("connection_config",)
1118
+ is_async: "ClassVar[bool]" = False
1119
+ supports_connection_pooling: "ClassVar[bool]" = False
1120
+ migration_tracker_type: "ClassVar[type[Any]]" = SyncMigrationTracker
1121
+
1122
+ def __init__(
1123
+ self,
1124
+ *,
1125
+ connection_config: dict[str, Any] | None = None,
1126
+ connection_instance: "Any" = None,
1127
+ migration_config: "dict[str, Any] | MigrationConfig | None" = None,
1128
+ statement_config: "StatementConfig | None" = None,
1129
+ driver_features: "dict[str, Any] | None" = None,
1130
+ bind_key: "str | None" = None,
1131
+ extension_config: "ExtensionConfigs | None" = None,
1132
+ observability_config: "ObservabilityConfig | None" = None,
1133
+ ) -> None:
1134
+ self.bind_key = bind_key
1135
+ self.connection_instance = connection_instance
1136
+ self.connection_config = connection_config or {}
1137
+ self.extension_config = extension_config or {}
1138
+ self.migration_config: dict[str, Any] | MigrationConfig = migration_config or {}
1139
+ self._ensure_extension_migrations()
1140
+ self._init_observability(observability_config)
1141
+ self._initialize_migration_components()
1142
+
1143
+ if statement_config is None:
1144
+ default_parameter_config = ParameterStyleConfig(
1145
+ default_parameter_style=ParameterStyle.QMARK, supported_parameter_styles={ParameterStyle.QMARK}
1146
+ )
1147
+ self.statement_config = StatementConfig(dialect="sqlite", parameter_config=default_parameter_config)
1148
+ else:
1149
+ self.statement_config = statement_config
1150
+ self.driver_features = driver_features or {}
1151
+ self._storage_capabilities = None
1152
+ self.driver_features.setdefault("storage_capabilities", self.storage_capabilities())
1153
+ self._promote_driver_feature_hooks()
1154
+ self._configure_observability_extensions()
1155
+
1156
+ def create_connection(self) -> ConnectionT:
1157
+ """Create a database connection."""
1158
+ raise NotImplementedError
1159
+
1160
+ def provide_connection(self, *args: Any, **kwargs: Any) -> "AbstractContextManager[ConnectionT]":
1161
+ """Provide a database connection context manager."""
1162
+ raise NotImplementedError
1163
+
1164
+ def provide_session(
1165
+ self, *args: Any, statement_config: "StatementConfig | None" = None, **kwargs: Any
1166
+ ) -> "AbstractContextManager[DriverT]":
1167
+ """Provide a database session context manager."""
1168
+ raise NotImplementedError
1169
+
1170
+ def create_pool(self) -> None:
1171
+ return None
1172
+
1173
+ def close_pool(self) -> None:
1174
+ return None
1175
+
1176
+ def provide_pool(self, *args: Any, **kwargs: Any) -> None:
1177
+ return None
1178
+
1179
+ def migrate_up(
1180
+ self, revision: str = "head", allow_missing: bool = False, auto_sync: bool = True, dry_run: bool = False
1181
+ ) -> None:
1182
+ """Apply database migrations up to specified revision.
1183
+
1184
+ Args:
1185
+ revision: Target revision or "head" for latest.
1186
+ allow_missing: Allow out-of-order migrations.
1187
+ auto_sync: Auto-reconcile renamed migrations.
1188
+ dry_run: Show what would be done without applying.
1189
+ """
1190
+ commands = self._ensure_migration_commands()
1191
+ commands.upgrade(revision, allow_missing, auto_sync, dry_run)
1192
+
1193
+ def migrate_down(self, revision: str = "-1", *, dry_run: bool = False) -> None:
1194
+ """Apply database migrations down to specified revision.
1195
+
1196
+ Args:
1197
+ revision: Target revision, "-1" for one step back, or "base" for all migrations.
1198
+ dry_run: Show what would be done without applying.
1199
+ """
1200
+ commands = self._ensure_migration_commands()
1201
+ commands.downgrade(revision, dry_run=dry_run)
1202
+
1203
+ def get_current_migration(self, verbose: bool = False) -> "str | None":
1204
+ """Get the current migration version.
1205
+
1206
+ Args:
1207
+ verbose: Whether to show detailed migration history.
1208
+
1209
+ Returns:
1210
+ Current migration version or None if no migrations applied.
1211
+ """
1212
+ commands = cast("SyncMigrationCommands[Any]", self._ensure_migration_commands())
1213
+ return commands.current(verbose=verbose)
1214
+
1215
+ def create_migration(self, message: str, file_type: str = "sql") -> None:
1216
+ """Create a new migration file.
1217
+
1218
+ Args:
1219
+ message: Description for the migration.
1220
+ file_type: Type of migration file to create ('sql' or 'py').
1221
+ """
1222
+ commands = self._ensure_migration_commands()
1223
+ commands.revision(message, file_type)
1224
+
1225
+ def init_migrations(self, directory: "str | None" = None, package: bool = True) -> None:
1226
+ """Initialize migration directory structure.
1227
+
1228
+ Args:
1229
+ directory: Directory to initialize migrations in.
1230
+ package: Whether to create __init__.py file.
1231
+ """
1232
+ if directory is None:
1233
+ migration_config = self.migration_config or {}
1234
+ directory = str(migration_config.get("script_location") or "migrations")
1235
+
1236
+ commands = self._ensure_migration_commands()
1237
+ assert directory is not None
1238
+ commands.init(directory, package)
1239
+
1240
+ def stamp_migration(self, revision: str) -> None:
1241
+ """Mark database as being at a specific revision without running migrations.
1242
+
1243
+ Args:
1244
+ revision: The revision to stamp.
1245
+ """
1246
+ commands = self._ensure_migration_commands()
1247
+ commands.stamp(revision)
1248
+
1249
+ def fix_migrations(self, dry_run: bool = False, update_database: bool = True, yes: bool = False) -> None:
1250
+ """Convert timestamp migrations to sequential format.
1251
+
1252
+ Args:
1253
+ dry_run: Preview changes without applying.
1254
+ update_database: Update migration records in database.
1255
+ yes: Skip confirmation prompt.
1256
+ """
1257
+ commands = self._ensure_migration_commands()
1258
+ commands.fix(dry_run, update_database, yes)
1259
+
1260
+
1261
+ class NoPoolAsyncConfig(DatabaseConfigProtocol[ConnectionT, None, DriverT]):
1262
+ """Base class for async database configurations that do not implement a pool."""
1263
+
1264
+ __slots__ = ("connection_config",)
1265
+ is_async: "ClassVar[bool]" = True
1266
+ supports_connection_pooling: "ClassVar[bool]" = False
1267
+ migration_tracker_type: "ClassVar[type[Any]]" = AsyncMigrationTracker
1268
+
1269
+ def __init__(
1270
+ self,
1271
+ *,
1272
+ connection_config: "dict[str, Any] | None" = None,
1273
+ connection_instance: "Any" = None,
1274
+ migration_config: "dict[str, Any] | MigrationConfig | None" = None,
1275
+ statement_config: "StatementConfig | None" = None,
1276
+ driver_features: "dict[str, Any] | None" = None,
1277
+ bind_key: "str | None" = None,
1278
+ extension_config: "ExtensionConfigs | None" = None,
1279
+ observability_config: "ObservabilityConfig | None" = None,
1280
+ ) -> None:
1281
+ self.bind_key = bind_key
1282
+ self.connection_instance = connection_instance
1283
+ self.connection_config = connection_config or {}
1284
+ self.extension_config = extension_config or {}
1285
+ self.migration_config: dict[str, Any] | MigrationConfig = migration_config or {}
1286
+ self._ensure_extension_migrations()
1287
+ self._init_observability(observability_config)
1288
+ self._initialize_migration_components()
1289
+
1290
+ if statement_config is None:
1291
+ default_parameter_config = ParameterStyleConfig(
1292
+ default_parameter_style=ParameterStyle.QMARK, supported_parameter_styles={ParameterStyle.QMARK}
1293
+ )
1294
+ self.statement_config = StatementConfig(dialect="sqlite", parameter_config=default_parameter_config)
1295
+ else:
1296
+ self.statement_config = statement_config
1297
+ self.driver_features = driver_features or {}
1298
+ self._promote_driver_feature_hooks()
1299
+ self._configure_observability_extensions()
1300
+
1301
+ async def create_connection(self) -> ConnectionT:
1302
+ """Create a database connection."""
1303
+ raise NotImplementedError
1304
+
1305
+ def provide_connection(self, *args: Any, **kwargs: Any) -> "AbstractAsyncContextManager[ConnectionT]":
1306
+ """Provide a database connection context manager."""
1307
+ raise NotImplementedError
1308
+
1309
+ def provide_session(
1310
+ self, *args: Any, statement_config: "StatementConfig | None" = None, **kwargs: Any
1311
+ ) -> "AbstractAsyncContextManager[DriverT]":
1312
+ """Provide a database session context manager."""
1313
+ raise NotImplementedError
1314
+
1315
+ async def create_pool(self) -> None:
1316
+ return None
1317
+
1318
+ async def close_pool(self) -> None:
1319
+ return None
1320
+
1321
+ def provide_pool(self, *args: Any, **kwargs: Any) -> None:
1322
+ return None
1323
+
1324
+ async def migrate_up(
1325
+ self, revision: str = "head", allow_missing: bool = False, auto_sync: bool = True, dry_run: bool = False
1326
+ ) -> None:
1327
+ """Apply database migrations up to specified revision.
1328
+
1329
+ Args:
1330
+ revision: Target revision or "head" for latest.
1331
+ allow_missing: Allow out-of-order migrations.
1332
+ auto_sync: Auto-reconcile renamed migrations.
1333
+ dry_run: Show what would be done without applying.
1334
+ """
1335
+ commands = cast("AsyncMigrationCommands[Any]", self._ensure_migration_commands())
1336
+ await commands.upgrade(revision, allow_missing, auto_sync, dry_run)
1337
+
1338
+ async def migrate_down(self, revision: str = "-1", *, dry_run: bool = False) -> None:
1339
+ """Apply database migrations down to specified revision.
1340
+
1341
+ Args:
1342
+ revision: Target revision, "-1" for one step back, or "base" for all migrations.
1343
+ dry_run: Show what would be done without applying.
1344
+ """
1345
+ commands = cast("AsyncMigrationCommands[Any]", self._ensure_migration_commands())
1346
+ await commands.downgrade(revision, dry_run=dry_run)
1347
+
1348
+ async def get_current_migration(self, verbose: bool = False) -> "str | None":
1349
+ """Get the current migration version.
1350
+
1351
+ Args:
1352
+ verbose: Whether to show detailed migration history.
1353
+
1354
+ Returns:
1355
+ Current migration version or None if no migrations applied.
1356
+ """
1357
+ commands = cast("AsyncMigrationCommands[Any]", self._ensure_migration_commands())
1358
+ return await commands.current(verbose=verbose)
1359
+
1360
+ async def create_migration(self, message: str, file_type: str = "sql") -> None:
1361
+ """Create a new migration file.
1362
+
1363
+ Args:
1364
+ message: Description for the migration.
1365
+ file_type: Type of migration file to create ('sql' or 'py').
1366
+ """
1367
+ commands = cast("AsyncMigrationCommands[Any]", self._ensure_migration_commands())
1368
+ await commands.revision(message, file_type)
1369
+
1370
+ async def init_migrations(self, directory: "str | None" = None, package: bool = True) -> None:
1371
+ """Initialize migration directory structure.
1372
+
1373
+ Args:
1374
+ directory: Directory to initialize migrations in.
1375
+ package: Whether to create __init__.py file.
1376
+ """
1377
+ if directory is None:
1378
+ migration_config = self.migration_config or {}
1379
+ directory = str(migration_config.get("script_location") or "migrations")
1380
+
1381
+ commands = cast("AsyncMigrationCommands[Any]", self._ensure_migration_commands())
1382
+ assert directory is not None
1383
+ await commands.init(directory, package)
1384
+
1385
+ async def stamp_migration(self, revision: str) -> None:
1386
+ """Mark database as being at a specific revision without running migrations.
1387
+
1388
+ Args:
1389
+ revision: The revision to stamp.
1390
+ """
1391
+ commands = cast("AsyncMigrationCommands[Any]", self._ensure_migration_commands())
1392
+ await commands.stamp(revision)
1393
+
1394
+ async def fix_migrations(self, dry_run: bool = False, update_database: bool = True, yes: bool = False) -> None:
1395
+ """Convert timestamp migrations to sequential format.
1396
+
1397
+ Args:
1398
+ dry_run: Preview changes without applying.
1399
+ update_database: Update migration records in database.
1400
+ yes: Skip confirmation prompt.
1401
+ """
1402
+ commands = cast("AsyncMigrationCommands[Any]", self._ensure_migration_commands())
1403
+ await commands.fix(dry_run, update_database, yes)
1404
+
1405
+
1406
+ class SyncDatabaseConfig(DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]):
1407
+ """Base class for sync database configurations with connection pooling."""
1408
+
1409
+ __slots__ = ("connection_config",)
1410
+ is_async: "ClassVar[bool]" = False
1411
+ supports_connection_pooling: "ClassVar[bool]" = True
1412
+ migration_tracker_type: "ClassVar[type[Any]]" = SyncMigrationTracker
1413
+
1414
+ def __init__(
1415
+ self,
1416
+ *,
1417
+ connection_config: "dict[str, Any] | None" = None,
1418
+ connection_instance: "PoolT | None" = None,
1419
+ migration_config: "dict[str, Any] | MigrationConfig | None" = None,
1420
+ statement_config: "StatementConfig | None" = None,
1421
+ driver_features: "dict[str, Any] | None" = None,
1422
+ bind_key: "str | None" = None,
1423
+ extension_config: "ExtensionConfigs | None" = None,
1424
+ observability_config: "ObservabilityConfig | None" = None,
1425
+ **kwargs: Any,
1426
+ ) -> None:
1427
+ self.bind_key = bind_key
1428
+ self.connection_instance = connection_instance
1429
+ self.connection_config = connection_config or {}
1430
+ self.extension_config = extension_config or {}
1431
+ self.migration_config: dict[str, Any] | MigrationConfig = migration_config or {}
1432
+ self._ensure_extension_migrations()
1433
+ self._init_observability(observability_config)
1434
+ self._initialize_migration_components()
1435
+
1436
+ if statement_config is None:
1437
+ default_parameter_config = ParameterStyleConfig(
1438
+ default_parameter_style=ParameterStyle.QMARK, supported_parameter_styles={ParameterStyle.QMARK}
1439
+ )
1440
+ self.statement_config = StatementConfig(dialect="postgres", parameter_config=default_parameter_config)
1441
+ else:
1442
+ self.statement_config = statement_config
1443
+ self.driver_features = driver_features or {}
1444
+ self._storage_capabilities = None
1445
+ self.driver_features.setdefault("storage_capabilities", self.storage_capabilities())
1446
+ self._promote_driver_feature_hooks()
1447
+ self._configure_observability_extensions()
1448
+
1449
+ def create_pool(self) -> PoolT:
1450
+ """Create and return the connection pool.
1451
+
1452
+ Returns:
1453
+ The created pool.
1454
+ """
1455
+ if self.connection_instance is not None:
1456
+ return self.connection_instance
1457
+ self.connection_instance = self._create_pool()
1458
+ self.get_observability_runtime().emit_pool_create(self.connection_instance)
1459
+ return self.connection_instance
1460
+
1461
+ def close_pool(self) -> None:
1462
+ """Close the connection pool."""
1463
+ pool = self.connection_instance
1464
+ self._close_pool()
1465
+ if pool is not None:
1466
+ self.get_observability_runtime().emit_pool_destroy(pool)
1467
+ self.connection_instance = None
1468
+
1469
+ def provide_pool(self, *args: Any, **kwargs: Any) -> PoolT:
1470
+ """Provide pool instance."""
1471
+ if self.connection_instance is None:
1472
+ self.connection_instance = self.create_pool()
1473
+ return self.connection_instance
1474
+
1475
+ def create_connection(self) -> ConnectionT:
1476
+ """Create a database connection."""
1477
+ raise NotImplementedError
1478
+
1479
+ def provide_connection(self, *args: Any, **kwargs: Any) -> "AbstractContextManager[ConnectionT]":
1480
+ """Provide a database connection context manager."""
1481
+ raise NotImplementedError
1482
+
1483
+ def provide_session(
1484
+ self, *args: Any, statement_config: "StatementConfig | None" = None, **kwargs: Any
1485
+ ) -> "AbstractContextManager[DriverT]":
1486
+ """Provide a database session context manager."""
1487
+ raise NotImplementedError
1488
+
1489
+ @abstractmethod
1490
+ def _create_pool(self) -> PoolT:
1491
+ """Actual pool creation implementation."""
1492
+ raise NotImplementedError
1493
+
1494
+ @abstractmethod
1495
+ def _close_pool(self) -> None:
1496
+ """Actual pool destruction implementation."""
1497
+ raise NotImplementedError
1498
+
1499
+ def migrate_up(
1500
+ self, revision: str = "head", allow_missing: bool = False, auto_sync: bool = True, dry_run: bool = False
1501
+ ) -> None:
1502
+ """Apply database migrations up to specified revision.
1503
+
1504
+ Args:
1505
+ revision: Target revision or "head" for latest.
1506
+ allow_missing: Allow out-of-order migrations.
1507
+ auto_sync: Auto-reconcile renamed migrations.
1508
+ dry_run: Show what would be done without applying.
1509
+ """
1510
+ commands = self._ensure_migration_commands()
1511
+ commands.upgrade(revision, allow_missing, auto_sync, dry_run)
1512
+
1513
+ def migrate_down(self, revision: str = "-1", *, dry_run: bool = False) -> None:
1514
+ """Apply database migrations down to specified revision.
1515
+
1516
+ Args:
1517
+ revision: Target revision, "-1" for one step back, or "base" for all migrations.
1518
+ dry_run: Show what would be done without applying.
1519
+ """
1520
+ commands = self._ensure_migration_commands()
1521
+ commands.downgrade(revision, dry_run=dry_run)
1522
+
1523
+ def get_current_migration(self, verbose: bool = False) -> "str | None":
1524
+ """Get the current migration version.
1525
+
1526
+ Args:
1527
+ verbose: Whether to show detailed migration history.
1528
+
1529
+ Returns:
1530
+ Current migration version or None if no migrations applied.
1531
+ """
1532
+ commands = cast("SyncMigrationCommands[Any]", self._ensure_migration_commands())
1533
+ return commands.current(verbose=verbose)
1534
+
1535
+ def create_migration(self, message: str, file_type: str = "sql") -> None:
1536
+ """Create a new migration file.
1537
+
1538
+ Args:
1539
+ message: Description for the migration.
1540
+ file_type: Type of migration file to create ('sql' or 'py').
1541
+ """
1542
+ commands = self._ensure_migration_commands()
1543
+ commands.revision(message, file_type)
1544
+
1545
+ def init_migrations(self, directory: "str | None" = None, package: bool = True) -> None:
1546
+ """Initialize migration directory structure.
1547
+
1548
+ Args:
1549
+ directory: Directory to initialize migrations in.
1550
+ package: Whether to create __init__.py file.
1551
+ """
1552
+ if directory is None:
1553
+ migration_config = self.migration_config or {}
1554
+ directory = str(migration_config.get("script_location") or "migrations")
1555
+
1556
+ commands = self._ensure_migration_commands()
1557
+ assert directory is not None
1558
+ commands.init(directory, package)
1559
+
1560
+ def stamp_migration(self, revision: str) -> None:
1561
+ """Mark database as being at a specific revision without running migrations.
1562
+
1563
+ Args:
1564
+ revision: The revision to stamp.
1565
+ """
1566
+ commands = self._ensure_migration_commands()
1567
+ commands.stamp(revision)
1568
+
1569
+ def fix_migrations(self, dry_run: bool = False, update_database: bool = True, yes: bool = False) -> None:
1570
+ """Convert timestamp migrations to sequential format.
1571
+
1572
+ Args:
1573
+ dry_run: Preview changes without applying.
1574
+ update_database: Update migration records in database.
1575
+ yes: Skip confirmation prompt.
1576
+ """
1577
+ commands = self._ensure_migration_commands()
1578
+ commands.fix(dry_run, update_database, yes)
1579
+
1580
+
1581
+ class AsyncDatabaseConfig(DatabaseConfigProtocol[ConnectionT, PoolT, DriverT]):
1582
+ """Base class for async database configurations with connection pooling."""
1583
+
1584
+ __slots__ = ("connection_config",)
1585
+ is_async: "ClassVar[bool]" = True
1586
+ supports_connection_pooling: "ClassVar[bool]" = True
1587
+ migration_tracker_type: "ClassVar[type[Any]]" = AsyncMigrationTracker
1588
+
1589
+ def __init__(
1590
+ self,
1591
+ *,
1592
+ connection_config: "dict[str, Any] | None" = None,
1593
+ connection_instance: "PoolT | None" = None,
1594
+ migration_config: "dict[str, Any] | MigrationConfig | None" = None,
1595
+ statement_config: "StatementConfig | None" = None,
1596
+ driver_features: "dict[str, Any] | None" = None,
1597
+ bind_key: "str | None" = None,
1598
+ extension_config: "ExtensionConfigs | None" = None,
1599
+ observability_config: "ObservabilityConfig | None" = None,
1600
+ **kwargs: Any,
1601
+ ) -> None:
1602
+ self.bind_key = bind_key
1603
+ self.connection_instance = connection_instance
1604
+ self.connection_config = connection_config or {}
1605
+ self.extension_config = extension_config or {}
1606
+ self.migration_config: dict[str, Any] | MigrationConfig = migration_config or {}
1607
+ self._ensure_extension_migrations()
1608
+ self._init_observability(observability_config)
1609
+ self._initialize_migration_components()
1610
+
1611
+ if statement_config is None:
1612
+ self.statement_config = StatementConfig(
1613
+ parameter_config=ParameterStyleConfig(
1614
+ default_parameter_style=ParameterStyle.QMARK, supported_parameter_styles={ParameterStyle.QMARK}
1615
+ ),
1616
+ dialect="postgres",
1617
+ )
1618
+ else:
1619
+ self.statement_config = statement_config
1620
+ self.driver_features = driver_features or {}
1621
+ self._storage_capabilities = None
1622
+ self.driver_features.setdefault("storage_capabilities", self.storage_capabilities())
1623
+ self._promote_driver_feature_hooks()
1624
+ self._configure_observability_extensions()
1625
+
1626
+ async def create_pool(self) -> PoolT:
1627
+ """Create and return the connection pool.
1628
+
1629
+ Returns:
1630
+ The created pool.
1631
+ """
1632
+ if self.connection_instance is not None:
1633
+ return self.connection_instance
1634
+ self.connection_instance = await self._create_pool()
1635
+ self.get_observability_runtime().emit_pool_create(self.connection_instance)
1636
+ return self.connection_instance
1637
+
1638
+ async def close_pool(self) -> None:
1639
+ """Close the connection pool."""
1640
+ pool = self.connection_instance
1641
+ await self._close_pool()
1642
+ if pool is not None:
1643
+ self.get_observability_runtime().emit_pool_destroy(pool)
1644
+ self.connection_instance = None
1645
+
1646
+ async def provide_pool(self, *args: Any, **kwargs: Any) -> PoolT:
1647
+ """Provide pool instance."""
1648
+ if self.connection_instance is None:
1649
+ self.connection_instance = await self.create_pool()
1650
+ return self.connection_instance
1651
+
1652
+ async def create_connection(self) -> ConnectionT:
1653
+ """Create a database connection."""
1654
+ raise NotImplementedError
1655
+
1656
+ def provide_connection(self, *args: Any, **kwargs: Any) -> "AbstractAsyncContextManager[ConnectionT]":
1657
+ """Provide a database connection context manager."""
1658
+ raise NotImplementedError
1659
+
1660
+ def provide_session(
1661
+ self, *args: Any, statement_config: "StatementConfig | None" = None, **kwargs: Any
1662
+ ) -> "AbstractAsyncContextManager[DriverT]":
1663
+ """Provide a database session context manager."""
1664
+ raise NotImplementedError
1665
+
1666
+ @abstractmethod
1667
+ async def _create_pool(self) -> PoolT:
1668
+ """Actual async pool creation implementation."""
1669
+ raise NotImplementedError
1670
+
1671
+ @abstractmethod
1672
+ async def _close_pool(self) -> None:
1673
+ """Actual async pool destruction implementation."""
1674
+ raise NotImplementedError
1675
+
1676
+ async def migrate_up(
1677
+ self, revision: str = "head", allow_missing: bool = False, auto_sync: bool = True, dry_run: bool = False
1678
+ ) -> None:
1679
+ """Apply database migrations up to specified revision.
1680
+
1681
+ Args:
1682
+ revision: Target revision or "head" for latest.
1683
+ allow_missing: Allow out-of-order migrations.
1684
+ auto_sync: Auto-reconcile renamed migrations.
1685
+ dry_run: Show what would be done without applying.
1686
+ """
1687
+ commands = cast("AsyncMigrationCommands[Any]", self._ensure_migration_commands())
1688
+ await commands.upgrade(revision, allow_missing, auto_sync, dry_run)
1689
+
1690
+ async def migrate_down(self, revision: str = "-1", *, dry_run: bool = False) -> None:
1691
+ """Apply database migrations down to specified revision.
1692
+
1693
+ Args:
1694
+ revision: Target revision, "-1" for one step back, or "base" for all migrations.
1695
+ dry_run: Show what would be done without applying.
1696
+ """
1697
+ commands = cast("AsyncMigrationCommands[Any]", self._ensure_migration_commands())
1698
+ await commands.downgrade(revision, dry_run=dry_run)
1699
+
1700
+ async def get_current_migration(self, verbose: bool = False) -> "str | None":
1701
+ """Get the current migration version.
1702
+
1703
+ Args:
1704
+ verbose: Whether to show detailed migration history.
1705
+
1706
+ Returns:
1707
+ Current migration version or None if no migrations applied.
1708
+ """
1709
+ commands = cast("AsyncMigrationCommands[Any]", self._ensure_migration_commands())
1710
+ return await commands.current(verbose=verbose)
1711
+
1712
+ async def create_migration(self, message: str, file_type: str = "sql") -> None:
1713
+ """Create a new migration file.
1714
+
1715
+ Args:
1716
+ message: Description for the migration.
1717
+ file_type: Type of migration file to create ('sql' or 'py').
1718
+ """
1719
+ commands = cast("AsyncMigrationCommands[Any]", self._ensure_migration_commands())
1720
+ await commands.revision(message, file_type)
1721
+
1722
+ async def init_migrations(self, directory: "str | None" = None, package: bool = True) -> None:
1723
+ """Initialize migration directory structure.
1724
+
1725
+ Args:
1726
+ directory: Directory to initialize migrations in.
1727
+ package: Whether to create __init__.py file.
1728
+ """
1729
+ if directory is None:
1730
+ migration_config = self.migration_config or {}
1731
+ directory = str(migration_config.get("script_location") or "migrations")
1732
+
1733
+ commands = cast("AsyncMigrationCommands[Any]", self._ensure_migration_commands())
1734
+ assert directory is not None
1735
+ await commands.init(directory, package)
1736
+
1737
+ async def stamp_migration(self, revision: str) -> None:
1738
+ """Mark database as being at a specific revision without running migrations.
1739
+
1740
+ Args:
1741
+ revision: The revision to stamp.
1742
+ """
1743
+ commands = cast("AsyncMigrationCommands[Any]", self._ensure_migration_commands())
1744
+ await commands.stamp(revision)
1745
+
1746
+ async def fix_migrations(self, dry_run: bool = False, update_database: bool = True, yes: bool = False) -> None:
1747
+ """Convert timestamp migrations to sequential format.
1748
+
1749
+ Args:
1750
+ dry_run: Preview changes without applying.
1751
+ update_database: Update migration records in database.
1752
+ yes: Skip confirmation prompt.
1753
+ """
1754
+ commands = cast("AsyncMigrationCommands[Any]", self._ensure_migration_commands())
1755
+ await commands.fix(dry_run, update_database, yes)