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