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,120 @@
1
+ """MySQL-specific data dictionary for metadata queries via PyMySQL."""
2
+
3
+ from typing import TYPE_CHECKING, ClassVar
4
+
5
+ from mypy_extensions import mypyc_attr
6
+
7
+ from sqlspec.data_dictionary.dialects.mysql import resolve_mysql_json_type
8
+ from sqlspec.driver import SyncDataDictionaryBase
9
+ from sqlspec.typing import ColumnMetadata, ForeignKeyMetadata, IndexMetadata, TableMetadata, VersionInfo
10
+
11
+ if TYPE_CHECKING:
12
+ from sqlspec.adapters.pymysql.driver import PyMysqlDriver
13
+
14
+ __all__ = ("PyMysqlDataDictionary",)
15
+
16
+
17
+ @mypyc_attr(allow_interpreted_subclasses=True, native_class=False)
18
+ class PyMysqlDataDictionary(SyncDataDictionaryBase):
19
+ """MySQL-specific sync data dictionary."""
20
+
21
+ dialect: ClassVar[str] = "mysql"
22
+
23
+ def __init__(self) -> None:
24
+ super().__init__()
25
+
26
+ def get_version(self, driver: "PyMysqlDriver") -> "VersionInfo | None":
27
+ """Get MySQL database version information."""
28
+ driver_id = id(driver)
29
+ # Inline cache check to avoid cross-module method call that causes mypyc segfault
30
+ if driver_id in self._version_fetch_attempted:
31
+ return self._version_cache.get(driver_id)
32
+ # Not cached, fetch from database
33
+
34
+ version_value = driver.select_value_or_none(self.get_query("version"))
35
+ if not version_value:
36
+ self._log_version_unavailable(type(self).dialect, "missing")
37
+ self.cache_version(driver_id, None)
38
+ return None
39
+
40
+ version_info = self.parse_version_with_pattern(self.get_dialect_config().version_pattern, str(version_value))
41
+ if version_info is None:
42
+ self._log_version_unavailable(type(self).dialect, "parse_failed")
43
+ self.cache_version(driver_id, None)
44
+ return None
45
+
46
+ self._log_version_detected(type(self).dialect, version_info)
47
+ self.cache_version(driver_id, version_info)
48
+ return version_info
49
+
50
+ def get_feature_flag(self, driver: "PyMysqlDriver", feature: str) -> bool:
51
+ """Check if MySQL database supports a specific feature."""
52
+ version_info = self.get_version(driver)
53
+ return self.resolve_feature_flag(feature, version_info)
54
+
55
+ def get_optimal_type(self, driver: "PyMysqlDriver", type_category: str) -> str:
56
+ """Get optimal MySQL type for a category."""
57
+ config = self.get_dialect_config()
58
+ version_info = self.get_version(driver)
59
+
60
+ if type_category == "json":
61
+ return resolve_mysql_json_type(version_info)
62
+
63
+ return config.get_optimal_type(type_category)
64
+
65
+ def get_tables(self, driver: "PyMysqlDriver", schema: "str | None" = None) -> "list[TableMetadata]":
66
+ """Get tables sorted by topological dependency order using the MySQL catalog."""
67
+ schema_name = self.resolve_schema(schema)
68
+ self._log_schema_introspect(driver, schema_name=schema_name, table_name=None, operation="tables")
69
+ return driver.select(self.get_query("tables_by_schema"), schema_name=schema_name, schema_type=TableMetadata)
70
+
71
+ def get_columns(
72
+ self, driver: "PyMysqlDriver", table: "str | None" = None, schema: "str | None" = None
73
+ ) -> "list[ColumnMetadata]":
74
+ """Get column information for a table or schema."""
75
+ schema_name = self.resolve_schema(schema)
76
+ if table is None:
77
+ self._log_schema_introspect(driver, schema_name=schema_name, table_name=None, operation="columns")
78
+ return driver.select(
79
+ self.get_query("columns_by_schema"), schema_name=schema_name, schema_type=ColumnMetadata
80
+ )
81
+
82
+ self._log_table_describe(driver, schema_name=schema_name, table_name=table, operation="columns")
83
+ return driver.select(
84
+ self.get_query("columns_by_table"), table_name=table, schema_name=schema_name, schema_type=ColumnMetadata
85
+ )
86
+
87
+ def get_indexes(
88
+ self, driver: "PyMysqlDriver", table: "str | None" = None, schema: "str | None" = None
89
+ ) -> "list[IndexMetadata]":
90
+ """Get index metadata for a table or schema."""
91
+ schema_name = self.resolve_schema(schema)
92
+ if table is None:
93
+ self._log_schema_introspect(driver, schema_name=schema_name, table_name=None, operation="indexes")
94
+ return driver.select(
95
+ self.get_query("indexes_by_schema"), schema_name=schema_name, schema_type=IndexMetadata
96
+ )
97
+
98
+ self._log_table_describe(driver, schema_name=schema_name, table_name=table, operation="indexes")
99
+ return driver.select(
100
+ self.get_query("indexes_by_table"), table_name=table, schema_name=schema_name, schema_type=IndexMetadata
101
+ )
102
+
103
+ def get_foreign_keys(
104
+ self, driver: "PyMysqlDriver", table: "str | None" = None, schema: "str | None" = None
105
+ ) -> "list[ForeignKeyMetadata]":
106
+ """Get foreign key metadata."""
107
+ schema_name = self.resolve_schema(schema)
108
+ if table is None:
109
+ self._log_schema_introspect(driver, schema_name=schema_name, table_name=None, operation="foreign_keys")
110
+ return driver.select(
111
+ self.get_query("foreign_keys_by_schema"), schema_name=schema_name, schema_type=ForeignKeyMetadata
112
+ )
113
+
114
+ self._log_table_describe(driver, schema_name=schema_name, table_name=table, operation="foreign_keys")
115
+ return driver.select(
116
+ self.get_query("foreign_keys_by_table"),
117
+ table_name=table,
118
+ schema_name=schema_name,
119
+ schema_type=ForeignKeyMetadata,
120
+ )
@@ -0,0 +1,271 @@
1
+ """PyMySQL MySQL driver implementation."""
2
+
3
+ from collections.abc import Sized
4
+ from typing import TYPE_CHECKING, Any, Final, cast
5
+
6
+ import pymysql
7
+ from pymysql.constants import FIELD_TYPE
8
+
9
+ from sqlspec.adapters.pymysql._typing import PyMysqlCursor, PyMysqlSessionContext
10
+ from sqlspec.adapters.pymysql.core import (
11
+ build_insert_statement,
12
+ collect_rows,
13
+ create_mapped_exception,
14
+ default_statement_config,
15
+ detect_json_columns_from_description,
16
+ driver_profile,
17
+ format_identifier,
18
+ normalize_execute_many_parameters,
19
+ normalize_execute_parameters,
20
+ normalize_lastrowid,
21
+ resolve_column_names,
22
+ resolve_many_rowcount,
23
+ resolve_rowcount,
24
+ )
25
+ from sqlspec.adapters.pymysql.data_dictionary import PyMysqlDataDictionary
26
+ from sqlspec.core import ArrowResult, get_cache_config, register_driver_profile
27
+ from sqlspec.driver import BaseSyncExceptionHandler, SyncDriverAdapterBase
28
+ from sqlspec.exceptions import SQLSpecError
29
+ from sqlspec.utils.logging import get_logger
30
+ from sqlspec.utils.serializers import from_json
31
+ from sqlspec.utils.type_guards import supports_json_type
32
+
33
+ if TYPE_CHECKING:
34
+ from collections.abc import Callable
35
+
36
+ from sqlspec.adapters.pymysql._typing import PyMysqlConnection
37
+ from sqlspec.core import SQL, StatementConfig
38
+ from sqlspec.driver import ExecutionResult
39
+ from sqlspec.storage import StorageBridgeJob, StorageDestination, StorageFormat, StorageTelemetry
40
+
41
+ __all__ = ("PyMysqlCursor", "PyMysqlDriver", "PyMysqlExceptionHandler", "PyMysqlSessionContext")
42
+
43
+ logger = get_logger("sqlspec.adapters.pymysql")
44
+
45
+ json_type_value = FIELD_TYPE.JSON if supports_json_type(FIELD_TYPE) else None
46
+ PYMYSQL_JSON_TYPE_CODES: Final[set[int]] = {json_type_value} if json_type_value is not None else set()
47
+
48
+
49
+ class PyMysqlExceptionHandler(BaseSyncExceptionHandler):
50
+ """Context manager for handling PyMySQL exceptions."""
51
+
52
+ __slots__ = ()
53
+
54
+ def _handle_exception(self, exc_type: "type[BaseException] | None", exc_val: "BaseException") -> bool:
55
+ if exc_type is None:
56
+ return False
57
+ if issubclass(exc_type, pymysql.MySQLError):
58
+ result = create_mapped_exception(exc_val, logger=logger)
59
+ if result is True:
60
+ return True
61
+ self.pending_exception = cast("Exception", result)
62
+ return True
63
+ return False
64
+
65
+
66
+ class PyMysqlDriver(SyncDriverAdapterBase):
67
+ """MySQL/MariaDB database driver using PyMySQL."""
68
+
69
+ __slots__ = ("_data_dictionary",)
70
+ dialect = "mysql"
71
+
72
+ def __init__(
73
+ self,
74
+ connection: "PyMysqlConnection",
75
+ statement_config: "StatementConfig | None" = None,
76
+ driver_features: "dict[str, Any] | None" = None,
77
+ ) -> None:
78
+ if statement_config is None:
79
+ statement_config = default_statement_config.replace(
80
+ enable_caching=get_cache_config().compiled_cache_enabled
81
+ )
82
+
83
+ super().__init__(connection=connection, statement_config=statement_config, driver_features=driver_features)
84
+ self._data_dictionary: PyMysqlDataDictionary | None = None
85
+
86
+ def dispatch_execute(self, cursor: Any, statement: "SQL") -> "ExecutionResult":
87
+ sql, prepared_parameters = self._get_compiled_sql(statement, self.statement_config)
88
+ cursor.execute(sql, normalize_execute_parameters(prepared_parameters))
89
+
90
+ if statement.returns_rows():
91
+ fetched_data = cursor.fetchall()
92
+ description = cursor.description or None
93
+ column_names = resolve_column_names(description)
94
+ json_indexes = detect_json_columns_from_description(description, PYMYSQL_JSON_TYPE_CODES)
95
+ deserializer = cast("Callable[[Any], Any]", self.driver_features.get("json_deserializer", from_json))
96
+ rows, column_names, row_format = collect_rows(
97
+ fetched_data, description, json_indexes, deserializer, column_names=column_names, logger=logger
98
+ )
99
+
100
+ return self.create_execution_result(
101
+ cursor,
102
+ selected_data=rows,
103
+ column_names=column_names,
104
+ data_row_count=len(rows),
105
+ is_select_result=True,
106
+ row_format=row_format,
107
+ )
108
+
109
+ affected_rows = resolve_rowcount(cursor)
110
+ last_id = normalize_lastrowid(cursor)
111
+ return self.create_execution_result(cursor, rowcount_override=affected_rows, last_inserted_id=last_id)
112
+
113
+ def dispatch_execute_many(self, cursor: Any, statement: "SQL") -> "ExecutionResult":
114
+ sql, prepared_parameters = self._get_compiled_sql(statement, self.statement_config)
115
+
116
+ prepared_parameters = normalize_execute_many_parameters(prepared_parameters)
117
+ parameter_count = len(prepared_parameters) if isinstance(prepared_parameters, Sized) else None
118
+ cursor.executemany(sql, prepared_parameters)
119
+
120
+ affected_rows = resolve_many_rowcount(cursor, prepared_parameters, fallback_count=parameter_count)
121
+ return self.create_execution_result(cursor, rowcount_override=affected_rows, is_many_result=True)
122
+
123
+ def dispatch_execute_script(self, cursor: Any, statement: "SQL") -> "ExecutionResult":
124
+ sql, prepared_parameters = self._get_compiled_sql(statement, self.statement_config)
125
+ statements = self.split_script_statements(sql, statement.statement_config, strip_trailing_semicolon=True)
126
+
127
+ successful_count = 0
128
+ last_cursor = cursor
129
+
130
+ for stmt in statements:
131
+ cursor.execute(stmt, normalize_execute_parameters(prepared_parameters))
132
+ successful_count += 1
133
+
134
+ return self.create_execution_result(
135
+ last_cursor, statement_count=len(statements), successful_statements=successful_count, is_script_result=True
136
+ )
137
+
138
+ def begin(self) -> None:
139
+ try:
140
+ with PyMysqlCursor(self.connection) as cursor:
141
+ cursor.execute("BEGIN")
142
+ except pymysql.MySQLError as exc:
143
+ msg = f"Failed to begin MySQL transaction: {exc}"
144
+ raise SQLSpecError(msg) from exc
145
+
146
+ def commit(self) -> None:
147
+ try:
148
+ self.connection.commit()
149
+ except pymysql.MySQLError as exc:
150
+ msg = f"Failed to commit MySQL transaction: {exc}"
151
+ raise SQLSpecError(msg) from exc
152
+
153
+ def rollback(self) -> None:
154
+ try:
155
+ self.connection.rollback()
156
+ except pymysql.MySQLError as exc:
157
+ msg = f"Failed to rollback MySQL transaction: {exc}"
158
+ raise SQLSpecError(msg) from exc
159
+
160
+ def with_cursor(self, connection: "PyMysqlConnection") -> "PyMysqlCursor":
161
+ return PyMysqlCursor(connection)
162
+
163
+ def handle_database_exceptions(self) -> "PyMysqlExceptionHandler":
164
+ return PyMysqlExceptionHandler()
165
+
166
+ def select_to_storage(
167
+ self,
168
+ statement: "SQL | str",
169
+ destination: "StorageDestination",
170
+ /,
171
+ *parameters: Any,
172
+ statement_config: "StatementConfig | None" = None,
173
+ partitioner: "dict[str, object] | None" = None,
174
+ format_hint: "StorageFormat | None" = None,
175
+ telemetry: "StorageTelemetry | None" = None,
176
+ **kwargs: Any,
177
+ ) -> "StorageBridgeJob":
178
+ self._require_capability("arrow_export_enabled")
179
+ arrow_result = self.select_to_arrow(statement, *parameters, statement_config=statement_config, **kwargs)
180
+ pipeline = self._storage_pipeline()
181
+ telemetry_payload = self._write_result_to_storage_sync(
182
+ arrow_result, destination, format_hint=format_hint, pipeline=pipeline
183
+ )
184
+ self._attach_partition_telemetry(telemetry_payload, partitioner)
185
+ return self._create_storage_job(telemetry_payload, telemetry)
186
+
187
+ def load_from_arrow(
188
+ self,
189
+ table: str,
190
+ source: "ArrowResult | Any",
191
+ *,
192
+ partitioner: "dict[str, object] | None" = None,
193
+ overwrite: bool = False,
194
+ telemetry: "StorageTelemetry | None" = None,
195
+ ) -> "StorageBridgeJob":
196
+ self._require_capability("arrow_import_enabled")
197
+ arrow_table = self._coerce_arrow_table(source)
198
+ if overwrite:
199
+ statement = f"TRUNCATE TABLE {format_identifier(table)}"
200
+ exc_handler = self.handle_database_exceptions()
201
+ with exc_handler, self.with_cursor(self.connection) as cursor:
202
+ cursor.execute(statement)
203
+ if exc_handler.pending_exception is not None:
204
+ raise exc_handler.pending_exception from None
205
+
206
+ columns, records = self._arrow_table_to_rows(arrow_table)
207
+ if records:
208
+ insert_sql = build_insert_statement(table, columns)
209
+ prepared_records = (
210
+ self.prepare_driver_parameters(records, self.statement_config, is_many=True)
211
+ if self._arrow_table_needs_parameter_preparation(arrow_table)
212
+ else records
213
+ )
214
+ exc_handler = self.handle_database_exceptions()
215
+ with exc_handler, self.with_cursor(self.connection) as cursor:
216
+ cursor.executemany(insert_sql, cast("Any", prepared_records))
217
+ if exc_handler.pending_exception is not None:
218
+ raise exc_handler.pending_exception from None
219
+
220
+ telemetry_payload = self._build_ingest_telemetry(arrow_table)
221
+ telemetry_payload["destination"] = table
222
+ self._attach_partition_telemetry(telemetry_payload, partitioner)
223
+ return self._create_storage_job(telemetry_payload, telemetry)
224
+
225
+ def load_from_storage(
226
+ self,
227
+ table: str,
228
+ source: "StorageDestination",
229
+ *,
230
+ file_format: "StorageFormat",
231
+ partitioner: "dict[str, object] | None" = None,
232
+ overwrite: bool = False,
233
+ ) -> "StorageBridgeJob":
234
+ arrow_table, inbound = self._read_arrow_from_storage_sync(source, file_format=file_format)
235
+ return self.load_from_arrow(table, arrow_table, partitioner=partitioner, overwrite=overwrite, telemetry=inbound)
236
+
237
+ @property
238
+ def data_dictionary(self) -> "PyMysqlDataDictionary":
239
+ if self._data_dictionary is None:
240
+ self._data_dictionary = PyMysqlDataDictionary()
241
+ return self._data_dictionary
242
+
243
+ def collect_rows(self, cursor: Any, fetched: "list[Any]") -> "tuple[list[Any], list[str], int]":
244
+ """Collect PyMySQL rows for the direct execution path."""
245
+ description = cursor.description or None
246
+ column_names = resolve_column_names(description)
247
+ json_indexes = detect_json_columns_from_description(description, PYMYSQL_JSON_TYPE_CODES)
248
+ deserializer = cast("Callable[[Any], Any]", self.driver_features.get("json_deserializer", from_json))
249
+ rows, column_names, _row_format = collect_rows(
250
+ fetched, description, json_indexes, deserializer, column_names=column_names, logger=logger
251
+ )
252
+ return rows, column_names, len(rows)
253
+
254
+ def resolve_rowcount(self, cursor: Any) -> int:
255
+ """Resolve rowcount from PyMySQL cursor for the direct execution path."""
256
+ return resolve_rowcount(cursor)
257
+
258
+ def _connection_in_transaction(self) -> bool:
259
+ get_autocommit = getattr(self.connection, "get_autocommit", None)
260
+ if callable(get_autocommit):
261
+ return not bool(get_autocommit())
262
+ autocommit = getattr(self.connection, "autocommit", None)
263
+ if autocommit is not None:
264
+ try:
265
+ return not bool(autocommit)
266
+ except Exception:
267
+ return False
268
+ return False
269
+
270
+
271
+ register_driver_profile("pymysql", driver_profile)
@@ -0,0 +1,5 @@
1
+ """Events helpers for the PyMySQL adapter."""
2
+
3
+ from sqlspec.adapters.pymysql.events.store import PyMysqlEventQueueStore
4
+
5
+ __all__ = ("PyMysqlEventQueueStore",)
@@ -0,0 +1,50 @@
1
+ """PyMySQL event queue store with MySQL-specific DDL."""
2
+
3
+ from typing import Final
4
+
5
+ from sqlspec.adapters.pymysql.config import PyMysqlConfig
6
+ from sqlspec.extensions.events import BaseEventQueueStore
7
+
8
+ __all__ = ("PyMysqlEventQueueStore",)
9
+
10
+ SCHEMA_QUALIFIED_SEGMENTS: Final[int] = 2
11
+
12
+
13
+ class PyMysqlEventQueueStore(BaseEventQueueStore[PyMysqlConfig]):
14
+ """Queue DDL for PyMySQL configs."""
15
+
16
+ __slots__ = ()
17
+
18
+ def _column_types(self) -> "tuple[str, str, str]":
19
+ return "JSON", "JSON", "DATETIME(6)"
20
+
21
+ def _timestamp_default(self) -> str:
22
+ return "CURRENT_TIMESTAMP(6)"
23
+
24
+ def _build_index_sql(self) -> str | None:
25
+ table_name = self.table_name
26
+ segments = table_name.split(".", 1)
27
+
28
+ if len(segments) == SCHEMA_QUALIFIED_SEGMENTS:
29
+ schema = segments[0]
30
+ table = segments[1]
31
+ schema_selector = f"'{schema}'"
32
+ else:
33
+ table = segments[0]
34
+ schema_selector = "DATABASE()"
35
+
36
+ index_name = self._index_name()
37
+
38
+ return (
39
+ "SET @sqlspec_events_idx_exists := ("
40
+ "SELECT COUNT(1) FROM information_schema.statistics "
41
+ f"WHERE table_schema = {schema_selector} "
42
+ f"AND table_name = '{table}' "
43
+ f"AND index_name = '{index_name}');"
44
+ "SET @sqlspec_events_idx_stmt := IF(@sqlspec_events_idx_exists = 0, "
45
+ f"'ALTER TABLE {table_name} ADD INDEX {index_name} (channel, status, available_at)', "
46
+ "'SELECT 1');"
47
+ "PREPARE sqlspec_events_stmt FROM @sqlspec_events_idx_stmt;"
48
+ "EXECUTE sqlspec_events_stmt;"
49
+ "DEALLOCATE PREPARE sqlspec_events_stmt;"
50
+ )
@@ -0,0 +1,5 @@
1
+ """Litestar helpers for the PyMySQL adapter."""
2
+
3
+ from sqlspec.adapters.pymysql.litestar.store import PyMysqlStore
4
+
5
+ __all__ = ("PyMysqlStore",)
@@ -0,0 +1,232 @@
1
+ """PyMySQL session store for Litestar integration."""
2
+
3
+ from datetime import datetime, timedelta, timezone
4
+ from typing import TYPE_CHECKING, Final
5
+
6
+ import pymysql
7
+
8
+ from sqlspec.extensions.litestar.store import BaseSQLSpecStore
9
+ from sqlspec.utils.logging import get_logger
10
+ from sqlspec.utils.sync_tools import async_
11
+
12
+ if TYPE_CHECKING:
13
+ from sqlspec.adapters.pymysql.config import PyMysqlConfig
14
+
15
+ logger = get_logger("sqlspec.adapters.pymysql.litestar.store")
16
+
17
+ __all__ = ("PyMysqlStore",)
18
+
19
+ MYSQL_TABLE_NOT_FOUND_ERROR: Final = 1146
20
+
21
+
22
+ class PyMysqlStore(BaseSQLSpecStore["PyMysqlConfig"]):
23
+ """MySQL/MariaDB session store using PyMySQL sync driver."""
24
+
25
+ __slots__ = ()
26
+
27
+ def __init__(self, config: "PyMysqlConfig") -> None:
28
+ super().__init__(config)
29
+
30
+ def _get_create_table_sql(self) -> str:
31
+ return f"""
32
+ CREATE TABLE IF NOT EXISTS {self._table_name} (
33
+ session_id VARCHAR(255) PRIMARY KEY,
34
+ data LONGBLOB NOT NULL,
35
+ expires_at DATETIME(6),
36
+ created_at DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
37
+ updated_at DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
38
+ INDEX idx_{self._table_name}_expires_at (expires_at)
39
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
40
+ """
41
+
42
+ def _get_drop_table_sql(self) -> "list[str]":
43
+ return [
44
+ f"DROP INDEX idx_{self._table_name}_expires_at ON {self._table_name}",
45
+ f"DROP TABLE IF EXISTS {self._table_name}",
46
+ ]
47
+
48
+ def _create_table(self) -> None:
49
+ sql = self._get_create_table_sql()
50
+ with self._config.provide_session() as driver:
51
+ driver.execute_script(sql)
52
+ driver.commit()
53
+ self._log_table_created()
54
+
55
+ async def create_table(self) -> None:
56
+ await async_(self._create_table)()
57
+
58
+ def _get(self, key: str, renew_for: "int | timedelta | None" = None) -> "bytes | None":
59
+ sql = f"""
60
+ SELECT data, expires_at FROM {self._table_name}
61
+ WHERE session_id = %s
62
+ AND (expires_at IS NULL OR expires_at > UTC_TIMESTAMP(6))
63
+ """
64
+
65
+ try:
66
+ with self._config.provide_connection() as conn:
67
+ cursor = conn.cursor(pymysql.cursors.DictCursor)
68
+ try:
69
+ cursor.execute(sql, (key,))
70
+ row = cursor.fetchone()
71
+ finally:
72
+ cursor.close()
73
+
74
+ if row is None:
75
+ return None
76
+
77
+ if renew_for is not None and row["expires_at"] is not None:
78
+ new_expires_at = self._calculate_expires_at(renew_for)
79
+ if new_expires_at is not None:
80
+ naive_expires_at = new_expires_at.replace(tzinfo=None)
81
+ update_sql = f"""
82
+ UPDATE {self._table_name}
83
+ SET expires_at = %s, updated_at = UTC_TIMESTAMP(6)
84
+ WHERE session_id = %s
85
+ """
86
+ update_cursor = conn.cursor()
87
+ try:
88
+ update_cursor.execute(update_sql, (naive_expires_at, key))
89
+ finally:
90
+ update_cursor.close()
91
+ conn.commit()
92
+
93
+ return bytes(row["data"])
94
+ except pymysql.MySQLError as exc:
95
+ if "doesn't exist" in str(exc) or getattr(exc, "args", [None])[0] == MYSQL_TABLE_NOT_FOUND_ERROR:
96
+ return None
97
+ raise
98
+
99
+ async def get(self, key: str, renew_for: "int | timedelta | None" = None) -> "bytes | None":
100
+ return await async_(self._get)(key, renew_for)
101
+
102
+ def _set(self, key: str, value: "str | bytes", expires_in: "int | timedelta | None" = None) -> None:
103
+ data = self._value_to_bytes(value)
104
+ expires_at = self._calculate_expires_at(expires_in)
105
+ naive_expires_at = expires_at.replace(tzinfo=None) if expires_at else None
106
+
107
+ sql = f"""
108
+ INSERT INTO {self._table_name} (session_id, data, expires_at)
109
+ VALUES (%s, %s, %s) AS new
110
+ ON DUPLICATE KEY UPDATE
111
+ data = new.data,
112
+ expires_at = new.expires_at,
113
+ updated_at = UTC_TIMESTAMP(6)
114
+ """
115
+
116
+ with self._config.provide_connection() as conn:
117
+ cursor = conn.cursor()
118
+ try:
119
+ cursor.execute(sql, (key, data, naive_expires_at))
120
+ finally:
121
+ cursor.close()
122
+ conn.commit()
123
+
124
+ async def set(self, key: str, value: "str | bytes", expires_in: "int | timedelta | None" = None) -> None:
125
+ await async_(self._set)(key, value, expires_in)
126
+
127
+ def _delete(self, key: str) -> None:
128
+ sql = f"DELETE FROM {self._table_name} WHERE session_id = %s"
129
+
130
+ with self._config.provide_connection() as conn:
131
+ cursor = conn.cursor()
132
+ try:
133
+ cursor.execute(sql, (key,))
134
+ finally:
135
+ cursor.close()
136
+ conn.commit()
137
+
138
+ async def delete(self, key: str) -> None:
139
+ await async_(self._delete)(key)
140
+
141
+ def _delete_all(self) -> None:
142
+ sql = f"DELETE FROM {self._table_name}"
143
+
144
+ try:
145
+ with self._config.provide_connection() as conn:
146
+ cursor = conn.cursor()
147
+ try:
148
+ cursor.execute(sql)
149
+ finally:
150
+ cursor.close()
151
+ conn.commit()
152
+ self._log_delete_all()
153
+ except pymysql.MySQLError as exc:
154
+ if "doesn't exist" in str(exc) or getattr(exc, "args", [None])[0] == MYSQL_TABLE_NOT_FOUND_ERROR:
155
+ logger.debug("Table %s does not exist, skipping delete_all", self._table_name)
156
+ return
157
+ raise
158
+
159
+ async def delete_all(self) -> None:
160
+ await async_(self._delete_all)()
161
+
162
+ def _exists(self, key: str) -> bool:
163
+ sql = f"""
164
+ SELECT 1 FROM {self._table_name}
165
+ WHERE session_id = %s
166
+ AND (expires_at IS NULL OR expires_at > UTC_TIMESTAMP(6))
167
+ """
168
+
169
+ try:
170
+ with self._config.provide_connection() as conn:
171
+ cursor = conn.cursor()
172
+ try:
173
+ cursor.execute(sql, (key,))
174
+ result = cursor.fetchone()
175
+ finally:
176
+ cursor.close()
177
+ return result is not None
178
+ except pymysql.MySQLError as exc:
179
+ if "doesn't exist" in str(exc) or getattr(exc, "args", [None])[0] == MYSQL_TABLE_NOT_FOUND_ERROR:
180
+ return False
181
+ raise
182
+
183
+ async def exists(self, key: str) -> bool:
184
+ return await async_(self._exists)(key)
185
+
186
+ def _expires_in(self, key: str) -> "int | None":
187
+ sql = f"""
188
+ SELECT expires_at FROM {self._table_name}
189
+ WHERE session_id = %s
190
+ """
191
+
192
+ with self._config.provide_connection() as conn:
193
+ cursor = conn.cursor()
194
+ try:
195
+ cursor.execute(sql, (key,))
196
+ row = cursor.fetchone()
197
+ finally:
198
+ cursor.close()
199
+
200
+ if row is None or row[0] is None:
201
+ return None
202
+
203
+ expires_at_naive = row[0]
204
+ expires_at_utc = expires_at_naive.replace(tzinfo=timezone.utc)
205
+ now = datetime.now(timezone.utc)
206
+
207
+ if expires_at_utc <= now:
208
+ return 0
209
+
210
+ delta = expires_at_utc - now
211
+ return int(delta.total_seconds())
212
+
213
+ async def expires_in(self, key: str) -> "int | None":
214
+ return await async_(self._expires_in)(key)
215
+
216
+ def _delete_expired(self) -> int:
217
+ sql = f"DELETE FROM {self._table_name} WHERE expires_at <= UTC_TIMESTAMP(6)"
218
+
219
+ with self._config.provide_connection() as conn:
220
+ cursor = conn.cursor()
221
+ try:
222
+ cursor.execute(sql)
223
+ conn.commit()
224
+ count: int = cursor.rowcount
225
+ finally:
226
+ cursor.close()
227
+ if count > 0:
228
+ self._log_delete_expired(count)
229
+ return count
230
+
231
+ async def delete_expired(self) -> int:
232
+ return await async_(self._delete_expired)()