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,1830 @@
1
+ """Asynchronous driver protocol implementation."""
2
+
3
+ from abc import abstractmethod
4
+ from time import perf_counter
5
+ from typing import TYPE_CHECKING, Any, ClassVar, Final, cast, final, overload
6
+
7
+ from mypy_extensions import mypyc_attr
8
+
9
+ from sqlspec.core import SQL, ProcessedState, StackResult, Statement, create_arrow_result
10
+ from sqlspec.core.result import DMLResult
11
+ from sqlspec.core.stack import StackOperation, StatementStack
12
+ from sqlspec.driver._common import (
13
+ AsyncExceptionHandler,
14
+ CommonDriverAttributesMixin,
15
+ DataDictionaryDialectMixin,
16
+ DataDictionaryMixin,
17
+ ExecutionResult,
18
+ StackExecutionObserver,
19
+ _raise_database_exception,
20
+ describe_stack_statement,
21
+ handle_single_row_error,
22
+ )
23
+ from sqlspec.driver._query_cache import CachedQuery
24
+ from sqlspec.driver._sql_helpers import DEFAULT_PRETTY
25
+ from sqlspec.driver._sql_helpers import convert_to_dialect as _convert_to_dialect_impl
26
+ from sqlspec.driver._storage_helpers import stringify_storage_target
27
+ from sqlspec.exceptions import ImproperConfigurationError, StackExecutionError
28
+ from sqlspec.storage import AsyncStoragePipeline, StorageBridgeJob, StorageDestination, StorageFormat, StorageTelemetry
29
+ from sqlspec.utils.arrow_helpers import convert_dict_to_arrow_with_schema
30
+ from sqlspec.utils.logging import get_logger
31
+ from sqlspec.utils.schema import ValueT, to_value_type
32
+
33
+ if TYPE_CHECKING:
34
+ from collections.abc import Awaitable, Sequence
35
+
36
+ from sqlglot.dialects.dialect import DialectType
37
+
38
+ from sqlspec.builder import QueryBuilder
39
+ from sqlspec.core import ArrowResult, SQLResult, StatementConfig, StatementFilter
40
+ from sqlspec.typing import (
41
+ ArrowReturnFormat,
42
+ ArrowTable,
43
+ ColumnMetadata,
44
+ ForeignKeyMetadata,
45
+ IndexMetadata,
46
+ SchemaT,
47
+ StatementParameters,
48
+ TableMetadata,
49
+ VersionInfo,
50
+ )
51
+
52
+
53
+ __all__ = ("AsyncDataDictionaryBase", "AsyncDriverAdapterBase", "AsyncPoolConnectionContext", "AsyncPoolSessionFactory")
54
+
55
+
56
+ EMPTY_FILTERS: Final["list[StatementFilter]"] = []
57
+ _LOGGER_NAME: Final[str] = "sqlspec.driver"
58
+ logger = get_logger(_LOGGER_NAME)
59
+
60
+
61
+ @mypyc_attr(allow_interpreted_subclasses=True)
62
+ class AsyncPoolConnectionContext:
63
+ """Base async connection context using pool acquire/release pattern.
64
+
65
+ Subclass per adapter and override ``__aenter__``/``__aexit__`` for
66
+ adapter-specific pool acquisition and release logic.
67
+ """
68
+
69
+ __slots__ = ("_config", "_connection")
70
+
71
+ def __init__(self, config: Any) -> None:
72
+ self._config = config
73
+ self._connection: Any = None
74
+
75
+ async def __aenter__(self) -> Any:
76
+ pool = self._config.connection_instance
77
+ if pool is None:
78
+ pool = await self._config.create_pool()
79
+ self._config.connection_instance = pool
80
+ self._connection = await pool.acquire()
81
+ return self._connection
82
+
83
+ async def __aexit__(
84
+ self, exc_type: "type[BaseException] | None", exc_val: "BaseException | None", exc_tb: Any
85
+ ) -> "bool | None":
86
+ if self._connection is not None:
87
+ if self._config.connection_instance:
88
+ await self._config.connection_instance.release(self._connection)
89
+ self._connection = None
90
+ return None
91
+
92
+
93
+ @mypyc_attr(allow_interpreted_subclasses=True)
94
+ class AsyncPoolSessionFactory:
95
+ """Base async session factory using pool acquire/release pattern.
96
+
97
+ Subclass per adapter and override ``acquire_connection``/``release_connection``
98
+ for adapter-specific pool acquisition and release logic.
99
+ """
100
+
101
+ __slots__ = ("_config", "_connection")
102
+
103
+ def __init__(self, config: Any) -> None:
104
+ self._config = config
105
+ self._connection: Any = None
106
+
107
+ async def acquire_connection(self) -> Any:
108
+ pool = self._config.connection_instance
109
+ if pool is None:
110
+ pool = await self._config.create_pool()
111
+ self._config.connection_instance = pool
112
+ self._connection = await pool.acquire()
113
+ return self._connection
114
+
115
+ async def release_connection(self, _conn: Any, **kwargs: Any) -> None:
116
+ if self._connection is not None and self._config.connection_instance is not None:
117
+ await self._config.connection_instance.release(self._connection)
118
+ self._connection = None
119
+
120
+
121
+ @mypyc_attr(allow_interpreted_subclasses=True)
122
+ class AsyncDriverAdapterBase(CommonDriverAttributesMixin):
123
+ """Base class for asynchronous database drivers.
124
+
125
+ This class includes flattened storage and SQL translation methods that were
126
+ previously in StorageDriverMixin and SQLTranslatorMixin. The flattening
127
+ eliminates cross-trait attribute access that caused mypyc segmentation faults.
128
+
129
+ Method Organization:
130
+ 1. Core dispatch methods (the execution engine)
131
+ 2. Transaction management (abstract methods)
132
+ 3. Public API - execution methods
133
+ 4. Public API - query methods (select/fetch variants)
134
+ 5. Arrow API methods
135
+ 6. Stack execution
136
+ 7. Storage API methods
137
+ 8. Utility methods
138
+ 9. Private/internal methods
139
+
140
+ """
141
+
142
+ __slots__ = ()
143
+
144
+ dialect: "DialectType | None" = None
145
+
146
+ @property
147
+ def is_async(self) -> bool:
148
+ """Return whether the driver executes asynchronously.
149
+
150
+ Returns:
151
+ True for async drivers.
152
+
153
+ """
154
+ return True
155
+
156
+ @property
157
+ @abstractmethod
158
+ def data_dictionary(self) -> "AsyncDataDictionaryBase":
159
+ """Get the data dictionary for this driver.
160
+
161
+ Returns:
162
+ Data dictionary instance for metadata queries
163
+
164
+ """
165
+
166
+ # ─────────────────────────────────────────────────────────────────────────────
167
+ # CORE DISPATCH METHODS - The Execution Engine
168
+ # ─────────────────────────────────────────────────────────────────────────────
169
+
170
+ @staticmethod
171
+ def _check_pending_exception(exc_handler: AsyncExceptionHandler) -> None:
172
+ """Raise any pending mapped exception after context manager exit."""
173
+ if exc_handler.pending_exception is not None:
174
+ raise exc_handler.pending_exception from None
175
+
176
+ @final
177
+ async def dispatch_statement_execution(self, statement: "SQL", connection: "Any") -> "SQLResult":
178
+ """Central execution dispatcher using the Template Method Pattern.
179
+
180
+ Args:
181
+ statement: The SQL statement to execute
182
+ connection: The database connection to use
183
+
184
+ Returns:
185
+ The result of the SQL execution
186
+
187
+ """
188
+ try:
189
+ runtime = self._observability
190
+ compiled_sql, execution_parameters = statement.compile()
191
+ _ = cast("ProcessedState", statement.get_processed_state())
192
+ result: SQLResult | None = None
193
+
194
+ # FAST PATH: Skip all instrumentation if runtime is absent or idle.
195
+ if runtime is None or runtime.is_idle:
196
+ exc_handler = self.handle_database_exceptions()
197
+ async with exc_handler, self.with_cursor(connection) as cursor:
198
+ special_result = await self.dispatch_special_handling(cursor, statement)
199
+ if special_result is not None:
200
+ result = special_result
201
+ elif statement.is_script:
202
+ execution_result = await self.dispatch_execute_script(cursor, statement)
203
+ result = self.build_statement_result(statement, execution_result)
204
+ elif statement.is_many:
205
+ execution_result = await self.dispatch_execute_many(cursor, statement)
206
+ result = self.build_statement_result(statement, execution_result)
207
+ else:
208
+ execution_result = await self.dispatch_execute(cursor, statement)
209
+ result = self.build_statement_result(statement, execution_result)
210
+ self._check_pending_exception(exc_handler)
211
+ assert result is not None
212
+ return result
213
+
214
+ operation = statement.operation_type
215
+ query_context = {
216
+ "sql": compiled_sql,
217
+ "parameters": execution_parameters,
218
+ "driver": type(self).__name__,
219
+ "operation": operation,
220
+ "is_many": statement.is_many,
221
+ "is_script": statement.is_script,
222
+ }
223
+ runtime.emit_query_start(**query_context)
224
+ span = runtime.start_query_span(compiled_sql, operation, type(self).__name__)
225
+ started = perf_counter()
226
+
227
+ exc_handler = self.handle_database_exceptions()
228
+ try:
229
+ async with exc_handler, self.with_cursor(connection) as cursor:
230
+ special_result = await self.dispatch_special_handling(cursor, statement)
231
+ if special_result is not None:
232
+ result = special_result
233
+ elif statement.is_script:
234
+ execution_result = await self.dispatch_execute_script(cursor, statement)
235
+ result = self.build_statement_result(statement, execution_result)
236
+ elif statement.is_many:
237
+ execution_result = await self.dispatch_execute_many(cursor, statement)
238
+ result = self.build_statement_result(statement, execution_result)
239
+ else:
240
+ execution_result = await self.dispatch_execute(cursor, statement)
241
+ result = self.build_statement_result(statement, execution_result)
242
+ except Exception as exc: # pragma: no cover - instrumentation path
243
+ pending_exception = exc_handler.pending_exception
244
+ if pending_exception is not None:
245
+ mapped_exc = pending_exception
246
+ runtime.span_manager.end_span(span, error=mapped_exc)
247
+ runtime.emit_error(mapped_exc, **query_context)
248
+ _raise_database_exception(exc_handler, exc)
249
+ runtime.span_manager.end_span(span, error=exc)
250
+ runtime.emit_error(exc, **query_context)
251
+ _raise_database_exception(exc_handler, exc)
252
+
253
+ pending_exception = exc_handler.pending_exception
254
+ if pending_exception is not None:
255
+ mapped_exc = pending_exception
256
+ runtime.span_manager.end_span(span, error=mapped_exc)
257
+ runtime.emit_error(mapped_exc, **query_context)
258
+ _raise_database_exception(exc_handler, None)
259
+
260
+ assert result is not None # Guaranteed: no exception means result was assigned
261
+
262
+ runtime.span_manager.end_span(span)
263
+ duration = perf_counter() - started
264
+ runtime.emit_query_complete(**{**query_context, "rows_affected": result.rows_affected})
265
+ runtime.emit_statement_event(
266
+ sql=compiled_sql,
267
+ parameters=execution_parameters,
268
+ driver=type(self).__name__,
269
+ operation=operation,
270
+ execution_mode=self.statement_config.execution_mode,
271
+ is_many=statement.is_many,
272
+ is_script=statement.is_script,
273
+ rows_affected=result.rows_affected,
274
+ duration_s=duration,
275
+ storage_backend=(result.metadata or {}).get("storage_backend"),
276
+ started_at=started,
277
+ )
278
+ return result
279
+ finally:
280
+ self._release_pooled_statement(statement)
281
+
282
+ @abstractmethod
283
+ async def dispatch_execute(self, cursor: Any, statement: "SQL") -> ExecutionResult:
284
+ """Execute a single SQL statement.
285
+
286
+ Must be implemented by each driver for database-specific execution logic.
287
+
288
+ Args:
289
+ cursor: Database cursor/connection object
290
+ statement: SQL statement object with all necessary data and configuration
291
+
292
+ Returns:
293
+ ExecutionResult with execution data
294
+
295
+ """
296
+
297
+ @abstractmethod
298
+ async def dispatch_execute_many(self, cursor: Any, statement: "SQL") -> ExecutionResult:
299
+ """Execute SQL with multiple parameter sets (executemany).
300
+
301
+ Must be implemented by each driver for database-specific executemany logic.
302
+
303
+ Args:
304
+ cursor: Database cursor/connection object
305
+ statement: SQL statement object with all necessary data and configuration
306
+
307
+ Returns:
308
+ ExecutionResult with execution data for the many operation
309
+
310
+ """
311
+
312
+ async def dispatch_execute_script(self, cursor: Any, statement: "SQL") -> ExecutionResult:
313
+ """Execute a SQL script containing multiple statements.
314
+
315
+ Default implementation splits the script and executes statements individually.
316
+ Drivers can override for database-specific script execution methods.
317
+
318
+ Args:
319
+ cursor: Database cursor/connection object
320
+ statement: SQL statement object with all necessary data and configuration
321
+
322
+ Returns:
323
+ ExecutionResult with script execution data including statement counts
324
+
325
+ """
326
+ sql, prepared_parameters = self._get_compiled_sql(statement, self.statement_config)
327
+ statements = self.split_script_statements(sql, self.statement_config, strip_trailing_semicolon=True)
328
+
329
+ statement_count: int = len(statements)
330
+ successful_count: int = 0
331
+
332
+ for stmt in statements:
333
+ single_stmt = statement.copy(statement=stmt, parameters=prepared_parameters)
334
+ await self.dispatch_execute(cursor, single_stmt)
335
+ successful_count += 1
336
+
337
+ return self.create_execution_result(
338
+ cursor, statement_count=statement_count, successful_statements=successful_count, is_script_result=True
339
+ )
340
+
341
+ async def dispatch_special_handling(self, cursor: Any, statement: "SQL") -> "SQLResult | None":
342
+ """Hook for database-specific special operations (e.g., PostgreSQL COPY, bulk operations).
343
+
344
+ This method is called first in dispatch_statement_execution() to allow drivers to handle
345
+ special operations that don't follow the standard SQL execution pattern.
346
+
347
+ Args:
348
+ cursor: Database cursor/connection object
349
+ statement: SQL statement to analyze
350
+
351
+ Returns:
352
+ SQLResult if the special operation was handled and completed,
353
+ None if standard execution should proceed
354
+
355
+ """
356
+ _ = (cursor, statement)
357
+ return None
358
+
359
+ def collect_rows(self, cursor: Any, fetched: "list[Any]") -> "tuple[list[Any], list[str], int]":
360
+ """Collect rows from cursor after fetchall for the direct execution path.
361
+
362
+ Adapters should override this method to provide optimized row collection
363
+ that bypasses full dispatch_execute overhead.
364
+
365
+ Args:
366
+ cursor: Database cursor with description metadata.
367
+ fetched: Rows returned from cursor.fetchall().
368
+
369
+ Returns:
370
+ Tuple of (data, column_names, row_count).
371
+
372
+ Raises:
373
+ NotImplementedError: If the adapter does not implement this method.
374
+
375
+ """
376
+ msg = "Adapter must implement collect_rows() for direct execution path"
377
+ raise NotImplementedError(msg)
378
+
379
+ def resolve_rowcount(self, cursor: Any) -> int:
380
+ """Resolve the number of affected rows from cursor for the direct execution path.
381
+
382
+ Adapters should override this method to provide optimized rowcount resolution
383
+ that bypasses full dispatch_execute overhead.
384
+
385
+ Args:
386
+ cursor: Database cursor with rowcount metadata.
387
+
388
+ Returns:
389
+ Number of affected rows, or 0 when unknown.
390
+
391
+ Raises:
392
+ NotImplementedError: If the adapter does not implement this method.
393
+
394
+ """
395
+ msg = "Adapter must implement resolve_rowcount() for direct execution path"
396
+ raise NotImplementedError(msg)
397
+
398
+ async def _stmt_cache_execute_direct(
399
+ self, sql: str, params: "tuple[Any, ...] | list[Any]", cached: CachedQuery
400
+ ) -> "SQLResult":
401
+ """Execute pre-compiled query via ultra-fast path (async).
402
+
403
+ Uses _stmt_cache_build_direct + dispatch_execute since async drivers can't
404
+ call cursor.execute directly. For DML operations, returns DMLResult
405
+ to bypass full SQLResult construction.
406
+
407
+ Args:
408
+ sql: Raw SQL string (original, not compiled).
409
+ params: Query parameters.
410
+ cached: Cached query metadata.
411
+
412
+ Returns:
413
+ SQLResult or DMLResult.
414
+ """
415
+ compiled_sql = cached.compiled_sql
416
+ direct_statement = self._stmt_cache_build_direct(
417
+ sql, params, cached, params, params_are_simple=True, compiled_sql=compiled_sql
418
+ )
419
+
420
+ exc_handler = self.handle_database_exceptions()
421
+ result: SQLResult | None = None
422
+ try:
423
+ async with exc_handler, self.with_cursor(self.connection) as cursor:
424
+ execution_result = await self.dispatch_execute(cursor, direct_statement)
425
+
426
+ if cached.operation_profile.returns_rows:
427
+ result = self.build_statement_result(direct_statement, execution_result)
428
+ else:
429
+ # DML path: use DMLResult to bypass full SQLResult construction
430
+ affected_rows = (
431
+ execution_result.rowcount_override
432
+ if execution_result.rowcount_override is not None and execution_result.rowcount_override >= 0
433
+ else 0
434
+ )
435
+ result = DMLResult(cached.operation_type, affected_rows)
436
+
437
+ self._check_pending_exception(exc_handler)
438
+ assert result is not None
439
+ return result
440
+ finally:
441
+ self._release_pooled_statement(direct_statement)
442
+
443
+ async def _stmt_cache_lookup(self, statement: str, params: "tuple[Any, ...] | list[Any]") -> "SQLResult | None":
444
+ """Attempt fast-path execution for cached query (async).
445
+
446
+ Args:
447
+ statement: Raw SQL string.
448
+ params: Query parameters.
449
+
450
+ Returns:
451
+ SQLResult if cache hit and execution succeeds, None otherwise.
452
+ """
453
+ result = super()._stmt_cache_lookup(statement, params)
454
+ if result is None:
455
+ return None
456
+ return await cast("Awaitable[SQLResult | None]", result)
457
+
458
+ async def _stmt_cache_execute(self, statement: "SQL") -> "SQLResult":
459
+ """Execute pre-compiled query via fast path (async).
460
+
461
+ The statement is already compiled by _stmt_cache_prepare_direct, so dispatch_execute
462
+ will hit the fast path in _get_compiled_statement (is_processed check).
463
+ """
464
+ exc_handler = self.handle_database_exceptions()
465
+ result: SQLResult | None = None
466
+ try:
467
+ async with exc_handler, self.with_cursor(self.connection) as cursor:
468
+ execution_result = await self.dispatch_execute(cursor, statement)
469
+ result = self.build_statement_result(statement, execution_result)
470
+
471
+ self._check_pending_exception(exc_handler)
472
+ assert result is not None
473
+ return result
474
+ finally:
475
+ self._release_pooled_statement(statement)
476
+
477
+ # ─────────────────────────────────────────────────────────────────────────────
478
+ # TRANSACTION MANAGEMENT - Required Abstract Methods
479
+ # ─────────────────────────────────────────────────────────────────────────────
480
+
481
+ @abstractmethod
482
+ async def begin(self) -> None:
483
+ """Begin a database transaction on the current connection."""
484
+
485
+ @abstractmethod
486
+ async def commit(self) -> None:
487
+ """Commit the current transaction on the current connection."""
488
+
489
+ @abstractmethod
490
+ async def rollback(self) -> None:
491
+ """Rollback the current transaction on the current connection."""
492
+
493
+ @abstractmethod
494
+ def with_cursor(self, connection: Any) -> Any:
495
+ """Create and return an async context manager for cursor acquisition and cleanup.
496
+
497
+ Returns an async context manager that yields a cursor for database operations.
498
+ Concrete implementations handle database-specific cursor creation and cleanup.
499
+ """
500
+
501
+ @abstractmethod
502
+ def handle_database_exceptions(self) -> "AsyncExceptionHandler":
503
+ """Handle database-specific exceptions and wrap them appropriately.
504
+
505
+ Returns:
506
+ Exception handler with deferred exception pattern for mypyc compatibility.
507
+ The handler stores mapped exceptions in pending_exception rather than
508
+ raising from __aexit__ to avoid ABI boundary violations.
509
+
510
+ """
511
+
512
+ # ─────────────────────────────────────────────────────────────────────────────
513
+ # PUBLIC API - Core Execution Methods
514
+ # ─────────────────────────────────────────────────────────────────────────────
515
+
516
+ async def execute(
517
+ self,
518
+ statement: "SQL | Statement | QueryBuilder",
519
+ /,
520
+ *parameters: "StatementParameters | StatementFilter",
521
+ statement_config: "StatementConfig | None" = None,
522
+ **kwargs: Any,
523
+ ) -> "SQLResult":
524
+ """Execute a statement with parameter handling."""
525
+ exc_handler = self.handle_database_exceptions()
526
+ result: SQLResult | None = None
527
+ async with exc_handler:
528
+ if (
529
+ self._stmt_cache_enabled
530
+ and (statement_config is None or statement_config is self.statement_config)
531
+ and isinstance(statement, str)
532
+ and len(parameters) == 1
533
+ and isinstance(parameters[0], (tuple, list))
534
+ and not kwargs
535
+ ):
536
+ fast_result = await self._stmt_cache_lookup(statement, parameters[0])
537
+ if fast_result is not None:
538
+ result = fast_result
539
+ if result is None:
540
+ sql_statement = self.prepare_statement(
541
+ statement, parameters, statement_config=statement_config or self.statement_config, kwargs=kwargs
542
+ )
543
+ result = await self.dispatch_statement_execution(statement=sql_statement, connection=self.connection)
544
+ self._check_pending_exception(exc_handler)
545
+ assert result is not None
546
+ return result
547
+
548
+ async def execute_many(
549
+ self,
550
+ statement: "SQL | Statement | QueryBuilder",
551
+ /,
552
+ parameters: "Sequence[StatementParameters]",
553
+ *filters: "StatementParameters | StatementFilter",
554
+ statement_config: "StatementConfig | None" = None,
555
+ **kwargs: Any,
556
+ ) -> "SQLResult":
557
+ """Execute statement multiple times with different parameters.
558
+
559
+ Parameters passed will be used as the batch execution sequence.
560
+ """
561
+ exc_handler = self.handle_database_exceptions()
562
+ result: SQLResult | None = None
563
+ async with exc_handler:
564
+ config = statement_config or self.statement_config
565
+
566
+ if isinstance(statement, str) and not filters and not kwargs:
567
+ sql_statement = SQL(statement, parameters, statement_config=config, is_many=True)
568
+ elif isinstance(statement, SQL):
569
+ statement_seed = statement.raw_expression or statement.raw_sql
570
+ sql_statement = SQL(statement_seed, parameters, statement_config=config, is_many=True, **kwargs)
571
+ else:
572
+ base_statement = self.prepare_statement(statement, filters, statement_config=config, kwargs=kwargs)
573
+ statement_seed = base_statement.raw_expression or base_statement.raw_sql
574
+ sql_statement = SQL(statement_seed, parameters, statement_config=config, is_many=True, **kwargs)
575
+
576
+ result = await self.dispatch_statement_execution(statement=sql_statement, connection=self.connection)
577
+ self._check_pending_exception(exc_handler)
578
+ assert result is not None
579
+ return result
580
+
581
+ async def execute_script(
582
+ self,
583
+ statement: "str | SQL",
584
+ /,
585
+ *parameters: "StatementParameters | StatementFilter",
586
+ statement_config: "StatementConfig | None" = None,
587
+ **kwargs: Any,
588
+ ) -> "SQLResult":
589
+ """Execute a multi-statement script.
590
+
591
+ By default, validates each statement and logs warnings for dangerous
592
+ operations. Use suppress_warnings=True for migrations and admin scripts.
593
+ """
594
+ exc_handler = self.handle_database_exceptions()
595
+ result: SQLResult | None = None
596
+ async with exc_handler:
597
+ config = statement_config or self.statement_config
598
+ sql_statement = self.prepare_statement(statement, parameters, statement_config=config, kwargs=kwargs)
599
+ result = await self.dispatch_statement_execution(
600
+ statement=sql_statement.as_script(), connection=self.connection
601
+ )
602
+ self._check_pending_exception(exc_handler)
603
+ assert result is not None
604
+ return result
605
+
606
+ # ─────────────────────────────────────────────────────────────────────────────
607
+ # PUBLIC API - Query Methods (select/fetch variants)
608
+ # ─────────────────────────────────────────────────────────────────────────────
609
+
610
+ @overload
611
+ async def select(
612
+ self,
613
+ statement: "Statement | QueryBuilder",
614
+ /,
615
+ *parameters: "StatementParameters | StatementFilter",
616
+ schema_type: "type[SchemaT]",
617
+ statement_config: "StatementConfig | None" = None,
618
+ **kwargs: Any,
619
+ ) -> "list[SchemaT]": ...
620
+
621
+ @overload
622
+ async def select(
623
+ self,
624
+ statement: "Statement | QueryBuilder",
625
+ /,
626
+ *parameters: "StatementParameters | StatementFilter",
627
+ schema_type: None = None,
628
+ statement_config: "StatementConfig | None" = None,
629
+ **kwargs: Any,
630
+ ) -> "list[dict[str, Any]]": ...
631
+
632
+ async def select(
633
+ self,
634
+ statement: "Statement | QueryBuilder",
635
+ /,
636
+ *parameters: "StatementParameters | StatementFilter",
637
+ schema_type: "type[SchemaT] | None" = None,
638
+ statement_config: "StatementConfig | None" = None,
639
+ **kwargs: Any,
640
+ ) -> "list[SchemaT] | list[dict[str, Any]]":
641
+ """Execute a select statement and return all rows."""
642
+ result = await self.execute(statement, *parameters, statement_config=statement_config, **kwargs)
643
+ return result.get_data(schema_type=schema_type)
644
+
645
+ @overload
646
+ async def fetch(
647
+ self,
648
+ statement: "Statement | QueryBuilder",
649
+ /,
650
+ *parameters: "StatementParameters | StatementFilter",
651
+ schema_type: "type[SchemaT]",
652
+ statement_config: "StatementConfig | None" = None,
653
+ **kwargs: Any,
654
+ ) -> "list[SchemaT]": ...
655
+
656
+ @overload
657
+ async def fetch(
658
+ self,
659
+ statement: "Statement | QueryBuilder",
660
+ /,
661
+ *parameters: "StatementParameters | StatementFilter",
662
+ schema_type: None = None,
663
+ statement_config: "StatementConfig | None" = None,
664
+ **kwargs: Any,
665
+ ) -> "list[dict[str, Any]]": ...
666
+
667
+ async def fetch(
668
+ self,
669
+ statement: "Statement | QueryBuilder",
670
+ /,
671
+ *parameters: "StatementParameters | StatementFilter",
672
+ schema_type: "type[SchemaT] | None" = None,
673
+ statement_config: "StatementConfig | None" = None,
674
+ **kwargs: Any,
675
+ ) -> "list[SchemaT] | list[dict[str, Any]]":
676
+ """Execute a select statement and return all rows.
677
+
678
+ This is an alias for :meth:`select` provided for users familiar
679
+ with asyncpg's fetch() naming convention.
680
+
681
+ See Also:
682
+ select(): Primary method with identical behavior
683
+
684
+ """
685
+ return await self.select(
686
+ statement, *parameters, schema_type=schema_type, statement_config=statement_config, **kwargs
687
+ )
688
+
689
+ @overload
690
+ async def select_one(
691
+ self,
692
+ statement: "Statement | QueryBuilder",
693
+ /,
694
+ *parameters: "StatementParameters | StatementFilter",
695
+ schema_type: "type[SchemaT]",
696
+ statement_config: "StatementConfig | None" = None,
697
+ **kwargs: Any,
698
+ ) -> "SchemaT": ...
699
+
700
+ @overload
701
+ async def select_one(
702
+ self,
703
+ statement: "Statement | QueryBuilder",
704
+ /,
705
+ *parameters: "StatementParameters | StatementFilter",
706
+ schema_type: None = None,
707
+ statement_config: "StatementConfig | None" = None,
708
+ **kwargs: Any,
709
+ ) -> "dict[str, Any]": ...
710
+
711
+ async def select_one(
712
+ self,
713
+ statement: "Statement | QueryBuilder",
714
+ /,
715
+ *parameters: "StatementParameters | StatementFilter",
716
+ schema_type: "type[SchemaT] | None" = None,
717
+ statement_config: "StatementConfig | None" = None,
718
+ **kwargs: Any,
719
+ ) -> "SchemaT | dict[str, Any]":
720
+ """Execute a select statement and return exactly one row.
721
+
722
+ Raises an exception if no rows or more than one row is returned.
723
+ """
724
+ result = await self.execute(statement, *parameters, statement_config=statement_config, **kwargs)
725
+ try:
726
+ return result.one(schema_type=schema_type)
727
+ except ValueError as error:
728
+ handle_single_row_error(error)
729
+
730
+ @overload
731
+ async def fetch_one(
732
+ self,
733
+ statement: "Statement | QueryBuilder",
734
+ /,
735
+ *parameters: "StatementParameters | StatementFilter",
736
+ schema_type: "type[SchemaT]",
737
+ statement_config: "StatementConfig | None" = None,
738
+ **kwargs: Any,
739
+ ) -> "SchemaT": ...
740
+
741
+ @overload
742
+ async def fetch_one(
743
+ self,
744
+ statement: "Statement | QueryBuilder",
745
+ /,
746
+ *parameters: "StatementParameters | StatementFilter",
747
+ schema_type: None = None,
748
+ statement_config: "StatementConfig | None" = None,
749
+ **kwargs: Any,
750
+ ) -> "dict[str, Any]": ...
751
+
752
+ async def fetch_one(
753
+ self,
754
+ statement: "Statement | QueryBuilder",
755
+ /,
756
+ *parameters: "StatementParameters | StatementFilter",
757
+ schema_type: "type[SchemaT] | None" = None,
758
+ statement_config: "StatementConfig | None" = None,
759
+ **kwargs: Any,
760
+ ) -> "SchemaT | dict[str, Any]":
761
+ """Execute a select statement and return exactly one row.
762
+
763
+ This is an alias for :meth:`select_one` provided for users familiar
764
+ with asyncpg's fetch_one() naming convention.
765
+
766
+ Raises an exception if no rows or more than one row is returned.
767
+
768
+ See Also:
769
+ select_one(): Primary method with identical behavior
770
+
771
+ """
772
+ return await self.select_one(
773
+ statement, *parameters, schema_type=schema_type, statement_config=statement_config, **kwargs
774
+ )
775
+
776
+ @overload
777
+ async def select_one_or_none(
778
+ self,
779
+ statement: "Statement | QueryBuilder",
780
+ /,
781
+ *parameters: "StatementParameters | StatementFilter",
782
+ schema_type: "type[SchemaT]",
783
+ statement_config: "StatementConfig | None" = None,
784
+ **kwargs: Any,
785
+ ) -> "SchemaT | None": ...
786
+
787
+ @overload
788
+ async def select_one_or_none(
789
+ self,
790
+ statement: "Statement | QueryBuilder",
791
+ /,
792
+ *parameters: "StatementParameters | StatementFilter",
793
+ schema_type: None = None,
794
+ statement_config: "StatementConfig | None" = None,
795
+ **kwargs: Any,
796
+ ) -> "dict[str, Any] | None": ...
797
+
798
+ async def select_one_or_none(
799
+ self,
800
+ statement: "Statement | QueryBuilder",
801
+ /,
802
+ *parameters: "StatementParameters | StatementFilter",
803
+ schema_type: "type[SchemaT] | None" = None,
804
+ statement_config: "StatementConfig | None" = None,
805
+ **kwargs: Any,
806
+ ) -> "SchemaT | dict[str, Any] | None":
807
+ """Execute a select statement and return at most one row.
808
+
809
+ Returns None if no rows are found. Raises ``ValueError`` if more than one
810
+ row is returned. Any database or SQL execution errors raised by the driver
811
+ are propagated unchanged.
812
+ """
813
+ result = await self.execute(statement, *parameters, statement_config=statement_config, **kwargs)
814
+ return result.one_or_none(schema_type=schema_type)
815
+
816
+ @overload
817
+ async def fetch_one_or_none(
818
+ self,
819
+ statement: "Statement | QueryBuilder",
820
+ /,
821
+ *parameters: "StatementParameters | StatementFilter",
822
+ schema_type: "type[SchemaT]",
823
+ statement_config: "StatementConfig | None" = None,
824
+ **kwargs: Any,
825
+ ) -> "SchemaT | None": ...
826
+
827
+ @overload
828
+ async def fetch_one_or_none(
829
+ self,
830
+ statement: "Statement | QueryBuilder",
831
+ /,
832
+ *parameters: "StatementParameters | StatementFilter",
833
+ schema_type: None = None,
834
+ statement_config: "StatementConfig | None" = None,
835
+ **kwargs: Any,
836
+ ) -> "dict[str, Any] | None": ...
837
+
838
+ async def fetch_one_or_none(
839
+ self,
840
+ statement: "Statement | QueryBuilder",
841
+ /,
842
+ *parameters: "StatementParameters | StatementFilter",
843
+ schema_type: "type[SchemaT] | None" = None,
844
+ statement_config: "StatementConfig | None" = None,
845
+ **kwargs: Any,
846
+ ) -> "SchemaT | dict[str, Any] | None":
847
+ """Execute a select statement and return at most one row.
848
+
849
+ This is an alias for :meth:`select_one_or_none` provided for users familiar
850
+ with asyncpg's fetch_one_or_none() naming convention.
851
+
852
+ Returns None if no rows are found.
853
+ Raises an exception if more than one row is returned.
854
+
855
+ See Also:
856
+ select_one_or_none(): Primary method with identical behavior
857
+
858
+ """
859
+ return await self.select_one_or_none(
860
+ statement, *parameters, schema_type=schema_type, statement_config=statement_config, **kwargs
861
+ )
862
+
863
+ @overload
864
+ async def select_value(
865
+ self,
866
+ statement: "Statement | QueryBuilder",
867
+ /,
868
+ *parameters: "StatementParameters | StatementFilter",
869
+ value_type: "type[ValueT]",
870
+ statement_config: "StatementConfig | None" = None,
871
+ **kwargs: Any,
872
+ ) -> "ValueT": ...
873
+
874
+ @overload
875
+ async def select_value(
876
+ self,
877
+ statement: "Statement | QueryBuilder",
878
+ /,
879
+ *parameters: "StatementParameters | StatementFilter",
880
+ value_type: None = None,
881
+ statement_config: "StatementConfig | None" = None,
882
+ **kwargs: Any,
883
+ ) -> Any: ...
884
+
885
+ async def select_value(
886
+ self,
887
+ statement: "Statement | QueryBuilder",
888
+ /,
889
+ *parameters: "StatementParameters | StatementFilter",
890
+ value_type: "type[ValueT] | None" = None,
891
+ statement_config: "StatementConfig | None" = None,
892
+ **kwargs: Any,
893
+ ) -> "ValueT | Any":
894
+ """Execute a select statement and return a single scalar value.
895
+
896
+ Expects exactly one row with one column.
897
+ Raises an exception if no rows or more than one row/column is returned.
898
+
899
+ Args:
900
+ statement: SQL statement or query builder to execute.
901
+ *parameters: Positional parameters for the statement.
902
+ value_type: Optional type to convert the result to. When provided,
903
+ the return value is converted to this type and the return type
904
+ is narrowed for type checkers. Supports int, float, str, bool,
905
+ datetime, date, time, Decimal, UUID, Path, dict, and list.
906
+ statement_config: Optional statement configuration.
907
+ **kwargs: Additional keyword arguments.
908
+
909
+ Returns:
910
+ The scalar value, optionally converted to the specified type
911
+
912
+ Examples:
913
+ Basic usage (returns Any):
914
+
915
+ >>> count = await driver.select_value(
916
+ ... "SELECT COUNT(*) FROM users"
917
+ ... )
918
+
919
+ With type hint (returns int):
920
+
921
+ >>> count = await driver.select_value(
922
+ ... "SELECT COUNT(*) FROM users", value_type=int
923
+ ... )
924
+
925
+ With UUID conversion:
926
+
927
+ >>> user_id = await driver.select_value(
928
+ ... "SELECT id FROM users WHERE name = :name",
929
+ ... {"name": "alice"},
930
+ ... value_type=UUID,
931
+ ... )
932
+ """
933
+ result = await self.execute(statement, *parameters, statement_config=statement_config, **kwargs)
934
+ try:
935
+ value = result.scalar()
936
+ except ValueError as error:
937
+ handle_single_row_error(error)
938
+
939
+ if value_type is not None:
940
+ return to_value_type(value, value_type)
941
+ return value
942
+
943
+ @overload
944
+ async def fetch_value(
945
+ self,
946
+ statement: "Statement | QueryBuilder",
947
+ /,
948
+ *parameters: "StatementParameters | StatementFilter",
949
+ value_type: "type[ValueT]",
950
+ statement_config: "StatementConfig | None" = None,
951
+ **kwargs: Any,
952
+ ) -> "ValueT": ...
953
+
954
+ @overload
955
+ async def fetch_value(
956
+ self,
957
+ statement: "Statement | QueryBuilder",
958
+ /,
959
+ *parameters: "StatementParameters | StatementFilter",
960
+ value_type: None = None,
961
+ statement_config: "StatementConfig | None" = None,
962
+ **kwargs: Any,
963
+ ) -> Any: ...
964
+
965
+ async def fetch_value(
966
+ self,
967
+ statement: "Statement | QueryBuilder",
968
+ /,
969
+ *parameters: "StatementParameters | StatementFilter",
970
+ value_type: "type[ValueT] | None" = None,
971
+ statement_config: "StatementConfig | None" = None,
972
+ **kwargs: Any,
973
+ ) -> "ValueT | Any":
974
+ """Execute a select statement and return a single scalar value.
975
+
976
+ This is an alias for :meth:`select_value` provided for users familiar
977
+ with asyncpg's fetch_value() naming convention.
978
+
979
+ Expects exactly one row with one column.
980
+ Raises an exception if no rows or more than one row/column is returned.
981
+
982
+ See Also:
983
+ select_value(): Primary method with identical behavior
984
+
985
+ """
986
+ return await self.select_value(
987
+ statement, *parameters, value_type=value_type, statement_config=statement_config, **kwargs
988
+ )
989
+
990
+ @overload
991
+ async def select_value_or_none(
992
+ self,
993
+ statement: "Statement | QueryBuilder",
994
+ /,
995
+ *parameters: "StatementParameters | StatementFilter",
996
+ value_type: "type[ValueT]",
997
+ statement_config: "StatementConfig | None" = None,
998
+ **kwargs: Any,
999
+ ) -> "ValueT | None": ...
1000
+
1001
+ @overload
1002
+ async def select_value_or_none(
1003
+ self,
1004
+ statement: "Statement | QueryBuilder",
1005
+ /,
1006
+ *parameters: "StatementParameters | StatementFilter",
1007
+ value_type: None = None,
1008
+ statement_config: "StatementConfig | None" = None,
1009
+ **kwargs: Any,
1010
+ ) -> Any: ...
1011
+
1012
+ async def select_value_or_none(
1013
+ self,
1014
+ statement: "Statement | QueryBuilder",
1015
+ /,
1016
+ *parameters: "StatementParameters | StatementFilter",
1017
+ value_type: "type[ValueT] | None" = None,
1018
+ statement_config: "StatementConfig | None" = None,
1019
+ **kwargs: Any,
1020
+ ) -> "ValueT | None | Any":
1021
+ """Execute a select statement and return a single scalar value or None.
1022
+
1023
+ Returns None if no rows are found.
1024
+ Expects at most one row with one column.
1025
+ Raises an exception if more than one row is returned.
1026
+
1027
+ Args:
1028
+ statement: SQL statement or query builder to execute.
1029
+ *parameters: Positional parameters for the statement.
1030
+ value_type: Optional type to convert the result to. When provided,
1031
+ the return value is converted to this type and the return type
1032
+ is narrowed to ``T | None`` for type checkers. Supports int, float,
1033
+ str, bool, datetime, date, time, Decimal, UUID, Path, dict, and list.
1034
+ statement_config: Optional statement configuration.
1035
+ **kwargs: Additional keyword arguments.
1036
+
1037
+ Returns:
1038
+ The scalar value (optionally converted), or None if no rows found.
1039
+
1040
+ Examples:
1041
+ Basic usage:
1042
+
1043
+ >>> email = await driver.select_value_or_none(
1044
+ ... "SELECT email FROM users WHERE id = :id", {"id": 123}
1045
+ ... )
1046
+ >>> if email is not None:
1047
+ ... print(email)
1048
+
1049
+ With type hint:
1050
+
1051
+ >>> count = await driver.select_value_or_none(
1052
+ ... "SELECT COUNT(*) FROM users WHERE active = true",
1053
+ ... value_type=int,
1054
+ ... )
1055
+ >>> if count is not None and count > 0:
1056
+ ... print(f"Found {count} active users")
1057
+ """
1058
+ result = await self.execute(statement, *parameters, statement_config=statement_config, **kwargs)
1059
+ value = result.scalar_or_none()
1060
+
1061
+ if value is None:
1062
+ return None
1063
+ if value_type is not None:
1064
+ return to_value_type(value, value_type)
1065
+ return value
1066
+
1067
+ @overload
1068
+ async def fetch_value_or_none(
1069
+ self,
1070
+ statement: "Statement | QueryBuilder",
1071
+ /,
1072
+ *parameters: "StatementParameters | StatementFilter",
1073
+ value_type: "type[ValueT]",
1074
+ statement_config: "StatementConfig | None" = None,
1075
+ **kwargs: Any,
1076
+ ) -> "ValueT | None": ...
1077
+
1078
+ @overload
1079
+ async def fetch_value_or_none(
1080
+ self,
1081
+ statement: "Statement | QueryBuilder",
1082
+ /,
1083
+ *parameters: "StatementParameters | StatementFilter",
1084
+ value_type: None = None,
1085
+ statement_config: "StatementConfig | None" = None,
1086
+ **kwargs: Any,
1087
+ ) -> Any: ...
1088
+
1089
+ async def fetch_value_or_none(
1090
+ self,
1091
+ statement: "Statement | QueryBuilder",
1092
+ /,
1093
+ *parameters: "StatementParameters | StatementFilter",
1094
+ value_type: "type[ValueT] | None" = None,
1095
+ statement_config: "StatementConfig | None" = None,
1096
+ **kwargs: Any,
1097
+ ) -> "ValueT | None | Any":
1098
+ """Execute a select statement and return a single scalar value or None.
1099
+
1100
+ This is an alias for :meth:`select_value_or_none` provided for users familiar
1101
+ with asyncpg's fetch_value_or_none() naming convention.
1102
+
1103
+ Returns None if no rows are found.
1104
+ Expects at most one row with one column.
1105
+ Raises an exception if more than one row is returned.
1106
+
1107
+ See Also:
1108
+ select_value_or_none(): Primary method with identical behavior
1109
+
1110
+ """
1111
+ return await self.select_value_or_none(
1112
+ statement, *parameters, value_type=value_type, statement_config=statement_config, **kwargs
1113
+ )
1114
+
1115
+ @overload
1116
+ async def select_with_total(
1117
+ self,
1118
+ statement: "Statement | QueryBuilder",
1119
+ /,
1120
+ *parameters: "StatementParameters | StatementFilter",
1121
+ schema_type: "type[SchemaT]",
1122
+ statement_config: "StatementConfig | None" = None,
1123
+ count_with_window: bool = False,
1124
+ **kwargs: Any,
1125
+ ) -> "tuple[list[SchemaT], int]": ...
1126
+
1127
+ @overload
1128
+ async def select_with_total(
1129
+ self,
1130
+ statement: "Statement | QueryBuilder",
1131
+ /,
1132
+ *parameters: "StatementParameters | StatementFilter",
1133
+ schema_type: None = None,
1134
+ statement_config: "StatementConfig | None" = None,
1135
+ count_with_window: bool = False,
1136
+ **kwargs: Any,
1137
+ ) -> "tuple[list[dict[str, Any]], int]": ...
1138
+
1139
+ async def select_with_total(
1140
+ self,
1141
+ statement: "Statement | QueryBuilder",
1142
+ /,
1143
+ *parameters: "StatementParameters | StatementFilter",
1144
+ schema_type: "type[SchemaT] | None" = None,
1145
+ statement_config: "StatementConfig | None" = None,
1146
+ count_with_window: bool = False,
1147
+ **kwargs: Any,
1148
+ ) -> "tuple[list[SchemaT] | list[dict[str, Any]], int]":
1149
+ """Execute a select statement and return both the data and total count.
1150
+
1151
+ This method is designed for pagination scenarios where you need both
1152
+ the current page of data and the total number of rows that match the query.
1153
+
1154
+ Args:
1155
+ statement: The SQL statement, QueryBuilder, or raw SQL string
1156
+ *parameters: Parameters for the SQL statement
1157
+ schema_type: Optional schema type for data transformation
1158
+ statement_config: Optional SQL configuration
1159
+ count_with_window: If True, use a single query with COUNT(*) OVER() window
1160
+ function instead of two separate queries. This can be more efficient
1161
+ for some databases but adds a column to each row. Default False.
1162
+ **kwargs: Additional keyword arguments
1163
+
1164
+ Returns:
1165
+ A tuple containing:
1166
+ - List of data rows (transformed by schema_type if provided)
1167
+ - Total count of rows matching the query (ignoring LIMIT/OFFSET)
1168
+
1169
+ Example:
1170
+ >>> # Two-query approach (default):
1171
+ >>> data, total = await driver.select_with_total(
1172
+ ... sql
1173
+ ... .select("*")
1174
+ ... .from_("users")
1175
+ ... .where_eq("status", "active")
1176
+ ... .limit(10)
1177
+ ... )
1178
+
1179
+ >>> # Single-query with window function:
1180
+ >>> data, total = await driver.select_with_total(
1181
+ ... sql
1182
+ ... .select("*")
1183
+ ... .from_("users")
1184
+ ... .where_eq("status", "active")
1185
+ ... .limit(10),
1186
+ ... count_with_window=True,
1187
+ ... )
1188
+
1189
+ """
1190
+ sql_statement = self.prepare_statement(
1191
+ statement, parameters, statement_config=statement_config or self.statement_config, kwargs=kwargs
1192
+ )
1193
+
1194
+ if count_with_window:
1195
+ modified_sql = self._add_count_over_column(sql_statement)
1196
+ result = await self.dispatch_statement_execution(modified_sql, self.connection)
1197
+ rows = result.all()
1198
+ data, total = self._extract_total_from_rows(rows)
1199
+
1200
+ if schema_type is not None:
1201
+ return ([schema_type(**r) for r in data], total)
1202
+ return (data, total)
1203
+
1204
+ count_result = await self.dispatch_statement_execution(self._create_count_query(sql_statement), self.connection)
1205
+ select_result = await self.dispatch_statement_execution(sql_statement, self.connection)
1206
+
1207
+ return (select_result.get_data(schema_type=schema_type), count_result.scalar())
1208
+
1209
+ @overload
1210
+ async def fetch_with_total(
1211
+ self,
1212
+ statement: "Statement | QueryBuilder",
1213
+ /,
1214
+ *parameters: "StatementParameters | StatementFilter",
1215
+ schema_type: "type[SchemaT]",
1216
+ statement_config: "StatementConfig | None" = None,
1217
+ count_with_window: bool = False,
1218
+ **kwargs: Any,
1219
+ ) -> "tuple[list[SchemaT], int]": ...
1220
+
1221
+ @overload
1222
+ async def fetch_with_total(
1223
+ self,
1224
+ statement: "Statement | QueryBuilder",
1225
+ /,
1226
+ *parameters: "StatementParameters | StatementFilter",
1227
+ schema_type: None = None,
1228
+ statement_config: "StatementConfig | None" = None,
1229
+ count_with_window: bool = False,
1230
+ **kwargs: Any,
1231
+ ) -> "tuple[list[dict[str, Any]], int]": ...
1232
+
1233
+ async def fetch_with_total(
1234
+ self,
1235
+ statement: "Statement | QueryBuilder",
1236
+ /,
1237
+ *parameters: "StatementParameters | StatementFilter",
1238
+ schema_type: "type[SchemaT] | None" = None,
1239
+ statement_config: "StatementConfig | None" = None,
1240
+ count_with_window: bool = False,
1241
+ **kwargs: Any,
1242
+ ) -> "tuple[list[SchemaT] | list[dict[str, Any]], int]":
1243
+ """Execute a select statement and return both the data and total count.
1244
+
1245
+ This is an alias for :meth:`select_with_total` provided for users familiar
1246
+ with asyncpg's fetch() naming convention.
1247
+
1248
+ This method is designed for pagination scenarios where you need both
1249
+ the current page of data and the total number of rows that match the query.
1250
+
1251
+ See Also:
1252
+ select_with_total(): Primary method with identical behavior and full documentation
1253
+
1254
+ """
1255
+ return await self.select_with_total(
1256
+ statement,
1257
+ *parameters,
1258
+ schema_type=schema_type,
1259
+ statement_config=statement_config,
1260
+ count_with_window=count_with_window,
1261
+ **kwargs,
1262
+ )
1263
+
1264
+ # ─────────────────────────────────────────────────────────────────────────────
1265
+ # ARROW API METHODS
1266
+ # ─────────────────────────────────────────────────────────────────────────────
1267
+
1268
+ async def select_to_arrow(
1269
+ self,
1270
+ statement: "Statement | QueryBuilder",
1271
+ /,
1272
+ *parameters: "StatementParameters | StatementFilter",
1273
+ statement_config: "StatementConfig | None" = None,
1274
+ return_format: "ArrowReturnFormat" = "table",
1275
+ native_only: bool = False,
1276
+ batch_size: int | None = None,
1277
+ arrow_schema: Any = None,
1278
+ **kwargs: Any,
1279
+ ) -> "ArrowResult":
1280
+ """Execute query and return results as Apache Arrow format (async).
1281
+
1282
+ This base implementation uses the conversion path: execute() → dict → Arrow.
1283
+ Adapters with native Arrow support (ADBC, DuckDB, BigQuery) override this
1284
+ method to use zero-copy native paths for 5-10x performance improvement.
1285
+
1286
+ Args:
1287
+ statement: SQL query string, Statement, or QueryBuilder
1288
+ *parameters: Query parameters (same format as execute()/select())
1289
+ statement_config: Optional statement configuration override
1290
+ return_format: "table" for pyarrow.Table (default), "batch" for single RecordBatch,
1291
+ "batches" for iterator of RecordBatches, "reader" for RecordBatchReader
1292
+ native_only: If True, raise error if native Arrow unavailable (default: False)
1293
+ batch_size: Rows per batch for "batch"/"batches" format (default: None = all rows)
1294
+ arrow_schema: Optional pyarrow.Schema for type casting
1295
+ **kwargs: Additional keyword arguments
1296
+
1297
+ Returns:
1298
+ ArrowResult containing pyarrow.Table, RecordBatchReader, or RecordBatches
1299
+
1300
+ Raises:
1301
+ ImproperConfigurationError: If native_only=True and adapter doesn't support native Arrow
1302
+
1303
+ Examples:
1304
+ >>> result = await driver.select_to_arrow(
1305
+ ... "SELECT * FROM users WHERE age > ?", 18
1306
+ ... )
1307
+ >>> df = result.to_pandas()
1308
+ >>> print(df.head())
1309
+
1310
+ >>> # Force native Arrow path (raises error if unavailable)
1311
+ >>> result = await driver.select_to_arrow(
1312
+ ... "SELECT * FROM users", native_only=True
1313
+ ... )
1314
+
1315
+ """
1316
+ if native_only:
1317
+ msg = (
1318
+ f"Adapter '{self.__class__.__name__}' does not support native Arrow results. "
1319
+ f"Use native_only=False to allow conversion path, or switch to an adapter "
1320
+ f"with native Arrow support (ADBC, DuckDB, BigQuery)."
1321
+ )
1322
+ raise ImproperConfigurationError(msg)
1323
+
1324
+ result = await self.execute(statement, *parameters, statement_config=statement_config, **kwargs)
1325
+
1326
+ arrow_data = convert_dict_to_arrow_with_schema(
1327
+ result.get_data(), return_format=return_format, batch_size=batch_size, arrow_schema=arrow_schema
1328
+ )
1329
+ return create_arrow_result(
1330
+ statement=result.statement,
1331
+ data=arrow_data,
1332
+ rows_affected=result.rows_affected,
1333
+ last_inserted_id=result.last_inserted_id,
1334
+ execution_time=result.execution_time,
1335
+ metadata=result.metadata,
1336
+ )
1337
+
1338
+ async def fetch_to_arrow(
1339
+ self,
1340
+ statement: "Statement | QueryBuilder",
1341
+ /,
1342
+ *parameters: "StatementParameters | StatementFilter",
1343
+ statement_config: "StatementConfig | None" = None,
1344
+ return_format: "ArrowReturnFormat" = "table",
1345
+ native_only: bool = False,
1346
+ batch_size: int | None = None,
1347
+ arrow_schema: Any = None,
1348
+ **kwargs: Any,
1349
+ ) -> "ArrowResult":
1350
+ """Execute query and return results as Apache Arrow format (async).
1351
+
1352
+ This is an alias for :meth:`select_to_arrow` provided for users familiar
1353
+ with asyncpg's fetch() naming convention.
1354
+
1355
+ See Also:
1356
+ select_to_arrow(): Primary method with identical behavior and full documentation
1357
+
1358
+ """
1359
+ return await self.select_to_arrow(
1360
+ statement,
1361
+ *parameters,
1362
+ statement_config=statement_config,
1363
+ return_format=return_format,
1364
+ native_only=native_only,
1365
+ batch_size=batch_size,
1366
+ arrow_schema=arrow_schema,
1367
+ **kwargs,
1368
+ )
1369
+
1370
+ # ─────────────────────────────────────────────────────────────────────────────
1371
+ # STACK EXECUTION
1372
+ # ─────────────────────────────────────────────────────────────────────────────
1373
+
1374
+ async def execute_stack(
1375
+ self, stack: "StatementStack", *, continue_on_error: bool = False
1376
+ ) -> "tuple[StackResult, ...]":
1377
+ """Execute a StatementStack sequentially using the adapter's primitives."""
1378
+ if not isinstance(stack, StatementStack):
1379
+ msg = "execute_stack expects a StatementStack instance"
1380
+ raise TypeError(msg)
1381
+ if not stack:
1382
+ msg = "Cannot execute an empty StatementStack"
1383
+ raise ValueError(msg)
1384
+
1385
+ results: list[StackResult] = []
1386
+ single_transaction = not continue_on_error
1387
+
1388
+ with StackExecutionObserver(self, stack, continue_on_error, native_pipeline=False) as observer:
1389
+ started_transaction = False
1390
+
1391
+ try:
1392
+ if single_transaction and not self._connection_in_transaction():
1393
+ await self.begin()
1394
+ started_transaction = True
1395
+
1396
+ for index, operation in enumerate(stack.operations):
1397
+ try:
1398
+ result = await self._execute_stack_operation(operation)
1399
+ except Exception as exc: # pragma: no cover - exercised via tests
1400
+ stack_error = StackExecutionError(
1401
+ index,
1402
+ describe_stack_statement(operation.statement),
1403
+ exc,
1404
+ adapter=type(self).__name__,
1405
+ mode="continue-on-error" if continue_on_error else "fail-fast",
1406
+ )
1407
+
1408
+ if started_transaction and not continue_on_error:
1409
+ try:
1410
+ await self.rollback()
1411
+ except Exception as rollback_error: # pragma: no cover - diagnostics only
1412
+ logger.debug("Rollback after stack failure failed: %s", rollback_error)
1413
+ started_transaction = False
1414
+
1415
+ if continue_on_error:
1416
+ await self._rollback_after_stack_error_async()
1417
+ observer.record_operation_error(stack_error)
1418
+ results.append(StackResult.from_error(stack_error))
1419
+ continue
1420
+
1421
+ raise stack_error from exc
1422
+
1423
+ results.append(StackResult(result=result))
1424
+
1425
+ if continue_on_error:
1426
+ await self._commit_after_stack_operation_async()
1427
+
1428
+ if started_transaction:
1429
+ await self.commit()
1430
+ except Exception:
1431
+ if started_transaction:
1432
+ try:
1433
+ await self.rollback()
1434
+ except Exception as rollback_error: # pragma: no cover - diagnostics only
1435
+ logger.debug("Rollback after stack failure failed: %s", rollback_error)
1436
+ raise
1437
+
1438
+ return tuple(results)
1439
+
1440
+ # ─────────────────────────────────────────────────────────────────────────────
1441
+ # STORAGE API METHODS
1442
+ # ─────────────────────────────────────────────────────────────────────────────
1443
+
1444
+ async def select_to_storage(
1445
+ self,
1446
+ statement: "SQL | str",
1447
+ destination: "StorageDestination",
1448
+ /,
1449
+ *parameters: "StatementParameters | StatementFilter",
1450
+ statement_config: "StatementConfig | None" = None,
1451
+ partitioner: "dict[str, object] | None" = None,
1452
+ format_hint: "StorageFormat | None" = None,
1453
+ telemetry: "StorageTelemetry | None" = None,
1454
+ ) -> "StorageBridgeJob":
1455
+ """Stream a SELECT statement directly into storage.
1456
+
1457
+ Args:
1458
+ statement: SQL statement to execute.
1459
+ destination: Storage destination path.
1460
+ parameters: Query parameters.
1461
+ statement_config: Optional statement configuration.
1462
+ partitioner: Optional partitioner configuration.
1463
+ format_hint: Optional format hint for storage.
1464
+ telemetry: Optional telemetry dict to merge.
1465
+
1466
+ Returns:
1467
+ StorageBridgeJob with execution telemetry.
1468
+
1469
+ """
1470
+ self._raise_storage_not_implemented("select_to_storage")
1471
+ raise NotImplementedError
1472
+
1473
+ async def load_from_arrow(
1474
+ self,
1475
+ table: str,
1476
+ source: "ArrowResult | Any",
1477
+ *,
1478
+ partitioner: "dict[str, object] | None" = None,
1479
+ overwrite: bool = False,
1480
+ ) -> "StorageBridgeJob":
1481
+ """Load Arrow data into the target table.
1482
+
1483
+ Args:
1484
+ table: Target table name.
1485
+ source: Arrow data source.
1486
+ partitioner: Optional partitioner configuration.
1487
+ overwrite: Whether to overwrite existing data.
1488
+
1489
+ Returns:
1490
+ StorageBridgeJob with execution telemetry.
1491
+
1492
+ Raises:
1493
+ NotImplementedError: If not implemented.
1494
+
1495
+ """
1496
+ self._raise_storage_not_implemented("load_from_arrow")
1497
+ raise NotImplementedError
1498
+
1499
+ async def load_from_storage(
1500
+ self,
1501
+ table: str,
1502
+ source: "StorageDestination",
1503
+ *,
1504
+ file_format: "StorageFormat",
1505
+ partitioner: "dict[str, object] | None" = None,
1506
+ overwrite: bool = False,
1507
+ ) -> "StorageBridgeJob":
1508
+ """Load artifacts from storage into the target table.
1509
+
1510
+ Args:
1511
+ table: Target table name.
1512
+ source: Storage source path.
1513
+ file_format: File format of source.
1514
+ partitioner: Optional partitioner configuration.
1515
+ overwrite: Whether to overwrite existing data.
1516
+
1517
+ Returns:
1518
+ StorageBridgeJob with execution telemetry.
1519
+
1520
+ """
1521
+ self._raise_storage_not_implemented("load_from_storage")
1522
+ raise NotImplementedError
1523
+
1524
+ def stage_artifact(self, request: "dict[str, Any]") -> "dict[str, Any]":
1525
+ """Provision staging metadata for adapters that require remote URIs.
1526
+
1527
+ Args:
1528
+ request: Staging request configuration.
1529
+
1530
+ Returns:
1531
+ Staging metadata dict.
1532
+
1533
+ """
1534
+ self._raise_storage_not_implemented("stage_artifact")
1535
+ raise NotImplementedError
1536
+
1537
+ def flush_staging_artifacts(self, artifacts: "list[dict[str, Any]]", *, error: Exception | None = None) -> None:
1538
+ """Clean up staged artifacts after a job completes.
1539
+
1540
+ Args:
1541
+ artifacts: List of staging artifacts to clean up.
1542
+ error: Optional error that triggered cleanup.
1543
+
1544
+ """
1545
+ if artifacts:
1546
+ self._raise_storage_not_implemented("flush_staging_artifacts")
1547
+
1548
+ def get_storage_job(self, job_id: str) -> "StorageBridgeJob | None":
1549
+ """Fetch a previously created job handle.
1550
+
1551
+ Args:
1552
+ job_id: Job identifier.
1553
+
1554
+ Returns:
1555
+ StorageBridgeJob if found, None otherwise.
1556
+
1557
+ """
1558
+ return None
1559
+
1560
+ # ─────────────────────────────────────────────────────────────────────────────
1561
+ # UTILITY METHODS
1562
+ # ─────────────────────────────────────────────────────────────────────────────
1563
+
1564
+ def convert_to_dialect(
1565
+ self, statement: "Statement", to_dialect: "DialectType | None" = None, pretty: bool = DEFAULT_PRETTY
1566
+ ) -> str:
1567
+ """Convert a statement to a target SQL dialect.
1568
+
1569
+ Args:
1570
+ statement: SQL statement to convert.
1571
+ to_dialect: Target dialect (defaults to current dialect).
1572
+ pretty: Whether to format the output SQL.
1573
+
1574
+ Returns:
1575
+ SQL string in target dialect.
1576
+
1577
+ """
1578
+ return _convert_to_dialect_impl(statement, self.dialect, to_dialect, pretty)
1579
+
1580
+ # ─────────────────────────────────────────────────────────────────────────────
1581
+ # PRIVATE/INTERNAL METHODS
1582
+ # ─────────────────────────────────────────────────────────────────────────────
1583
+
1584
+ def _connection_in_transaction(self) -> bool:
1585
+ """Check if the connection is inside a transaction.
1586
+
1587
+ Each adapter MUST override this method with direct attribute access
1588
+ for optimal mypyc performance. Do not use getattr chains.
1589
+
1590
+ Raises:
1591
+ NotImplementedError: Always - subclasses must override.
1592
+
1593
+ """
1594
+ msg = "Adapters must override _connection_in_transaction()"
1595
+ raise NotImplementedError(msg)
1596
+
1597
+ async def _execute_stack_operation(self, operation: "StackOperation") -> "SQLResult | ArrowResult | None":
1598
+ kwargs = dict(operation.keyword_arguments) if operation.keyword_arguments else {}
1599
+
1600
+ if operation.method == "execute":
1601
+ return await self.execute(operation.statement, *operation.arguments, **kwargs)
1602
+
1603
+ if operation.method == "execute_many":
1604
+ if not operation.arguments:
1605
+ msg = "execute_many stack operation requires parameter sets"
1606
+ raise ValueError(msg)
1607
+ parameter_sets = operation.arguments[0]
1608
+ filters = operation.arguments[1:]
1609
+ return await self.execute_many(operation.statement, parameter_sets, *filters, **kwargs)
1610
+
1611
+ if operation.method == "execute_script":
1612
+ return await self.execute_script(operation.statement, *operation.arguments, **kwargs)
1613
+
1614
+ if operation.method == "execute_arrow":
1615
+ return await self.select_to_arrow(operation.statement, *operation.arguments, **kwargs)
1616
+
1617
+ msg = f"Unsupported stack operation method: {operation.method}"
1618
+ raise ValueError(msg)
1619
+
1620
+ async def _rollback_after_stack_error_async(self) -> None:
1621
+ """Attempt to rollback after a stack operation error (async)."""
1622
+ try:
1623
+ await self.rollback()
1624
+ except Exception as rollback_error: # pragma: no cover - driver-specific cleanup
1625
+ logger.debug("Rollback after stack error failed: %s", rollback_error)
1626
+
1627
+ async def _commit_after_stack_operation_async(self) -> None:
1628
+ """Attempt to commit after a successful stack operation when not batching (async)."""
1629
+ try:
1630
+ await self.commit()
1631
+ except Exception as commit_error: # pragma: no cover - driver-specific cleanup
1632
+ logger.debug("Commit after stack operation failed: %s", commit_error)
1633
+
1634
+ def _storage_pipeline(self) -> "AsyncStoragePipeline":
1635
+ """Get or create an async storage pipeline.
1636
+
1637
+ Returns:
1638
+ AsyncStoragePipeline instance.
1639
+
1640
+ """
1641
+ factory = self.storage_pipeline_factory
1642
+ if factory is None:
1643
+ return AsyncStoragePipeline()
1644
+ return cast("AsyncStoragePipeline", factory())
1645
+
1646
+ async def _write_result_to_storage_async(
1647
+ self,
1648
+ result: "ArrowResult",
1649
+ destination: "StorageDestination",
1650
+ *,
1651
+ format_hint: "StorageFormat | None" = None,
1652
+ storage_options: "dict[str, Any] | None" = None,
1653
+ pipeline: "AsyncStoragePipeline | None" = None,
1654
+ ) -> "StorageTelemetry":
1655
+ """Write Arrow result to storage with telemetry.
1656
+
1657
+ Args:
1658
+ result: Arrow result to write.
1659
+ destination: Storage destination.
1660
+ format_hint: Optional format hint.
1661
+ storage_options: Optional storage options.
1662
+ pipeline: Optional storage pipeline.
1663
+
1664
+ Returns:
1665
+ StorageTelemetry with write metrics.
1666
+
1667
+ """
1668
+ runtime = self.observability
1669
+ span = runtime.start_storage_span(
1670
+ "write", destination=stringify_storage_target(destination), format_label=format_hint
1671
+ )
1672
+ try:
1673
+ telemetry = await result.write_to_storage_async(
1674
+ destination, format_hint=format_hint, storage_options=storage_options, pipeline=pipeline
1675
+ )
1676
+ except Exception as exc:
1677
+ runtime.end_storage_span(span, error=exc)
1678
+ raise
1679
+ telemetry = runtime.annotate_storage_telemetry(telemetry)
1680
+ runtime.end_storage_span(span, telemetry=telemetry)
1681
+ return telemetry
1682
+
1683
+ async def _read_arrow_from_storage_async(
1684
+ self,
1685
+ source: "StorageDestination",
1686
+ *,
1687
+ file_format: "StorageFormat",
1688
+ storage_options: "dict[str, Any] | None" = None,
1689
+ ) -> "tuple[ArrowTable, StorageTelemetry]":
1690
+ """Read Arrow table from storage with telemetry.
1691
+
1692
+ Args:
1693
+ source: Storage source path.
1694
+ file_format: File format to read.
1695
+ storage_options: Optional storage options.
1696
+
1697
+ Returns:
1698
+ Tuple of (ArrowTable, StorageTelemetry).
1699
+
1700
+ """
1701
+ runtime = self.observability
1702
+ span = runtime.start_storage_span(
1703
+ "read", destination=stringify_storage_target(source), format_label=file_format
1704
+ )
1705
+ pipeline = self._storage_pipeline()
1706
+ try:
1707
+ table, telemetry = await pipeline.read_arrow_async(
1708
+ source, file_format=file_format, storage_options=storage_options
1709
+ )
1710
+ except Exception as exc:
1711
+ runtime.end_storage_span(span, error=exc)
1712
+ raise
1713
+ telemetry = runtime.annotate_storage_telemetry(telemetry)
1714
+ runtime.end_storage_span(span, telemetry=telemetry)
1715
+ return table, telemetry
1716
+
1717
+
1718
+ @mypyc_attr(allow_interpreted_subclasses=True)
1719
+ class AsyncDataDictionaryBase(DataDictionaryDialectMixin, DataDictionaryMixin):
1720
+ """Base class for asynchronous data dictionary implementations.
1721
+
1722
+ Uses Python-compatible class layouts for cross-module inheritance.
1723
+ Child classes define dialect as a class attribute.
1724
+ """
1725
+
1726
+ dialect: "ClassVar[str]"
1727
+ """Dialect identifier. Must be defined by subclasses as a class attribute."""
1728
+
1729
+ def __init__(self) -> None:
1730
+ self._version_cache: dict[int, VersionInfo | None] = {}
1731
+ self._version_fetch_attempted: set[int] = set()
1732
+
1733
+ @abstractmethod
1734
+ async def get_version(self, driver: Any) -> "VersionInfo | None":
1735
+ """Get database version information.
1736
+
1737
+ Args:
1738
+ driver: Async database driver instance
1739
+
1740
+ Returns:
1741
+ Version information or None if detection fails
1742
+
1743
+ """
1744
+
1745
+ @abstractmethod
1746
+ async def get_feature_flag(self, driver: Any, feature: str) -> bool:
1747
+ """Check if database supports a specific feature.
1748
+
1749
+ Args:
1750
+ driver: Async database driver instance
1751
+ feature: Feature name to check
1752
+
1753
+ Returns:
1754
+ True if feature is supported, False otherwise
1755
+
1756
+ """
1757
+
1758
+ @abstractmethod
1759
+ async def get_optimal_type(self, driver: Any, type_category: str) -> str:
1760
+ """Get optimal database type for a category.
1761
+
1762
+ Args:
1763
+ driver: Async database driver instance
1764
+ type_category: Type category (e.g., 'json', 'uuid', 'boolean')
1765
+
1766
+ Returns:
1767
+ Database-specific type name
1768
+
1769
+ """
1770
+
1771
+ @abstractmethod
1772
+ async def get_tables(self, driver: Any, schema: "str | None" = None) -> "list[TableMetadata]":
1773
+ """Get list of tables in schema.
1774
+
1775
+ Args:
1776
+ driver: Async database driver instance
1777
+ schema: Schema name (None for default)
1778
+
1779
+ Returns:
1780
+ List of table metadata dictionaries
1781
+
1782
+ """
1783
+
1784
+ @abstractmethod
1785
+ async def get_columns(
1786
+ self, driver: Any, table: "str | None" = None, schema: "str | None" = None
1787
+ ) -> "list[ColumnMetadata]":
1788
+ """Get column information for a table or schema.
1789
+
1790
+ Args:
1791
+ driver: Async database driver instance
1792
+ table: Table name (None to fetch columns for all tables in schema)
1793
+ schema: Schema name (None for default)
1794
+
1795
+ Returns:
1796
+ List of column metadata dictionaries
1797
+
1798
+ """
1799
+
1800
+ @abstractmethod
1801
+ async def get_indexes(
1802
+ self, driver: Any, table: "str | None" = None, schema: "str | None" = None
1803
+ ) -> "list[IndexMetadata]":
1804
+ """Get index information for a table or schema.
1805
+
1806
+ Args:
1807
+ driver: Async database driver instance
1808
+ table: Table name (None to fetch indexes for all tables in schema)
1809
+ schema: Schema name (None for default)
1810
+
1811
+ Returns:
1812
+ List of index metadata dictionaries
1813
+
1814
+ """
1815
+
1816
+ @abstractmethod
1817
+ async def get_foreign_keys(
1818
+ self, driver: Any, table: "str | None" = None, schema: "str | None" = None
1819
+ ) -> "list[ForeignKeyMetadata]":
1820
+ """Get foreign key metadata.
1821
+
1822
+ Args:
1823
+ driver: Async database driver instance
1824
+ table: Optional table name filter
1825
+ schema: Optional schema name filter
1826
+
1827
+ Returns:
1828
+ List of foreign key metadata
1829
+
1830
+ """