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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (531) hide show
  1. ac8f31065839703b4e70__mypyc.cpython-310-aarch64-linux-gnu.so +0 -0
  2. sqlspec/__init__.py +140 -0
  3. sqlspec/__main__.py +12 -0
  4. sqlspec/__metadata__.py +14 -0
  5. sqlspec/_serialization.py +315 -0
  6. sqlspec/_typing.py +700 -0
  7. sqlspec/adapters/__init__.py +0 -0
  8. sqlspec/adapters/adbc/__init__.py +5 -0
  9. sqlspec/adapters/adbc/_typing.py +82 -0
  10. sqlspec/adapters/adbc/adk/__init__.py +5 -0
  11. sqlspec/adapters/adbc/adk/store.py +1273 -0
  12. sqlspec/adapters/adbc/config.py +295 -0
  13. sqlspec/adapters/adbc/core.cpython-310-aarch64-linux-gnu.so +0 -0
  14. sqlspec/adapters/adbc/core.py +735 -0
  15. sqlspec/adapters/adbc/data_dictionary.py +334 -0
  16. sqlspec/adapters/adbc/driver.py +529 -0
  17. sqlspec/adapters/adbc/events/__init__.py +5 -0
  18. sqlspec/adapters/adbc/events/store.py +285 -0
  19. sqlspec/adapters/adbc/litestar/__init__.py +5 -0
  20. sqlspec/adapters/adbc/litestar/store.py +502 -0
  21. sqlspec/adapters/adbc/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  22. sqlspec/adapters/adbc/type_converter.py +140 -0
  23. sqlspec/adapters/aiosqlite/__init__.py +25 -0
  24. sqlspec/adapters/aiosqlite/_typing.py +82 -0
  25. sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
  26. sqlspec/adapters/aiosqlite/adk/store.py +818 -0
  27. sqlspec/adapters/aiosqlite/config.py +334 -0
  28. sqlspec/adapters/aiosqlite/core.cpython-310-aarch64-linux-gnu.so +0 -0
  29. sqlspec/adapters/aiosqlite/core.py +315 -0
  30. sqlspec/adapters/aiosqlite/data_dictionary.py +208 -0
  31. sqlspec/adapters/aiosqlite/driver.py +313 -0
  32. sqlspec/adapters/aiosqlite/events/__init__.py +5 -0
  33. sqlspec/adapters/aiosqlite/events/store.py +20 -0
  34. sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
  35. sqlspec/adapters/aiosqlite/litestar/store.py +279 -0
  36. sqlspec/adapters/aiosqlite/pool.py +533 -0
  37. sqlspec/adapters/asyncmy/__init__.py +21 -0
  38. sqlspec/adapters/asyncmy/_typing.py +87 -0
  39. sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
  40. sqlspec/adapters/asyncmy/adk/store.py +703 -0
  41. sqlspec/adapters/asyncmy/config.py +302 -0
  42. sqlspec/adapters/asyncmy/core.cpython-310-aarch64-linux-gnu.so +0 -0
  43. sqlspec/adapters/asyncmy/core.py +360 -0
  44. sqlspec/adapters/asyncmy/data_dictionary.py +124 -0
  45. sqlspec/adapters/asyncmy/driver.py +383 -0
  46. sqlspec/adapters/asyncmy/events/__init__.py +5 -0
  47. sqlspec/adapters/asyncmy/events/store.py +104 -0
  48. sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
  49. sqlspec/adapters/asyncmy/litestar/store.py +296 -0
  50. sqlspec/adapters/asyncpg/__init__.py +19 -0
  51. sqlspec/adapters/asyncpg/_typing.py +88 -0
  52. sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
  53. sqlspec/adapters/asyncpg/adk/store.py +748 -0
  54. sqlspec/adapters/asyncpg/config.py +569 -0
  55. sqlspec/adapters/asyncpg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  56. sqlspec/adapters/asyncpg/core.py +367 -0
  57. sqlspec/adapters/asyncpg/data_dictionary.py +162 -0
  58. sqlspec/adapters/asyncpg/driver.py +487 -0
  59. sqlspec/adapters/asyncpg/events/__init__.py +6 -0
  60. sqlspec/adapters/asyncpg/events/backend.py +286 -0
  61. sqlspec/adapters/asyncpg/events/store.py +40 -0
  62. sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
  63. sqlspec/adapters/asyncpg/litestar/store.py +251 -0
  64. sqlspec/adapters/bigquery/__init__.py +14 -0
  65. sqlspec/adapters/bigquery/_typing.py +86 -0
  66. sqlspec/adapters/bigquery/adk/__init__.py +5 -0
  67. sqlspec/adapters/bigquery/adk/store.py +827 -0
  68. sqlspec/adapters/bigquery/config.py +353 -0
  69. sqlspec/adapters/bigquery/core.cpython-310-aarch64-linux-gnu.so +0 -0
  70. sqlspec/adapters/bigquery/core.py +715 -0
  71. sqlspec/adapters/bigquery/data_dictionary.py +128 -0
  72. sqlspec/adapters/bigquery/driver.py +548 -0
  73. sqlspec/adapters/bigquery/events/__init__.py +5 -0
  74. sqlspec/adapters/bigquery/events/store.py +139 -0
  75. sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
  76. sqlspec/adapters/bigquery/litestar/store.py +325 -0
  77. sqlspec/adapters/bigquery/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  78. sqlspec/adapters/bigquery/type_converter.py +107 -0
  79. sqlspec/adapters/cockroach_asyncpg/__init__.py +24 -0
  80. sqlspec/adapters/cockroach_asyncpg/_typing.py +72 -0
  81. sqlspec/adapters/cockroach_asyncpg/adk/__init__.py +3 -0
  82. sqlspec/adapters/cockroach_asyncpg/adk/store.py +410 -0
  83. sqlspec/adapters/cockroach_asyncpg/config.py +238 -0
  84. sqlspec/adapters/cockroach_asyncpg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  85. sqlspec/adapters/cockroach_asyncpg/core.py +55 -0
  86. sqlspec/adapters/cockroach_asyncpg/data_dictionary.py +107 -0
  87. sqlspec/adapters/cockroach_asyncpg/driver.py +144 -0
  88. sqlspec/adapters/cockroach_asyncpg/events/__init__.py +3 -0
  89. sqlspec/adapters/cockroach_asyncpg/events/store.py +20 -0
  90. sqlspec/adapters/cockroach_asyncpg/litestar/__init__.py +3 -0
  91. sqlspec/adapters/cockroach_asyncpg/litestar/store.py +142 -0
  92. sqlspec/adapters/cockroach_psycopg/__init__.py +38 -0
  93. sqlspec/adapters/cockroach_psycopg/_typing.py +129 -0
  94. sqlspec/adapters/cockroach_psycopg/adk/__init__.py +13 -0
  95. sqlspec/adapters/cockroach_psycopg/adk/store.py +868 -0
  96. sqlspec/adapters/cockroach_psycopg/config.py +484 -0
  97. sqlspec/adapters/cockroach_psycopg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  98. sqlspec/adapters/cockroach_psycopg/core.py +63 -0
  99. sqlspec/adapters/cockroach_psycopg/data_dictionary.py +215 -0
  100. sqlspec/adapters/cockroach_psycopg/driver.py +284 -0
  101. sqlspec/adapters/cockroach_psycopg/events/__init__.py +6 -0
  102. sqlspec/adapters/cockroach_psycopg/events/store.py +34 -0
  103. sqlspec/adapters/cockroach_psycopg/litestar/__init__.py +3 -0
  104. sqlspec/adapters/cockroach_psycopg/litestar/store.py +325 -0
  105. sqlspec/adapters/duckdb/__init__.py +25 -0
  106. sqlspec/adapters/duckdb/_typing.py +81 -0
  107. sqlspec/adapters/duckdb/adk/__init__.py +14 -0
  108. sqlspec/adapters/duckdb/adk/store.py +850 -0
  109. sqlspec/adapters/duckdb/config.py +463 -0
  110. sqlspec/adapters/duckdb/core.cpython-310-aarch64-linux-gnu.so +0 -0
  111. sqlspec/adapters/duckdb/core.py +257 -0
  112. sqlspec/adapters/duckdb/data_dictionary.py +140 -0
  113. sqlspec/adapters/duckdb/driver.py +430 -0
  114. sqlspec/adapters/duckdb/events/__init__.py +5 -0
  115. sqlspec/adapters/duckdb/events/store.py +57 -0
  116. sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
  117. sqlspec/adapters/duckdb/litestar/store.py +330 -0
  118. sqlspec/adapters/duckdb/pool.py +293 -0
  119. sqlspec/adapters/duckdb/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  120. sqlspec/adapters/duckdb/type_converter.py +118 -0
  121. sqlspec/adapters/mock/__init__.py +72 -0
  122. sqlspec/adapters/mock/_typing.py +147 -0
  123. sqlspec/adapters/mock/config.py +483 -0
  124. sqlspec/adapters/mock/core.py +319 -0
  125. sqlspec/adapters/mock/data_dictionary.py +366 -0
  126. sqlspec/adapters/mock/driver.py +721 -0
  127. sqlspec/adapters/mysqlconnector/__init__.py +36 -0
  128. sqlspec/adapters/mysqlconnector/_typing.py +141 -0
  129. sqlspec/adapters/mysqlconnector/adk/__init__.py +15 -0
  130. sqlspec/adapters/mysqlconnector/adk/store.py +1060 -0
  131. sqlspec/adapters/mysqlconnector/config.py +394 -0
  132. sqlspec/adapters/mysqlconnector/core.cpython-310-aarch64-linux-gnu.so +0 -0
  133. sqlspec/adapters/mysqlconnector/core.py +303 -0
  134. sqlspec/adapters/mysqlconnector/data_dictionary.py +235 -0
  135. sqlspec/adapters/mysqlconnector/driver.py +483 -0
  136. sqlspec/adapters/mysqlconnector/events/__init__.py +8 -0
  137. sqlspec/adapters/mysqlconnector/events/store.py +98 -0
  138. sqlspec/adapters/mysqlconnector/litestar/__init__.py +5 -0
  139. sqlspec/adapters/mysqlconnector/litestar/store.py +426 -0
  140. sqlspec/adapters/oracledb/__init__.py +60 -0
  141. sqlspec/adapters/oracledb/_numpy_handlers.py +141 -0
  142. sqlspec/adapters/oracledb/_typing.py +182 -0
  143. sqlspec/adapters/oracledb/_uuid_handlers.py +166 -0
  144. sqlspec/adapters/oracledb/adk/__init__.py +10 -0
  145. sqlspec/adapters/oracledb/adk/store.py +2369 -0
  146. sqlspec/adapters/oracledb/config.py +550 -0
  147. sqlspec/adapters/oracledb/core.cpython-310-aarch64-linux-gnu.so +0 -0
  148. sqlspec/adapters/oracledb/core.py +543 -0
  149. sqlspec/adapters/oracledb/data_dictionary.py +536 -0
  150. sqlspec/adapters/oracledb/driver.py +1229 -0
  151. sqlspec/adapters/oracledb/events/__init__.py +16 -0
  152. sqlspec/adapters/oracledb/events/backend.py +347 -0
  153. sqlspec/adapters/oracledb/events/store.py +420 -0
  154. sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
  155. sqlspec/adapters/oracledb/litestar/store.py +781 -0
  156. sqlspec/adapters/oracledb/migrations.py +535 -0
  157. sqlspec/adapters/oracledb/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  158. sqlspec/adapters/oracledb/type_converter.py +211 -0
  159. sqlspec/adapters/psqlpy/__init__.py +17 -0
  160. sqlspec/adapters/psqlpy/_typing.py +79 -0
  161. sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
  162. sqlspec/adapters/psqlpy/adk/store.py +766 -0
  163. sqlspec/adapters/psqlpy/config.py +304 -0
  164. sqlspec/adapters/psqlpy/core.cpython-310-aarch64-linux-gnu.so +0 -0
  165. sqlspec/adapters/psqlpy/core.py +480 -0
  166. sqlspec/adapters/psqlpy/data_dictionary.py +126 -0
  167. sqlspec/adapters/psqlpy/driver.py +438 -0
  168. sqlspec/adapters/psqlpy/events/__init__.py +6 -0
  169. sqlspec/adapters/psqlpy/events/backend.py +310 -0
  170. sqlspec/adapters/psqlpy/events/store.py +20 -0
  171. sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
  172. sqlspec/adapters/psqlpy/litestar/store.py +270 -0
  173. sqlspec/adapters/psqlpy/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  174. sqlspec/adapters/psqlpy/type_converter.py +113 -0
  175. sqlspec/adapters/psycopg/__init__.py +32 -0
  176. sqlspec/adapters/psycopg/_typing.py +164 -0
  177. sqlspec/adapters/psycopg/adk/__init__.py +10 -0
  178. sqlspec/adapters/psycopg/adk/store.py +1387 -0
  179. sqlspec/adapters/psycopg/config.py +576 -0
  180. sqlspec/adapters/psycopg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  181. sqlspec/adapters/psycopg/core.py +450 -0
  182. sqlspec/adapters/psycopg/data_dictionary.py +289 -0
  183. sqlspec/adapters/psycopg/driver.py +975 -0
  184. sqlspec/adapters/psycopg/events/__init__.py +20 -0
  185. sqlspec/adapters/psycopg/events/backend.py +458 -0
  186. sqlspec/adapters/psycopg/events/store.py +42 -0
  187. sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
  188. sqlspec/adapters/psycopg/litestar/store.py +552 -0
  189. sqlspec/adapters/psycopg/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  190. sqlspec/adapters/psycopg/type_converter.py +93 -0
  191. sqlspec/adapters/pymysql/__init__.py +21 -0
  192. sqlspec/adapters/pymysql/_typing.py +71 -0
  193. sqlspec/adapters/pymysql/adk/__init__.py +5 -0
  194. sqlspec/adapters/pymysql/adk/store.py +540 -0
  195. sqlspec/adapters/pymysql/config.py +195 -0
  196. sqlspec/adapters/pymysql/core.cpython-310-aarch64-linux-gnu.so +0 -0
  197. sqlspec/adapters/pymysql/core.py +299 -0
  198. sqlspec/adapters/pymysql/data_dictionary.py +122 -0
  199. sqlspec/adapters/pymysql/driver.py +259 -0
  200. sqlspec/adapters/pymysql/events/__init__.py +5 -0
  201. sqlspec/adapters/pymysql/events/store.py +50 -0
  202. sqlspec/adapters/pymysql/litestar/__init__.py +5 -0
  203. sqlspec/adapters/pymysql/litestar/store.py +232 -0
  204. sqlspec/adapters/pymysql/pool.py +137 -0
  205. sqlspec/adapters/spanner/__init__.py +40 -0
  206. sqlspec/adapters/spanner/_typing.py +86 -0
  207. sqlspec/adapters/spanner/adk/__init__.py +5 -0
  208. sqlspec/adapters/spanner/adk/store.py +732 -0
  209. sqlspec/adapters/spanner/config.py +352 -0
  210. sqlspec/adapters/spanner/core.cpython-310-aarch64-linux-gnu.so +0 -0
  211. sqlspec/adapters/spanner/core.py +188 -0
  212. sqlspec/adapters/spanner/data_dictionary.py +120 -0
  213. sqlspec/adapters/spanner/dialect/__init__.py +6 -0
  214. sqlspec/adapters/spanner/dialect/_spangres.py +57 -0
  215. sqlspec/adapters/spanner/dialect/_spanner.py +130 -0
  216. sqlspec/adapters/spanner/driver.py +373 -0
  217. sqlspec/adapters/spanner/events/__init__.py +5 -0
  218. sqlspec/adapters/spanner/events/store.py +187 -0
  219. sqlspec/adapters/spanner/litestar/__init__.py +5 -0
  220. sqlspec/adapters/spanner/litestar/store.py +291 -0
  221. sqlspec/adapters/spanner/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  222. sqlspec/adapters/spanner/type_converter.py +331 -0
  223. sqlspec/adapters/sqlite/__init__.py +19 -0
  224. sqlspec/adapters/sqlite/_typing.py +80 -0
  225. sqlspec/adapters/sqlite/adk/__init__.py +5 -0
  226. sqlspec/adapters/sqlite/adk/store.py +958 -0
  227. sqlspec/adapters/sqlite/config.py +280 -0
  228. sqlspec/adapters/sqlite/core.cpython-310-aarch64-linux-gnu.so +0 -0
  229. sqlspec/adapters/sqlite/core.py +312 -0
  230. sqlspec/adapters/sqlite/data_dictionary.py +202 -0
  231. sqlspec/adapters/sqlite/driver.py +359 -0
  232. sqlspec/adapters/sqlite/events/__init__.py +5 -0
  233. sqlspec/adapters/sqlite/events/store.py +20 -0
  234. sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
  235. sqlspec/adapters/sqlite/litestar/store.py +316 -0
  236. sqlspec/adapters/sqlite/pool.py +198 -0
  237. sqlspec/adapters/sqlite/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  238. sqlspec/adapters/sqlite/type_converter.py +114 -0
  239. sqlspec/base.py +747 -0
  240. sqlspec/builder/__init__.py +179 -0
  241. sqlspec/builder/_base.cpython-310-aarch64-linux-gnu.so +0 -0
  242. sqlspec/builder/_base.py +1022 -0
  243. sqlspec/builder/_column.cpython-310-aarch64-linux-gnu.so +0 -0
  244. sqlspec/builder/_column.py +521 -0
  245. sqlspec/builder/_ddl.cpython-310-aarch64-linux-gnu.so +0 -0
  246. sqlspec/builder/_ddl.py +1642 -0
  247. sqlspec/builder/_delete.cpython-310-aarch64-linux-gnu.so +0 -0
  248. sqlspec/builder/_delete.py +95 -0
  249. sqlspec/builder/_dml.cpython-310-aarch64-linux-gnu.so +0 -0
  250. sqlspec/builder/_dml.py +365 -0
  251. sqlspec/builder/_explain.cpython-310-aarch64-linux-gnu.so +0 -0
  252. sqlspec/builder/_explain.py +579 -0
  253. sqlspec/builder/_expression_wrappers.cpython-310-aarch64-linux-gnu.so +0 -0
  254. sqlspec/builder/_expression_wrappers.py +46 -0
  255. sqlspec/builder/_factory.cpython-310-aarch64-linux-gnu.so +0 -0
  256. sqlspec/builder/_factory.py +1697 -0
  257. sqlspec/builder/_insert.cpython-310-aarch64-linux-gnu.so +0 -0
  258. sqlspec/builder/_insert.py +328 -0
  259. sqlspec/builder/_join.cpython-310-aarch64-linux-gnu.so +0 -0
  260. sqlspec/builder/_join.py +499 -0
  261. sqlspec/builder/_merge.cpython-310-aarch64-linux-gnu.so +0 -0
  262. sqlspec/builder/_merge.py +821 -0
  263. sqlspec/builder/_parsing_utils.cpython-310-aarch64-linux-gnu.so +0 -0
  264. sqlspec/builder/_parsing_utils.py +297 -0
  265. sqlspec/builder/_select.cpython-310-aarch64-linux-gnu.so +0 -0
  266. sqlspec/builder/_select.py +1660 -0
  267. sqlspec/builder/_temporal.cpython-310-aarch64-linux-gnu.so +0 -0
  268. sqlspec/builder/_temporal.py +139 -0
  269. sqlspec/builder/_update.cpython-310-aarch64-linux-gnu.so +0 -0
  270. sqlspec/builder/_update.py +173 -0
  271. sqlspec/builder/_vector_expressions.py +267 -0
  272. sqlspec/cli.py +911 -0
  273. sqlspec/config.py +1755 -0
  274. sqlspec/core/__init__.py +374 -0
  275. sqlspec/core/_correlation.cpython-310-aarch64-linux-gnu.so +0 -0
  276. sqlspec/core/_correlation.py +176 -0
  277. sqlspec/core/cache.cpython-310-aarch64-linux-gnu.so +0 -0
  278. sqlspec/core/cache.py +1069 -0
  279. sqlspec/core/compiler.cpython-310-aarch64-linux-gnu.so +0 -0
  280. sqlspec/core/compiler.py +954 -0
  281. sqlspec/core/explain.cpython-310-aarch64-linux-gnu.so +0 -0
  282. sqlspec/core/explain.py +275 -0
  283. sqlspec/core/filters.cpython-310-aarch64-linux-gnu.so +0 -0
  284. sqlspec/core/filters.py +952 -0
  285. sqlspec/core/hashing.cpython-310-aarch64-linux-gnu.so +0 -0
  286. sqlspec/core/hashing.py +262 -0
  287. sqlspec/core/metrics.cpython-310-aarch64-linux-gnu.so +0 -0
  288. sqlspec/core/metrics.py +83 -0
  289. sqlspec/core/parameters/__init__.py +71 -0
  290. sqlspec/core/parameters/_alignment.cpython-310-aarch64-linux-gnu.so +0 -0
  291. sqlspec/core/parameters/_alignment.py +270 -0
  292. sqlspec/core/parameters/_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  293. sqlspec/core/parameters/_converter.py +543 -0
  294. sqlspec/core/parameters/_processor.cpython-310-aarch64-linux-gnu.so +0 -0
  295. sqlspec/core/parameters/_processor.py +505 -0
  296. sqlspec/core/parameters/_registry.cpython-310-aarch64-linux-gnu.so +0 -0
  297. sqlspec/core/parameters/_registry.py +206 -0
  298. sqlspec/core/parameters/_transformers.cpython-310-aarch64-linux-gnu.so +0 -0
  299. sqlspec/core/parameters/_transformers.py +292 -0
  300. sqlspec/core/parameters/_types.cpython-310-aarch64-linux-gnu.so +0 -0
  301. sqlspec/core/parameters/_types.py +499 -0
  302. sqlspec/core/parameters/_validator.cpython-310-aarch64-linux-gnu.so +0 -0
  303. sqlspec/core/parameters/_validator.py +180 -0
  304. sqlspec/core/pipeline.cpython-310-aarch64-linux-gnu.so +0 -0
  305. sqlspec/core/pipeline.py +319 -0
  306. sqlspec/core/query_modifiers.cpython-310-aarch64-linux-gnu.so +0 -0
  307. sqlspec/core/query_modifiers.py +437 -0
  308. sqlspec/core/result/__init__.py +23 -0
  309. sqlspec/core/result/_base.cpython-310-aarch64-linux-gnu.so +0 -0
  310. sqlspec/core/result/_base.py +1121 -0
  311. sqlspec/core/result/_io.cpython-310-aarch64-linux-gnu.so +0 -0
  312. sqlspec/core/result/_io.py +28 -0
  313. sqlspec/core/splitter.cpython-310-aarch64-linux-gnu.so +0 -0
  314. sqlspec/core/splitter.py +966 -0
  315. sqlspec/core/stack.cpython-310-aarch64-linux-gnu.so +0 -0
  316. sqlspec/core/stack.py +163 -0
  317. sqlspec/core/statement.cpython-310-aarch64-linux-gnu.so +0 -0
  318. sqlspec/core/statement.py +1503 -0
  319. sqlspec/core/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  320. sqlspec/core/type_converter.py +339 -0
  321. sqlspec/data_dictionary/__init__.py +22 -0
  322. sqlspec/data_dictionary/_loader.py +123 -0
  323. sqlspec/data_dictionary/_registry.cpython-310-aarch64-linux-gnu.so +0 -0
  324. sqlspec/data_dictionary/_registry.py +74 -0
  325. sqlspec/data_dictionary/_types.cpython-310-aarch64-linux-gnu.so +0 -0
  326. sqlspec/data_dictionary/_types.py +121 -0
  327. sqlspec/data_dictionary/dialects/__init__.py +21 -0
  328. sqlspec/data_dictionary/dialects/bigquery.cpython-310-aarch64-linux-gnu.so +0 -0
  329. sqlspec/data_dictionary/dialects/bigquery.py +49 -0
  330. sqlspec/data_dictionary/dialects/cockroachdb.cpython-310-aarch64-linux-gnu.so +0 -0
  331. sqlspec/data_dictionary/dialects/cockroachdb.py +43 -0
  332. sqlspec/data_dictionary/dialects/duckdb.cpython-310-aarch64-linux-gnu.so +0 -0
  333. sqlspec/data_dictionary/dialects/duckdb.py +47 -0
  334. sqlspec/data_dictionary/dialects/mysql.cpython-310-aarch64-linux-gnu.so +0 -0
  335. sqlspec/data_dictionary/dialects/mysql.py +42 -0
  336. sqlspec/data_dictionary/dialects/oracle.cpython-310-aarch64-linux-gnu.so +0 -0
  337. sqlspec/data_dictionary/dialects/oracle.py +34 -0
  338. sqlspec/data_dictionary/dialects/postgres.cpython-310-aarch64-linux-gnu.so +0 -0
  339. sqlspec/data_dictionary/dialects/postgres.py +46 -0
  340. sqlspec/data_dictionary/dialects/spanner.cpython-310-aarch64-linux-gnu.so +0 -0
  341. sqlspec/data_dictionary/dialects/spanner.py +37 -0
  342. sqlspec/data_dictionary/dialects/sqlite.cpython-310-aarch64-linux-gnu.so +0 -0
  343. sqlspec/data_dictionary/dialects/sqlite.py +42 -0
  344. sqlspec/data_dictionary/sql/.gitkeep +0 -0
  345. sqlspec/data_dictionary/sql/bigquery/columns.sql +23 -0
  346. sqlspec/data_dictionary/sql/bigquery/foreign_keys.sql +34 -0
  347. sqlspec/data_dictionary/sql/bigquery/indexes.sql +19 -0
  348. sqlspec/data_dictionary/sql/bigquery/tables.sql +33 -0
  349. sqlspec/data_dictionary/sql/bigquery/version.sql +3 -0
  350. sqlspec/data_dictionary/sql/cockroachdb/columns.sql +34 -0
  351. sqlspec/data_dictionary/sql/cockroachdb/foreign_keys.sql +40 -0
  352. sqlspec/data_dictionary/sql/cockroachdb/indexes.sql +32 -0
  353. sqlspec/data_dictionary/sql/cockroachdb/tables.sql +44 -0
  354. sqlspec/data_dictionary/sql/cockroachdb/version.sql +3 -0
  355. sqlspec/data_dictionary/sql/duckdb/columns.sql +23 -0
  356. sqlspec/data_dictionary/sql/duckdb/foreign_keys.sql +36 -0
  357. sqlspec/data_dictionary/sql/duckdb/indexes.sql +19 -0
  358. sqlspec/data_dictionary/sql/duckdb/tables.sql +38 -0
  359. sqlspec/data_dictionary/sql/duckdb/version.sql +3 -0
  360. sqlspec/data_dictionary/sql/mysql/columns.sql +23 -0
  361. sqlspec/data_dictionary/sql/mysql/foreign_keys.sql +28 -0
  362. sqlspec/data_dictionary/sql/mysql/indexes.sql +26 -0
  363. sqlspec/data_dictionary/sql/mysql/tables.sql +33 -0
  364. sqlspec/data_dictionary/sql/mysql/version.sql +3 -0
  365. sqlspec/data_dictionary/sql/oracle/columns.sql +23 -0
  366. sqlspec/data_dictionary/sql/oracle/foreign_keys.sql +48 -0
  367. sqlspec/data_dictionary/sql/oracle/indexes.sql +44 -0
  368. sqlspec/data_dictionary/sql/oracle/tables.sql +25 -0
  369. sqlspec/data_dictionary/sql/oracle/version.sql +20 -0
  370. sqlspec/data_dictionary/sql/postgres/columns.sql +34 -0
  371. sqlspec/data_dictionary/sql/postgres/foreign_keys.sql +40 -0
  372. sqlspec/data_dictionary/sql/postgres/indexes.sql +56 -0
  373. sqlspec/data_dictionary/sql/postgres/tables.sql +44 -0
  374. sqlspec/data_dictionary/sql/postgres/version.sql +3 -0
  375. sqlspec/data_dictionary/sql/spanner/columns.sql +23 -0
  376. sqlspec/data_dictionary/sql/spanner/foreign_keys.sql +70 -0
  377. sqlspec/data_dictionary/sql/spanner/indexes.sql +30 -0
  378. sqlspec/data_dictionary/sql/spanner/tables.sql +9 -0
  379. sqlspec/data_dictionary/sql/spanner/version.sql +3 -0
  380. sqlspec/data_dictionary/sql/sqlite/columns.sql +23 -0
  381. sqlspec/data_dictionary/sql/sqlite/foreign_keys.sql +22 -0
  382. sqlspec/data_dictionary/sql/sqlite/indexes.sql +7 -0
  383. sqlspec/data_dictionary/sql/sqlite/tables.sql +28 -0
  384. sqlspec/data_dictionary/sql/sqlite/version.sql +3 -0
  385. sqlspec/driver/__init__.py +32 -0
  386. sqlspec/driver/_async.cpython-310-aarch64-linux-gnu.so +0 -0
  387. sqlspec/driver/_async.py +1737 -0
  388. sqlspec/driver/_common.cpython-310-aarch64-linux-gnu.so +0 -0
  389. sqlspec/driver/_common.py +1478 -0
  390. sqlspec/driver/_sql_helpers.cpython-310-aarch64-linux-gnu.so +0 -0
  391. sqlspec/driver/_sql_helpers.py +148 -0
  392. sqlspec/driver/_storage_helpers.cpython-310-aarch64-linux-gnu.so +0 -0
  393. sqlspec/driver/_storage_helpers.py +144 -0
  394. sqlspec/driver/_sync.cpython-310-aarch64-linux-gnu.so +0 -0
  395. sqlspec/driver/_sync.py +1710 -0
  396. sqlspec/exceptions.py +338 -0
  397. sqlspec/extensions/__init__.py +0 -0
  398. sqlspec/extensions/adk/__init__.py +70 -0
  399. sqlspec/extensions/adk/_types.py +51 -0
  400. sqlspec/extensions/adk/converters.py +172 -0
  401. sqlspec/extensions/adk/memory/__init__.py +69 -0
  402. sqlspec/extensions/adk/memory/_types.py +30 -0
  403. sqlspec/extensions/adk/memory/converters.py +149 -0
  404. sqlspec/extensions/adk/memory/service.py +217 -0
  405. sqlspec/extensions/adk/memory/store.py +569 -0
  406. sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +246 -0
  407. sqlspec/extensions/adk/migrations/__init__.py +0 -0
  408. sqlspec/extensions/adk/service.py +225 -0
  409. sqlspec/extensions/adk/store.py +567 -0
  410. sqlspec/extensions/events/__init__.py +51 -0
  411. sqlspec/extensions/events/_channel.py +703 -0
  412. sqlspec/extensions/events/_hints.py +45 -0
  413. sqlspec/extensions/events/_models.py +23 -0
  414. sqlspec/extensions/events/_payload.py +69 -0
  415. sqlspec/extensions/events/_protocols.py +134 -0
  416. sqlspec/extensions/events/_queue.py +461 -0
  417. sqlspec/extensions/events/_store.py +209 -0
  418. sqlspec/extensions/events/migrations/0001_create_event_queue.py +59 -0
  419. sqlspec/extensions/events/migrations/__init__.py +3 -0
  420. sqlspec/extensions/fastapi/__init__.py +19 -0
  421. sqlspec/extensions/fastapi/extension.py +351 -0
  422. sqlspec/extensions/fastapi/providers.py +607 -0
  423. sqlspec/extensions/flask/__init__.py +37 -0
  424. sqlspec/extensions/flask/_state.py +76 -0
  425. sqlspec/extensions/flask/_utils.py +71 -0
  426. sqlspec/extensions/flask/extension.py +519 -0
  427. sqlspec/extensions/litestar/__init__.py +28 -0
  428. sqlspec/extensions/litestar/_utils.py +52 -0
  429. sqlspec/extensions/litestar/channels.py +165 -0
  430. sqlspec/extensions/litestar/cli.py +102 -0
  431. sqlspec/extensions/litestar/config.py +90 -0
  432. sqlspec/extensions/litestar/handlers.py +316 -0
  433. sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
  434. sqlspec/extensions/litestar/migrations/__init__.py +3 -0
  435. sqlspec/extensions/litestar/plugin.py +671 -0
  436. sqlspec/extensions/litestar/providers.py +526 -0
  437. sqlspec/extensions/litestar/store.py +296 -0
  438. sqlspec/extensions/otel/__init__.py +58 -0
  439. sqlspec/extensions/prometheus/__init__.py +113 -0
  440. sqlspec/extensions/starlette/__init__.py +19 -0
  441. sqlspec/extensions/starlette/_state.py +30 -0
  442. sqlspec/extensions/starlette/_utils.py +96 -0
  443. sqlspec/extensions/starlette/extension.py +346 -0
  444. sqlspec/extensions/starlette/middleware.py +235 -0
  445. sqlspec/loader.cpython-310-aarch64-linux-gnu.so +0 -0
  446. sqlspec/loader.py +702 -0
  447. sqlspec/migrations/__init__.py +36 -0
  448. sqlspec/migrations/base.py +731 -0
  449. sqlspec/migrations/commands.py +1232 -0
  450. sqlspec/migrations/context.py +157 -0
  451. sqlspec/migrations/fix.py +204 -0
  452. sqlspec/migrations/loaders.py +443 -0
  453. sqlspec/migrations/runner.py +1172 -0
  454. sqlspec/migrations/templates.py +234 -0
  455. sqlspec/migrations/tracker.py +611 -0
  456. sqlspec/migrations/utils.py +256 -0
  457. sqlspec/migrations/validation.py +207 -0
  458. sqlspec/migrations/version.py +446 -0
  459. sqlspec/observability/__init__.py +55 -0
  460. sqlspec/observability/_common.cpython-310-aarch64-linux-gnu.so +0 -0
  461. sqlspec/observability/_common.py +77 -0
  462. sqlspec/observability/_config.cpython-310-aarch64-linux-gnu.so +0 -0
  463. sqlspec/observability/_config.py +348 -0
  464. sqlspec/observability/_diagnostics.cpython-310-aarch64-linux-gnu.so +0 -0
  465. sqlspec/observability/_diagnostics.py +74 -0
  466. sqlspec/observability/_dispatcher.cpython-310-aarch64-linux-gnu.so +0 -0
  467. sqlspec/observability/_dispatcher.py +152 -0
  468. sqlspec/observability/_formatters/__init__.py +13 -0
  469. sqlspec/observability/_formatters/_aws.cpython-310-aarch64-linux-gnu.so +0 -0
  470. sqlspec/observability/_formatters/_aws.py +102 -0
  471. sqlspec/observability/_formatters/_azure.cpython-310-aarch64-linux-gnu.so +0 -0
  472. sqlspec/observability/_formatters/_azure.py +96 -0
  473. sqlspec/observability/_formatters/_base.cpython-310-aarch64-linux-gnu.so +0 -0
  474. sqlspec/observability/_formatters/_base.py +57 -0
  475. sqlspec/observability/_formatters/_gcp.cpython-310-aarch64-linux-gnu.so +0 -0
  476. sqlspec/observability/_formatters/_gcp.py +131 -0
  477. sqlspec/observability/_formatting.py +58 -0
  478. sqlspec/observability/_observer.cpython-310-aarch64-linux-gnu.so +0 -0
  479. sqlspec/observability/_observer.py +357 -0
  480. sqlspec/observability/_runtime.cpython-310-aarch64-linux-gnu.so +0 -0
  481. sqlspec/observability/_runtime.py +420 -0
  482. sqlspec/observability/_sampling.cpython-310-aarch64-linux-gnu.so +0 -0
  483. sqlspec/observability/_sampling.py +188 -0
  484. sqlspec/observability/_spans.cpython-310-aarch64-linux-gnu.so +0 -0
  485. sqlspec/observability/_spans.py +161 -0
  486. sqlspec/protocols.py +916 -0
  487. sqlspec/py.typed +0 -0
  488. sqlspec/storage/__init__.py +48 -0
  489. sqlspec/storage/_utils.py +104 -0
  490. sqlspec/storage/backends/__init__.py +1 -0
  491. sqlspec/storage/backends/base.py +253 -0
  492. sqlspec/storage/backends/fsspec.py +529 -0
  493. sqlspec/storage/backends/local.py +441 -0
  494. sqlspec/storage/backends/obstore.py +916 -0
  495. sqlspec/storage/errors.py +104 -0
  496. sqlspec/storage/pipeline.py +582 -0
  497. sqlspec/storage/registry.py +301 -0
  498. sqlspec/typing.py +395 -0
  499. sqlspec/utils/__init__.py +7 -0
  500. sqlspec/utils/arrow_helpers.py +318 -0
  501. sqlspec/utils/config_tools.py +332 -0
  502. sqlspec/utils/correlation.cpython-310-aarch64-linux-gnu.so +0 -0
  503. sqlspec/utils/correlation.py +134 -0
  504. sqlspec/utils/deprecation.py +190 -0
  505. sqlspec/utils/fixtures.cpython-310-aarch64-linux-gnu.so +0 -0
  506. sqlspec/utils/fixtures.py +258 -0
  507. sqlspec/utils/logging.py +222 -0
  508. sqlspec/utils/module_loader.py +306 -0
  509. sqlspec/utils/portal.cpython-310-aarch64-linux-gnu.so +0 -0
  510. sqlspec/utils/portal.py +375 -0
  511. sqlspec/utils/schema.cpython-310-aarch64-linux-gnu.so +0 -0
  512. sqlspec/utils/schema.py +485 -0
  513. sqlspec/utils/serializers.cpython-310-aarch64-linux-gnu.so +0 -0
  514. sqlspec/utils/serializers.py +408 -0
  515. sqlspec/utils/singleton.cpython-310-aarch64-linux-gnu.so +0 -0
  516. sqlspec/utils/singleton.py +41 -0
  517. sqlspec/utils/sync_tools.cpython-310-aarch64-linux-gnu.so +0 -0
  518. sqlspec/utils/sync_tools.py +311 -0
  519. sqlspec/utils/text.cpython-310-aarch64-linux-gnu.so +0 -0
  520. sqlspec/utils/text.py +108 -0
  521. sqlspec/utils/type_converters.cpython-310-aarch64-linux-gnu.so +0 -0
  522. sqlspec/utils/type_converters.py +128 -0
  523. sqlspec/utils/type_guards.cpython-310-aarch64-linux-gnu.so +0 -0
  524. sqlspec/utils/type_guards.py +1360 -0
  525. sqlspec/utils/uuids.cpython-310-aarch64-linux-gnu.so +0 -0
  526. sqlspec/utils/uuids.py +225 -0
  527. sqlspec-0.36.0.dist-info/METADATA +205 -0
  528. sqlspec-0.36.0.dist-info/RECORD +531 -0
  529. sqlspec-0.36.0.dist-info/WHEEL +7 -0
  530. sqlspec-0.36.0.dist-info/entry_points.txt +2 -0
  531. sqlspec-0.36.0.dist-info/licenses/LICENSE +21 -0
sqlspec/cli.py ADDED
@@ -0,0 +1,911 @@
1
+ # ruff: noqa: C901
2
+ import sys
3
+ from collections.abc import Callable, Sequence
4
+ from pathlib import Path
5
+ from typing import TYPE_CHECKING, Any, cast
6
+
7
+ import rich_click as click
8
+ from click.core import ParameterSource
9
+ from rich import get_console
10
+ from rich.prompt import Confirm, Prompt
11
+ from rich.table import Table
12
+
13
+ from sqlspec.config import AsyncDatabaseConfig, SyncDatabaseConfig
14
+ from sqlspec.exceptions import ConfigResolverError
15
+ from sqlspec.utils.config_tools import discover_config_from_pyproject, resolve_config_sync
16
+ from sqlspec.utils.module_loader import import_string
17
+ from sqlspec.utils.sync_tools import run_
18
+
19
+ if TYPE_CHECKING:
20
+ from rich_click import Group
21
+
22
+ from sqlspec.extensions.adk.memory.store import BaseAsyncADKMemoryStore, BaseSyncADKMemoryStore
23
+ from sqlspec.migrations.commands import AsyncMigrationCommands, SyncMigrationCommands
24
+
25
+ __all__ = ("add_migration_commands", "get_sqlspec_group")
26
+
27
+
28
+ def _safe_group_command(
29
+ group: "Group", *, aliases: "list[str] | None" = None, **kwargs: Any
30
+ ) -> "Callable[[Callable[..., Any]], Callable[..., Any]]":
31
+ if aliases is None:
32
+ return group.command(**kwargs)
33
+ try:
34
+ return group.command(aliases=aliases, **kwargs)
35
+ except TypeError:
36
+ return group.command(**kwargs)
37
+
38
+
39
+ def get_sqlspec_group() -> "Group":
40
+ """Get the SQLSpec CLI group.
41
+
42
+ Returns:
43
+ The SQLSpec CLI group.
44
+ """
45
+
46
+ @click.group(name="sqlspec")
47
+ @click.option(
48
+ "--config",
49
+ help="Dotted path to SQLSpec config(s) or callable function (env: SQLSPEC_CONFIG)",
50
+ required=False,
51
+ default=None,
52
+ type=str,
53
+ envvar="SQLSPEC_CONFIG",
54
+ )
55
+ @click.option(
56
+ "--validate-config", is_flag=True, default=False, help="Validate configuration before executing migrations"
57
+ )
58
+ @click.pass_context
59
+ def sqlspec_group(ctx: "click.Context", config: str | None, validate_config: bool) -> None:
60
+ """SQLSpec CLI commands.
61
+
62
+ Configuration resolution prefers CLI flag, SQLSPEC_CONFIG env var, and finally the [tool.sqlspec] section.
63
+ Comma-separated paths are split, deduplicated by bind key, and loaded from the current working directory so local modules can be imported.
64
+ When --validate-config is used we report each config's async capability.
65
+ """
66
+ console = get_console()
67
+ ctx.ensure_object(dict)
68
+
69
+ if config is None:
70
+ config = discover_config_from_pyproject()
71
+ if config:
72
+ console.print("[dim]Using config from pyproject.toml[/]")
73
+
74
+ if config is None:
75
+ console.print("[red]Error: No SQLSpec config found.[/]")
76
+ console.print("\nSpecify config using one of:")
77
+ console.print(" 1. CLI flag: sqlspec --config myapp.config:get_configs <command>")
78
+ console.print(" 2. Environment var: export SQLSPEC_CONFIG=myapp.config:get_configs")
79
+ console.print(" 3. pyproject.toml: [tool.sqlspec]")
80
+ console.print(' config = "myapp.config:get_configs"')
81
+ ctx.exit(1)
82
+
83
+ cwd = str(Path.cwd())
84
+ cwd_added = False
85
+ if cwd not in sys.path:
86
+ sys.path.insert(0, cwd)
87
+ cwd_added = True
88
+
89
+ try:
90
+ all_configs: list[AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]] = []
91
+ for config_path in config.split(","):
92
+ config_path = config_path.strip()
93
+ if not config_path:
94
+ continue
95
+ config_result = resolve_config_sync(config_path)
96
+ if isinstance(config_result, Sequence) and not isinstance(config_result, str):
97
+ all_configs.extend(config_result)
98
+ else:
99
+ all_configs.append(config_result) # pyright: ignore
100
+
101
+ configs_by_key: dict[
102
+ str | None, AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]
103
+ ] = {}
104
+ for cfg in all_configs:
105
+ configs_by_key[cfg.bind_key] = cfg
106
+
107
+ ctx.obj["configs"] = list(configs_by_key.values())
108
+
109
+ if not ctx.obj["configs"]:
110
+ console.print("[red]Error: No valid configs found after resolution.[/]")
111
+ console.print("\nEnsure your config path returns valid config instance(s).")
112
+ ctx.exit(1)
113
+
114
+ ctx.obj["validate_config"] = validate_config
115
+
116
+ if validate_config:
117
+ console.print(f"[green]✓[/] Successfully loaded {len(ctx.obj['configs'])} config(s)")
118
+ for i, cfg in enumerate(ctx.obj["configs"]):
119
+ config_name = cfg.bind_key or f"config-{i}"
120
+ config_type = type(cfg).__name__
121
+ is_async = cfg.is_async
122
+ execution_hint = "[dim cyan](async-capable)[/]" if is_async else "[dim](sync)[/]"
123
+ console.print(f" [dim]•[/] {config_name}: {config_type} {execution_hint}")
124
+
125
+ except (ImportError, ConfigResolverError) as e:
126
+ console.print(f"[red]Error loading config: {e}[/]")
127
+ ctx.exit(1)
128
+ finally:
129
+ if cwd_added and cwd in sys.path and sys.path[0] == cwd:
130
+ sys.path.remove(cwd)
131
+
132
+ return sqlspec_group
133
+
134
+
135
+ def _ensure_click_context() -> "click.Context":
136
+ """Return the active Click context, raising if missing (for type-checkers)."""
137
+
138
+ context = click.get_current_context()
139
+ if context is None: # pragma: no cover - click guarantees context in commands
140
+ msg = "SQLSpec CLI commands require an active Click context"
141
+ raise RuntimeError(msg)
142
+ return cast("click.Context", context)
143
+
144
+
145
+ def add_migration_commands(database_group: "Group | None" = None) -> "Group":
146
+ """Add migration commands to the database group.
147
+
148
+ Args:
149
+ database_group: The database group to add the commands to.
150
+
151
+ Returns:
152
+ The database group with the migration commands added.
153
+ """
154
+ console = get_console()
155
+
156
+ if database_group is None:
157
+ database_group = get_sqlspec_group()
158
+
159
+ bind_key_option = click.option(
160
+ "--bind-key", help="Specify which SQLSpec config to use by bind key", type=str, default=None
161
+ )
162
+ verbose_option = click.option("--verbose", help="Enable verbose output.", type=bool, default=False, is_flag=True)
163
+ no_prompt_option = click.option(
164
+ "--no-prompt",
165
+ help="Do not prompt for confirmation before executing the command.",
166
+ type=bool,
167
+ default=False,
168
+ required=False,
169
+ show_default=True,
170
+ is_flag=True,
171
+ )
172
+ include_option = click.option(
173
+ "--include", multiple=True, help="Include only specific configurations (can be used multiple times)"
174
+ )
175
+ exclude_option = click.option(
176
+ "--exclude", multiple=True, help="Exclude specific configurations (can be used multiple times)"
177
+ )
178
+ dry_run_option = click.option(
179
+ "--dry-run", is_flag=True, default=False, help="Show what would be executed without making changes"
180
+ )
181
+ execution_mode_option = click.option(
182
+ "--execution-mode",
183
+ type=click.Choice(["auto", "sync", "async"]),
184
+ default="auto",
185
+ help="Force execution mode (auto-detects by default)",
186
+ )
187
+ no_auto_sync_option = click.option(
188
+ "--no-auto-sync",
189
+ is_flag=True,
190
+ default=False,
191
+ help="Disable automatic version reconciliation when migrations have been renamed",
192
+ )
193
+
194
+ def get_config_by_bind_key(
195
+ ctx: "click.Context", bind_key: str | None
196
+ ) -> "AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]":
197
+ """Get the SQLSpec config for the specified bind key.
198
+
199
+ Args:
200
+ ctx: The click context.
201
+ bind_key: The bind key to get the config for.
202
+
203
+ Returns:
204
+ The SQLSpec config for the specified bind key.
205
+ """
206
+ configs = ctx.obj["configs"]
207
+ if bind_key is None:
208
+ config = configs[0]
209
+ else:
210
+ config = None
211
+ for cfg in configs:
212
+ config_name = cfg.bind_key
213
+ if config_name == bind_key:
214
+ config = cfg
215
+ break
216
+
217
+ if config is None:
218
+ console.print(f"[red]No config found for bind key: {bind_key}[/]")
219
+ sys.exit(1)
220
+
221
+ return cast("AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]", config)
222
+
223
+ def _get_adk_configs(
224
+ ctx: "click.Context", bind_key: str | None
225
+ ) -> "list[AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]]":
226
+ if bind_key is not None:
227
+ return [get_config_by_bind_key(ctx, bind_key)]
228
+
229
+ configs = ctx.obj["configs"]
230
+ return [cfg for cfg in configs if "adk" in cfg.extension_config]
231
+
232
+ def _get_memory_store_class(
233
+ config: "AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]",
234
+ ) -> "type[BaseAsyncADKMemoryStore[Any] | BaseSyncADKMemoryStore[Any]] | None":
235
+ config_module = type(config).__module__
236
+ config_name = type(config).__name__
237
+
238
+ if not config_module.startswith("sqlspec.adapters."):
239
+ return None
240
+
241
+ adapter_name = config_module.split(".")[2]
242
+ store_class_name = config_name.replace("Config", "ADKMemoryStore")
243
+ store_path = f"sqlspec.adapters.{adapter_name}.adk.store.{store_class_name}"
244
+
245
+ try:
246
+ return cast("type[BaseAsyncADKMemoryStore[Any] | BaseSyncADKMemoryStore[Any]]", import_string(store_path))
247
+ except ImportError:
248
+ return None
249
+
250
+ def _is_adk_memory_enabled(
251
+ config: "AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]",
252
+ ) -> bool:
253
+ adk_config = cast("dict[str, Any]", config.extension_config.get("adk", {}))
254
+ return bool(adk_config.get("enable_memory", True))
255
+
256
+ async def _cleanup_memory_entries_async(store: "BaseAsyncADKMemoryStore[Any]", days: int) -> int:
257
+ return await store.delete_entries_older_than(days)
258
+
259
+ async def _verify_memory_table_async(config: "AsyncDatabaseConfig[Any, Any, Any]", sql: str) -> None:
260
+ async with config.provide_session() as driver:
261
+ await driver.execute(sql)
262
+
263
+ def get_configs_with_migrations(
264
+ ctx: "click.Context", enabled_only: bool = False
265
+ ) -> "list[tuple[str, AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]]]":
266
+ """Get all configurations that have migrations enabled.
267
+
268
+ Args:
269
+ ctx: The click context.
270
+ enabled_only: If True, only return configs with enabled=True.
271
+
272
+ Returns:
273
+ List of tuples (config_name, config) for configs with migrations enabled.
274
+ """
275
+ configs: list[AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]] = ctx.obj["configs"]
276
+ migration_configs: list[tuple[str, AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]]] = []
277
+
278
+ for config in configs:
279
+ migration_config = config.migration_config
280
+ if migration_config:
281
+ enabled = migration_config.get("enabled", True)
282
+ if not enabled_only or enabled:
283
+ config_name = config.bind_key or str(type(config).__name__)
284
+ migration_configs.append((config_name, config))
285
+
286
+ return migration_configs
287
+
288
+ def filter_configs(
289
+ configs: "list[tuple[str, Any]]", include: "tuple[str, ...]", exclude: "tuple[str, ...]"
290
+ ) -> "list[tuple[str, Any]]":
291
+ """Filter configuration list based on include/exclude criteria.
292
+
293
+ Args:
294
+ configs: List of (config_name, config) tuples.
295
+ include: Config names to include (empty means include all).
296
+ exclude: Config names to exclude.
297
+
298
+ Returns:
299
+ Filtered list of configurations.
300
+ """
301
+ filtered = configs
302
+ if include:
303
+ filtered = [(name, config) for name, config in filtered if name in include]
304
+ if exclude:
305
+ filtered = [(name, config) for name, config in filtered if name not in exclude]
306
+ return filtered
307
+
308
+ def _execute_for_config(
309
+ config: "AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]",
310
+ sync_fn: "Callable[[], Any]",
311
+ async_fn: "Callable[[], Any]",
312
+ ) -> Any:
313
+ """Execute a migration command with appropriate sync/async handling.
314
+
315
+ For sync configs, executes the sync function directly without an event loop.
316
+ For async configs, wraps the async function in run_() to execute with event loop.
317
+
318
+ Args:
319
+ config: The database configuration.
320
+ sync_fn: Function to call for sync configs (should call sync migration methods).
321
+ async_fn: Async function to call for async configs (should await async migration methods).
322
+
323
+ Returns:
324
+ The result of the executed function.
325
+ """
326
+ if config.is_async:
327
+ return run_(async_fn)()
328
+ return sync_fn()
329
+
330
+ def _partition_configs_by_async(
331
+ configs: "list[tuple[str, Any]]",
332
+ ) -> "tuple[list[tuple[str, Any]], list[tuple[str, Any]]]":
333
+ """Partition configs into sync and async groups.
334
+
335
+ Args:
336
+ configs: List of (config_name, config) tuples.
337
+
338
+ Returns:
339
+ Tuple of (sync_configs, async_configs).
340
+ """
341
+ sync_configs = [(name, cfg) for name, cfg in configs if not cfg.is_async]
342
+ async_configs = [(name, cfg) for name, cfg in configs if cfg.is_async]
343
+ return sync_configs, async_configs
344
+
345
+ def process_multiple_configs(
346
+ ctx: "click.Context",
347
+ bind_key: str | None,
348
+ include: "tuple[str, ...]",
349
+ exclude: "tuple[str, ...]",
350
+ dry_run: bool,
351
+ operation_name: str,
352
+ ) -> "list[tuple[str, Any]] | None":
353
+ """Process configuration selection for multi-config operations.
354
+
355
+ Requests targeting a single bind key or with only one available config run in single-config mode.
356
+ Enabled configs are used unless include/exclude widen the set, and dry runs simply list the configs that would execute.
357
+
358
+ Args:
359
+ ctx: Click context.
360
+ bind_key: Specific bind key to target.
361
+ include: Config names to include.
362
+ exclude: Config names to exclude.
363
+ dry_run: Whether this is a dry run.
364
+ operation_name: Name of the operation for display.
365
+
366
+ Returns:
367
+ List of (config_name, config) tuples to process, or None for single config mode.
368
+ """
369
+ if bind_key and not include and not exclude:
370
+ return None
371
+
372
+ enabled_only = not include and not exclude
373
+ migration_configs = get_configs_with_migrations(ctx, enabled_only=enabled_only)
374
+
375
+ if len(migration_configs) <= 1 and not include and not exclude:
376
+ return None
377
+
378
+ configs_to_process = filter_configs(migration_configs, include, exclude)
379
+
380
+ if not configs_to_process:
381
+ console.print("[yellow]No configurations match the specified criteria.[/]")
382
+ return []
383
+
384
+ if dry_run:
385
+ console.print(f"[blue]Dry run: Would {operation_name} {len(configs_to_process)} configuration(s)[/]")
386
+ for config_name, _ in configs_to_process:
387
+ console.print(f" • {config_name}")
388
+ return []
389
+
390
+ return configs_to_process
391
+
392
+ @database_group.command(name="show-current-revision", help="Shows the current revision for the database.")
393
+ @bind_key_option
394
+ @verbose_option
395
+ @include_option
396
+ @exclude_option
397
+ def show_database_revision( # pyright: ignore[reportUnusedFunction]
398
+ bind_key: str | None, verbose: bool, include: "tuple[str, ...]", exclude: "tuple[str, ...]"
399
+ ) -> None:
400
+ """Show current database revision.
401
+
402
+ Supports multi-config execution by partitioning selected configs into sync and async groups before dispatching them separately.
403
+ """
404
+ from sqlspec.migrations.commands import create_migration_commands
405
+
406
+ ctx = _ensure_click_context()
407
+
408
+ def _show_for_config(config: Any) -> None:
409
+ """Show current revision for a single config with sync/async dispatch."""
410
+ migration_commands: SyncMigrationCommands[Any] | AsyncMigrationCommands[Any] = create_migration_commands(
411
+ config=config
412
+ )
413
+
414
+ def sync_show() -> None:
415
+ migration_commands.current(verbose=verbose)
416
+
417
+ async def async_show() -> None:
418
+ await cast("AsyncMigrationCommands[Any]", migration_commands).current(verbose=verbose)
419
+
420
+ _execute_for_config(config, sync_show, async_show)
421
+
422
+ configs_to_process = process_multiple_configs(
423
+ ctx, bind_key, include, exclude, dry_run=False, operation_name="show current revision"
424
+ )
425
+
426
+ if configs_to_process is not None:
427
+ if not configs_to_process:
428
+ return
429
+
430
+ console.rule("[yellow]Listing current revisions for all configurations[/]", align="left")
431
+
432
+ sync_configs, async_configs = _partition_configs_by_async(configs_to_process)
433
+
434
+ for config_name, config in sync_configs:
435
+ console.print(f"\n[blue]Configuration: {config_name}[/]")
436
+ try:
437
+ _show_for_config(config)
438
+ except Exception as e:
439
+ console.print(f"[red]✗ Failed to get current revision for {config_name}: {e}[/]")
440
+
441
+ if async_configs:
442
+
443
+ async def _run_async_configs() -> None:
444
+ for config_name, config in async_configs:
445
+ console.print(f"\n[blue]Configuration: {config_name}[/]")
446
+ try:
447
+ migration_commands: AsyncMigrationCommands[Any] = cast(
448
+ "AsyncMigrationCommands[Any]", create_migration_commands(config=config)
449
+ )
450
+ await migration_commands.current(verbose=verbose)
451
+ except Exception as e:
452
+ console.print(f"[red]✗ Failed to get current revision for {config_name}: {e}[/]")
453
+
454
+ run_(_run_async_configs)()
455
+ else:
456
+ console.rule("[yellow]Listing current revision[/]", align="left")
457
+ sqlspec_config = get_config_by_bind_key(ctx, bind_key)
458
+ _show_for_config(sqlspec_config)
459
+
460
+ @database_group.command(name="downgrade", help="Downgrade database to a specific revision.")
461
+ @bind_key_option
462
+ @no_prompt_option
463
+ @include_option
464
+ @exclude_option
465
+ @dry_run_option
466
+ @click.argument("revision", type=str, default="-1")
467
+ def downgrade_database( # pyright: ignore[reportUnusedFunction]
468
+ bind_key: str | None,
469
+ revision: str,
470
+ no_prompt: bool,
471
+ include: "tuple[str, ...]",
472
+ exclude: "tuple[str, ...]",
473
+ dry_run: bool,
474
+ ) -> None:
475
+ """Downgrade the database to the latest revision."""
476
+
477
+ from sqlspec.migrations.commands import create_migration_commands
478
+
479
+ ctx = _ensure_click_context()
480
+
481
+ def _downgrade_for_config(config: Any) -> None:
482
+ """Downgrade a single config with sync/async dispatch."""
483
+ migration_commands: SyncMigrationCommands[Any] | AsyncMigrationCommands[Any] = create_migration_commands(
484
+ config=config
485
+ )
486
+
487
+ def sync_downgrade() -> None:
488
+ migration_commands.downgrade(revision=revision, dry_run=dry_run)
489
+
490
+ async def async_downgrade() -> None:
491
+ await cast("AsyncMigrationCommands[Any]", migration_commands).downgrade(
492
+ revision=revision, dry_run=dry_run
493
+ )
494
+
495
+ _execute_for_config(config, sync_downgrade, async_downgrade)
496
+
497
+ configs_to_process = process_multiple_configs(
498
+ ctx, bind_key, include, exclude, dry_run=dry_run, operation_name=f"downgrade to {revision}"
499
+ )
500
+
501
+ if configs_to_process is not None:
502
+ if not configs_to_process:
503
+ return
504
+
505
+ if not no_prompt and not Confirm.ask(
506
+ f"[bold]Are you sure you want to downgrade {len(configs_to_process)} configuration(s) to revision {revision}?[/]"
507
+ ):
508
+ console.print("[yellow]Operation cancelled.[/]")
509
+ return
510
+
511
+ console.rule("[yellow]Starting multi-configuration downgrade process[/]", align="left")
512
+
513
+ sync_configs, async_configs = _partition_configs_by_async(configs_to_process)
514
+
515
+ for config_name, config in sync_configs:
516
+ console.print(f"[blue]Downgrading configuration: {config_name}[/]")
517
+ try:
518
+ _downgrade_for_config(config)
519
+ console.print(f"[green]✓ Successfully downgraded: {config_name}[/]")
520
+ except Exception as e:
521
+ console.print(f"[red]✗ Failed to downgrade {config_name}: {e}[/]")
522
+
523
+ if async_configs:
524
+
525
+ async def _run_async_configs() -> None:
526
+ for config_name, config in async_configs:
527
+ console.print(f"[blue]Downgrading configuration: {config_name}[/]")
528
+ try:
529
+ migration_commands: AsyncMigrationCommands[Any] = cast(
530
+ "AsyncMigrationCommands[Any]", create_migration_commands(config=config)
531
+ )
532
+ await migration_commands.downgrade(revision=revision, dry_run=dry_run)
533
+ console.print(f"[green]✓ Successfully downgraded: {config_name}[/]")
534
+ except Exception as e:
535
+ console.print(f"[red]✗ Failed to downgrade {config_name}: {e}[/]")
536
+
537
+ run_(_run_async_configs)()
538
+ else:
539
+ console.rule("[yellow]Starting database downgrade process[/]", align="left")
540
+ input_confirmed = (
541
+ True
542
+ if no_prompt
543
+ else Confirm.ask(f"Are you sure you want to downgrade the database to the `{revision}` revision?")
544
+ )
545
+ if input_confirmed:
546
+ sqlspec_config = get_config_by_bind_key(ctx, bind_key)
547
+ _downgrade_for_config(sqlspec_config)
548
+
549
+ @database_group.command(name="upgrade", help="Upgrade database to a specific revision.")
550
+ @bind_key_option
551
+ @no_prompt_option
552
+ @include_option
553
+ @exclude_option
554
+ @dry_run_option
555
+ @execution_mode_option
556
+ @no_auto_sync_option
557
+ @click.argument("revision", type=str, default="head")
558
+ def upgrade_database( # pyright: ignore[reportUnusedFunction]
559
+ bind_key: str | None,
560
+ revision: str,
561
+ no_prompt: bool,
562
+ include: "tuple[str, ...]",
563
+ exclude: "tuple[str, ...]",
564
+ dry_run: bool,
565
+ execution_mode: str,
566
+ no_auto_sync: bool,
567
+ ) -> None:
568
+ """Upgrade the database to the latest revision.
569
+
570
+ Non-automatic execution modes are surfaced in the console, and multi-config flows reuse ``process_multiple_configs`` to split sync/async executions while honoring dry-run and auto-sync flags.
571
+ """
572
+ from sqlspec.migrations.commands import create_migration_commands
573
+
574
+ ctx = _ensure_click_context()
575
+ if execution_mode != "auto":
576
+ console.print(f"[dim]Execution mode: {execution_mode}[/]")
577
+
578
+ def _upgrade_for_config(config: Any) -> None:
579
+ """Upgrade a single config with sync/async dispatch."""
580
+ migration_commands: SyncMigrationCommands[Any] | AsyncMigrationCommands[Any] = create_migration_commands(
581
+ config=config
582
+ )
583
+
584
+ def sync_upgrade() -> None:
585
+ migration_commands.upgrade(revision=revision, auto_sync=not no_auto_sync, dry_run=dry_run)
586
+
587
+ async def async_upgrade() -> None:
588
+ await cast("AsyncMigrationCommands[Any]", migration_commands).upgrade(
589
+ revision=revision, auto_sync=not no_auto_sync, dry_run=dry_run
590
+ )
591
+
592
+ _execute_for_config(config, sync_upgrade, async_upgrade)
593
+
594
+ configs_to_process = process_multiple_configs(
595
+ ctx, bind_key, include, exclude, dry_run, operation_name=f"upgrade to {revision}"
596
+ )
597
+
598
+ if configs_to_process is not None:
599
+ if not configs_to_process:
600
+ return
601
+
602
+ if not no_prompt and not Confirm.ask(
603
+ f"[bold]Are you sure you want to upgrade {len(configs_to_process)} configuration(s) to revision {revision}?[/]"
604
+ ):
605
+ console.print("[yellow]Operation cancelled.[/]")
606
+ return
607
+
608
+ console.rule("[yellow]Starting multi-configuration upgrade process[/]", align="left")
609
+
610
+ sync_configs, async_configs = _partition_configs_by_async(configs_to_process)
611
+
612
+ for config_name, config in sync_configs:
613
+ console.print(f"[blue]Upgrading configuration: {config_name}[/]")
614
+ try:
615
+ _upgrade_for_config(config)
616
+ console.print(f"[green]✓ Successfully upgraded: {config_name}[/]")
617
+ except Exception as e:
618
+ console.print(f"[red]✗ Failed to upgrade {config_name}: {e}[/]")
619
+
620
+ if async_configs:
621
+
622
+ async def _run_async_configs() -> None:
623
+ for config_name, config in async_configs:
624
+ console.print(f"[blue]Upgrading configuration: {config_name}[/]")
625
+ try:
626
+ migration_commands: AsyncMigrationCommands[Any] = cast(
627
+ "AsyncMigrationCommands[Any]", create_migration_commands(config=config)
628
+ )
629
+ await migration_commands.upgrade(
630
+ revision=revision, auto_sync=not no_auto_sync, dry_run=dry_run
631
+ )
632
+ console.print(f"[green]✓ Successfully upgraded: {config_name}[/]")
633
+ except Exception as e:
634
+ console.print(f"[red]✗ Failed to upgrade {config_name}: {e}[/]")
635
+
636
+ run_(_run_async_configs)()
637
+ else:
638
+ console.rule("[yellow]Starting database upgrade process[/]", align="left")
639
+ input_confirmed = (
640
+ True
641
+ if no_prompt
642
+ else Confirm.ask(f"[bold]Are you sure you want migrate the database to the `{revision}` revision?[/]")
643
+ )
644
+ if input_confirmed:
645
+ sqlspec_config = get_config_by_bind_key(ctx, bind_key)
646
+ _upgrade_for_config(sqlspec_config)
647
+
648
+ @database_group.command(help="Stamp the revision table with the given revision")
649
+ @click.argument("revision", type=str)
650
+ @bind_key_option
651
+ def stamp(bind_key: str | None, revision: str) -> None: # pyright: ignore[reportUnusedFunction]
652
+ """Stamp the revision table with the given revision."""
653
+ from sqlspec.migrations.commands import create_migration_commands
654
+
655
+ ctx = _ensure_click_context()
656
+
657
+ sqlspec_config = get_config_by_bind_key(ctx, bind_key)
658
+ migration_commands = create_migration_commands(config=sqlspec_config)
659
+
660
+ def sync_stamp() -> None:
661
+ migration_commands.stamp(revision=revision)
662
+
663
+ async def async_stamp() -> None:
664
+ await cast("AsyncMigrationCommands[Any]", migration_commands).stamp(revision=revision)
665
+
666
+ _execute_for_config(sqlspec_config, sync_stamp, async_stamp)
667
+
668
+ @database_group.command(name="init", help="Initialize migrations for the project.")
669
+ @bind_key_option
670
+ @click.argument("directory", default=None, required=False)
671
+ @click.option("--package", is_flag=True, default=True, help="Create `__init__.py` for created folder")
672
+ @no_prompt_option
673
+ def init_sqlspec( # pyright: ignore[reportUnusedFunction]
674
+ bind_key: str | None, directory: str | None, package: bool, no_prompt: bool
675
+ ) -> None:
676
+ """Initialize the database migrations.
677
+
678
+ Sync configs are handled inline while async configs run via a single ``run_`` call so migrations stay in sync.
679
+ """
680
+ from sqlspec.migrations.commands import create_migration_commands
681
+
682
+ ctx = _ensure_click_context()
683
+
684
+ console.rule("[yellow]Initializing database migrations.", align="left")
685
+ input_confirmed = (
686
+ True if no_prompt else Confirm.ask("[bold]Are you sure you want initialize migrations for the project?[/]")
687
+ )
688
+ if not input_confirmed:
689
+ return
690
+
691
+ configs = [get_config_by_bind_key(ctx, bind_key)] if bind_key is not None else ctx.obj["configs"]
692
+
693
+ sync_configs = [cfg for cfg in configs if not cfg.is_async]
694
+ async_configs = [cfg for cfg in configs if cfg.is_async]
695
+
696
+ for config in sync_configs:
697
+ migration_config_dict = config.migration_config or {}
698
+ target_directory = (
699
+ str(migration_config_dict.get("script_location", "migrations")) if directory is None else directory
700
+ )
701
+ migration_commands = create_migration_commands(config=config)
702
+ migration_commands.init(directory=target_directory, package=package)
703
+
704
+ if async_configs:
705
+
706
+ async def _init_async_configs() -> None:
707
+ for config in async_configs:
708
+ migration_config_dict = config.migration_config or {}
709
+ target_directory = (
710
+ str(migration_config_dict.get("script_location", "migrations"))
711
+ if directory is None
712
+ else directory
713
+ )
714
+ migration_commands: AsyncMigrationCommands[Any] = cast(
715
+ "AsyncMigrationCommands[Any]", create_migration_commands(config=config)
716
+ )
717
+ await migration_commands.init(directory=target_directory, package=package)
718
+
719
+ run_(_init_async_configs)()
720
+
721
+ @_safe_group_command(
722
+ database_group, name="create-migration", help="Create a new migration revision.", aliases=["make-migration"]
723
+ )
724
+ @bind_key_option
725
+ @click.option("-m", "--message", default=None, help="Revision message")
726
+ @click.option(
727
+ "--format",
728
+ "--file-type",
729
+ "file_format",
730
+ type=click.Choice(["sql", "py"]),
731
+ default=None,
732
+ help="File format for the generated migration (defaults to template profile)",
733
+ )
734
+ @no_prompt_option
735
+ def create_revision( # pyright: ignore[reportUnusedFunction]
736
+ bind_key: str | None, message: str | None, file_format: str | None, no_prompt: bool
737
+ ) -> None:
738
+ """Create a new database revision."""
739
+ from sqlspec.migrations.commands import create_migration_commands
740
+
741
+ ctx = _ensure_click_context()
742
+
743
+ console.rule("[yellow]Creating new migration revision[/]", align="left")
744
+ message_text = message
745
+ if message_text is None:
746
+ message_text = (
747
+ "new migration" if no_prompt else Prompt.ask("Please enter a message describing this revision")
748
+ )
749
+
750
+ sqlspec_config = get_config_by_bind_key(ctx, bind_key)
751
+ param_source = ctx.get_parameter_source("file_format")
752
+ effective_format = None if param_source is ParameterSource.DEFAULT else file_format
753
+ migration_commands = create_migration_commands(config=sqlspec_config)
754
+
755
+ def sync_revision() -> None:
756
+ migration_commands.revision(message=message_text, file_type=effective_format)
757
+
758
+ async def async_revision() -> None:
759
+ await cast("AsyncMigrationCommands[Any]", migration_commands).revision(
760
+ message=message_text, file_type=effective_format
761
+ )
762
+
763
+ _execute_for_config(sqlspec_config, sync_revision, async_revision)
764
+
765
+ @database_group.command(name="fix", help="Convert timestamp migrations to sequential format.")
766
+ @bind_key_option
767
+ @dry_run_option
768
+ @click.option("--yes", is_flag=True, help="Skip confirmation prompt")
769
+ @click.option("--no-database", is_flag=True, help="Skip database record updates")
770
+ def fix_migrations( # pyright: ignore[reportUnusedFunction]
771
+ bind_key: str | None, dry_run: bool, yes: bool, no_database: bool
772
+ ) -> None:
773
+ """Convert timestamp migrations to sequential format."""
774
+ from sqlspec.migrations.commands import create_migration_commands
775
+
776
+ ctx = _ensure_click_context()
777
+
778
+ console.rule("[yellow]Migration Fix Command[/]", align="left")
779
+ sqlspec_config = get_config_by_bind_key(ctx, bind_key)
780
+ migration_commands = create_migration_commands(config=sqlspec_config)
781
+
782
+ def sync_fix() -> None:
783
+ migration_commands.fix(dry_run=dry_run, update_database=not no_database, yes=yes)
784
+
785
+ async def async_fix() -> None:
786
+ await cast("AsyncMigrationCommands[Any]", migration_commands).fix(
787
+ dry_run=dry_run, update_database=not no_database, yes=yes
788
+ )
789
+
790
+ _execute_for_config(sqlspec_config, sync_fix, async_fix)
791
+
792
+ @database_group.command(name="show-config", help="Show all configurations with migrations enabled.")
793
+ @bind_key_option
794
+ def show_config(bind_key: str | None = None) -> None: # pyright: ignore[reportUnusedFunction]
795
+ """Show and display all configurations with migrations enabled.
796
+
797
+ Providing a bind key validates that config while still iterating the original config list to remain compatible with existing callers.
798
+ """
799
+ ctx = _ensure_click_context()
800
+
801
+ if bind_key is not None:
802
+ get_config_by_bind_key(ctx, bind_key)
803
+ all_configs: list[AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]] = ctx.obj[
804
+ "configs"
805
+ ]
806
+ migration_configs: list[
807
+ tuple[str, AsyncDatabaseConfig[Any, Any, Any] | SyncDatabaseConfig[Any, Any, Any]]
808
+ ] = []
809
+ for cfg in all_configs:
810
+ config_name = cfg.bind_key
811
+ if config_name == bind_key and cfg.migration_config:
812
+ migration_configs.append((config_name, cfg)) # pyright: ignore[reportArgumentType]
813
+ else:
814
+ migration_configs = get_configs_with_migrations(ctx)
815
+
816
+ if not migration_configs:
817
+ console.print("[yellow]No configurations with migrations detected.[/]")
818
+ return
819
+
820
+ table = Table(title="Migration Configurations")
821
+ table.add_column("Configuration Name", style="cyan")
822
+ table.add_column("Migration Path", style="blue")
823
+ table.add_column("Status", style="green")
824
+
825
+ for config_name, config in migration_configs:
826
+ migration_config_dict = config.migration_config or {}
827
+ script_location = migration_config_dict.get("script_location", "migrations")
828
+ table.add_row(config_name, str(script_location), "Migration Enabled")
829
+
830
+ console.print(table)
831
+ console.print(f"[blue]Found {len(migration_configs)} configuration(s) with migrations enabled.[/]")
832
+
833
+ @database_group.group(name="adk", help="ADK extension commands")
834
+ def adk_group() -> None: # pyright: ignore[reportUnusedFunction]
835
+ """ADK extension commands."""
836
+
837
+ @adk_group.group(name="memory", help="ADK memory store commands")
838
+ def adk_memory_group() -> None: # pyright: ignore[reportUnusedFunction]
839
+ """ADK memory store commands."""
840
+
841
+ @adk_memory_group.command(name="cleanup", help="Delete memory entries older than N days")
842
+ @bind_key_option
843
+ @click.option("--days", type=int, required=True, help="Delete entries older than this many days")
844
+ def cleanup_memory(bind_key: str | None, days: int) -> None: # pyright: ignore[reportUnusedFunction]
845
+ """Cleanup memory entries older than N days."""
846
+ ctx = _ensure_click_context()
847
+ configs = _get_adk_configs(ctx, bind_key)
848
+
849
+ if not configs:
850
+ console.print("[yellow]No ADK configurations found.[/]")
851
+ return
852
+
853
+ for cfg in configs:
854
+ config_name = cfg.bind_key or "default"
855
+ if not _is_adk_memory_enabled(cfg):
856
+ console.print(f"[yellow]Memory disabled for {config_name}; skipping.[/]")
857
+ continue
858
+
859
+ store_class = _get_memory_store_class(cfg)
860
+ if store_class is None:
861
+ console.print(f"[yellow]No memory store found for {config_name}; skipping.[/]")
862
+ continue
863
+
864
+ if isinstance(cfg, AsyncDatabaseConfig):
865
+ async_store = cast("BaseAsyncADKMemoryStore[Any]", store_class(cfg))
866
+ deleted = run_(_cleanup_memory_entries_async)(async_store, days)
867
+ console.print(f"[green]✓[/] {config_name}: deleted {deleted} memory entries older than {days} days")
868
+ continue
869
+ sync_store = cast("BaseSyncADKMemoryStore[Any]", store_class(cfg))
870
+ deleted = sync_store.delete_entries_older_than(days)
871
+ console.print(f"[green]✓[/] {config_name}: deleted {deleted} memory entries older than {days} days")
872
+
873
+ @adk_memory_group.command(name="verify", help="Verify memory table exists and is reachable")
874
+ @bind_key_option
875
+ def verify_memory(bind_key: str | None) -> None: # pyright: ignore[reportUnusedFunction]
876
+ """Verify memory tables are reachable for configured adapters."""
877
+ ctx = _ensure_click_context()
878
+ configs = _get_adk_configs(ctx, bind_key)
879
+
880
+ if not configs:
881
+ console.print("[yellow]No ADK configurations found.[/]")
882
+ return
883
+
884
+ for cfg in configs:
885
+ config_name = cfg.bind_key or "default"
886
+ if not _is_adk_memory_enabled(cfg):
887
+ console.print(f"[yellow]Memory disabled for {config_name}; skipping.[/]")
888
+ continue
889
+
890
+ store_class = _get_memory_store_class(cfg)
891
+ if store_class is None:
892
+ console.print(f"[yellow]No memory store found for {config_name}; skipping.[/]")
893
+ continue
894
+
895
+ try:
896
+ if isinstance(cfg, AsyncDatabaseConfig):
897
+ async_cfg: AsyncDatabaseConfig[Any, Any, Any] = cfg
898
+ async_store = cast("BaseAsyncADKMemoryStore[Any]", store_class(async_cfg))
899
+ sql = f"SELECT 1 FROM {async_store.memory_table} WHERE 1 = 0"
900
+ run_(_verify_memory_table_async)(async_cfg, sql)
901
+ console.print(f"[green]✓[/] {config_name}: memory table reachable")
902
+ continue
903
+ sync_store = cast("BaseSyncADKMemoryStore[Any]", store_class(cfg))
904
+ sql = f"SELECT 1 FROM {sync_store.memory_table} WHERE 1 = 0"
905
+ with cfg.provide_session() as driver:
906
+ driver.execute(sql)
907
+ console.print(f"[green]✓[/] {config_name}: memory table reachable")
908
+ except Exception as exc:
909
+ console.print(f"[red]✗[/] {config_name}: {exc}")
910
+
911
+ return database_group