sqlspec 0.47.0__cp314-cp314-win_amd64.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 (621) hide show
  1. f68e0789eb443ecb1c2c__mypyc.cp314-win_amd64.pyd +0 -0
  2. sqlspec/__init__.py +167 -0
  3. sqlspec/__main__.py +12 -0
  4. sqlspec/__metadata__.py +14 -0
  5. sqlspec/_typing.py +714 -0
  6. sqlspec/adapters/__init__.py +0 -0
  7. sqlspec/adapters/adbc/__init__.py +13 -0
  8. sqlspec/adapters/adbc/_typing.py +106 -0
  9. sqlspec/adapters/adbc/adk/__init__.py +5 -0
  10. sqlspec/adapters/adbc/adk/store.py +1280 -0
  11. sqlspec/adapters/adbc/config.py +378 -0
  12. sqlspec/adapters/adbc/core.cp314-win_amd64.pyd +0 -0
  13. sqlspec/adapters/adbc/core.py +922 -0
  14. sqlspec/adapters/adbc/data_dictionary.py +339 -0
  15. sqlspec/adapters/adbc/driver.py +534 -0
  16. sqlspec/adapters/adbc/events/__init__.py +5 -0
  17. sqlspec/adapters/adbc/events/store.py +285 -0
  18. sqlspec/adapters/adbc/litestar/__init__.py +5 -0
  19. sqlspec/adapters/adbc/litestar/store.py +534 -0
  20. sqlspec/adapters/adbc/type_converter.cp314-win_amd64.pyd +0 -0
  21. sqlspec/adapters/adbc/type_converter.py +142 -0
  22. sqlspec/adapters/aiomysql/__init__.py +21 -0
  23. sqlspec/adapters/aiomysql/_typing.py +137 -0
  24. sqlspec/adapters/aiomysql/adk/__init__.py +5 -0
  25. sqlspec/adapters/aiomysql/adk/store.py +678 -0
  26. sqlspec/adapters/aiomysql/config.py +305 -0
  27. sqlspec/adapters/aiomysql/core.cp314-win_amd64.pyd +0 -0
  28. sqlspec/adapters/aiomysql/core.py +536 -0
  29. sqlspec/adapters/aiomysql/data_dictionary.py +121 -0
  30. sqlspec/adapters/aiomysql/driver.py +386 -0
  31. sqlspec/adapters/aiomysql/events/__init__.py +5 -0
  32. sqlspec/adapters/aiomysql/events/store.py +104 -0
  33. sqlspec/adapters/aiomysql/litestar/__init__.py +5 -0
  34. sqlspec/adapters/aiomysql/litestar/store.py +314 -0
  35. sqlspec/adapters/aiosqlite/__init__.py +26 -0
  36. sqlspec/adapters/aiosqlite/_typing.py +109 -0
  37. sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
  38. sqlspec/adapters/aiosqlite/adk/store.py +829 -0
  39. sqlspec/adapters/aiosqlite/config.py +315 -0
  40. sqlspec/adapters/aiosqlite/core.cp314-win_amd64.pyd +0 -0
  41. sqlspec/adapters/aiosqlite/core.py +315 -0
  42. sqlspec/adapters/aiosqlite/data_dictionary.py +202 -0
  43. sqlspec/adapters/aiosqlite/driver.py +311 -0
  44. sqlspec/adapters/aiosqlite/events/__init__.py +5 -0
  45. sqlspec/adapters/aiosqlite/events/store.py +20 -0
  46. sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
  47. sqlspec/adapters/aiosqlite/litestar/store.py +279 -0
  48. sqlspec/adapters/aiosqlite/pool.cp314-win_amd64.pyd +0 -0
  49. sqlspec/adapters/aiosqlite/pool.py +734 -0
  50. sqlspec/adapters/asyncmy/__init__.py +21 -0
  51. sqlspec/adapters/asyncmy/_typing.py +113 -0
  52. sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
  53. sqlspec/adapters/asyncmy/adk/store.py +644 -0
  54. sqlspec/adapters/asyncmy/config.py +307 -0
  55. sqlspec/adapters/asyncmy/core.cp314-win_amd64.pyd +0 -0
  56. sqlspec/adapters/asyncmy/core.py +538 -0
  57. sqlspec/adapters/asyncmy/data_dictionary.py +122 -0
  58. sqlspec/adapters/asyncmy/driver.py +391 -0
  59. sqlspec/adapters/asyncmy/events/__init__.py +5 -0
  60. sqlspec/adapters/asyncmy/events/store.py +104 -0
  61. sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
  62. sqlspec/adapters/asyncmy/litestar/store.py +296 -0
  63. sqlspec/adapters/asyncpg/__init__.py +26 -0
  64. sqlspec/adapters/asyncpg/_typing.py +103 -0
  65. sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
  66. sqlspec/adapters/asyncpg/adk/store.py +483 -0
  67. sqlspec/adapters/asyncpg/config.py +575 -0
  68. sqlspec/adapters/asyncpg/core.cp314-win_amd64.pyd +0 -0
  69. sqlspec/adapters/asyncpg/core.py +480 -0
  70. sqlspec/adapters/asyncpg/data_dictionary.py +157 -0
  71. sqlspec/adapters/asyncpg/driver.py +487 -0
  72. sqlspec/adapters/asyncpg/events/__init__.py +6 -0
  73. sqlspec/adapters/asyncpg/events/_hub.py +181 -0
  74. sqlspec/adapters/asyncpg/events/backend.py +210 -0
  75. sqlspec/adapters/asyncpg/events/store.py +40 -0
  76. sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
  77. sqlspec/adapters/asyncpg/litestar/store.py +251 -0
  78. sqlspec/adapters/bigquery/__init__.py +15 -0
  79. sqlspec/adapters/bigquery/_typing.py +108 -0
  80. sqlspec/adapters/bigquery/config.py +362 -0
  81. sqlspec/adapters/bigquery/core.cp314-win_amd64.pyd +0 -0
  82. sqlspec/adapters/bigquery/core.py +768 -0
  83. sqlspec/adapters/bigquery/data_dictionary.py +120 -0
  84. sqlspec/adapters/bigquery/driver.py +542 -0
  85. sqlspec/adapters/bigquery/events/__init__.py +5 -0
  86. sqlspec/adapters/bigquery/events/store.py +139 -0
  87. sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
  88. sqlspec/adapters/bigquery/litestar/store.py +325 -0
  89. sqlspec/adapters/bigquery/type_converter.cp314-win_amd64.pyd +0 -0
  90. sqlspec/adapters/bigquery/type_converter.py +107 -0
  91. sqlspec/adapters/cockroach_asyncpg/__init__.py +26 -0
  92. sqlspec/adapters/cockroach_asyncpg/_typing.py +73 -0
  93. sqlspec/adapters/cockroach_asyncpg/adk/__init__.py +3 -0
  94. sqlspec/adapters/cockroach_asyncpg/adk/store.py +465 -0
  95. sqlspec/adapters/cockroach_asyncpg/config.py +248 -0
  96. sqlspec/adapters/cockroach_asyncpg/core.cp314-win_amd64.pyd +0 -0
  97. sqlspec/adapters/cockroach_asyncpg/core.py +55 -0
  98. sqlspec/adapters/cockroach_asyncpg/data_dictionary.py +110 -0
  99. sqlspec/adapters/cockroach_asyncpg/driver.py +142 -0
  100. sqlspec/adapters/cockroach_asyncpg/events/__init__.py +3 -0
  101. sqlspec/adapters/cockroach_asyncpg/events/store.py +20 -0
  102. sqlspec/adapters/cockroach_asyncpg/litestar/__init__.py +3 -0
  103. sqlspec/adapters/cockroach_asyncpg/litestar/store.py +142 -0
  104. sqlspec/adapters/cockroach_psycopg/__init__.py +39 -0
  105. sqlspec/adapters/cockroach_psycopg/_typing.py +137 -0
  106. sqlspec/adapters/cockroach_psycopg/adk/__init__.py +13 -0
  107. sqlspec/adapters/cockroach_psycopg/adk/store.py +1039 -0
  108. sqlspec/adapters/cockroach_psycopg/config.py +511 -0
  109. sqlspec/adapters/cockroach_psycopg/core.cp314-win_amd64.pyd +0 -0
  110. sqlspec/adapters/cockroach_psycopg/core.py +63 -0
  111. sqlspec/adapters/cockroach_psycopg/data_dictionary.py +220 -0
  112. sqlspec/adapters/cockroach_psycopg/driver.py +273 -0
  113. sqlspec/adapters/cockroach_psycopg/events/__init__.py +6 -0
  114. sqlspec/adapters/cockroach_psycopg/events/store.py +34 -0
  115. sqlspec/adapters/cockroach_psycopg/litestar/__init__.py +3 -0
  116. sqlspec/adapters/cockroach_psycopg/litestar/store.py +327 -0
  117. sqlspec/adapters/duckdb/__init__.py +29 -0
  118. sqlspec/adapters/duckdb/_typing.py +104 -0
  119. sqlspec/adapters/duckdb/adk/__init__.py +14 -0
  120. sqlspec/adapters/duckdb/adk/store.py +935 -0
  121. sqlspec/adapters/duckdb/config.py +386 -0
  122. sqlspec/adapters/duckdb/core.cp314-win_amd64.pyd +0 -0
  123. sqlspec/adapters/duckdb/core.py +332 -0
  124. sqlspec/adapters/duckdb/data_dictionary.py +140 -0
  125. sqlspec/adapters/duckdb/driver.py +426 -0
  126. sqlspec/adapters/duckdb/events/__init__.py +5 -0
  127. sqlspec/adapters/duckdb/events/store.py +57 -0
  128. sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
  129. sqlspec/adapters/duckdb/litestar/store.py +330 -0
  130. sqlspec/adapters/duckdb/pool.cp314-win_amd64.pyd +0 -0
  131. sqlspec/adapters/duckdb/pool.py +350 -0
  132. sqlspec/adapters/duckdb/type_converter.cp314-win_amd64.pyd +0 -0
  133. sqlspec/adapters/duckdb/type_converter.py +118 -0
  134. sqlspec/adapters/mysqlconnector/__init__.py +39 -0
  135. sqlspec/adapters/mysqlconnector/_typing.py +186 -0
  136. sqlspec/adapters/mysqlconnector/adk/__init__.py +15 -0
  137. sqlspec/adapters/mysqlconnector/adk/store.py +1183 -0
  138. sqlspec/adapters/mysqlconnector/config.py +421 -0
  139. sqlspec/adapters/mysqlconnector/core.cp314-win_amd64.pyd +0 -0
  140. sqlspec/adapters/mysqlconnector/core.py +472 -0
  141. sqlspec/adapters/mysqlconnector/data_dictionary.py +230 -0
  142. sqlspec/adapters/mysqlconnector/driver.py +516 -0
  143. sqlspec/adapters/mysqlconnector/events/__init__.py +8 -0
  144. sqlspec/adapters/mysqlconnector/events/store.py +98 -0
  145. sqlspec/adapters/mysqlconnector/litestar/__init__.py +5 -0
  146. sqlspec/adapters/mysqlconnector/litestar/store.py +426 -0
  147. sqlspec/adapters/oracledb/__init__.py +39 -0
  148. sqlspec/adapters/oracledb/_json_handlers.cp314-win_amd64.pyd +0 -0
  149. sqlspec/adapters/oracledb/_json_handlers.py +196 -0
  150. sqlspec/adapters/oracledb/_param_types.cp314-win_amd64.pyd +0 -0
  151. sqlspec/adapters/oracledb/_param_types.py +46 -0
  152. sqlspec/adapters/oracledb/_typing.py +258 -0
  153. sqlspec/adapters/oracledb/_uuid_handlers.cp314-win_amd64.pyd +0 -0
  154. sqlspec/adapters/oracledb/_uuid_handlers.py +163 -0
  155. sqlspec/adapters/oracledb/_vector_handlers.cp314-win_amd64.pyd +0 -0
  156. sqlspec/adapters/oracledb/_vector_handlers.py +228 -0
  157. sqlspec/adapters/oracledb/adk/__init__.py +21 -0
  158. sqlspec/adapters/oracledb/adk/store.py +2453 -0
  159. sqlspec/adapters/oracledb/config.py +575 -0
  160. sqlspec/adapters/oracledb/core.cp314-win_amd64.pyd +0 -0
  161. sqlspec/adapters/oracledb/core.py +820 -0
  162. sqlspec/adapters/oracledb/data_dictionary.py +404 -0
  163. sqlspec/adapters/oracledb/driver.py +1277 -0
  164. sqlspec/adapters/oracledb/events/__init__.py +16 -0
  165. sqlspec/adapters/oracledb/events/_hub.py +345 -0
  166. sqlspec/adapters/oracledb/events/backend.py +300 -0
  167. sqlspec/adapters/oracledb/events/store.py +420 -0
  168. sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
  169. sqlspec/adapters/oracledb/litestar/store.py +781 -0
  170. sqlspec/adapters/oracledb/migrations.py +539 -0
  171. sqlspec/adapters/oracledb/type_converter.cp314-win_amd64.pyd +0 -0
  172. sqlspec/adapters/oracledb/type_converter.py +211 -0
  173. sqlspec/adapters/psqlpy/__init__.py +18 -0
  174. sqlspec/adapters/psqlpy/_typing.py +121 -0
  175. sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
  176. sqlspec/adapters/psqlpy/adk/store.py +591 -0
  177. sqlspec/adapters/psqlpy/config.py +376 -0
  178. sqlspec/adapters/psqlpy/core.cp314-win_amd64.pyd +0 -0
  179. sqlspec/adapters/psqlpy/core.py +694 -0
  180. sqlspec/adapters/psqlpy/data_dictionary.py +121 -0
  181. sqlspec/adapters/psqlpy/driver.py +411 -0
  182. sqlspec/adapters/psqlpy/events/__init__.py +6 -0
  183. sqlspec/adapters/psqlpy/events/_hub.py +204 -0
  184. sqlspec/adapters/psqlpy/events/backend.py +210 -0
  185. sqlspec/adapters/psqlpy/events/store.py +20 -0
  186. sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
  187. sqlspec/adapters/psqlpy/litestar/store.py +270 -0
  188. sqlspec/adapters/psqlpy/type_converter.cp314-win_amd64.pyd +0 -0
  189. sqlspec/adapters/psqlpy/type_converter.py +113 -0
  190. sqlspec/adapters/psycopg/__init__.py +38 -0
  191. sqlspec/adapters/psycopg/_typing.py +218 -0
  192. sqlspec/adapters/psycopg/adk/__init__.py +10 -0
  193. sqlspec/adapters/psycopg/adk/store.py +1106 -0
  194. sqlspec/adapters/psycopg/config.py +695 -0
  195. sqlspec/adapters/psycopg/core.cp314-win_amd64.pyd +0 -0
  196. sqlspec/adapters/psycopg/core.py +520 -0
  197. sqlspec/adapters/psycopg/data_dictionary.py +278 -0
  198. sqlspec/adapters/psycopg/driver.py +1033 -0
  199. sqlspec/adapters/psycopg/events/__init__.py +20 -0
  200. sqlspec/adapters/psycopg/events/_hub.py +388 -0
  201. sqlspec/adapters/psycopg/events/backend.py +398 -0
  202. sqlspec/adapters/psycopg/events/store.py +42 -0
  203. sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
  204. sqlspec/adapters/psycopg/litestar/store.py +554 -0
  205. sqlspec/adapters/psycopg/type_converter.cp314-win_amd64.pyd +0 -0
  206. sqlspec/adapters/psycopg/type_converter.py +93 -0
  207. sqlspec/adapters/pymysql/__init__.py +21 -0
  208. sqlspec/adapters/pymysql/_typing.py +92 -0
  209. sqlspec/adapters/pymysql/adk/__init__.py +5 -0
  210. sqlspec/adapters/pymysql/adk/store.py +657 -0
  211. sqlspec/adapters/pymysql/config.py +176 -0
  212. sqlspec/adapters/pymysql/core.cp314-win_amd64.pyd +0 -0
  213. sqlspec/adapters/pymysql/core.py +469 -0
  214. sqlspec/adapters/pymysql/data_dictionary.py +120 -0
  215. sqlspec/adapters/pymysql/driver.py +271 -0
  216. sqlspec/adapters/pymysql/events/__init__.py +5 -0
  217. sqlspec/adapters/pymysql/events/store.py +50 -0
  218. sqlspec/adapters/pymysql/litestar/__init__.py +5 -0
  219. sqlspec/adapters/pymysql/litestar/store.py +232 -0
  220. sqlspec/adapters/pymysql/pool.cp314-win_amd64.pyd +0 -0
  221. sqlspec/adapters/pymysql/pool.py +184 -0
  222. sqlspec/adapters/spanner/__init__.py +33 -0
  223. sqlspec/adapters/spanner/_typing.py +102 -0
  224. sqlspec/adapters/spanner/adk/__init__.py +5 -0
  225. sqlspec/adapters/spanner/adk/store.py +758 -0
  226. sqlspec/adapters/spanner/config.py +355 -0
  227. sqlspec/adapters/spanner/core.cp314-win_amd64.pyd +0 -0
  228. sqlspec/adapters/spanner/core.py +263 -0
  229. sqlspec/adapters/spanner/data_dictionary.py +120 -0
  230. sqlspec/adapters/spanner/driver.py +407 -0
  231. sqlspec/adapters/spanner/events/__init__.py +5 -0
  232. sqlspec/adapters/spanner/events/store.py +187 -0
  233. sqlspec/adapters/spanner/litestar/__init__.py +5 -0
  234. sqlspec/adapters/spanner/litestar/store.py +291 -0
  235. sqlspec/adapters/spanner/type_converter.cp314-win_amd64.pyd +0 -0
  236. sqlspec/adapters/spanner/type_converter.py +342 -0
  237. sqlspec/adapters/sqlite/__init__.py +19 -0
  238. sqlspec/adapters/sqlite/_typing.py +123 -0
  239. sqlspec/adapters/sqlite/adk/__init__.py +5 -0
  240. sqlspec/adapters/sqlite/adk/store.py +992 -0
  241. sqlspec/adapters/sqlite/config.py +240 -0
  242. sqlspec/adapters/sqlite/core.cp314-win_amd64.pyd +0 -0
  243. sqlspec/adapters/sqlite/core.py +357 -0
  244. sqlspec/adapters/sqlite/data_dictionary.py +198 -0
  245. sqlspec/adapters/sqlite/driver.py +527 -0
  246. sqlspec/adapters/sqlite/events/__init__.py +5 -0
  247. sqlspec/adapters/sqlite/events/store.py +20 -0
  248. sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
  249. sqlspec/adapters/sqlite/litestar/store.py +316 -0
  250. sqlspec/adapters/sqlite/pool.cp314-win_amd64.pyd +0 -0
  251. sqlspec/adapters/sqlite/pool.py +237 -0
  252. sqlspec/adapters/sqlite/type_converter.cp314-win_amd64.pyd +0 -0
  253. sqlspec/adapters/sqlite/type_converter.py +114 -0
  254. sqlspec/base.py +832 -0
  255. sqlspec/builder/__init__.py +181 -0
  256. sqlspec/builder/_base.cp314-win_amd64.pyd +0 -0
  257. sqlspec/builder/_base.py +1071 -0
  258. sqlspec/builder/_column.cp314-win_amd64.pyd +0 -0
  259. sqlspec/builder/_column.py +521 -0
  260. sqlspec/builder/_ddl.cp314-win_amd64.pyd +0 -0
  261. sqlspec/builder/_ddl.py +1691 -0
  262. sqlspec/builder/_delete.cp314-win_amd64.pyd +0 -0
  263. sqlspec/builder/_delete.py +95 -0
  264. sqlspec/builder/_dml.cp314-win_amd64.pyd +0 -0
  265. sqlspec/builder/_dml.py +386 -0
  266. sqlspec/builder/_explain.cp314-win_amd64.pyd +0 -0
  267. sqlspec/builder/_explain.py +579 -0
  268. sqlspec/builder/_expression_wrappers.cp314-win_amd64.pyd +0 -0
  269. sqlspec/builder/_expression_wrappers.py +46 -0
  270. sqlspec/builder/_factory.cp314-win_amd64.pyd +0 -0
  271. sqlspec/builder/_factory.py +1884 -0
  272. sqlspec/builder/_insert.cp314-win_amd64.pyd +0 -0
  273. sqlspec/builder/_insert.py +405 -0
  274. sqlspec/builder/_join.cp314-win_amd64.pyd +0 -0
  275. sqlspec/builder/_join.py +489 -0
  276. sqlspec/builder/_merge.cp314-win_amd64.pyd +0 -0
  277. sqlspec/builder/_merge.py +823 -0
  278. sqlspec/builder/_parsing_utils.cp314-win_amd64.pyd +0 -0
  279. sqlspec/builder/_parsing_utils.py +295 -0
  280. sqlspec/builder/_select.cp314-win_amd64.pyd +0 -0
  281. sqlspec/builder/_select.py +1666 -0
  282. sqlspec/builder/_temporal.cp314-win_amd64.pyd +0 -0
  283. sqlspec/builder/_temporal.py +167 -0
  284. sqlspec/builder/_update.cp314-win_amd64.pyd +0 -0
  285. sqlspec/builder/_update.py +173 -0
  286. sqlspec/builder/_vector_distance.cp314-win_amd64.pyd +0 -0
  287. sqlspec/builder/_vector_distance.py +330 -0
  288. sqlspec/cli.py +1095 -0
  289. sqlspec/config.py +2383 -0
  290. sqlspec/core/__init__.py +372 -0
  291. sqlspec/core/_correlation.cp314-win_amd64.pyd +0 -0
  292. sqlspec/core/_correlation.py +176 -0
  293. sqlspec/core/_pagination.py +42 -0
  294. sqlspec/core/_pool.cp314-win_amd64.pyd +0 -0
  295. sqlspec/core/_pool.py +76 -0
  296. sqlspec/core/cache.cp314-win_amd64.pyd +0 -0
  297. sqlspec/core/cache.py +1085 -0
  298. sqlspec/core/compiler.cp314-win_amd64.pyd +0 -0
  299. sqlspec/core/compiler.py +1090 -0
  300. sqlspec/core/config_runtime.cp314-win_amd64.pyd +0 -0
  301. sqlspec/core/config_runtime.py +174 -0
  302. sqlspec/core/explain.cp314-win_amd64.pyd +0 -0
  303. sqlspec/core/explain.py +275 -0
  304. sqlspec/core/filters.cp314-win_amd64.pyd +0 -0
  305. sqlspec/core/filters.py +969 -0
  306. sqlspec/core/hashing.cp314-win_amd64.pyd +0 -0
  307. sqlspec/core/hashing.py +266 -0
  308. sqlspec/core/metrics.cp314-win_amd64.pyd +0 -0
  309. sqlspec/core/metrics.py +83 -0
  310. sqlspec/core/parameters/__init__.py +72 -0
  311. sqlspec/core/parameters/_alignment.cp314-win_amd64.pyd +0 -0
  312. sqlspec/core/parameters/_alignment.py +283 -0
  313. sqlspec/core/parameters/_converter.cp314-win_amd64.pyd +0 -0
  314. sqlspec/core/parameters/_converter.py +554 -0
  315. sqlspec/core/parameters/_processor.cp314-win_amd64.pyd +0 -0
  316. sqlspec/core/parameters/_processor.py +1182 -0
  317. sqlspec/core/parameters/_registry.cp314-win_amd64.pyd +0 -0
  318. sqlspec/core/parameters/_registry.py +206 -0
  319. sqlspec/core/parameters/_transformers.cp314-win_amd64.pyd +0 -0
  320. sqlspec/core/parameters/_transformers.py +324 -0
  321. sqlspec/core/parameters/_types.cp314-win_amd64.pyd +0 -0
  322. sqlspec/core/parameters/_types.py +536 -0
  323. sqlspec/core/parameters/_validator.cp314-win_amd64.pyd +0 -0
  324. sqlspec/core/parameters/_validator.py +171 -0
  325. sqlspec/core/pipeline.cp314-win_amd64.pyd +0 -0
  326. sqlspec/core/pipeline.py +333 -0
  327. sqlspec/core/query_modifiers.cp314-win_amd64.pyd +0 -0
  328. sqlspec/core/query_modifiers.py +508 -0
  329. sqlspec/core/result/__init__.py +25 -0
  330. sqlspec/core/result/_base.cp314-win_amd64.pyd +0 -0
  331. sqlspec/core/result/_base.py +1232 -0
  332. sqlspec/core/result/_io.cp314-win_amd64.pyd +0 -0
  333. sqlspec/core/result/_io.py +28 -0
  334. sqlspec/core/splitter.cp314-win_amd64.pyd +0 -0
  335. sqlspec/core/splitter.py +1021 -0
  336. sqlspec/core/sqlcommenter.cp314-win_amd64.pyd +0 -0
  337. sqlspec/core/sqlcommenter.py +249 -0
  338. sqlspec/core/stack.cp314-win_amd64.pyd +0 -0
  339. sqlspec/core/stack.py +163 -0
  340. sqlspec/core/statement.cp314-win_amd64.pyd +0 -0
  341. sqlspec/core/statement.py +1865 -0
  342. sqlspec/core/type_converter.cp314-win_amd64.pyd +0 -0
  343. sqlspec/core/type_converter.py +340 -0
  344. sqlspec/data_dictionary/__init__.py +22 -0
  345. sqlspec/data_dictionary/_loader.cp314-win_amd64.pyd +0 -0
  346. sqlspec/data_dictionary/_loader.py +138 -0
  347. sqlspec/data_dictionary/_registry.cp314-win_amd64.pyd +0 -0
  348. sqlspec/data_dictionary/_registry.py +74 -0
  349. sqlspec/data_dictionary/_types.cp314-win_amd64.pyd +0 -0
  350. sqlspec/data_dictionary/_types.py +121 -0
  351. sqlspec/data_dictionary/dialects/__init__.py +21 -0
  352. sqlspec/data_dictionary/dialects/bigquery.cp314-win_amd64.pyd +0 -0
  353. sqlspec/data_dictionary/dialects/bigquery.py +81 -0
  354. sqlspec/data_dictionary/dialects/cockroachdb.cp314-win_amd64.pyd +0 -0
  355. sqlspec/data_dictionary/dialects/cockroachdb.py +54 -0
  356. sqlspec/data_dictionary/dialects/duckdb.cp314-win_amd64.pyd +0 -0
  357. sqlspec/data_dictionary/dialects/duckdb.py +47 -0
  358. sqlspec/data_dictionary/dialects/mysql.cp314-win_amd64.pyd +0 -0
  359. sqlspec/data_dictionary/dialects/mysql.py +53 -0
  360. sqlspec/data_dictionary/dialects/oracle.cp314-win_amd64.pyd +0 -0
  361. sqlspec/data_dictionary/dialects/oracle.py +197 -0
  362. sqlspec/data_dictionary/dialects/postgres.cp314-win_amd64.pyd +0 -0
  363. sqlspec/data_dictionary/dialects/postgres.py +69 -0
  364. sqlspec/data_dictionary/dialects/spanner.cp314-win_amd64.pyd +0 -0
  365. sqlspec/data_dictionary/dialects/spanner.py +37 -0
  366. sqlspec/data_dictionary/dialects/sqlite.cp314-win_amd64.pyd +0 -0
  367. sqlspec/data_dictionary/dialects/sqlite.py +59 -0
  368. sqlspec/data_dictionary/sql/.gitkeep +0 -0
  369. sqlspec/data_dictionary/sql/bigquery/columns.sql +23 -0
  370. sqlspec/data_dictionary/sql/bigquery/foreign_keys.sql +34 -0
  371. sqlspec/data_dictionary/sql/bigquery/indexes.sql +19 -0
  372. sqlspec/data_dictionary/sql/bigquery/tables.sql +33 -0
  373. sqlspec/data_dictionary/sql/bigquery/version.sql +3 -0
  374. sqlspec/data_dictionary/sql/cockroachdb/columns.sql +34 -0
  375. sqlspec/data_dictionary/sql/cockroachdb/foreign_keys.sql +40 -0
  376. sqlspec/data_dictionary/sql/cockroachdb/indexes.sql +32 -0
  377. sqlspec/data_dictionary/sql/cockroachdb/tables.sql +44 -0
  378. sqlspec/data_dictionary/sql/cockroachdb/version.sql +3 -0
  379. sqlspec/data_dictionary/sql/duckdb/columns.sql +23 -0
  380. sqlspec/data_dictionary/sql/duckdb/foreign_keys.sql +36 -0
  381. sqlspec/data_dictionary/sql/duckdb/indexes.sql +19 -0
  382. sqlspec/data_dictionary/sql/duckdb/tables.sql +38 -0
  383. sqlspec/data_dictionary/sql/duckdb/version.sql +3 -0
  384. sqlspec/data_dictionary/sql/mysql/columns.sql +23 -0
  385. sqlspec/data_dictionary/sql/mysql/foreign_keys.sql +28 -0
  386. sqlspec/data_dictionary/sql/mysql/indexes.sql +26 -0
  387. sqlspec/data_dictionary/sql/mysql/tables.sql +33 -0
  388. sqlspec/data_dictionary/sql/mysql/version.sql +3 -0
  389. sqlspec/data_dictionary/sql/oracle/columns.sql +23 -0
  390. sqlspec/data_dictionary/sql/oracle/foreign_keys.sql +48 -0
  391. sqlspec/data_dictionary/sql/oracle/indexes.sql +44 -0
  392. sqlspec/data_dictionary/sql/oracle/tables.sql +25 -0
  393. sqlspec/data_dictionary/sql/oracle/version.sql +20 -0
  394. sqlspec/data_dictionary/sql/postgres/columns.sql +34 -0
  395. sqlspec/data_dictionary/sql/postgres/foreign_keys.sql +40 -0
  396. sqlspec/data_dictionary/sql/postgres/indexes.sql +56 -0
  397. sqlspec/data_dictionary/sql/postgres/tables.sql +44 -0
  398. sqlspec/data_dictionary/sql/postgres/version.sql +3 -0
  399. sqlspec/data_dictionary/sql/spanner/columns.sql +23 -0
  400. sqlspec/data_dictionary/sql/spanner/foreign_keys.sql +70 -0
  401. sqlspec/data_dictionary/sql/spanner/indexes.sql +30 -0
  402. sqlspec/data_dictionary/sql/spanner/tables.sql +9 -0
  403. sqlspec/data_dictionary/sql/spanner/version.sql +3 -0
  404. sqlspec/data_dictionary/sql/sqlite/columns.sql +23 -0
  405. sqlspec/data_dictionary/sql/sqlite/foreign_keys.sql +22 -0
  406. sqlspec/data_dictionary/sql/sqlite/indexes.sql +7 -0
  407. sqlspec/data_dictionary/sql/sqlite/tables.sql +28 -0
  408. sqlspec/data_dictionary/sql/sqlite/version.sql +3 -0
  409. sqlspec/dialects/__init__.py +22 -0
  410. sqlspec/dialects/_compat.cp314-win_amd64.pyd +0 -0
  411. sqlspec/dialects/_compat.py +14 -0
  412. sqlspec/dialects/postgres/__init__.py +9 -0
  413. sqlspec/dialects/postgres/_generators.cp314-win_amd64.pyd +0 -0
  414. sqlspec/dialects/postgres/_generators.py +57 -0
  415. sqlspec/dialects/postgres/_operators.cp314-win_amd64.pyd +0 -0
  416. sqlspec/dialects/postgres/_operators.py +81 -0
  417. sqlspec/dialects/postgres/_paradedb.py +50 -0
  418. sqlspec/dialects/postgres/_pgvector.py +36 -0
  419. sqlspec/dialects/spanner/__init__.py +6 -0
  420. sqlspec/dialects/spanner/_generators.cp314-win_amd64.pyd +0 -0
  421. sqlspec/dialects/spanner/_generators.py +206 -0
  422. sqlspec/dialects/spanner/_spangres.py +77 -0
  423. sqlspec/dialects/spanner/_spanner.py +179 -0
  424. sqlspec/driver/__init__.py +49 -0
  425. sqlspec/driver/_async.cp314-win_amd64.pyd +0 -0
  426. sqlspec/driver/_async.py +1830 -0
  427. sqlspec/driver/_common.cp314-win_amd64.pyd +0 -0
  428. sqlspec/driver/_common.py +2292 -0
  429. sqlspec/driver/_exception_handler.cp314-win_amd64.pyd +0 -0
  430. sqlspec/driver/_exception_handler.py +108 -0
  431. sqlspec/driver/_query_cache.cp314-win_amd64.pyd +0 -0
  432. sqlspec/driver/_query_cache.py +96 -0
  433. sqlspec/driver/_sql_helpers.cp314-win_amd64.pyd +0 -0
  434. sqlspec/driver/_sql_helpers.py +139 -0
  435. sqlspec/driver/_storage_helpers.cp314-win_amd64.pyd +0 -0
  436. sqlspec/driver/_storage_helpers.py +153 -0
  437. sqlspec/driver/_sync.cp314-win_amd64.pyd +0 -0
  438. sqlspec/driver/_sync.py +1817 -0
  439. sqlspec/exceptions.cp314-win_amd64.pyd +0 -0
  440. sqlspec/exceptions.py +480 -0
  441. sqlspec/extensions/__init__.py +0 -0
  442. sqlspec/extensions/adk/__init__.py +84 -0
  443. sqlspec/extensions/adk/_config_utils.py +199 -0
  444. sqlspec/extensions/adk/_types.cp314-win_amd64.pyd +0 -0
  445. sqlspec/extensions/adk/_types.py +41 -0
  446. sqlspec/extensions/adk/artifact/__init__.py +57 -0
  447. sqlspec/extensions/adk/artifact/_types.cp314-win_amd64.pyd +0 -0
  448. sqlspec/extensions/adk/artifact/_types.py +32 -0
  449. sqlspec/extensions/adk/artifact/service.py +508 -0
  450. sqlspec/extensions/adk/artifact/store.py +361 -0
  451. sqlspec/extensions/adk/converters.py +212 -0
  452. sqlspec/extensions/adk/memory/__init__.py +69 -0
  453. sqlspec/extensions/adk/memory/_types.cp314-win_amd64.pyd +0 -0
  454. sqlspec/extensions/adk/memory/_types.py +30 -0
  455. sqlspec/extensions/adk/memory/converters.py +225 -0
  456. sqlspec/extensions/adk/memory/service.py +316 -0
  457. sqlspec/extensions/adk/memory/store.py +525 -0
  458. sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +184 -0
  459. sqlspec/extensions/adk/migrations/__init__.py +0 -0
  460. sqlspec/extensions/adk/service.py +279 -0
  461. sqlspec/extensions/adk/store.py +590 -0
  462. sqlspec/extensions/events/__init__.py +51 -0
  463. sqlspec/extensions/events/_channel.py +703 -0
  464. sqlspec/extensions/events/_hints.cp314-win_amd64.pyd +0 -0
  465. sqlspec/extensions/events/_hints.py +45 -0
  466. sqlspec/extensions/events/_models.py +23 -0
  467. sqlspec/extensions/events/_payload.cp314-win_amd64.pyd +0 -0
  468. sqlspec/extensions/events/_payload.py +69 -0
  469. sqlspec/extensions/events/_protocols.py +134 -0
  470. sqlspec/extensions/events/_queue.py +462 -0
  471. sqlspec/extensions/events/_store.py +209 -0
  472. sqlspec/extensions/events/migrations/0001_create_event_queue.py +59 -0
  473. sqlspec/extensions/events/migrations/__init__.py +3 -0
  474. sqlspec/extensions/fastapi/__init__.py +22 -0
  475. sqlspec/extensions/fastapi/extension.py +391 -0
  476. sqlspec/extensions/fastapi/providers.cp314-win_amd64.pyd +0 -0
  477. sqlspec/extensions/fastapi/providers.py +712 -0
  478. sqlspec/extensions/flask/__init__.py +38 -0
  479. sqlspec/extensions/flask/_state.py +87 -0
  480. sqlspec/extensions/flask/_utils.py +71 -0
  481. sqlspec/extensions/flask/extension.py +539 -0
  482. sqlspec/extensions/litestar/__init__.py +31 -0
  483. sqlspec/extensions/litestar/_utils.py +52 -0
  484. sqlspec/extensions/litestar/channels.py +165 -0
  485. sqlspec/extensions/litestar/cli.py +102 -0
  486. sqlspec/extensions/litestar/config.py +90 -0
  487. sqlspec/extensions/litestar/handlers.py +316 -0
  488. sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
  489. sqlspec/extensions/litestar/migrations/__init__.py +3 -0
  490. sqlspec/extensions/litestar/plugin.py +1066 -0
  491. sqlspec/extensions/litestar/providers.cp314-win_amd64.pyd +0 -0
  492. sqlspec/extensions/litestar/providers.py +784 -0
  493. sqlspec/extensions/litestar/store.py +298 -0
  494. sqlspec/extensions/otel/__init__.py +58 -0
  495. sqlspec/extensions/prometheus/__init__.py +113 -0
  496. sqlspec/extensions/sanic/__init__.py +19 -0
  497. sqlspec/extensions/sanic/_state.py +43 -0
  498. sqlspec/extensions/sanic/_utils.py +127 -0
  499. sqlspec/extensions/sanic/extension.py +647 -0
  500. sqlspec/extensions/starlette/__init__.py +22 -0
  501. sqlspec/extensions/starlette/_state.py +42 -0
  502. sqlspec/extensions/starlette/_utils.py +96 -0
  503. sqlspec/extensions/starlette/extension.py +374 -0
  504. sqlspec/extensions/starlette/middleware.py +281 -0
  505. sqlspec/loader.cp314-win_amd64.pyd +0 -0
  506. sqlspec/loader.py +727 -0
  507. sqlspec/migrations/__init__.py +39 -0
  508. sqlspec/migrations/base.cp314-win_amd64.pyd +0 -0
  509. sqlspec/migrations/base.py +862 -0
  510. sqlspec/migrations/commands.py +2151 -0
  511. sqlspec/migrations/context.cp314-win_amd64.pyd +0 -0
  512. sqlspec/migrations/context.py +157 -0
  513. sqlspec/migrations/fix.cp314-win_amd64.pyd +0 -0
  514. sqlspec/migrations/fix.py +204 -0
  515. sqlspec/migrations/loaders.cp314-win_amd64.pyd +0 -0
  516. sqlspec/migrations/loaders.py +443 -0
  517. sqlspec/migrations/runner.cp314-win_amd64.pyd +0 -0
  518. sqlspec/migrations/runner.py +1195 -0
  519. sqlspec/migrations/squash.cp314-win_amd64.pyd +0 -0
  520. sqlspec/migrations/squash.py +490 -0
  521. sqlspec/migrations/templates.cp314-win_amd64.pyd +0 -0
  522. sqlspec/migrations/templates.py +234 -0
  523. sqlspec/migrations/tracker.cp314-win_amd64.pyd +0 -0
  524. sqlspec/migrations/tracker.py +792 -0
  525. sqlspec/migrations/utils.cp314-win_amd64.pyd +0 -0
  526. sqlspec/migrations/utils.py +256 -0
  527. sqlspec/migrations/validation.cp314-win_amd64.pyd +0 -0
  528. sqlspec/migrations/validation.py +359 -0
  529. sqlspec/migrations/version.cp314-win_amd64.pyd +0 -0
  530. sqlspec/migrations/version.py +446 -0
  531. sqlspec/observability/__init__.py +57 -0
  532. sqlspec/observability/_common.cp314-win_amd64.pyd +0 -0
  533. sqlspec/observability/_common.py +77 -0
  534. sqlspec/observability/_config.cp314-win_amd64.pyd +0 -0
  535. sqlspec/observability/_config.py +364 -0
  536. sqlspec/observability/_diagnostics.cp314-win_amd64.pyd +0 -0
  537. sqlspec/observability/_diagnostics.py +74 -0
  538. sqlspec/observability/_dispatcher.cp314-win_amd64.pyd +0 -0
  539. sqlspec/observability/_dispatcher.py +200 -0
  540. sqlspec/observability/_formatters/__init__.py +13 -0
  541. sqlspec/observability/_formatters/_aws.cp314-win_amd64.pyd +0 -0
  542. sqlspec/observability/_formatters/_aws.py +102 -0
  543. sqlspec/observability/_formatters/_azure.cp314-win_amd64.pyd +0 -0
  544. sqlspec/observability/_formatters/_azure.py +96 -0
  545. sqlspec/observability/_formatters/_base.cp314-win_amd64.pyd +0 -0
  546. sqlspec/observability/_formatters/_base.py +57 -0
  547. sqlspec/observability/_formatters/_gcp.cp314-win_amd64.pyd +0 -0
  548. sqlspec/observability/_formatters/_gcp.py +131 -0
  549. sqlspec/observability/_formatting.py +58 -0
  550. sqlspec/observability/_observer.cp314-win_amd64.pyd +0 -0
  551. sqlspec/observability/_observer.py +361 -0
  552. sqlspec/observability/_runtime.cp314-win_amd64.pyd +0 -0
  553. sqlspec/observability/_runtime.py +461 -0
  554. sqlspec/observability/_sampling.cp314-win_amd64.pyd +0 -0
  555. sqlspec/observability/_sampling.py +188 -0
  556. sqlspec/observability/_spans.cp314-win_amd64.pyd +0 -0
  557. sqlspec/observability/_spans.py +161 -0
  558. sqlspec/protocols.py +955 -0
  559. sqlspec/py.typed +0 -0
  560. sqlspec/service.py +433 -0
  561. sqlspec/storage/__init__.py +48 -0
  562. sqlspec/storage/_arrow_payload.py +68 -0
  563. sqlspec/storage/_paths.cp314-win_amd64.pyd +0 -0
  564. sqlspec/storage/_paths.py +58 -0
  565. sqlspec/storage/_utils.py +46 -0
  566. sqlspec/storage/backends/__init__.py +1 -0
  567. sqlspec/storage/backends/base.cp314-win_amd64.pyd +0 -0
  568. sqlspec/storage/backends/base.py +374 -0
  569. sqlspec/storage/backends/fsspec.py +574 -0
  570. sqlspec/storage/backends/local.py +468 -0
  571. sqlspec/storage/backends/obstore.py +956 -0
  572. sqlspec/storage/errors.cp314-win_amd64.pyd +0 -0
  573. sqlspec/storage/errors.py +102 -0
  574. sqlspec/storage/pipeline.cp314-win_amd64.pyd +0 -0
  575. sqlspec/storage/pipeline.py +628 -0
  576. sqlspec/storage/registry.cp314-win_amd64.pyd +0 -0
  577. sqlspec/storage/registry.py +329 -0
  578. sqlspec/typing.py +405 -0
  579. sqlspec/utils/__init__.py +7 -0
  580. sqlspec/utils/arrow_helpers.py +384 -0
  581. sqlspec/utils/config_tools.cp314-win_amd64.pyd +0 -0
  582. sqlspec/utils/config_tools.py +314 -0
  583. sqlspec/utils/correlation.cp314-win_amd64.pyd +0 -0
  584. sqlspec/utils/correlation.py +134 -0
  585. sqlspec/utils/deprecation.cp314-win_amd64.pyd +0 -0
  586. sqlspec/utils/deprecation.py +157 -0
  587. sqlspec/utils/dispatch.cp314-win_amd64.pyd +0 -0
  588. sqlspec/utils/dispatch.py +101 -0
  589. sqlspec/utils/fixtures.cp314-win_amd64.pyd +0 -0
  590. sqlspec/utils/fixtures.py +260 -0
  591. sqlspec/utils/logging.cp314-win_amd64.pyd +0 -0
  592. sqlspec/utils/logging.py +251 -0
  593. sqlspec/utils/module_loader.py +306 -0
  594. sqlspec/utils/portal.cp314-win_amd64.pyd +0 -0
  595. sqlspec/utils/portal.py +377 -0
  596. sqlspec/utils/schema.cp314-win_amd64.pyd +0 -0
  597. sqlspec/utils/schema.py +1040 -0
  598. sqlspec/utils/serializers/__init__.py +30 -0
  599. sqlspec/utils/serializers/_json.cp314-win_amd64.pyd +0 -0
  600. sqlspec/utils/serializers/_json.py +415 -0
  601. sqlspec/utils/serializers/_numpy.cp314-win_amd64.pyd +0 -0
  602. sqlspec/utils/serializers/_numpy.py +65 -0
  603. sqlspec/utils/serializers/_schema.cp314-win_amd64.pyd +0 -0
  604. sqlspec/utils/serializers/_schema.py +285 -0
  605. sqlspec/utils/singleton.cp314-win_amd64.pyd +0 -0
  606. sqlspec/utils/singleton.py +41 -0
  607. sqlspec/utils/sync_tools.cp314-win_amd64.pyd +0 -0
  608. sqlspec/utils/sync_tools.py +316 -0
  609. sqlspec/utils/text.cp314-win_amd64.pyd +0 -0
  610. sqlspec/utils/text.py +109 -0
  611. sqlspec/utils/type_converters.cp314-win_amd64.pyd +0 -0
  612. sqlspec/utils/type_converters.py +216 -0
  613. sqlspec/utils/type_guards.cp314-win_amd64.pyd +0 -0
  614. sqlspec/utils/type_guards.py +1508 -0
  615. sqlspec/utils/uuids.cp314-win_amd64.pyd +0 -0
  616. sqlspec/utils/uuids.py +241 -0
  617. sqlspec-0.47.0.dist-info/METADATA +202 -0
  618. sqlspec-0.47.0.dist-info/RECORD +621 -0
  619. sqlspec-0.47.0.dist-info/WHEEL +4 -0
  620. sqlspec-0.47.0.dist-info/entry_points.txt +6 -0
  621. sqlspec-0.47.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,792 @@
1
+ """Migration version tracking for SQLSpec.
2
+
3
+ This module provides functionality to track applied migrations in the database.
4
+ """
5
+
6
+ import logging
7
+ import os
8
+ from collections.abc import Mapping
9
+ from contextlib import suppress
10
+ from typing import TYPE_CHECKING, Any
11
+
12
+ from rich.console import Console
13
+
14
+ from sqlspec.builder import sql
15
+ from sqlspec.migrations.base import BaseMigrationTracker
16
+ from sqlspec.migrations.version import parse_version
17
+ from sqlspec.observability import resolve_db_system
18
+ from sqlspec.utils.logging import get_logger, log_with_context
19
+
20
+ if TYPE_CHECKING:
21
+ from sqlspec.driver import AsyncDriverAdapterBase, SyncDriverAdapterBase
22
+
23
+ __all__ = ("AsyncMigrationTracker", "SyncMigrationTracker")
24
+
25
+ logger = get_logger("sqlspec.migrations.tracker")
26
+
27
+
28
+ def _extract_column_name(metadata: Any) -> "str | None":
29
+ """Extract column name from a metadata entry."""
30
+ if isinstance(metadata, Mapping):
31
+ value = metadata.get("column_name")
32
+ if value is None:
33
+ value = metadata.get("COLUMN_NAME")
34
+ return str(value).lower() if value is not None else None
35
+ value = getattr(metadata, "column_name", None)
36
+ if value is not None:
37
+ return str(value).lower()
38
+ return None
39
+
40
+
41
+ class SyncMigrationTracker(BaseMigrationTracker["SyncDriverAdapterBase"]):
42
+ """Synchronous migration version tracker."""
43
+
44
+ def _migrate_schema_if_needed(self, driver: "SyncDriverAdapterBase") -> None:
45
+ """Check for and add any missing columns to the tracking table.
46
+
47
+ Uses the adapter's data_dictionary to query existing columns,
48
+ then compares to the target schema and adds missing columns one by one.
49
+
50
+ Args:
51
+ driver: The database driver to use.
52
+ """
53
+ console = Console()
54
+ try:
55
+ columns_data = driver.data_dictionary.get_columns(driver, self.version_table)
56
+ if not columns_data:
57
+ log_with_context(
58
+ logger,
59
+ logging.DEBUG,
60
+ "migration.track",
61
+ db_system=resolve_db_system(type(driver).__name__),
62
+ table=self.version_table,
63
+ operation="table_check",
64
+ status="missing",
65
+ )
66
+ columns_data = []
67
+
68
+ existing_columns = {name for col in columns_data if (name := _extract_column_name(col)) is not None}
69
+ missing_columns = self._detect_missing_columns(existing_columns)
70
+
71
+ if not missing_columns:
72
+ log_with_context(
73
+ logger,
74
+ logging.DEBUG,
75
+ "migration.track",
76
+ db_system=resolve_db_system(type(driver).__name__),
77
+ table=self.version_table,
78
+ operation="schema_check",
79
+ status="current",
80
+ )
81
+ return
82
+
83
+ if self._should_echo():
84
+ console.print(
85
+ f"[cyan]Migrating tracking table schema, adding columns: {', '.join(sorted(missing_columns))}[/]"
86
+ )
87
+
88
+ for col_name in sorted(missing_columns):
89
+ self._add_column(driver, col_name)
90
+
91
+ driver.commit()
92
+ if self._should_echo():
93
+ console.print("[green]Migration tracking table schema updated successfully[/]")
94
+
95
+ except Exception as exc:
96
+ with suppress(Exception):
97
+ driver.rollback()
98
+ log_with_context(
99
+ logger,
100
+ logging.ERROR,
101
+ "migration.track",
102
+ db_system=resolve_db_system(type(driver).__name__),
103
+ table=self.version_table,
104
+ operation="schema_check",
105
+ status="failed",
106
+ error_type=type(exc).__name__,
107
+ )
108
+
109
+ def _add_column(self, driver: "SyncDriverAdapterBase", column_name: str) -> None:
110
+ """Add a single column to the tracking table.
111
+
112
+ Args:
113
+ driver: The database driver to use.
114
+ column_name: Name of the column to add (lowercase).
115
+ """
116
+ target_create = self._get_create_table_sql()
117
+ column_def = next((col for col in target_create.columns if col.name.lower() == column_name), None)
118
+
119
+ if not column_def:
120
+ return
121
+
122
+ alter_sql = sql.alter_table(self.version_table).add_column(
123
+ name=column_def.name, dtype=column_def.dtype, default=column_def.default, not_null=column_def.not_null
124
+ )
125
+ driver.execute(alter_sql)
126
+ log_with_context(
127
+ logger,
128
+ logging.INFO,
129
+ "migration.track",
130
+ db_system=resolve_db_system(type(driver).__name__),
131
+ table=self.version_table,
132
+ column_name=column_name,
133
+ operation="schema_update",
134
+ status="column_added",
135
+ )
136
+
137
+ def ensure_tracking_table(self, driver: "SyncDriverAdapterBase") -> None:
138
+ """Create the migration tracking table if it doesn't exist.
139
+
140
+ Also checks for and adds any missing columns to support schema migrations.
141
+
142
+ Args:
143
+ driver: The database driver to use.
144
+ """
145
+ driver.execute(self._get_create_table_sql())
146
+ self._safe_commit(driver)
147
+
148
+ self._migrate_schema_if_needed(driver)
149
+
150
+ def get_current_version(self, driver: "SyncDriverAdapterBase") -> str | None:
151
+ """Get the latest applied migration version.
152
+
153
+ Args:
154
+ driver: The database driver to use.
155
+
156
+ Returns:
157
+ The current version number or None if no migrations applied.
158
+ """
159
+ result = driver.execute(self._get_current_version_sql())
160
+ current = result.get_data()[0]["version_num"] if result.data else None
161
+ log_with_context(
162
+ logger,
163
+ logging.DEBUG,
164
+ "migration.history",
165
+ db_system=resolve_db_system(type(driver).__name__),
166
+ current_version=current,
167
+ status="current",
168
+ )
169
+ return current
170
+
171
+ def get_applied_migrations(self, driver: "SyncDriverAdapterBase") -> "list[dict[str, Any]]":
172
+ """Get all applied migrations in order.
173
+
174
+ Args:
175
+ driver: The database driver to use.
176
+
177
+ Returns:
178
+ List of migration records.
179
+ """
180
+ result = driver.execute(self._get_applied_migrations_sql())
181
+ applied = result.get_data()
182
+ log_with_context(
183
+ logger,
184
+ logging.DEBUG,
185
+ "migration.history",
186
+ db_system=resolve_db_system(type(driver).__name__),
187
+ applied_count=len(applied),
188
+ status="listed",
189
+ )
190
+ return applied
191
+
192
+ def record_migration(
193
+ self, driver: "SyncDriverAdapterBase", version: str, description: str, execution_time_ms: int, checksum: str
194
+ ) -> None:
195
+ """Record a successfully applied migration.
196
+
197
+ Parses version to determine type (sequential or timestamp) and
198
+ auto-increments execution_sequence for application order tracking.
199
+
200
+ Args:
201
+ driver: The database driver to use.
202
+ version: Version number of the migration.
203
+ description: Description of the migration.
204
+ execution_time_ms: Execution time in milliseconds.
205
+ checksum: MD5 checksum of the migration content.
206
+ """
207
+ parsed_version = parse_version(version)
208
+ version_type = parsed_version.type.value
209
+
210
+ result = driver.execute(self._get_next_execution_sequence_sql())
211
+ next_sequence = result.get_data()[0]["next_seq"] if result.data else 1
212
+
213
+ driver.execute(
214
+ self._get_record_migration_sql(
215
+ version,
216
+ version_type,
217
+ next_sequence,
218
+ description,
219
+ execution_time_ms,
220
+ checksum,
221
+ os.environ.get("USER", "unknown"),
222
+ )
223
+ )
224
+ self._safe_commit(driver)
225
+ log_with_context(
226
+ logger,
227
+ logging.DEBUG,
228
+ "migration.track",
229
+ db_system=resolve_db_system(type(driver).__name__),
230
+ version=version,
231
+ operation="record",
232
+ status="recorded",
233
+ )
234
+
235
+ def remove_migration(self, driver: "SyncDriverAdapterBase", version: str) -> None:
236
+ """Remove a migration record (used during downgrade).
237
+
238
+ Args:
239
+ driver: The database driver to use.
240
+ version: Version number to remove.
241
+ """
242
+ driver.execute(self._get_remove_migration_sql(version))
243
+ self._safe_commit(driver)
244
+ log_with_context(
245
+ logger,
246
+ logging.DEBUG,
247
+ "migration.track",
248
+ db_system=resolve_db_system(type(driver).__name__),
249
+ version=version,
250
+ operation="remove",
251
+ status="removed",
252
+ )
253
+
254
+ def update_version_record(self, driver: "SyncDriverAdapterBase", old_version: str, new_version: str) -> None:
255
+ """Update migration version record from timestamp to sequential.
256
+
257
+ Updates version_num and version_type while preserving execution_sequence,
258
+ applied_at, and other tracking metadata. Used during fix command.
259
+
260
+ Idempotent: If the version is already updated, logs and continues without error.
261
+ This allows fix command to be safely re-run after pulling changes.
262
+
263
+ Args:
264
+ driver: The database driver to use.
265
+ old_version: Current timestamp version string.
266
+ new_version: New sequential version string.
267
+
268
+ Raises:
269
+ ValueError: If neither old_version nor new_version found in database.
270
+ """
271
+ parsed_new_version = parse_version(new_version)
272
+ new_version_type = parsed_new_version.type.value
273
+
274
+ result = driver.execute(self._get_update_version_sql(old_version, new_version, new_version_type))
275
+
276
+ if result.rows_affected == 0:
277
+ check_result = driver.execute(self._get_applied_migrations_sql())
278
+ applied_versions = {row["version_num"] for row in check_result.get_data()} if check_result.data else set()
279
+
280
+ if new_version in applied_versions:
281
+ log_with_context(
282
+ logger,
283
+ logging.DEBUG,
284
+ "migration.track",
285
+ db_system=resolve_db_system(type(driver).__name__),
286
+ old_version=old_version,
287
+ new_version=new_version,
288
+ operation="version_update",
289
+ status="skipped",
290
+ )
291
+ return
292
+
293
+ msg = f"Migration version {old_version} not found in database"
294
+ raise ValueError(msg)
295
+
296
+ self._safe_commit(driver)
297
+ log_with_context(
298
+ logger,
299
+ logging.INFO,
300
+ "migration.track",
301
+ db_system=resolve_db_system(type(driver).__name__),
302
+ old_version=old_version,
303
+ new_version=new_version,
304
+ operation="version_update",
305
+ status="updated",
306
+ )
307
+
308
+ def replace_with_squash(
309
+ self,
310
+ driver: "SyncDriverAdapterBase",
311
+ squashed_version: str,
312
+ replaced_versions: "list[str]",
313
+ description: str,
314
+ checksum: str,
315
+ ) -> None:
316
+ """Replace multiple migration records with a single squashed record.
317
+
318
+ Deletes all replaced version records and inserts a new record for the
319
+ squashed migration with metadata about which versions it replaces.
320
+
321
+ Args:
322
+ driver: The database driver to use.
323
+ squashed_version: Version number of the squashed migration.
324
+ replaced_versions: List of version strings being replaced.
325
+ description: Description of the squashed migration.
326
+ checksum: MD5 checksum of the squashed migration content.
327
+ """
328
+ driver.execute(self._get_delete_versions_sql(replaced_versions))
329
+
330
+ result = driver.execute(self._get_next_execution_sequence_sql())
331
+ next_sequence = result.get_data()[0]["next_seq"] if result.data else 1
332
+
333
+ parsed_version = parse_version(squashed_version)
334
+ version_type = parsed_version.type.value
335
+
336
+ replaces_str = ",".join(replaced_versions)
337
+ driver.execute(
338
+ self._get_record_squashed_migration_sql(
339
+ squashed_version,
340
+ version_type,
341
+ next_sequence,
342
+ description,
343
+ 0,
344
+ checksum,
345
+ os.environ.get("USER", "unknown"),
346
+ replaces_str,
347
+ )
348
+ )
349
+
350
+ self._safe_commit(driver)
351
+ log_with_context(
352
+ logger,
353
+ logging.INFO,
354
+ "migration.track",
355
+ db_system=resolve_db_system(type(driver).__name__),
356
+ squashed_version=squashed_version,
357
+ replaced_count=len(replaced_versions),
358
+ operation="squash",
359
+ status="recorded",
360
+ )
361
+
362
+ def is_squash_already_applied(
363
+ self, driver: "SyncDriverAdapterBase", squashed_version: str, replaced_versions: "list[str]"
364
+ ) -> bool:
365
+ """Check if a squash operation has already been applied.
366
+
367
+ Determines if any of the replaced versions exist in the database,
368
+ indicating that the original migrations were applied before the squash.
369
+
370
+ Args:
371
+ driver: The database driver to use.
372
+ squashed_version: Version number of the squashed migration (unused but kept for API consistency).
373
+ replaced_versions: List of version strings that would be replaced.
374
+
375
+ Returns:
376
+ True if any replaced version exists (squash already applied), False otherwise.
377
+ """
378
+ result = driver.execute(self._get_applied_migrations_sql())
379
+ applied_versions = {row["version_num"] for row in result.get_data()} if result.data else set()
380
+
381
+ # Check if any replaced version exists in applied migrations
382
+ return any(version in applied_versions for version in replaced_versions)
383
+
384
+ def _safe_commit(self, driver: "SyncDriverAdapterBase") -> None:
385
+ """Safely commit a transaction only if autocommit is disabled.
386
+
387
+ Args:
388
+ driver: The database driver to use.
389
+
390
+ Raises:
391
+ Exception: Re-raises non-autocommit related exceptions to prevent
392
+ silent failures (e.g., SQLite isolation errors).
393
+ """
394
+ if driver.driver_features.get("autocommit", False):
395
+ return
396
+
397
+ try:
398
+ driver.commit()
399
+ except Exception as exc:
400
+ # Only suppress autocommit-related exceptions
401
+ exc_str = str(exc).lower()
402
+ if "autocommit" in exc_str or "cannot commit" in exc_str:
403
+ log_with_context(
404
+ logger,
405
+ logging.DEBUG,
406
+ "migration.track",
407
+ db_system=resolve_db_system(type(driver).__name__),
408
+ operation="commit",
409
+ status="skipped",
410
+ reason="autocommit",
411
+ error_type=type(exc).__name__,
412
+ )
413
+ else:
414
+ # Re-raise non-autocommit exceptions to prevent silent failures
415
+ raise
416
+
417
+
418
+ class AsyncMigrationTracker(BaseMigrationTracker["AsyncDriverAdapterBase"]):
419
+ """Asynchronous migration version tracker."""
420
+
421
+ async def _migrate_schema_if_needed(self, driver: "AsyncDriverAdapterBase") -> None:
422
+ """Check for and add any missing columns to the tracking table.
423
+
424
+ Uses the driver's data_dictionary to query existing columns,
425
+ then compares to the target schema and adds missing columns one by one.
426
+
427
+ Args:
428
+ driver: The database driver to use.
429
+ """
430
+ console = Console()
431
+ try:
432
+ columns_data = await driver.data_dictionary.get_columns(driver, self.version_table)
433
+ if not columns_data:
434
+ log_with_context(
435
+ logger,
436
+ logging.DEBUG,
437
+ "migration.track",
438
+ db_system=resolve_db_system(type(driver).__name__),
439
+ table=self.version_table,
440
+ operation="table_check",
441
+ status="missing",
442
+ )
443
+ columns_data = []
444
+
445
+ existing_columns = {name for col in columns_data if (name := _extract_column_name(col)) is not None}
446
+ missing_columns = self._detect_missing_columns(existing_columns)
447
+
448
+ if not missing_columns:
449
+ log_with_context(
450
+ logger,
451
+ logging.DEBUG,
452
+ "migration.track",
453
+ db_system=resolve_db_system(type(driver).__name__),
454
+ table=self.version_table,
455
+ operation="schema_check",
456
+ status="current",
457
+ )
458
+ return
459
+
460
+ if self._should_echo():
461
+ console.print(
462
+ f"[cyan]Migrating tracking table schema, adding columns: {', '.join(sorted(missing_columns))}[/]"
463
+ )
464
+
465
+ for col_name in sorted(missing_columns):
466
+ await self._add_column(driver, col_name)
467
+
468
+ await driver.commit()
469
+ if self._should_echo():
470
+ console.print("[green]Migration tracking table schema updated successfully[/]")
471
+
472
+ except Exception as exc:
473
+ with suppress(Exception):
474
+ await driver.rollback()
475
+ log_with_context(
476
+ logger,
477
+ logging.ERROR,
478
+ "migration.track",
479
+ db_system=resolve_db_system(type(driver).__name__),
480
+ table=self.version_table,
481
+ operation="schema_check",
482
+ status="failed",
483
+ error_type=type(exc).__name__,
484
+ )
485
+
486
+ async def _add_column(self, driver: "AsyncDriverAdapterBase", column_name: str) -> None:
487
+ """Add a single column to the tracking table.
488
+
489
+ Args:
490
+ driver: The database driver to use.
491
+ column_name: Name of the column to add (lowercase).
492
+ """
493
+ target_create = self._get_create_table_sql()
494
+ column_def = next((col for col in target_create.columns if col.name.lower() == column_name), None)
495
+
496
+ if not column_def:
497
+ return
498
+
499
+ alter_sql = sql.alter_table(self.version_table).add_column(
500
+ name=column_def.name, dtype=column_def.dtype, default=column_def.default, not_null=column_def.not_null
501
+ )
502
+ await driver.execute(alter_sql)
503
+ log_with_context(
504
+ logger,
505
+ logging.INFO,
506
+ "migration.track",
507
+ db_system=resolve_db_system(type(driver).__name__),
508
+ table=self.version_table,
509
+ column_name=column_name,
510
+ operation="schema_update",
511
+ status="column_added",
512
+ )
513
+
514
+ async def ensure_tracking_table(self, driver: "AsyncDriverAdapterBase") -> None:
515
+ """Create the migration tracking table if it doesn't exist.
516
+
517
+ Also checks for and adds any missing columns to support schema migrations.
518
+
519
+ Args:
520
+ driver: The database driver to use.
521
+ """
522
+ await driver.execute(self._get_create_table_sql())
523
+ await self._safe_commit_async(driver)
524
+
525
+ await self._migrate_schema_if_needed(driver)
526
+
527
+ async def get_current_version(self, driver: "AsyncDriverAdapterBase") -> str | None:
528
+ """Get the latest applied migration version.
529
+
530
+ Args:
531
+ driver: The database driver to use.
532
+
533
+ Returns:
534
+ The current version number or None if no migrations applied.
535
+ """
536
+ result = await driver.execute(self._get_current_version_sql())
537
+ current = result.get_data()[0]["version_num"] if result.data else None
538
+ log_with_context(
539
+ logger,
540
+ logging.DEBUG,
541
+ "migration.history",
542
+ db_system=resolve_db_system(type(driver).__name__),
543
+ current_version=current,
544
+ status="current",
545
+ )
546
+ return current
547
+
548
+ async def get_applied_migrations(self, driver: "AsyncDriverAdapterBase") -> "list[dict[str, Any]]":
549
+ """Get all applied migrations in order.
550
+
551
+ Args:
552
+ driver: The database driver to use.
553
+
554
+ Returns:
555
+ List of migration records.
556
+ """
557
+ result = await driver.execute(self._get_applied_migrations_sql())
558
+ applied = result.get_data()
559
+ log_with_context(
560
+ logger,
561
+ logging.DEBUG,
562
+ "migration.history",
563
+ db_system=resolve_db_system(type(driver).__name__),
564
+ applied_count=len(applied),
565
+ status="listed",
566
+ )
567
+ return applied
568
+
569
+ async def record_migration(
570
+ self, driver: "AsyncDriverAdapterBase", version: str, description: str, execution_time_ms: int, checksum: str
571
+ ) -> None:
572
+ """Record a successfully applied migration.
573
+
574
+ Parses version to determine type (sequential or timestamp) and
575
+ auto-increments execution_sequence for application order tracking.
576
+
577
+ Args:
578
+ driver: The database driver to use.
579
+ version: Version number of the migration.
580
+ description: Description of the migration.
581
+ execution_time_ms: Execution time in milliseconds.
582
+ checksum: MD5 checksum of the migration content.
583
+ """
584
+ parsed_version = parse_version(version)
585
+ version_type = parsed_version.type.value
586
+
587
+ result = await driver.execute(self._get_next_execution_sequence_sql())
588
+ next_sequence = result.get_data()[0]["next_seq"] if result.data else 1
589
+
590
+ await driver.execute(
591
+ self._get_record_migration_sql(
592
+ version,
593
+ version_type,
594
+ next_sequence,
595
+ description,
596
+ execution_time_ms,
597
+ checksum,
598
+ os.environ.get("USER", "unknown"),
599
+ )
600
+ )
601
+ await self._safe_commit_async(driver)
602
+ log_with_context(
603
+ logger,
604
+ logging.DEBUG,
605
+ "migration.track",
606
+ db_system=resolve_db_system(type(driver).__name__),
607
+ version=version,
608
+ operation="record",
609
+ status="recorded",
610
+ )
611
+
612
+ async def remove_migration(self, driver: "AsyncDriverAdapterBase", version: str) -> None:
613
+ """Remove a migration record (used during downgrade).
614
+
615
+ Args:
616
+ driver: The database driver to use.
617
+ version: Version number to remove.
618
+ """
619
+ await driver.execute(self._get_remove_migration_sql(version))
620
+ await self._safe_commit_async(driver)
621
+ log_with_context(
622
+ logger,
623
+ logging.DEBUG,
624
+ "migration.track",
625
+ db_system=resolve_db_system(type(driver).__name__),
626
+ version=version,
627
+ operation="remove",
628
+ status="removed",
629
+ )
630
+
631
+ async def update_version_record(self, driver: "AsyncDriverAdapterBase", old_version: str, new_version: str) -> None:
632
+ """Update migration version record from timestamp to sequential.
633
+
634
+ Updates version_num and version_type while preserving execution_sequence,
635
+ applied_at, and other tracking metadata. Used during fix command.
636
+
637
+ Idempotent: If the version is already updated, logs and continues without error.
638
+ This allows fix command to be safely re-run after pulling changes.
639
+
640
+ Args:
641
+ driver: The database driver to use.
642
+ old_version: Current timestamp version string.
643
+ new_version: New sequential version string.
644
+
645
+ Raises:
646
+ ValueError: If neither old_version nor new_version found in database.
647
+ """
648
+ parsed_new_version = parse_version(new_version)
649
+ new_version_type = parsed_new_version.type.value
650
+
651
+ result = await driver.execute(self._get_update_version_sql(old_version, new_version, new_version_type))
652
+
653
+ if result.rows_affected == 0:
654
+ check_result = await driver.execute(self._get_applied_migrations_sql())
655
+ applied_versions = {row["version_num"] for row in check_result.get_data()} if check_result.data else set()
656
+
657
+ if new_version in applied_versions:
658
+ log_with_context(
659
+ logger,
660
+ logging.DEBUG,
661
+ "migration.track",
662
+ db_system=resolve_db_system(type(driver).__name__),
663
+ old_version=old_version,
664
+ new_version=new_version,
665
+ operation="version_update",
666
+ status="skipped",
667
+ )
668
+ return
669
+
670
+ msg = f"Migration version {old_version} not found in database"
671
+ raise ValueError(msg)
672
+
673
+ await self._safe_commit_async(driver)
674
+ log_with_context(
675
+ logger,
676
+ logging.INFO,
677
+ "migration.track",
678
+ db_system=resolve_db_system(type(driver).__name__),
679
+ old_version=old_version,
680
+ new_version=new_version,
681
+ operation="version_update",
682
+ status="updated",
683
+ )
684
+
685
+ async def replace_with_squash(
686
+ self,
687
+ driver: "AsyncDriverAdapterBase",
688
+ squashed_version: str,
689
+ replaced_versions: "list[str]",
690
+ description: str,
691
+ checksum: str,
692
+ ) -> None:
693
+ """Replace multiple migration records with a single squashed record.
694
+
695
+ Deletes all replaced version records and inserts a new record for the
696
+ squashed migration with metadata about which versions it replaces.
697
+
698
+ Args:
699
+ driver: The database driver to use.
700
+ squashed_version: Version number of the squashed migration.
701
+ replaced_versions: List of version strings being replaced.
702
+ description: Description of the squashed migration.
703
+ checksum: MD5 checksum of the squashed migration content.
704
+ """
705
+ await driver.execute(self._get_delete_versions_sql(replaced_versions))
706
+
707
+ result = await driver.execute(self._get_next_execution_sequence_sql())
708
+ next_sequence = result.get_data()[0]["next_seq"] if result.data else 1
709
+
710
+ parsed_version = parse_version(squashed_version)
711
+ version_type = parsed_version.type.value
712
+
713
+ replaces_str = ",".join(replaced_versions)
714
+ await driver.execute(
715
+ self._get_record_squashed_migration_sql(
716
+ squashed_version,
717
+ version_type,
718
+ next_sequence,
719
+ description,
720
+ 0,
721
+ checksum,
722
+ os.environ.get("USER", "unknown"),
723
+ replaces_str,
724
+ )
725
+ )
726
+
727
+ await self._safe_commit_async(driver)
728
+ log_with_context(
729
+ logger,
730
+ logging.INFO,
731
+ "migration.track",
732
+ db_system=resolve_db_system(type(driver).__name__),
733
+ squashed_version=squashed_version,
734
+ replaced_count=len(replaced_versions),
735
+ operation="squash",
736
+ status="recorded",
737
+ )
738
+
739
+ async def is_squash_already_applied(
740
+ self, driver: "AsyncDriverAdapterBase", squashed_version: str, replaced_versions: "list[str]"
741
+ ) -> bool:
742
+ """Check if a squash operation has already been applied.
743
+
744
+ Determines if any of the replaced versions exist in the database,
745
+ indicating that the original migrations were applied before the squash.
746
+
747
+ Args:
748
+ driver: The database driver to use.
749
+ squashed_version: Version number of the squashed migration (unused but kept for API consistency).
750
+ replaced_versions: List of version strings that would be replaced.
751
+
752
+ Returns:
753
+ True if any replaced version exists (squash already applied), False otherwise.
754
+ """
755
+ result = await driver.execute(self._get_applied_migrations_sql())
756
+ applied_versions = {row["version_num"] for row in result.get_data()} if result.data else set()
757
+
758
+ # Check if any replaced version exists in applied migrations
759
+ return any(version in applied_versions for version in replaced_versions)
760
+
761
+ async def _safe_commit_async(self, driver: "AsyncDriverAdapterBase") -> None:
762
+ """Safely commit a transaction only if autocommit is disabled.
763
+
764
+ Args:
765
+ driver: The database driver to use.
766
+
767
+ Raises:
768
+ Exception: Re-raises non-autocommit related exceptions to prevent
769
+ silent failures (e.g., SQLite isolation errors).
770
+ """
771
+ if driver.driver_features.get("autocommit", False):
772
+ return
773
+
774
+ try:
775
+ await driver.commit()
776
+ except Exception as exc:
777
+ # Only suppress autocommit-related exceptions
778
+ exc_str = str(exc).lower()
779
+ if "autocommit" in exc_str or "cannot commit" in exc_str:
780
+ log_with_context(
781
+ logger,
782
+ logging.DEBUG,
783
+ "migration.track",
784
+ db_system=resolve_db_system(type(driver).__name__),
785
+ operation="commit",
786
+ status="skipped",
787
+ reason="autocommit",
788
+ error_type=type(exc).__name__,
789
+ )
790
+ else:
791
+ # Re-raise non-autocommit exceptions to prevent silent failures
792
+ raise