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,1090 @@
1
+ """SQL compilation and caching.
2
+
3
+ Components:
4
+ - CompiledSQL: Immutable compilation result
5
+ - SQLProcessor: SQL compiler with caching
6
+ - Parameter processing via ParameterProcessor
7
+ """
8
+
9
+ import logging
10
+ from collections import OrderedDict
11
+ from collections.abc import Mapping
12
+ from typing import TYPE_CHECKING, Any, Literal
13
+
14
+ import sqlglot
15
+ from mypy_extensions import mypyc_attr
16
+ from sqlglot import expressions as exp
17
+ from sqlglot.errors import ParseError
18
+
19
+ import sqlspec.exceptions
20
+ from sqlspec.core.parameters import (
21
+ ParameterProcessor,
22
+ ParameterProfile,
23
+ structural_fingerprint,
24
+ validate_parameter_alignment,
25
+ value_fingerprint,
26
+ )
27
+ from sqlspec.core.parameters._processor import _make_cache_key_tuple
28
+ from sqlspec.utils.logging import get_logger, log_with_context
29
+ from sqlspec.utils.type_guards import get_value_attribute
30
+
31
+ if TYPE_CHECKING:
32
+ from sqlspec.core.statement import StatementConfig
33
+
34
+
35
+ __all__ = (
36
+ "CompiledSQL",
37
+ "OperationProfile",
38
+ "OperationType",
39
+ "SQLProcessor",
40
+ "is_copy_from_operation",
41
+ "is_copy_operation",
42
+ "is_copy_to_operation",
43
+ )
44
+
45
+ logger: "logging.Logger" = get_logger("sqlspec.core.compiler")
46
+ OperationType = Literal[
47
+ "SELECT",
48
+ "INSERT",
49
+ "UPDATE",
50
+ "DELETE",
51
+ "COPY",
52
+ "COPY_FROM",
53
+ "COPY_TO",
54
+ "EXECUTE",
55
+ "SCRIPT",
56
+ "DDL",
57
+ "PRAGMA",
58
+ "MERGE",
59
+ "COMMAND",
60
+ "UNKNOWN",
61
+ ]
62
+
63
+ OPERATION_TYPE_MAP: "dict[type[exp.Expr], OperationType]" = {
64
+ # Queries
65
+ exp.Select: "SELECT",
66
+ exp.Union: "SELECT",
67
+ exp.Except: "SELECT",
68
+ exp.Intersect: "SELECT",
69
+ exp.Summarize: "SELECT", # DuckDB SUMMARIZE — returns rows
70
+ # DML
71
+ exp.Insert: "INSERT",
72
+ exp.Update: "UPDATE",
73
+ exp.Delete: "DELETE",
74
+ exp.Merge: "MERGE",
75
+ exp.LoadData: "INSERT", # Hive LOAD DATA — ingests data into a table
76
+ # DDL
77
+ exp.Create: "DDL",
78
+ exp.Drop: "DDL",
79
+ exp.Alter: "DDL",
80
+ exp.TruncateTable: "DDL",
81
+ exp.Grant: "DDL",
82
+ exp.Revoke: "DDL",
83
+ exp.Comment: "DDL",
84
+ # Procedure execution
85
+ exp.Execute: "EXECUTE", # TSQL EXEC/EXECUTE
86
+ # Session / Admin
87
+ exp.Pragma: "PRAGMA",
88
+ exp.Command: "COMMAND",
89
+ exp.Set: "COMMAND",
90
+ exp.Show: "COMMAND", # MySQL dialect
91
+ exp.Describe: "COMMAND",
92
+ exp.Use: "COMMAND",
93
+ exp.Kill: "COMMAND",
94
+ exp.Analyze: "COMMAND",
95
+ exp.Install: "COMMAND", # DuckDB
96
+ exp.Attach: "COMMAND", # DuckDB / SQLite
97
+ # Transaction control — mapped to COMMAND for now; a dedicated "TRANSACTION"
98
+ # OperationType could be added if downstream code needs to distinguish these.
99
+ exp.Transaction: "COMMAND",
100
+ exp.Commit: "COMMAND",
101
+ exp.Rollback: "COMMAND",
102
+ }
103
+
104
+ COPY_OPERATION_TYPES: "tuple[OperationType, ...]" = ("COPY", "COPY_FROM", "COPY_TO")
105
+
106
+ COPY_FROM_OPERATION_TYPES: "tuple[OperationType, ...]" = ("COPY", "COPY_FROM")
107
+
108
+ COPY_TO_OPERATION_TYPES: "tuple[OperationType, ...]" = ("COPY_TO",)
109
+
110
+ ParseCacheEntry = tuple[exp.Expr | None, OperationType, dict[int, str], tuple[bool, bool]]
111
+
112
+
113
+ def is_copy_operation(operation_type: "OperationType") -> bool:
114
+ """Determine if the operation corresponds to any PostgreSQL COPY variant.
115
+
116
+ Args:
117
+ operation_type: Operation type detected by the compiler.
118
+
119
+ Returns:
120
+ True when the operation type represents COPY, COPY FROM, or COPY TO.
121
+ """
122
+
123
+ return operation_type in COPY_OPERATION_TYPES
124
+
125
+
126
+ def is_copy_from_operation(operation_type: "OperationType") -> bool:
127
+ """Check if the operation streams data into the database using COPY.
128
+
129
+ Args:
130
+ operation_type: Operation type detected by the compiler.
131
+
132
+ Returns:
133
+ True for COPY operations that read from client input (COPY FROM).
134
+ """
135
+
136
+ return operation_type in COPY_FROM_OPERATION_TYPES
137
+
138
+
139
+ def is_copy_to_operation(operation_type: "OperationType") -> bool:
140
+ """Check if the operation streams data out from the database using COPY.
141
+
142
+ Args:
143
+ operation_type: Operation type detected by the compiler.
144
+
145
+ Returns:
146
+ True for COPY operations that write to client output (COPY TO).
147
+ """
148
+
149
+ return operation_type in COPY_TO_OPERATION_TYPES
150
+
151
+
152
+ def _assign_placeholder_position(
153
+ placeholder: "exp.Placeholder", placeholder_positions: "dict[str, int]", placeholder_counter: "list[int]"
154
+ ) -> "int | None":
155
+ name_expr = placeholder.name if placeholder.name is not None else None
156
+ if name_expr is not None:
157
+ placeholder_key = str(name_expr)
158
+ else:
159
+ value = placeholder.args.get("this")
160
+ placeholder_key = str(value) if value is not None else placeholder.sql()
161
+
162
+ if not placeholder_key:
163
+ return None
164
+
165
+ if placeholder_key not in placeholder_positions:
166
+ placeholder_counter[0] += 1
167
+ placeholder_positions[placeholder_key] = placeholder_counter[0]
168
+
169
+ return placeholder_positions[placeholder_key]
170
+
171
+
172
+ @mypyc_attr(allow_interpreted_subclasses=False)
173
+ class OperationProfile:
174
+ """Semantic characteristics derived from the parsed SQL expression."""
175
+
176
+ __slots__ = ("modifies_rows", "returns_rows")
177
+
178
+ def __init__(self, returns_rows: bool = False, modifies_rows: bool = False) -> None:
179
+ self.returns_rows = returns_rows
180
+ self.modifies_rows = modifies_rows
181
+
182
+ @classmethod
183
+ def empty(cls) -> "OperationProfile":
184
+ return cls(returns_rows=False, modifies_rows=False)
185
+
186
+ def __repr__(self) -> str:
187
+ return f"OperationProfile(returns_rows={self.returns_rows!r}, modifies_rows={self.modifies_rows!r})"
188
+
189
+
190
+ def _is_effectively_empty_parameters(value: Any) -> bool:
191
+ if value is None:
192
+ return True
193
+ # Fast type dispatch: check concrete types first (2-4x faster than ABC isinstance)
194
+ value_type = type(value)
195
+ if value_type is dict or value_type is list or value_type is tuple:
196
+ return len(value) == 0
197
+ if value_type is set or value_type is frozenset:
198
+ return len(value) == 0
199
+ # Fallback to ABC check for custom Mapping types
200
+ if isinstance(value, Mapping):
201
+ return len(value) == 0
202
+ return False
203
+
204
+
205
+ @mypyc_attr(allow_interpreted_subclasses=False)
206
+ class CompiledSQL:
207
+ """Compiled SQL result.
208
+
209
+ Contains the result of SQL compilation with information needed for execution.
210
+ Immutable container holding compiled SQL text, processed parameters, operation
211
+ type, and execution metadata.
212
+ """
213
+
214
+ __slots__ = (
215
+ "_hash",
216
+ "applied_wrap_types",
217
+ "compiled_sql",
218
+ "execution_parameters",
219
+ "expression",
220
+ "input_named_parameters",
221
+ "operation_profile",
222
+ "operation_type",
223
+ "parameter_casts",
224
+ "parameter_profile",
225
+ "parameter_style",
226
+ "supports_many",
227
+ )
228
+
229
+ operation_type: "OperationType"
230
+
231
+ def __init__(
232
+ self,
233
+ compiled_sql: str,
234
+ execution_parameters: Any,
235
+ operation_type: "OperationType",
236
+ expression: "exp.Expr | None" = None,
237
+ parameter_style: str | None = None,
238
+ supports_many: bool = False,
239
+ parameter_casts: "dict[int, str] | None" = None,
240
+ parameter_profile: "ParameterProfile | None" = None,
241
+ operation_profile: "OperationProfile | None" = None,
242
+ input_named_parameters: "tuple[str, ...]" = (),
243
+ applied_wrap_types: bool = False,
244
+ ) -> None:
245
+ """Initialize compiled result.
246
+
247
+ Args:
248
+ compiled_sql: SQL string ready for execution
249
+ execution_parameters: Parameters in driver-specific format
250
+ operation_type: SQL operation type (SELECT, INSERT, etc.)
251
+ expression: SQLGlot AST expression
252
+ parameter_style: Parameter style used in compilation
253
+ supports_many: Whether this supports execute_many operations
254
+ parameter_casts: Mapping of parameter positions to cast types
255
+ parameter_profile: Profile describing detected placeholders
256
+ operation_profile: Profile describing semantic characteristics
257
+ input_named_parameters: Original input named parameter order
258
+ applied_wrap_types: Whether type wrapping was applied
259
+ """
260
+ self.compiled_sql = compiled_sql
261
+ self.execution_parameters = execution_parameters
262
+ self.operation_type = operation_type
263
+ self.expression = expression
264
+ self.parameter_style = parameter_style
265
+ self.supports_many = supports_many
266
+ self.parameter_casts = parameter_casts or {}
267
+ self.parameter_profile = parameter_profile or ParameterProfile.empty()
268
+ self.operation_profile = operation_profile or OperationProfile.empty()
269
+ self.input_named_parameters = input_named_parameters
270
+ self.applied_wrap_types = applied_wrap_types
271
+ self._hash: int | None = None
272
+
273
+ def __hash__(self) -> int:
274
+ """Cached hash value."""
275
+ if self._hash is None:
276
+ param_str = str(self.execution_parameters)
277
+ self._hash = hash((self.compiled_sql, param_str, self.operation_type, self.parameter_style))
278
+ return self._hash
279
+
280
+ def __eq__(self, other: object) -> bool:
281
+ """Equality comparison."""
282
+ if not isinstance(other, CompiledSQL):
283
+ return False
284
+ return (
285
+ self.compiled_sql == other.compiled_sql
286
+ and self.execution_parameters == other.execution_parameters
287
+ and self.operation_type == other.operation_type
288
+ and self.parameter_style == other.parameter_style
289
+ )
290
+
291
+ def __repr__(self) -> str:
292
+ """String representation."""
293
+ return (
294
+ f"CompiledSQL(sql={self.compiled_sql!r}, "
295
+ f"params={self.execution_parameters!r}, "
296
+ f"type={self.operation_type!r})"
297
+ )
298
+
299
+
300
+ @mypyc_attr(allow_interpreted_subclasses=False)
301
+ class SQLProcessor:
302
+ """SQL processor with compilation and caching.
303
+
304
+ Processes SQL statements by compiling them into executable format with
305
+ parameter substitution. Includes LRU-style caching for compilation results
306
+ to avoid re-processing identical statements.
307
+ """
308
+
309
+ __slots__ = (
310
+ "_cache",
311
+ "_cache_enabled",
312
+ "_cache_hits",
313
+ "_cache_misses",
314
+ "_config",
315
+ "_dialect_str",
316
+ "_exec_style",
317
+ "_input_style",
318
+ "_last_cache_key",
319
+ "_last_result",
320
+ "_max_cache_size",
321
+ "_parameter_processor",
322
+ "_parse_cache",
323
+ "_parse_cache_hits",
324
+ "_parse_cache_max_size",
325
+ "_parse_cache_misses",
326
+ )
327
+
328
+ def __init__(
329
+ self,
330
+ config: "StatementConfig",
331
+ max_cache_size: int = 1000,
332
+ parse_cache_size: int | None = None,
333
+ parameter_cache_size: int | None = None,
334
+ validator_cache_size: int | None = None,
335
+ cache_enabled: bool = True,
336
+ ) -> None:
337
+ """Initialize processor.
338
+
339
+ Args:
340
+ config: Statement configuration
341
+ max_cache_size: Maximum number of compilation results to cache
342
+ parse_cache_size: Maximum number of parsed expressions to cache
343
+ parameter_cache_size: Maximum parameter conversion cache entries
344
+ validator_cache_size: Maximum cached parameter metadata entries
345
+ cache_enabled: Toggle compiled SQL caching (parse/parameter caches remain size-driven)
346
+ """
347
+ self._config = config
348
+ self._cache: OrderedDict[Any, CompiledSQL] = OrderedDict()
349
+ self._max_cache_size = max(max_cache_size, 0)
350
+ compiled_cache_active = cache_enabled and config.enable_caching and self._max_cache_size > 0
351
+ self._cache_enabled = compiled_cache_active
352
+ parse_cache_max_size = self._max_cache_size if parse_cache_size is None else parse_cache_size
353
+ self._parse_cache_max_size = max(parse_cache_max_size, 0)
354
+ if not config.enable_caching:
355
+ self._parse_cache_max_size = 0
356
+ parameter_cache = parameter_cache_size if parameter_cache_size is not None else self._parse_cache_max_size
357
+ validator_cache = validator_cache_size if validator_cache_size is not None else parameter_cache
358
+ if not config.enable_caching:
359
+ parameter_cache = 0
360
+ validator_cache = 0
361
+ self._parameter_processor = ParameterProcessor(
362
+ converter=config.parameter_converter,
363
+ validator=config.parameter_validator,
364
+ cache_max_size=parameter_cache,
365
+ validator_cache_max_size=validator_cache,
366
+ )
367
+ self._cache_hits = 0
368
+ self._cache_misses = 0
369
+ self._parse_cache: OrderedDict[
370
+ Any, tuple[exp.Expr | None, OperationType, dict[int, str], tuple[bool, bool]]
371
+ ] = OrderedDict()
372
+ self._parse_cache_hits = 0
373
+ self._parse_cache_misses = 0
374
+ self._last_cache_key: Any | None = None
375
+ self._last_result: CompiledSQL | None = None
376
+
377
+ # Pre-calculate static cache key components
378
+ self._dialect_str = str(config.dialect) if config.dialect else None
379
+ self._input_style = config.parameter_config.default_parameter_style.value
380
+ self._exec_style = (
381
+ config.parameter_config.default_execution_parameter_style.value
382
+ if config.parameter_config.default_execution_parameter_style
383
+ else self._input_style
384
+ )
385
+
386
+ def compile(
387
+ self, sql: str, parameters: Any = None, is_many: bool = False, expression: "exp.Expr | None" = None
388
+ ) -> CompiledSQL:
389
+ """Compile SQL statement.
390
+
391
+ Args:
392
+ sql: SQL string for compilation
393
+ parameters: Parameter values for substitution
394
+ is_many: Whether this is for execute_many operation
395
+ expression: Pre-parsed SQLGlot expression to reuse
396
+
397
+ Returns:
398
+ CompiledSQL with execution information
399
+ """
400
+ if not self._config.enable_caching or not self._cache_enabled:
401
+ return self._compile_uncached(sql, parameters, is_many, expression, param_fingerprint=None)
402
+
403
+ param_fingerprint = self._get_param_fingerprint(parameters, is_many)
404
+ cache_key = self._make_cache_key(sql, param_fingerprint, is_many)
405
+
406
+ # MICRO-CACHE: Fast path for repeating statements
407
+ if cache_key == self._last_cache_key and self._last_result is not None:
408
+ self._cache_hits += 1
409
+ return self._materialize_cached_result(self._last_result, parameters, is_many)
410
+
411
+ cached_result = self._cache.get(cache_key)
412
+ if cached_result is not None:
413
+ self._cache.move_to_end(cache_key)
414
+ self._cache_hits += 1
415
+
416
+ # Update micro-cache
417
+ self._last_cache_key = cache_key
418
+ self._last_result = cached_result
419
+ return self._materialize_cached_result(cached_result, parameters, is_many)
420
+
421
+ self._cache_misses += 1
422
+ result = self._compile_uncached(sql, parameters, is_many, expression, param_fingerprint=param_fingerprint)
423
+
424
+ if len(self._cache) >= self._max_cache_size:
425
+ self._cache.popitem(last=False)
426
+
427
+ self._cache[cache_key] = result
428
+ self._last_cache_key = cache_key
429
+ self._last_result = result
430
+ return result
431
+
432
+ def _materialize_cached_result(self, cached_result: CompiledSQL, parameters: Any, is_many: bool) -> CompiledSQL:
433
+ """Return cached compilation metadata with parameters for the current call."""
434
+ if self._config.parameter_config.needs_static_script_compilation:
435
+ return cached_result
436
+
437
+ # Structural fingerprinting means same SQL structure = same cache entry,
438
+ # but we must still process the caller's actual parameter values.
439
+ processed_params = self._parameter_processor._transform_cached_parameters( # pyright: ignore[reportPrivateUsage]
440
+ parameters,
441
+ cached_result.parameter_profile,
442
+ self._config.parameter_config,
443
+ input_named_parameters=cached_result.input_named_parameters,
444
+ is_many=is_many,
445
+ apply_wrap_types=cached_result.applied_wrap_types,
446
+ )
447
+
448
+ final_sql = cached_result.compiled_sql
449
+ output_transformer = self._config.output_transformer
450
+ if output_transformer:
451
+ final_sql, processed_params = output_transformer(final_sql, processed_params)
452
+
453
+ return CompiledSQL(
454
+ compiled_sql=final_sql,
455
+ execution_parameters=processed_params,
456
+ operation_type=cached_result.operation_type,
457
+ expression=cached_result.expression,
458
+ parameter_style=cached_result.parameter_style,
459
+ supports_many=cached_result.supports_many,
460
+ parameter_casts=cached_result.parameter_casts,
461
+ parameter_profile=cached_result.parameter_profile,
462
+ operation_profile=cached_result.operation_profile,
463
+ input_named_parameters=cached_result.input_named_parameters,
464
+ applied_wrap_types=cached_result.applied_wrap_types,
465
+ )
466
+
467
+ def _prepare_parameters(
468
+ self, sql: str, parameters: Any, is_many: bool, dialect_str: "str | None", *, param_fingerprint: Any | None
469
+ ) -> "tuple[str, Any, ParameterProfile, str, tuple[str, ...], bool]":
470
+ """Process SQL parameters for compilation.
471
+
472
+ Args:
473
+ sql: SQL string.
474
+ parameters: Raw parameters.
475
+ is_many: Whether this is for execute_many.
476
+ dialect_str: Dialect name.
477
+ param_fingerprint: Pre-computed parameter fingerprint for cache key.
478
+
479
+ Returns:
480
+ Tuple of processed SQL, processed parameters, parameter profile, SQLGlot SQL,
481
+ input named parameters, and applied wrap types flag.
482
+ """
483
+ process_result = self._parameter_processor.process(
484
+ sql=sql,
485
+ parameters=parameters,
486
+ config=self._config.parameter_config,
487
+ dialect=dialect_str,
488
+ is_many=is_many,
489
+ wrap_types=self._config.enable_parameter_type_wrapping,
490
+ param_fingerprint=param_fingerprint,
491
+ )
492
+ return (
493
+ process_result.sql,
494
+ process_result.parameters,
495
+ process_result.parameter_profile,
496
+ process_result.sqlglot_sql,
497
+ process_result.input_named_parameters,
498
+ process_result.applied_wrap_types,
499
+ )
500
+
501
+ def _normalize_expression_override(
502
+ self, expression_override: "exp.Expr | None", sqlglot_sql: str, sql: str
503
+ ) -> "exp.Expr | None":
504
+ """Validate expression overrides against the input SQL.
505
+
506
+ Args:
507
+ expression_override: Pre-parsed SQLGlot expression.
508
+ sqlglot_sql: SQL passed to SQLGlot.
509
+ sql: Original SQL string.
510
+
511
+ Returns:
512
+ Expression override when it is safe to reuse.
513
+ """
514
+ if expression_override is None:
515
+ return None
516
+ if sqlglot_sql != sql:
517
+ return None
518
+ return expression_override
519
+
520
+ def _parse_expression_uncached(
521
+ self, sqlglot_sql: str, dialect_str: "str | None", expression_override: "exp.Expr | None"
522
+ ) -> "tuple[exp.Expr | None, OperationType, dict[int, str], OperationProfile]":
523
+ """Parse SQL into an expression without cache.
524
+
525
+ Args:
526
+ sqlglot_sql: SQL string for SQLGlot.
527
+ dialect_str: Dialect name.
528
+ expression_override: Pre-parsed SQLGlot expression.
529
+
530
+ Returns:
531
+ Expression details and derived metadata.
532
+ """
533
+ try:
534
+ if expression_override is not None:
535
+ expression: exp.Expr = expression_override
536
+ else:
537
+ expression = sqlglot.parse_one(sqlglot_sql, dialect=dialect_str)
538
+ except ParseError:
539
+ return None, "COMMAND", {}, OperationProfile.empty()
540
+ else:
541
+ operation_type = self._detect_operation_type(expression)
542
+ parameter_casts = self._detect_parameter_casts(expression)
543
+ operation_profile = self._build_operation_profile(expression, operation_type)
544
+ return expression, operation_type, parameter_casts, operation_profile
545
+
546
+ def _store_parse_cache(
547
+ self,
548
+ parse_cache_key: Any,
549
+ expression: "exp.Expr | None",
550
+ operation_type: "OperationType",
551
+ parameter_casts: "dict[int, str]",
552
+ operation_profile: "OperationProfile",
553
+ ) -> None:
554
+ """Store parsed expression details in cache.
555
+
556
+ Args:
557
+ parse_cache_key: Cache key for the parsed SQL.
558
+ expression: Parsed SQLGlot expression.
559
+ operation_type: Detected operation type.
560
+ parameter_casts: Parameter cast mappings.
561
+ operation_profile: Operation metadata.
562
+ """
563
+ if len(self._parse_cache) >= self._parse_cache_max_size:
564
+ self._parse_cache.popitem(last=False)
565
+ # Store expression reference directly - _unpack_parse_cache_entry copies on retrieval
566
+ # so we avoid double-copying (store + retrieve)
567
+ self._parse_cache[parse_cache_key] = (
568
+ expression,
569
+ operation_type,
570
+ parameter_casts,
571
+ (operation_profile.returns_rows, operation_profile.modifies_rows),
572
+ )
573
+
574
+ def _unpack_parse_cache_entry(
575
+ self, parse_cache_entry: "ParseCacheEntry"
576
+ ) -> "tuple[exp.Expr | None, OperationType, dict[int, str], OperationProfile]":
577
+ """Expand cached parse results into runtime objects.
578
+
579
+ Args:
580
+ parse_cache_entry: Cached parse entry.
581
+
582
+ Returns:
583
+ Parsed expression metadata.
584
+ """
585
+ cached_expression, cached_operation, cached_casts, cached_profile = parse_cache_entry
586
+ # Return expression reference without copying - _apply_ast_transformers will copy
587
+ # if transformers are configured and will modify it. This avoids unnecessary copies
588
+ # when no transformers are active (common case).
589
+ operation_profile = OperationProfile(returns_rows=cached_profile[0], modifies_rows=cached_profile[1])
590
+ # cached_casts is already a dict, no need to copy - it's not mutated by callers
591
+ return cached_expression, cached_operation, cached_casts, operation_profile
592
+
593
+ def _resolve_expression(
594
+ self, sqlglot_sql: str, dialect_str: "str | None", expression_override: "exp.Expr | None"
595
+ ) -> "tuple[exp.Expr | None, OperationType, dict[int, str], OperationProfile, Any | None, ParseCacheEntry | None]":
596
+ """Resolve an SQLGlot expression with caching.
597
+
598
+ Args:
599
+ sqlglot_sql: SQL string for SQLGlot.
600
+ dialect_str: Dialect name.
601
+ expression_override: Pre-parsed SQLGlot expression.
602
+
603
+ Returns:
604
+ Expression metadata and parse cache information.
605
+ """
606
+ parse_cache_key = None
607
+ parse_cache_entry = None
608
+ if self._config.enable_caching and self._parse_cache_max_size > 0:
609
+ parse_cache_key = self._make_parse_cache_key(sqlglot_sql, dialect_str)
610
+ parse_cache_entry = self._parse_cache.get(parse_cache_key)
611
+ if parse_cache_entry is not None:
612
+ self._parse_cache_hits += 1
613
+ self._parse_cache.move_to_end(parse_cache_key)
614
+ if parse_cache_entry is None:
615
+ self._parse_cache_misses += 1
616
+ expression, operation_type, parameter_casts, operation_profile = self._parse_expression_uncached(
617
+ sqlglot_sql, dialect_str, expression_override
618
+ )
619
+ if parse_cache_key is not None:
620
+ self._store_parse_cache(parse_cache_key, expression, operation_type, parameter_casts, operation_profile)
621
+ else:
622
+ expression, operation_type, parameter_casts, operation_profile = self._unpack_parse_cache_entry(
623
+ parse_cache_entry
624
+ )
625
+ return expression, operation_type, parameter_casts, operation_profile, parse_cache_key, parse_cache_entry
626
+
627
+ def _apply_ast_transformers(
628
+ self,
629
+ expression: "exp.Expr | None",
630
+ parameters: Any,
631
+ parameter_profile: "ParameterProfile",
632
+ operation_type: "OperationType",
633
+ parameter_casts: "dict[int, str]",
634
+ operation_profile: "OperationProfile",
635
+ parse_cache_key: "Any | None",
636
+ parse_cache_entry: "ParseCacheEntry | None",
637
+ expression_override: "exp.Expr | None",
638
+ ) -> "tuple[exp.Expr | None, Any, bool, OperationType, dict[int, str], OperationProfile]":
639
+ """Apply AST transformers and update metadata.
640
+
641
+ Args:
642
+ expression: SQLGlot expression to transform.
643
+ parameters: Execution parameters.
644
+ parameter_profile: Parameter profile metadata.
645
+ operation_type: Current operation type.
646
+ parameter_casts: Current parameter cast mapping.
647
+ operation_profile: Current operation profile.
648
+ parse_cache_key: Parse cache key when used.
649
+ parse_cache_entry: Cached parse entry when available.
650
+ expression_override: Expression override reference.
651
+
652
+ Returns:
653
+ Updated expression metadata and transformation state.
654
+ """
655
+ statement_transformers = self._config.statement_transformers
656
+ ast_transformer = self._config.parameter_config.ast_transformer
657
+ if expression is None or (not statement_transformers and not ast_transformer):
658
+ return expression, parameters, False, operation_type, parameter_casts, operation_profile
659
+
660
+ # Must copy the expression before transformers modify it to avoid corrupting:
661
+ # 1. Cache entries (for both cache hits and misses that will be cached)
662
+ # 2. User-provided expression_override references
663
+ should_copy = False
664
+ if parse_cache_key is not None:
665
+ # Either cache miss (will be stored) or cache hit (reference from cache)
666
+ should_copy = True
667
+ if expression_override is not None and expression is expression_override:
668
+ should_copy = True
669
+ if should_copy:
670
+ expression = expression.copy()
671
+
672
+ ast_was_transformed = False
673
+ if statement_transformers:
674
+ for transformer in statement_transformers:
675
+ expression, parameters = transformer(expression, parameters)
676
+ ast_was_transformed = True
677
+ if ast_transformer:
678
+ expression, parameters = ast_transformer(expression, parameters, parameter_profile)
679
+ ast_was_transformed = True
680
+ if ast_was_transformed:
681
+ if expression is None:
682
+ return expression, parameters, ast_was_transformed, operation_type, parameter_casts, operation_profile
683
+ operation_type = self._detect_operation_type(expression)
684
+ parameter_casts = self._detect_parameter_casts(expression)
685
+ operation_profile = self._build_operation_profile(expression, operation_type)
686
+
687
+ return expression, parameters, ast_was_transformed, operation_type, parameter_casts, operation_profile
688
+
689
+ def _finalize_compilation(
690
+ self,
691
+ processed_sql: str,
692
+ processed_params: Any,
693
+ expression: "exp.Expr | None",
694
+ parameters: Any,
695
+ parameter_profile: "ParameterProfile",
696
+ is_many: bool,
697
+ dialect_str: "str | None",
698
+ ast_was_transformed: bool,
699
+ ) -> "tuple[str, Any, ParameterProfile, tuple[str, ...], bool]":
700
+ """Finalize SQL and parameter conversion for execution.
701
+
702
+ Args:
703
+ processed_sql: SQL after parameter processing.
704
+ processed_params: Parameters after initial processing.
705
+ expression: SQLGlot expression if available.
706
+ parameters: Parameters to compile for execution.
707
+ parameter_profile: Parameter profile metadata.
708
+ is_many: Whether this is for execute_many.
709
+ dialect_str: Dialect name.
710
+ ast_was_transformed: Whether AST transformations ran.
711
+
712
+ Returns:
713
+ Final SQL, execution parameters, parameter profile, input named parameters,
714
+ and applied wrap types flag.
715
+ """
716
+ if self._config.parameter_config.needs_static_script_compilation and processed_params is None:
717
+ return processed_sql, processed_params, parameter_profile, (), False
718
+ if ast_was_transformed and expression is not None:
719
+ # Pass the transformed expression through the pipeline to avoid re-parsing
720
+ transformed_result = self._parameter_processor.process_for_execution(
721
+ sql=expression.sql(dialect=dialect_str),
722
+ parameters=parameters,
723
+ config=self._config.parameter_config,
724
+ dialect=dialect_str,
725
+ is_many=is_many,
726
+ wrap_types=self._config.enable_parameter_type_wrapping,
727
+ parsed_expression=expression,
728
+ )
729
+ final_sql = transformed_result.sql
730
+ final_params = transformed_result.parameters
731
+ parameter_profile = transformed_result.parameter_profile
732
+ output_transformer = self._config.output_transformer
733
+ if output_transformer:
734
+ final_sql, final_params = output_transformer(final_sql, final_params)
735
+ return (
736
+ final_sql,
737
+ final_params,
738
+ parameter_profile,
739
+ transformed_result.input_named_parameters,
740
+ transformed_result.applied_wrap_types,
741
+ )
742
+
743
+ final_sql, final_params = self._apply_final_transformations(expression, processed_sql, parameters, dialect_str)
744
+ return final_sql, final_params, parameter_profile, (), False
745
+
746
+ def _should_validate_parameters(self, final_params: Any, raw_parameters: Any, is_many: bool) -> bool:
747
+ """Determine if parameter alignment should be validated.
748
+
749
+ Args:
750
+ final_params: Parameters after compilation.
751
+ raw_parameters: Original parameters.
752
+ is_many: Whether this is for execute_many.
753
+
754
+ Returns:
755
+ True when validation should run.
756
+ """
757
+ validation_enabled = self._config.enable_validation
758
+ has_final_params = not _is_effectively_empty_parameters(final_params)
759
+ has_raw_params = not _is_effectively_empty_parameters(raw_parameters)
760
+ has_params = has_final_params or has_raw_params
761
+ return (has_params or is_many) and validation_enabled
762
+
763
+ def _validate_parameters(self, parameter_profile: "ParameterProfile", final_params: Any, is_many: bool) -> None:
764
+ """Validate parameter alignment and log failures.
765
+
766
+ Args:
767
+ parameter_profile: Parameter metadata.
768
+ final_params: Execution parameters.
769
+ is_many: Whether this is for execute_many.
770
+ """
771
+ try:
772
+ validate_parameter_alignment(parameter_profile, final_params, is_many=is_many)
773
+ except Exception as exc:
774
+ log_with_context(logger, logging.ERROR, "sql.validate", error_type=type(exc).__name__)
775
+ raise
776
+
777
+ def _compile_uncached(
778
+ self,
779
+ sql: str,
780
+ parameters: Any,
781
+ is_many: bool = False,
782
+ expression_override: "exp.Expr | None" = None,
783
+ *,
784
+ param_fingerprint: Any | None,
785
+ ) -> CompiledSQL:
786
+ """Compile SQL without caching.
787
+
788
+ Args:
789
+ sql: SQL string
790
+ parameters: Parameter values
791
+ is_many: Whether this is for execute_many operation
792
+ expression_override: Pre-parsed SQLGlot expression to reuse
793
+ param_fingerprint: Pre-computed parameter fingerprint for cache key.
794
+
795
+ Returns:
796
+ CompiledSQL result
797
+ """
798
+ parameter_profile = ParameterProfile.empty()
799
+ operation_profile = OperationProfile.empty()
800
+
801
+ try:
802
+ dialect_str = str(self._config.dialect) if self._config.dialect else None
803
+ (
804
+ processed_sql,
805
+ processed_params,
806
+ parameter_profile,
807
+ sqlglot_sql,
808
+ input_named_parameters,
809
+ applied_wrap_types,
810
+ ) = self._prepare_parameters(sql, parameters, is_many, dialect_str, param_fingerprint=param_fingerprint)
811
+ expression_override = self._normalize_expression_override(expression_override, sqlglot_sql, sql)
812
+
813
+ final_parameters = processed_params
814
+ ast_was_transformed = False
815
+ expression = None
816
+ operation_type: OperationType = "COMMAND"
817
+ parameter_casts: dict[int, str] = {}
818
+ parse_cache_key = None
819
+ parse_cache_entry = None
820
+
821
+ if self._config.enable_parsing:
822
+ (expression, operation_type, parameter_casts, operation_profile, parse_cache_key, parse_cache_entry) = (
823
+ self._resolve_expression(sqlglot_sql, dialect_str, expression_override)
824
+ )
825
+ (
826
+ expression,
827
+ final_parameters,
828
+ ast_was_transformed,
829
+ operation_type,
830
+ parameter_casts,
831
+ operation_profile,
832
+ ) = self._apply_ast_transformers(
833
+ expression,
834
+ final_parameters,
835
+ parameter_profile,
836
+ operation_type,
837
+ parameter_casts,
838
+ operation_profile,
839
+ parse_cache_key,
840
+ parse_cache_entry,
841
+ expression_override,
842
+ )
843
+
844
+ final_sql, final_params, parameter_profile, input_named_params, applied_wrap = self._finalize_compilation(
845
+ processed_sql,
846
+ processed_params,
847
+ expression,
848
+ final_parameters,
849
+ parameter_profile,
850
+ is_many,
851
+ dialect_str,
852
+ ast_was_transformed,
853
+ )
854
+
855
+ # If not transformed, we still need input_named_parameters from _prepare_parameters
856
+ if not ast_was_transformed:
857
+ input_named_params = input_named_parameters
858
+ applied_wrap = applied_wrap_types
859
+
860
+ if self._should_validate_parameters(final_params, parameters, is_many):
861
+ self._validate_parameters(parameter_profile, final_params, is_many)
862
+
863
+ return CompiledSQL(
864
+ compiled_sql=final_sql,
865
+ execution_parameters=final_params,
866
+ operation_type=operation_type,
867
+ expression=expression,
868
+ parameter_style=self._config.parameter_config.default_parameter_style.value,
869
+ supports_many=isinstance(final_params, list) and len(final_params) > 0,
870
+ parameter_casts=parameter_casts,
871
+ parameter_profile=parameter_profile,
872
+ operation_profile=operation_profile,
873
+ input_named_parameters=input_named_params,
874
+ applied_wrap_types=applied_wrap,
875
+ )
876
+
877
+ except sqlspec.exceptions.SQLSpecError:
878
+ raise
879
+ except ParseError as exc:
880
+ log_with_context(logger, logging.DEBUG, "sql.compile", error_type=type(exc).__name__, status="fallback")
881
+ return CompiledSQL(
882
+ compiled_sql=sql,
883
+ execution_parameters=parameters,
884
+ operation_type="COMMAND",
885
+ parameter_casts={},
886
+ parameter_profile=parameter_profile,
887
+ operation_profile=operation_profile,
888
+ )
889
+ except Exception as exc:
890
+ log_with_context(logger, logging.ERROR, "sql.compile", error_type=type(exc).__name__, status="error")
891
+ raise
892
+
893
+ def _get_param_fingerprint(self, parameters: Any, is_many: bool) -> Any:
894
+ if self._config.parameter_config.needs_static_script_compilation:
895
+ return value_fingerprint(parameters)
896
+ return structural_fingerprint(parameters, is_many)
897
+
898
+ def _make_cache_key(self, sql: str, param_fingerprint: Any, is_many: bool = False) -> tuple[Any, ...]:
899
+ """Generate cache key.
900
+
901
+ Args:
902
+ sql: SQL string
903
+ param_fingerprint: Precomputed parameter fingerprint
904
+ is_many: Whether this is for execute_many operation
905
+
906
+ Returns:
907
+ Cache key tuple
908
+ """
909
+ return _make_cache_key_tuple(
910
+ sql, param_fingerprint, self._input_style, self._exec_style, self._dialect_str, is_many
911
+ )
912
+
913
+ def _detect_operation_type(self, expression: "exp.Expr") -> "OperationType":
914
+ """Detect operation type from AST.
915
+
916
+ Args:
917
+ expression: AST expression
918
+
919
+ Returns:
920
+ Operation type literal
921
+ """
922
+
923
+ expr_type = type(expression)
924
+ if expr_type in OPERATION_TYPE_MAP:
925
+ return OPERATION_TYPE_MAP[expr_type] # pyright: ignore
926
+
927
+ if isinstance(expression, exp.Copy):
928
+ copy_kind = expression.args.get("kind")
929
+ if copy_kind is True:
930
+ return "COPY_FROM"
931
+ if copy_kind is False:
932
+ return "COPY_TO"
933
+ return "COPY"
934
+
935
+ # COMMAND is the generic fallback for any database command
936
+ # that doesn't fit specific categories
937
+ return "COMMAND"
938
+
939
+ def _detect_parameter_casts(self, expression: "exp.Expr | None") -> "dict[int, str]":
940
+ """Detect explicit type casts on parameters in the AST.
941
+
942
+ Args:
943
+ expression: SQLGlot AST expression to analyze
944
+
945
+ Returns:
946
+ Dict mapping parameter positions (1-based) to cast type names
947
+ """
948
+ if not expression:
949
+ return {}
950
+
951
+ cast_positions: dict[int, str] = {}
952
+ placeholder_positions: dict[str, int] = {}
953
+ placeholder_counter = [0]
954
+
955
+ # Walk all nodes in order to track parameter positions
956
+ for node in expression.walk():
957
+ if isinstance(node, exp.Placeholder):
958
+ _assign_placeholder_position(node, placeholder_positions, placeholder_counter)
959
+ # Check for cast nodes with parameter children
960
+ if isinstance(node, exp.Cast):
961
+ cast_target = node.this
962
+ position = None
963
+
964
+ if isinstance(cast_target, exp.Parameter):
965
+ # Handle $1, $2 style parameters
966
+ param_value = cast_target.this
967
+ if isinstance(param_value, exp.Literal):
968
+ position = int(param_value.this)
969
+ elif isinstance(cast_target, exp.Placeholder):
970
+ position = _assign_placeholder_position(cast_target, placeholder_positions, placeholder_counter)
971
+ elif isinstance(cast_target, exp.Column):
972
+ # Handle cases where $1 gets parsed as a column
973
+ column_name = str(cast_target.this) if cast_target.this else str(cast_target)
974
+ if column_name.startswith("$") and column_name[1:].isdigit():
975
+ position = int(column_name[1:])
976
+
977
+ if position is not None:
978
+ # Extract cast type
979
+ if isinstance(node.to, exp.DataType):
980
+ cast_type = str(get_value_attribute(node.to.this))
981
+ else:
982
+ cast_type = str(node.to)
983
+ cast_positions[position] = cast_type.upper()
984
+
985
+ return cast_positions
986
+
987
+ def _apply_final_transformations(
988
+ self, expression: "exp.Expr | None", sql: str, parameters: Any, dialect_str: "str | None"
989
+ ) -> "tuple[str, Any]":
990
+ """Apply final transformations.
991
+
992
+ Args:
993
+ expression: SQLGlot AST expression
994
+ sql: SQL string
995
+ parameters: Execution parameters
996
+ dialect_str: SQL dialect
997
+
998
+ Returns:
999
+ Tuple of (final_sql, final_parameters)
1000
+ """
1001
+ output_transformer = self._config.output_transformer
1002
+ if output_transformer:
1003
+ if expression is not None:
1004
+ ast_sql = expression.sql(dialect=dialect_str)
1005
+ return output_transformer(ast_sql, parameters)
1006
+ return output_transformer(sql, parameters)
1007
+
1008
+ return sql, parameters
1009
+
1010
+ def _build_operation_profile(
1011
+ self, expression: "exp.Expr | None", operation_type: "OperationType"
1012
+ ) -> "OperationProfile":
1013
+ if expression is None:
1014
+ return OperationProfile.empty()
1015
+
1016
+ returns_rows = False
1017
+ modifies_rows = False
1018
+
1019
+ expr = expression
1020
+ if isinstance(
1021
+ expr,
1022
+ (exp.Select, exp.Union, exp.Except, exp.Intersect, exp.Values, exp.Table, exp.TableSample, exp.Summarize),
1023
+ ):
1024
+ returns_rows = True
1025
+ elif isinstance(expr, (exp.Insert, exp.Update, exp.Delete, exp.Merge)):
1026
+ modifies_rows = True
1027
+ returns_rows = bool(expr.args.get("returning"))
1028
+ elif isinstance(expr, exp.TruncateTable):
1029
+ modifies_rows = True
1030
+ elif isinstance(expr, exp.Copy):
1031
+ copy_kind = expr.args.get("kind")
1032
+ modifies_rows = copy_kind is True
1033
+ returns_rows = copy_kind is False
1034
+
1035
+ if not returns_rows and operation_type in {"SELECT", "WITH", "VALUES", "TABLE"}:
1036
+ returns_rows = True
1037
+
1038
+ if not modifies_rows and operation_type in {"INSERT", "UPDATE", "DELETE", "MERGE"}:
1039
+ modifies_rows = True
1040
+
1041
+ return OperationProfile(returns_rows=returns_rows, modifies_rows=modifies_rows)
1042
+
1043
+ def clear_cache(self) -> None:
1044
+ """Clear compilation cache and reset statistics."""
1045
+ self._cache.clear()
1046
+ self._cache_hits = 0
1047
+ self._cache_misses = 0
1048
+ self._parse_cache.clear()
1049
+ self._parse_cache_hits = 0
1050
+ self._parse_cache_misses = 0
1051
+ self._parameter_processor.clear_cache()
1052
+
1053
+ def _make_parse_cache_key(self, sql: str, dialect: "str | None") -> Any:
1054
+ dialect_marker = dialect or "default"
1055
+ # Use tuple as cache key instead of hashing. Python handles tuple keys efficiently.
1056
+ return (dialect_marker, sql)
1057
+
1058
+ @property
1059
+ def cache_stats(self) -> "dict[str, int]":
1060
+ """Get cache statistics.
1061
+
1062
+ Returns:
1063
+ Dictionary with cache statistics
1064
+ """
1065
+ total_requests = self._cache_hits + self._cache_misses
1066
+ hit_rate_pct = int((self._cache_hits / total_requests) * 100) if total_requests > 0 else 0
1067
+ parse_total = self._parse_cache_hits + self._parse_cache_misses
1068
+ parse_hit_rate_pct = int((self._parse_cache_hits / parse_total) * 100) if parse_total > 0 else 0
1069
+ parameter_stats = self._parameter_processor.cache_stats()
1070
+
1071
+ return {
1072
+ "hits": self._cache_hits,
1073
+ "misses": self._cache_misses,
1074
+ "size": len(self._cache),
1075
+ "max_size": self._max_cache_size,
1076
+ "hit_rate_percent": hit_rate_pct,
1077
+ "parse_hits": self._parse_cache_hits,
1078
+ "parse_misses": self._parse_cache_misses,
1079
+ "parse_size": len(self._parse_cache),
1080
+ "parse_max_size": self._parse_cache_max_size,
1081
+ "parse_hit_rate_percent": parse_hit_rate_pct,
1082
+ "parameter_hits": parameter_stats["hits"],
1083
+ "parameter_misses": parameter_stats["misses"],
1084
+ "parameter_size": parameter_stats["size"],
1085
+ "parameter_max_size": parameter_stats["max_size"],
1086
+ "validator_hits": parameter_stats["validator_hits"],
1087
+ "validator_misses": parameter_stats["validator_misses"],
1088
+ "validator_size": parameter_stats["validator_size"],
1089
+ "validator_max_size": parameter_stats["validator_max_size"],
1090
+ }