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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (531) hide show
  1. ac8f31065839703b4e70__mypyc.cpython-310-aarch64-linux-gnu.so +0 -0
  2. sqlspec/__init__.py +140 -0
  3. sqlspec/__main__.py +12 -0
  4. sqlspec/__metadata__.py +14 -0
  5. sqlspec/_serialization.py +315 -0
  6. sqlspec/_typing.py +700 -0
  7. sqlspec/adapters/__init__.py +0 -0
  8. sqlspec/adapters/adbc/__init__.py +5 -0
  9. sqlspec/adapters/adbc/_typing.py +82 -0
  10. sqlspec/adapters/adbc/adk/__init__.py +5 -0
  11. sqlspec/adapters/adbc/adk/store.py +1273 -0
  12. sqlspec/adapters/adbc/config.py +295 -0
  13. sqlspec/adapters/adbc/core.cpython-310-aarch64-linux-gnu.so +0 -0
  14. sqlspec/adapters/adbc/core.py +735 -0
  15. sqlspec/adapters/adbc/data_dictionary.py +334 -0
  16. sqlspec/adapters/adbc/driver.py +529 -0
  17. sqlspec/adapters/adbc/events/__init__.py +5 -0
  18. sqlspec/adapters/adbc/events/store.py +285 -0
  19. sqlspec/adapters/adbc/litestar/__init__.py +5 -0
  20. sqlspec/adapters/adbc/litestar/store.py +502 -0
  21. sqlspec/adapters/adbc/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  22. sqlspec/adapters/adbc/type_converter.py +140 -0
  23. sqlspec/adapters/aiosqlite/__init__.py +25 -0
  24. sqlspec/adapters/aiosqlite/_typing.py +82 -0
  25. sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
  26. sqlspec/adapters/aiosqlite/adk/store.py +818 -0
  27. sqlspec/adapters/aiosqlite/config.py +334 -0
  28. sqlspec/adapters/aiosqlite/core.cpython-310-aarch64-linux-gnu.so +0 -0
  29. sqlspec/adapters/aiosqlite/core.py +315 -0
  30. sqlspec/adapters/aiosqlite/data_dictionary.py +208 -0
  31. sqlspec/adapters/aiosqlite/driver.py +313 -0
  32. sqlspec/adapters/aiosqlite/events/__init__.py +5 -0
  33. sqlspec/adapters/aiosqlite/events/store.py +20 -0
  34. sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
  35. sqlspec/adapters/aiosqlite/litestar/store.py +279 -0
  36. sqlspec/adapters/aiosqlite/pool.py +533 -0
  37. sqlspec/adapters/asyncmy/__init__.py +21 -0
  38. sqlspec/adapters/asyncmy/_typing.py +87 -0
  39. sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
  40. sqlspec/adapters/asyncmy/adk/store.py +703 -0
  41. sqlspec/adapters/asyncmy/config.py +302 -0
  42. sqlspec/adapters/asyncmy/core.cpython-310-aarch64-linux-gnu.so +0 -0
  43. sqlspec/adapters/asyncmy/core.py +360 -0
  44. sqlspec/adapters/asyncmy/data_dictionary.py +124 -0
  45. sqlspec/adapters/asyncmy/driver.py +383 -0
  46. sqlspec/adapters/asyncmy/events/__init__.py +5 -0
  47. sqlspec/adapters/asyncmy/events/store.py +104 -0
  48. sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
  49. sqlspec/adapters/asyncmy/litestar/store.py +296 -0
  50. sqlspec/adapters/asyncpg/__init__.py +19 -0
  51. sqlspec/adapters/asyncpg/_typing.py +88 -0
  52. sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
  53. sqlspec/adapters/asyncpg/adk/store.py +748 -0
  54. sqlspec/adapters/asyncpg/config.py +569 -0
  55. sqlspec/adapters/asyncpg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  56. sqlspec/adapters/asyncpg/core.py +367 -0
  57. sqlspec/adapters/asyncpg/data_dictionary.py +162 -0
  58. sqlspec/adapters/asyncpg/driver.py +487 -0
  59. sqlspec/adapters/asyncpg/events/__init__.py +6 -0
  60. sqlspec/adapters/asyncpg/events/backend.py +286 -0
  61. sqlspec/adapters/asyncpg/events/store.py +40 -0
  62. sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
  63. sqlspec/adapters/asyncpg/litestar/store.py +251 -0
  64. sqlspec/adapters/bigquery/__init__.py +14 -0
  65. sqlspec/adapters/bigquery/_typing.py +86 -0
  66. sqlspec/adapters/bigquery/adk/__init__.py +5 -0
  67. sqlspec/adapters/bigquery/adk/store.py +827 -0
  68. sqlspec/adapters/bigquery/config.py +353 -0
  69. sqlspec/adapters/bigquery/core.cpython-310-aarch64-linux-gnu.so +0 -0
  70. sqlspec/adapters/bigquery/core.py +715 -0
  71. sqlspec/adapters/bigquery/data_dictionary.py +128 -0
  72. sqlspec/adapters/bigquery/driver.py +548 -0
  73. sqlspec/adapters/bigquery/events/__init__.py +5 -0
  74. sqlspec/adapters/bigquery/events/store.py +139 -0
  75. sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
  76. sqlspec/adapters/bigquery/litestar/store.py +325 -0
  77. sqlspec/adapters/bigquery/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  78. sqlspec/adapters/bigquery/type_converter.py +107 -0
  79. sqlspec/adapters/cockroach_asyncpg/__init__.py +24 -0
  80. sqlspec/adapters/cockroach_asyncpg/_typing.py +72 -0
  81. sqlspec/adapters/cockroach_asyncpg/adk/__init__.py +3 -0
  82. sqlspec/adapters/cockroach_asyncpg/adk/store.py +410 -0
  83. sqlspec/adapters/cockroach_asyncpg/config.py +238 -0
  84. sqlspec/adapters/cockroach_asyncpg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  85. sqlspec/adapters/cockroach_asyncpg/core.py +55 -0
  86. sqlspec/adapters/cockroach_asyncpg/data_dictionary.py +107 -0
  87. sqlspec/adapters/cockroach_asyncpg/driver.py +144 -0
  88. sqlspec/adapters/cockroach_asyncpg/events/__init__.py +3 -0
  89. sqlspec/adapters/cockroach_asyncpg/events/store.py +20 -0
  90. sqlspec/adapters/cockroach_asyncpg/litestar/__init__.py +3 -0
  91. sqlspec/adapters/cockroach_asyncpg/litestar/store.py +142 -0
  92. sqlspec/adapters/cockroach_psycopg/__init__.py +38 -0
  93. sqlspec/adapters/cockroach_psycopg/_typing.py +129 -0
  94. sqlspec/adapters/cockroach_psycopg/adk/__init__.py +13 -0
  95. sqlspec/adapters/cockroach_psycopg/adk/store.py +868 -0
  96. sqlspec/adapters/cockroach_psycopg/config.py +484 -0
  97. sqlspec/adapters/cockroach_psycopg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  98. sqlspec/adapters/cockroach_psycopg/core.py +63 -0
  99. sqlspec/adapters/cockroach_psycopg/data_dictionary.py +215 -0
  100. sqlspec/adapters/cockroach_psycopg/driver.py +284 -0
  101. sqlspec/adapters/cockroach_psycopg/events/__init__.py +6 -0
  102. sqlspec/adapters/cockroach_psycopg/events/store.py +34 -0
  103. sqlspec/adapters/cockroach_psycopg/litestar/__init__.py +3 -0
  104. sqlspec/adapters/cockroach_psycopg/litestar/store.py +325 -0
  105. sqlspec/adapters/duckdb/__init__.py +25 -0
  106. sqlspec/adapters/duckdb/_typing.py +81 -0
  107. sqlspec/adapters/duckdb/adk/__init__.py +14 -0
  108. sqlspec/adapters/duckdb/adk/store.py +850 -0
  109. sqlspec/adapters/duckdb/config.py +463 -0
  110. sqlspec/adapters/duckdb/core.cpython-310-aarch64-linux-gnu.so +0 -0
  111. sqlspec/adapters/duckdb/core.py +257 -0
  112. sqlspec/adapters/duckdb/data_dictionary.py +140 -0
  113. sqlspec/adapters/duckdb/driver.py +430 -0
  114. sqlspec/adapters/duckdb/events/__init__.py +5 -0
  115. sqlspec/adapters/duckdb/events/store.py +57 -0
  116. sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
  117. sqlspec/adapters/duckdb/litestar/store.py +330 -0
  118. sqlspec/adapters/duckdb/pool.py +293 -0
  119. sqlspec/adapters/duckdb/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  120. sqlspec/adapters/duckdb/type_converter.py +118 -0
  121. sqlspec/adapters/mock/__init__.py +72 -0
  122. sqlspec/adapters/mock/_typing.py +147 -0
  123. sqlspec/adapters/mock/config.py +483 -0
  124. sqlspec/adapters/mock/core.py +319 -0
  125. sqlspec/adapters/mock/data_dictionary.py +366 -0
  126. sqlspec/adapters/mock/driver.py +721 -0
  127. sqlspec/adapters/mysqlconnector/__init__.py +36 -0
  128. sqlspec/adapters/mysqlconnector/_typing.py +141 -0
  129. sqlspec/adapters/mysqlconnector/adk/__init__.py +15 -0
  130. sqlspec/adapters/mysqlconnector/adk/store.py +1060 -0
  131. sqlspec/adapters/mysqlconnector/config.py +394 -0
  132. sqlspec/adapters/mysqlconnector/core.cpython-310-aarch64-linux-gnu.so +0 -0
  133. sqlspec/adapters/mysqlconnector/core.py +303 -0
  134. sqlspec/adapters/mysqlconnector/data_dictionary.py +235 -0
  135. sqlspec/adapters/mysqlconnector/driver.py +483 -0
  136. sqlspec/adapters/mysqlconnector/events/__init__.py +8 -0
  137. sqlspec/adapters/mysqlconnector/events/store.py +98 -0
  138. sqlspec/adapters/mysqlconnector/litestar/__init__.py +5 -0
  139. sqlspec/adapters/mysqlconnector/litestar/store.py +426 -0
  140. sqlspec/adapters/oracledb/__init__.py +60 -0
  141. sqlspec/adapters/oracledb/_numpy_handlers.py +141 -0
  142. sqlspec/adapters/oracledb/_typing.py +182 -0
  143. sqlspec/adapters/oracledb/_uuid_handlers.py +166 -0
  144. sqlspec/adapters/oracledb/adk/__init__.py +10 -0
  145. sqlspec/adapters/oracledb/adk/store.py +2369 -0
  146. sqlspec/adapters/oracledb/config.py +550 -0
  147. sqlspec/adapters/oracledb/core.cpython-310-aarch64-linux-gnu.so +0 -0
  148. sqlspec/adapters/oracledb/core.py +543 -0
  149. sqlspec/adapters/oracledb/data_dictionary.py +536 -0
  150. sqlspec/adapters/oracledb/driver.py +1229 -0
  151. sqlspec/adapters/oracledb/events/__init__.py +16 -0
  152. sqlspec/adapters/oracledb/events/backend.py +347 -0
  153. sqlspec/adapters/oracledb/events/store.py +420 -0
  154. sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
  155. sqlspec/adapters/oracledb/litestar/store.py +781 -0
  156. sqlspec/adapters/oracledb/migrations.py +535 -0
  157. sqlspec/adapters/oracledb/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  158. sqlspec/adapters/oracledb/type_converter.py +211 -0
  159. sqlspec/adapters/psqlpy/__init__.py +17 -0
  160. sqlspec/adapters/psqlpy/_typing.py +79 -0
  161. sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
  162. sqlspec/adapters/psqlpy/adk/store.py +766 -0
  163. sqlspec/adapters/psqlpy/config.py +304 -0
  164. sqlspec/adapters/psqlpy/core.cpython-310-aarch64-linux-gnu.so +0 -0
  165. sqlspec/adapters/psqlpy/core.py +480 -0
  166. sqlspec/adapters/psqlpy/data_dictionary.py +126 -0
  167. sqlspec/adapters/psqlpy/driver.py +438 -0
  168. sqlspec/adapters/psqlpy/events/__init__.py +6 -0
  169. sqlspec/adapters/psqlpy/events/backend.py +310 -0
  170. sqlspec/adapters/psqlpy/events/store.py +20 -0
  171. sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
  172. sqlspec/adapters/psqlpy/litestar/store.py +270 -0
  173. sqlspec/adapters/psqlpy/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  174. sqlspec/adapters/psqlpy/type_converter.py +113 -0
  175. sqlspec/adapters/psycopg/__init__.py +32 -0
  176. sqlspec/adapters/psycopg/_typing.py +164 -0
  177. sqlspec/adapters/psycopg/adk/__init__.py +10 -0
  178. sqlspec/adapters/psycopg/adk/store.py +1387 -0
  179. sqlspec/adapters/psycopg/config.py +576 -0
  180. sqlspec/adapters/psycopg/core.cpython-310-aarch64-linux-gnu.so +0 -0
  181. sqlspec/adapters/psycopg/core.py +450 -0
  182. sqlspec/adapters/psycopg/data_dictionary.py +289 -0
  183. sqlspec/adapters/psycopg/driver.py +975 -0
  184. sqlspec/adapters/psycopg/events/__init__.py +20 -0
  185. sqlspec/adapters/psycopg/events/backend.py +458 -0
  186. sqlspec/adapters/psycopg/events/store.py +42 -0
  187. sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
  188. sqlspec/adapters/psycopg/litestar/store.py +552 -0
  189. sqlspec/adapters/psycopg/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  190. sqlspec/adapters/psycopg/type_converter.py +93 -0
  191. sqlspec/adapters/pymysql/__init__.py +21 -0
  192. sqlspec/adapters/pymysql/_typing.py +71 -0
  193. sqlspec/adapters/pymysql/adk/__init__.py +5 -0
  194. sqlspec/adapters/pymysql/adk/store.py +540 -0
  195. sqlspec/adapters/pymysql/config.py +195 -0
  196. sqlspec/adapters/pymysql/core.cpython-310-aarch64-linux-gnu.so +0 -0
  197. sqlspec/adapters/pymysql/core.py +299 -0
  198. sqlspec/adapters/pymysql/data_dictionary.py +122 -0
  199. sqlspec/adapters/pymysql/driver.py +259 -0
  200. sqlspec/adapters/pymysql/events/__init__.py +5 -0
  201. sqlspec/adapters/pymysql/events/store.py +50 -0
  202. sqlspec/adapters/pymysql/litestar/__init__.py +5 -0
  203. sqlspec/adapters/pymysql/litestar/store.py +232 -0
  204. sqlspec/adapters/pymysql/pool.py +137 -0
  205. sqlspec/adapters/spanner/__init__.py +40 -0
  206. sqlspec/adapters/spanner/_typing.py +86 -0
  207. sqlspec/adapters/spanner/adk/__init__.py +5 -0
  208. sqlspec/adapters/spanner/adk/store.py +732 -0
  209. sqlspec/adapters/spanner/config.py +352 -0
  210. sqlspec/adapters/spanner/core.cpython-310-aarch64-linux-gnu.so +0 -0
  211. sqlspec/adapters/spanner/core.py +188 -0
  212. sqlspec/adapters/spanner/data_dictionary.py +120 -0
  213. sqlspec/adapters/spanner/dialect/__init__.py +6 -0
  214. sqlspec/adapters/spanner/dialect/_spangres.py +57 -0
  215. sqlspec/adapters/spanner/dialect/_spanner.py +130 -0
  216. sqlspec/adapters/spanner/driver.py +373 -0
  217. sqlspec/adapters/spanner/events/__init__.py +5 -0
  218. sqlspec/adapters/spanner/events/store.py +187 -0
  219. sqlspec/adapters/spanner/litestar/__init__.py +5 -0
  220. sqlspec/adapters/spanner/litestar/store.py +291 -0
  221. sqlspec/adapters/spanner/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  222. sqlspec/adapters/spanner/type_converter.py +331 -0
  223. sqlspec/adapters/sqlite/__init__.py +19 -0
  224. sqlspec/adapters/sqlite/_typing.py +80 -0
  225. sqlspec/adapters/sqlite/adk/__init__.py +5 -0
  226. sqlspec/adapters/sqlite/adk/store.py +958 -0
  227. sqlspec/adapters/sqlite/config.py +280 -0
  228. sqlspec/adapters/sqlite/core.cpython-310-aarch64-linux-gnu.so +0 -0
  229. sqlspec/adapters/sqlite/core.py +312 -0
  230. sqlspec/adapters/sqlite/data_dictionary.py +202 -0
  231. sqlspec/adapters/sqlite/driver.py +359 -0
  232. sqlspec/adapters/sqlite/events/__init__.py +5 -0
  233. sqlspec/adapters/sqlite/events/store.py +20 -0
  234. sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
  235. sqlspec/adapters/sqlite/litestar/store.py +316 -0
  236. sqlspec/adapters/sqlite/pool.py +198 -0
  237. sqlspec/adapters/sqlite/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  238. sqlspec/adapters/sqlite/type_converter.py +114 -0
  239. sqlspec/base.py +747 -0
  240. sqlspec/builder/__init__.py +179 -0
  241. sqlspec/builder/_base.cpython-310-aarch64-linux-gnu.so +0 -0
  242. sqlspec/builder/_base.py +1022 -0
  243. sqlspec/builder/_column.cpython-310-aarch64-linux-gnu.so +0 -0
  244. sqlspec/builder/_column.py +521 -0
  245. sqlspec/builder/_ddl.cpython-310-aarch64-linux-gnu.so +0 -0
  246. sqlspec/builder/_ddl.py +1642 -0
  247. sqlspec/builder/_delete.cpython-310-aarch64-linux-gnu.so +0 -0
  248. sqlspec/builder/_delete.py +95 -0
  249. sqlspec/builder/_dml.cpython-310-aarch64-linux-gnu.so +0 -0
  250. sqlspec/builder/_dml.py +365 -0
  251. sqlspec/builder/_explain.cpython-310-aarch64-linux-gnu.so +0 -0
  252. sqlspec/builder/_explain.py +579 -0
  253. sqlspec/builder/_expression_wrappers.cpython-310-aarch64-linux-gnu.so +0 -0
  254. sqlspec/builder/_expression_wrappers.py +46 -0
  255. sqlspec/builder/_factory.cpython-310-aarch64-linux-gnu.so +0 -0
  256. sqlspec/builder/_factory.py +1697 -0
  257. sqlspec/builder/_insert.cpython-310-aarch64-linux-gnu.so +0 -0
  258. sqlspec/builder/_insert.py +328 -0
  259. sqlspec/builder/_join.cpython-310-aarch64-linux-gnu.so +0 -0
  260. sqlspec/builder/_join.py +499 -0
  261. sqlspec/builder/_merge.cpython-310-aarch64-linux-gnu.so +0 -0
  262. sqlspec/builder/_merge.py +821 -0
  263. sqlspec/builder/_parsing_utils.cpython-310-aarch64-linux-gnu.so +0 -0
  264. sqlspec/builder/_parsing_utils.py +297 -0
  265. sqlspec/builder/_select.cpython-310-aarch64-linux-gnu.so +0 -0
  266. sqlspec/builder/_select.py +1660 -0
  267. sqlspec/builder/_temporal.cpython-310-aarch64-linux-gnu.so +0 -0
  268. sqlspec/builder/_temporal.py +139 -0
  269. sqlspec/builder/_update.cpython-310-aarch64-linux-gnu.so +0 -0
  270. sqlspec/builder/_update.py +173 -0
  271. sqlspec/builder/_vector_expressions.py +267 -0
  272. sqlspec/cli.py +911 -0
  273. sqlspec/config.py +1755 -0
  274. sqlspec/core/__init__.py +374 -0
  275. sqlspec/core/_correlation.cpython-310-aarch64-linux-gnu.so +0 -0
  276. sqlspec/core/_correlation.py +176 -0
  277. sqlspec/core/cache.cpython-310-aarch64-linux-gnu.so +0 -0
  278. sqlspec/core/cache.py +1069 -0
  279. sqlspec/core/compiler.cpython-310-aarch64-linux-gnu.so +0 -0
  280. sqlspec/core/compiler.py +954 -0
  281. sqlspec/core/explain.cpython-310-aarch64-linux-gnu.so +0 -0
  282. sqlspec/core/explain.py +275 -0
  283. sqlspec/core/filters.cpython-310-aarch64-linux-gnu.so +0 -0
  284. sqlspec/core/filters.py +952 -0
  285. sqlspec/core/hashing.cpython-310-aarch64-linux-gnu.so +0 -0
  286. sqlspec/core/hashing.py +262 -0
  287. sqlspec/core/metrics.cpython-310-aarch64-linux-gnu.so +0 -0
  288. sqlspec/core/metrics.py +83 -0
  289. sqlspec/core/parameters/__init__.py +71 -0
  290. sqlspec/core/parameters/_alignment.cpython-310-aarch64-linux-gnu.so +0 -0
  291. sqlspec/core/parameters/_alignment.py +270 -0
  292. sqlspec/core/parameters/_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  293. sqlspec/core/parameters/_converter.py +543 -0
  294. sqlspec/core/parameters/_processor.cpython-310-aarch64-linux-gnu.so +0 -0
  295. sqlspec/core/parameters/_processor.py +505 -0
  296. sqlspec/core/parameters/_registry.cpython-310-aarch64-linux-gnu.so +0 -0
  297. sqlspec/core/parameters/_registry.py +206 -0
  298. sqlspec/core/parameters/_transformers.cpython-310-aarch64-linux-gnu.so +0 -0
  299. sqlspec/core/parameters/_transformers.py +292 -0
  300. sqlspec/core/parameters/_types.cpython-310-aarch64-linux-gnu.so +0 -0
  301. sqlspec/core/parameters/_types.py +499 -0
  302. sqlspec/core/parameters/_validator.cpython-310-aarch64-linux-gnu.so +0 -0
  303. sqlspec/core/parameters/_validator.py +180 -0
  304. sqlspec/core/pipeline.cpython-310-aarch64-linux-gnu.so +0 -0
  305. sqlspec/core/pipeline.py +319 -0
  306. sqlspec/core/query_modifiers.cpython-310-aarch64-linux-gnu.so +0 -0
  307. sqlspec/core/query_modifiers.py +437 -0
  308. sqlspec/core/result/__init__.py +23 -0
  309. sqlspec/core/result/_base.cpython-310-aarch64-linux-gnu.so +0 -0
  310. sqlspec/core/result/_base.py +1121 -0
  311. sqlspec/core/result/_io.cpython-310-aarch64-linux-gnu.so +0 -0
  312. sqlspec/core/result/_io.py +28 -0
  313. sqlspec/core/splitter.cpython-310-aarch64-linux-gnu.so +0 -0
  314. sqlspec/core/splitter.py +966 -0
  315. sqlspec/core/stack.cpython-310-aarch64-linux-gnu.so +0 -0
  316. sqlspec/core/stack.py +163 -0
  317. sqlspec/core/statement.cpython-310-aarch64-linux-gnu.so +0 -0
  318. sqlspec/core/statement.py +1503 -0
  319. sqlspec/core/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
  320. sqlspec/core/type_converter.py +339 -0
  321. sqlspec/data_dictionary/__init__.py +22 -0
  322. sqlspec/data_dictionary/_loader.py +123 -0
  323. sqlspec/data_dictionary/_registry.cpython-310-aarch64-linux-gnu.so +0 -0
  324. sqlspec/data_dictionary/_registry.py +74 -0
  325. sqlspec/data_dictionary/_types.cpython-310-aarch64-linux-gnu.so +0 -0
  326. sqlspec/data_dictionary/_types.py +121 -0
  327. sqlspec/data_dictionary/dialects/__init__.py +21 -0
  328. sqlspec/data_dictionary/dialects/bigquery.cpython-310-aarch64-linux-gnu.so +0 -0
  329. sqlspec/data_dictionary/dialects/bigquery.py +49 -0
  330. sqlspec/data_dictionary/dialects/cockroachdb.cpython-310-aarch64-linux-gnu.so +0 -0
  331. sqlspec/data_dictionary/dialects/cockroachdb.py +43 -0
  332. sqlspec/data_dictionary/dialects/duckdb.cpython-310-aarch64-linux-gnu.so +0 -0
  333. sqlspec/data_dictionary/dialects/duckdb.py +47 -0
  334. sqlspec/data_dictionary/dialects/mysql.cpython-310-aarch64-linux-gnu.so +0 -0
  335. sqlspec/data_dictionary/dialects/mysql.py +42 -0
  336. sqlspec/data_dictionary/dialects/oracle.cpython-310-aarch64-linux-gnu.so +0 -0
  337. sqlspec/data_dictionary/dialects/oracle.py +34 -0
  338. sqlspec/data_dictionary/dialects/postgres.cpython-310-aarch64-linux-gnu.so +0 -0
  339. sqlspec/data_dictionary/dialects/postgres.py +46 -0
  340. sqlspec/data_dictionary/dialects/spanner.cpython-310-aarch64-linux-gnu.so +0 -0
  341. sqlspec/data_dictionary/dialects/spanner.py +37 -0
  342. sqlspec/data_dictionary/dialects/sqlite.cpython-310-aarch64-linux-gnu.so +0 -0
  343. sqlspec/data_dictionary/dialects/sqlite.py +42 -0
  344. sqlspec/data_dictionary/sql/.gitkeep +0 -0
  345. sqlspec/data_dictionary/sql/bigquery/columns.sql +23 -0
  346. sqlspec/data_dictionary/sql/bigquery/foreign_keys.sql +34 -0
  347. sqlspec/data_dictionary/sql/bigquery/indexes.sql +19 -0
  348. sqlspec/data_dictionary/sql/bigquery/tables.sql +33 -0
  349. sqlspec/data_dictionary/sql/bigquery/version.sql +3 -0
  350. sqlspec/data_dictionary/sql/cockroachdb/columns.sql +34 -0
  351. sqlspec/data_dictionary/sql/cockroachdb/foreign_keys.sql +40 -0
  352. sqlspec/data_dictionary/sql/cockroachdb/indexes.sql +32 -0
  353. sqlspec/data_dictionary/sql/cockroachdb/tables.sql +44 -0
  354. sqlspec/data_dictionary/sql/cockroachdb/version.sql +3 -0
  355. sqlspec/data_dictionary/sql/duckdb/columns.sql +23 -0
  356. sqlspec/data_dictionary/sql/duckdb/foreign_keys.sql +36 -0
  357. sqlspec/data_dictionary/sql/duckdb/indexes.sql +19 -0
  358. sqlspec/data_dictionary/sql/duckdb/tables.sql +38 -0
  359. sqlspec/data_dictionary/sql/duckdb/version.sql +3 -0
  360. sqlspec/data_dictionary/sql/mysql/columns.sql +23 -0
  361. sqlspec/data_dictionary/sql/mysql/foreign_keys.sql +28 -0
  362. sqlspec/data_dictionary/sql/mysql/indexes.sql +26 -0
  363. sqlspec/data_dictionary/sql/mysql/tables.sql +33 -0
  364. sqlspec/data_dictionary/sql/mysql/version.sql +3 -0
  365. sqlspec/data_dictionary/sql/oracle/columns.sql +23 -0
  366. sqlspec/data_dictionary/sql/oracle/foreign_keys.sql +48 -0
  367. sqlspec/data_dictionary/sql/oracle/indexes.sql +44 -0
  368. sqlspec/data_dictionary/sql/oracle/tables.sql +25 -0
  369. sqlspec/data_dictionary/sql/oracle/version.sql +20 -0
  370. sqlspec/data_dictionary/sql/postgres/columns.sql +34 -0
  371. sqlspec/data_dictionary/sql/postgres/foreign_keys.sql +40 -0
  372. sqlspec/data_dictionary/sql/postgres/indexes.sql +56 -0
  373. sqlspec/data_dictionary/sql/postgres/tables.sql +44 -0
  374. sqlspec/data_dictionary/sql/postgres/version.sql +3 -0
  375. sqlspec/data_dictionary/sql/spanner/columns.sql +23 -0
  376. sqlspec/data_dictionary/sql/spanner/foreign_keys.sql +70 -0
  377. sqlspec/data_dictionary/sql/spanner/indexes.sql +30 -0
  378. sqlspec/data_dictionary/sql/spanner/tables.sql +9 -0
  379. sqlspec/data_dictionary/sql/spanner/version.sql +3 -0
  380. sqlspec/data_dictionary/sql/sqlite/columns.sql +23 -0
  381. sqlspec/data_dictionary/sql/sqlite/foreign_keys.sql +22 -0
  382. sqlspec/data_dictionary/sql/sqlite/indexes.sql +7 -0
  383. sqlspec/data_dictionary/sql/sqlite/tables.sql +28 -0
  384. sqlspec/data_dictionary/sql/sqlite/version.sql +3 -0
  385. sqlspec/driver/__init__.py +32 -0
  386. sqlspec/driver/_async.cpython-310-aarch64-linux-gnu.so +0 -0
  387. sqlspec/driver/_async.py +1737 -0
  388. sqlspec/driver/_common.cpython-310-aarch64-linux-gnu.so +0 -0
  389. sqlspec/driver/_common.py +1478 -0
  390. sqlspec/driver/_sql_helpers.cpython-310-aarch64-linux-gnu.so +0 -0
  391. sqlspec/driver/_sql_helpers.py +148 -0
  392. sqlspec/driver/_storage_helpers.cpython-310-aarch64-linux-gnu.so +0 -0
  393. sqlspec/driver/_storage_helpers.py +144 -0
  394. sqlspec/driver/_sync.cpython-310-aarch64-linux-gnu.so +0 -0
  395. sqlspec/driver/_sync.py +1710 -0
  396. sqlspec/exceptions.py +338 -0
  397. sqlspec/extensions/__init__.py +0 -0
  398. sqlspec/extensions/adk/__init__.py +70 -0
  399. sqlspec/extensions/adk/_types.py +51 -0
  400. sqlspec/extensions/adk/converters.py +172 -0
  401. sqlspec/extensions/adk/memory/__init__.py +69 -0
  402. sqlspec/extensions/adk/memory/_types.py +30 -0
  403. sqlspec/extensions/adk/memory/converters.py +149 -0
  404. sqlspec/extensions/adk/memory/service.py +217 -0
  405. sqlspec/extensions/adk/memory/store.py +569 -0
  406. sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +246 -0
  407. sqlspec/extensions/adk/migrations/__init__.py +0 -0
  408. sqlspec/extensions/adk/service.py +225 -0
  409. sqlspec/extensions/adk/store.py +567 -0
  410. sqlspec/extensions/events/__init__.py +51 -0
  411. sqlspec/extensions/events/_channel.py +703 -0
  412. sqlspec/extensions/events/_hints.py +45 -0
  413. sqlspec/extensions/events/_models.py +23 -0
  414. sqlspec/extensions/events/_payload.py +69 -0
  415. sqlspec/extensions/events/_protocols.py +134 -0
  416. sqlspec/extensions/events/_queue.py +461 -0
  417. sqlspec/extensions/events/_store.py +209 -0
  418. sqlspec/extensions/events/migrations/0001_create_event_queue.py +59 -0
  419. sqlspec/extensions/events/migrations/__init__.py +3 -0
  420. sqlspec/extensions/fastapi/__init__.py +19 -0
  421. sqlspec/extensions/fastapi/extension.py +351 -0
  422. sqlspec/extensions/fastapi/providers.py +607 -0
  423. sqlspec/extensions/flask/__init__.py +37 -0
  424. sqlspec/extensions/flask/_state.py +76 -0
  425. sqlspec/extensions/flask/_utils.py +71 -0
  426. sqlspec/extensions/flask/extension.py +519 -0
  427. sqlspec/extensions/litestar/__init__.py +28 -0
  428. sqlspec/extensions/litestar/_utils.py +52 -0
  429. sqlspec/extensions/litestar/channels.py +165 -0
  430. sqlspec/extensions/litestar/cli.py +102 -0
  431. sqlspec/extensions/litestar/config.py +90 -0
  432. sqlspec/extensions/litestar/handlers.py +316 -0
  433. sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
  434. sqlspec/extensions/litestar/migrations/__init__.py +3 -0
  435. sqlspec/extensions/litestar/plugin.py +671 -0
  436. sqlspec/extensions/litestar/providers.py +526 -0
  437. sqlspec/extensions/litestar/store.py +296 -0
  438. sqlspec/extensions/otel/__init__.py +58 -0
  439. sqlspec/extensions/prometheus/__init__.py +113 -0
  440. sqlspec/extensions/starlette/__init__.py +19 -0
  441. sqlspec/extensions/starlette/_state.py +30 -0
  442. sqlspec/extensions/starlette/_utils.py +96 -0
  443. sqlspec/extensions/starlette/extension.py +346 -0
  444. sqlspec/extensions/starlette/middleware.py +235 -0
  445. sqlspec/loader.cpython-310-aarch64-linux-gnu.so +0 -0
  446. sqlspec/loader.py +702 -0
  447. sqlspec/migrations/__init__.py +36 -0
  448. sqlspec/migrations/base.py +731 -0
  449. sqlspec/migrations/commands.py +1232 -0
  450. sqlspec/migrations/context.py +157 -0
  451. sqlspec/migrations/fix.py +204 -0
  452. sqlspec/migrations/loaders.py +443 -0
  453. sqlspec/migrations/runner.py +1172 -0
  454. sqlspec/migrations/templates.py +234 -0
  455. sqlspec/migrations/tracker.py +611 -0
  456. sqlspec/migrations/utils.py +256 -0
  457. sqlspec/migrations/validation.py +207 -0
  458. sqlspec/migrations/version.py +446 -0
  459. sqlspec/observability/__init__.py +55 -0
  460. sqlspec/observability/_common.cpython-310-aarch64-linux-gnu.so +0 -0
  461. sqlspec/observability/_common.py +77 -0
  462. sqlspec/observability/_config.cpython-310-aarch64-linux-gnu.so +0 -0
  463. sqlspec/observability/_config.py +348 -0
  464. sqlspec/observability/_diagnostics.cpython-310-aarch64-linux-gnu.so +0 -0
  465. sqlspec/observability/_diagnostics.py +74 -0
  466. sqlspec/observability/_dispatcher.cpython-310-aarch64-linux-gnu.so +0 -0
  467. sqlspec/observability/_dispatcher.py +152 -0
  468. sqlspec/observability/_formatters/__init__.py +13 -0
  469. sqlspec/observability/_formatters/_aws.cpython-310-aarch64-linux-gnu.so +0 -0
  470. sqlspec/observability/_formatters/_aws.py +102 -0
  471. sqlspec/observability/_formatters/_azure.cpython-310-aarch64-linux-gnu.so +0 -0
  472. sqlspec/observability/_formatters/_azure.py +96 -0
  473. sqlspec/observability/_formatters/_base.cpython-310-aarch64-linux-gnu.so +0 -0
  474. sqlspec/observability/_formatters/_base.py +57 -0
  475. sqlspec/observability/_formatters/_gcp.cpython-310-aarch64-linux-gnu.so +0 -0
  476. sqlspec/observability/_formatters/_gcp.py +131 -0
  477. sqlspec/observability/_formatting.py +58 -0
  478. sqlspec/observability/_observer.cpython-310-aarch64-linux-gnu.so +0 -0
  479. sqlspec/observability/_observer.py +357 -0
  480. sqlspec/observability/_runtime.cpython-310-aarch64-linux-gnu.so +0 -0
  481. sqlspec/observability/_runtime.py +420 -0
  482. sqlspec/observability/_sampling.cpython-310-aarch64-linux-gnu.so +0 -0
  483. sqlspec/observability/_sampling.py +188 -0
  484. sqlspec/observability/_spans.cpython-310-aarch64-linux-gnu.so +0 -0
  485. sqlspec/observability/_spans.py +161 -0
  486. sqlspec/protocols.py +916 -0
  487. sqlspec/py.typed +0 -0
  488. sqlspec/storage/__init__.py +48 -0
  489. sqlspec/storage/_utils.py +104 -0
  490. sqlspec/storage/backends/__init__.py +1 -0
  491. sqlspec/storage/backends/base.py +253 -0
  492. sqlspec/storage/backends/fsspec.py +529 -0
  493. sqlspec/storage/backends/local.py +441 -0
  494. sqlspec/storage/backends/obstore.py +916 -0
  495. sqlspec/storage/errors.py +104 -0
  496. sqlspec/storage/pipeline.py +582 -0
  497. sqlspec/storage/registry.py +301 -0
  498. sqlspec/typing.py +395 -0
  499. sqlspec/utils/__init__.py +7 -0
  500. sqlspec/utils/arrow_helpers.py +318 -0
  501. sqlspec/utils/config_tools.py +332 -0
  502. sqlspec/utils/correlation.cpython-310-aarch64-linux-gnu.so +0 -0
  503. sqlspec/utils/correlation.py +134 -0
  504. sqlspec/utils/deprecation.py +190 -0
  505. sqlspec/utils/fixtures.cpython-310-aarch64-linux-gnu.so +0 -0
  506. sqlspec/utils/fixtures.py +258 -0
  507. sqlspec/utils/logging.py +222 -0
  508. sqlspec/utils/module_loader.py +306 -0
  509. sqlspec/utils/portal.cpython-310-aarch64-linux-gnu.so +0 -0
  510. sqlspec/utils/portal.py +375 -0
  511. sqlspec/utils/schema.cpython-310-aarch64-linux-gnu.so +0 -0
  512. sqlspec/utils/schema.py +485 -0
  513. sqlspec/utils/serializers.cpython-310-aarch64-linux-gnu.so +0 -0
  514. sqlspec/utils/serializers.py +408 -0
  515. sqlspec/utils/singleton.cpython-310-aarch64-linux-gnu.so +0 -0
  516. sqlspec/utils/singleton.py +41 -0
  517. sqlspec/utils/sync_tools.cpython-310-aarch64-linux-gnu.so +0 -0
  518. sqlspec/utils/sync_tools.py +311 -0
  519. sqlspec/utils/text.cpython-310-aarch64-linux-gnu.so +0 -0
  520. sqlspec/utils/text.py +108 -0
  521. sqlspec/utils/type_converters.cpython-310-aarch64-linux-gnu.so +0 -0
  522. sqlspec/utils/type_converters.py +128 -0
  523. sqlspec/utils/type_guards.cpython-310-aarch64-linux-gnu.so +0 -0
  524. sqlspec/utils/type_guards.py +1360 -0
  525. sqlspec/utils/uuids.cpython-310-aarch64-linux-gnu.so +0 -0
  526. sqlspec/utils/uuids.py +225 -0
  527. sqlspec-0.36.0.dist-info/METADATA +205 -0
  528. sqlspec-0.36.0.dist-info/RECORD +531 -0
  529. sqlspec-0.36.0.dist-info/WHEEL +7 -0
  530. sqlspec-0.36.0.dist-info/entry_points.txt +2 -0
  531. sqlspec-0.36.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,954 @@
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 hashlib
10
+ import logging
11
+ from collections import OrderedDict
12
+ from collections.abc import Mapping
13
+ from typing import TYPE_CHECKING, Any, Literal
14
+
15
+ import sqlglot
16
+ from mypy_extensions import mypyc_attr
17
+ from sqlglot import expressions as exp
18
+ from sqlglot.errors import ParseError
19
+
20
+ import sqlspec.exceptions
21
+ from sqlspec.core.parameters import (
22
+ ParameterProcessor,
23
+ ParameterProfile,
24
+ fingerprint_parameters,
25
+ validate_parameter_alignment,
26
+ )
27
+ from sqlspec.utils.logging import get_logger, log_with_context
28
+ from sqlspec.utils.type_guards import get_value_attribute
29
+
30
+ if TYPE_CHECKING:
31
+ from sqlspec.core.statement import StatementConfig
32
+
33
+
34
+ __all__ = (
35
+ "CompiledSQL",
36
+ "OperationProfile",
37
+ "OperationType",
38
+ "SQLProcessor",
39
+ "is_copy_from_operation",
40
+ "is_copy_operation",
41
+ "is_copy_to_operation",
42
+ )
43
+
44
+ logger: "logging.Logger" = get_logger("sqlspec.core.compiler")
45
+ OperationType = Literal[
46
+ "SELECT",
47
+ "INSERT",
48
+ "UPDATE",
49
+ "DELETE",
50
+ "COPY",
51
+ "COPY_FROM",
52
+ "COPY_TO",
53
+ "EXECUTE",
54
+ "SCRIPT",
55
+ "DDL",
56
+ "PRAGMA",
57
+ "MERGE",
58
+ "UNKNOWN",
59
+ ]
60
+
61
+ OPERATION_TYPE_MAP: "dict[type[exp.Expression], OperationType]" = {
62
+ exp.Select: "SELECT",
63
+ exp.Union: "SELECT",
64
+ exp.Except: "SELECT",
65
+ exp.Intersect: "SELECT",
66
+ exp.With: "SELECT",
67
+ exp.Insert: "INSERT",
68
+ exp.Update: "UPDATE",
69
+ exp.Delete: "DELETE",
70
+ exp.Pragma: "PRAGMA",
71
+ exp.Command: "EXECUTE",
72
+ exp.Create: "DDL",
73
+ exp.Drop: "DDL",
74
+ exp.Alter: "DDL",
75
+ exp.Merge: "MERGE",
76
+ }
77
+
78
+ COPY_OPERATION_TYPES: "tuple[OperationType, ...]" = ("COPY", "COPY_FROM", "COPY_TO")
79
+
80
+ COPY_FROM_OPERATION_TYPES: "tuple[OperationType, ...]" = ("COPY", "COPY_FROM")
81
+
82
+ COPY_TO_OPERATION_TYPES: "tuple[OperationType, ...]" = ("COPY_TO",)
83
+
84
+ ParseCacheEntry = tuple[exp.Expression | None, OperationType, dict[int, str], tuple[bool, bool]]
85
+
86
+
87
+ def is_copy_operation(operation_type: "OperationType") -> bool:
88
+ """Determine if the operation corresponds to any PostgreSQL COPY variant.
89
+
90
+ Args:
91
+ operation_type: Operation type detected by the compiler.
92
+
93
+ Returns:
94
+ True when the operation type represents COPY, COPY FROM, or COPY TO.
95
+ """
96
+
97
+ return operation_type in COPY_OPERATION_TYPES
98
+
99
+
100
+ def is_copy_from_operation(operation_type: "OperationType") -> bool:
101
+ """Check if the operation streams data into the database using COPY.
102
+
103
+ Args:
104
+ operation_type: Operation type detected by the compiler.
105
+
106
+ Returns:
107
+ True for COPY operations that read from client input (COPY FROM).
108
+ """
109
+
110
+ return operation_type in COPY_FROM_OPERATION_TYPES
111
+
112
+
113
+ def is_copy_to_operation(operation_type: "OperationType") -> bool:
114
+ """Check if the operation streams data out from the database using COPY.
115
+
116
+ Args:
117
+ operation_type: Operation type detected by the compiler.
118
+
119
+ Returns:
120
+ True for COPY operations that write to client output (COPY TO).
121
+ """
122
+
123
+ return operation_type in COPY_TO_OPERATION_TYPES
124
+
125
+
126
+ def _assign_placeholder_position(
127
+ placeholder: "exp.Placeholder", placeholder_positions: "dict[str, int]", placeholder_counter: "list[int]"
128
+ ) -> "int | None":
129
+ name_expr = placeholder.name if placeholder.name is not None else None
130
+ if name_expr is not None:
131
+ placeholder_key = str(name_expr)
132
+ else:
133
+ value = placeholder.args.get("this")
134
+ placeholder_key = str(value) if value is not None else placeholder.sql()
135
+
136
+ if not placeholder_key:
137
+ return None
138
+
139
+ if placeholder_key not in placeholder_positions:
140
+ placeholder_counter[0] += 1
141
+ placeholder_positions[placeholder_key] = placeholder_counter[0]
142
+
143
+ return placeholder_positions[placeholder_key]
144
+
145
+
146
+ @mypyc_attr(allow_interpreted_subclasses=False)
147
+ class OperationProfile:
148
+ """Semantic characteristics derived from the parsed SQL expression."""
149
+
150
+ __slots__ = ("modifies_rows", "returns_rows")
151
+
152
+ def __init__(self, returns_rows: bool = False, modifies_rows: bool = False) -> None:
153
+ self.returns_rows = returns_rows
154
+ self.modifies_rows = modifies_rows
155
+
156
+ @classmethod
157
+ def empty(cls) -> "OperationProfile":
158
+ return cls(returns_rows=False, modifies_rows=False)
159
+
160
+ def __repr__(self) -> str:
161
+ return f"OperationProfile(returns_rows={self.returns_rows!r}, modifies_rows={self.modifies_rows!r})"
162
+
163
+
164
+ def _is_effectively_empty_parameters(value: Any) -> bool:
165
+ if value is None:
166
+ return True
167
+ if isinstance(value, Mapping):
168
+ return len(value) == 0
169
+ if isinstance(value, (list, tuple, set, frozenset)):
170
+ return len(value) == 0
171
+ return False
172
+
173
+
174
+ @mypyc_attr(allow_interpreted_subclasses=False)
175
+ class CompiledSQL:
176
+ """Compiled SQL result.
177
+
178
+ Contains the result of SQL compilation with information needed for execution.
179
+ Immutable container holding compiled SQL text, processed parameters, operation
180
+ type, and execution metadata.
181
+ """
182
+
183
+ __slots__ = (
184
+ "_hash",
185
+ "compiled_sql",
186
+ "execution_parameters",
187
+ "expression",
188
+ "operation_profile",
189
+ "operation_type",
190
+ "parameter_casts",
191
+ "parameter_profile",
192
+ "parameter_style",
193
+ "supports_many",
194
+ )
195
+
196
+ operation_type: "OperationType"
197
+
198
+ def __init__(
199
+ self,
200
+ compiled_sql: str,
201
+ execution_parameters: Any,
202
+ operation_type: "OperationType",
203
+ expression: "exp.Expression | None" = None,
204
+ parameter_style: str | None = None,
205
+ supports_many: bool = False,
206
+ parameter_casts: "dict[int, str] | None" = None,
207
+ parameter_profile: "ParameterProfile | None" = None,
208
+ operation_profile: "OperationProfile | None" = None,
209
+ ) -> None:
210
+ """Initialize compiled result.
211
+
212
+ Args:
213
+ compiled_sql: SQL string ready for execution
214
+ execution_parameters: Parameters in driver-specific format
215
+ operation_type: SQL operation type (SELECT, INSERT, etc.)
216
+ expression: SQLGlot AST expression
217
+ parameter_style: Parameter style used in compilation
218
+ supports_many: Whether this supports execute_many operations
219
+ parameter_casts: Mapping of parameter positions to cast types
220
+ parameter_profile: Profile describing detected placeholders
221
+ operation_profile: Profile describing semantic characteristics
222
+ """
223
+ self.compiled_sql = compiled_sql
224
+ self.execution_parameters = execution_parameters
225
+ self.operation_type = operation_type
226
+ self.expression = expression
227
+ self.parameter_style = parameter_style
228
+ self.supports_many = supports_many
229
+ self.parameter_casts = parameter_casts or {}
230
+ self.parameter_profile = parameter_profile
231
+ self.operation_profile = operation_profile or OperationProfile.empty()
232
+ self._hash: int | None = None
233
+
234
+ def __hash__(self) -> int:
235
+ """Cached hash value."""
236
+ if self._hash is None:
237
+ param_str = str(self.execution_parameters)
238
+ self._hash = hash((self.compiled_sql, param_str, self.operation_type, self.parameter_style))
239
+ return self._hash
240
+
241
+ def __eq__(self, other: object) -> bool:
242
+ """Equality comparison."""
243
+ if not isinstance(other, CompiledSQL):
244
+ return False
245
+ return (
246
+ self.compiled_sql == other.compiled_sql
247
+ and self.execution_parameters == other.execution_parameters
248
+ and self.operation_type == other.operation_type
249
+ and self.parameter_style == other.parameter_style
250
+ )
251
+
252
+ def __repr__(self) -> str:
253
+ """String representation."""
254
+ return (
255
+ f"CompiledSQL(sql={self.compiled_sql!r}, "
256
+ f"params={self.execution_parameters!r}, "
257
+ f"type={self.operation_type!r})"
258
+ )
259
+
260
+
261
+ @mypyc_attr(allow_interpreted_subclasses=False)
262
+ class SQLProcessor:
263
+ """SQL processor with compilation and caching.
264
+
265
+ Processes SQL statements by compiling them into executable format with
266
+ parameter substitution. Includes LRU-style caching for compilation results
267
+ to avoid re-processing identical statements.
268
+ """
269
+
270
+ __slots__ = (
271
+ "_cache",
272
+ "_cache_enabled",
273
+ "_cache_hits",
274
+ "_cache_misses",
275
+ "_config",
276
+ "_max_cache_size",
277
+ "_parameter_processor",
278
+ "_parse_cache",
279
+ "_parse_cache_hits",
280
+ "_parse_cache_max_size",
281
+ "_parse_cache_misses",
282
+ )
283
+
284
+ def __init__(
285
+ self,
286
+ config: "StatementConfig",
287
+ max_cache_size: int = 1000,
288
+ parse_cache_size: int | None = None,
289
+ parameter_cache_size: int | None = None,
290
+ validator_cache_size: int | None = None,
291
+ cache_enabled: bool = True,
292
+ ) -> None:
293
+ """Initialize processor.
294
+
295
+ Args:
296
+ config: Statement configuration
297
+ max_cache_size: Maximum number of compilation results to cache
298
+ parse_cache_size: Maximum number of parsed expressions to cache
299
+ parameter_cache_size: Maximum parameter conversion cache entries
300
+ validator_cache_size: Maximum cached parameter metadata entries
301
+ cache_enabled: Toggle compiled SQL caching (parse/parameter caches remain size-driven)
302
+ """
303
+ self._config = config
304
+ self._cache: OrderedDict[str, CompiledSQL] = OrderedDict()
305
+ self._max_cache_size = max(max_cache_size, 0)
306
+ compiled_cache_active = cache_enabled and config.enable_caching and self._max_cache_size > 0
307
+ self._cache_enabled = compiled_cache_active
308
+ parse_cache_max_size = self._max_cache_size if parse_cache_size is None else parse_cache_size
309
+ self._parse_cache_max_size = max(parse_cache_max_size, 0)
310
+ if not config.enable_caching:
311
+ self._parse_cache_max_size = 0
312
+ parameter_cache = parameter_cache_size if parameter_cache_size is not None else self._parse_cache_max_size
313
+ validator_cache = validator_cache_size if validator_cache_size is not None else parameter_cache
314
+ if not config.enable_caching:
315
+ parameter_cache = 0
316
+ validator_cache = 0
317
+ self._parameter_processor = ParameterProcessor(
318
+ converter=config.parameter_converter,
319
+ validator=config.parameter_validator,
320
+ cache_max_size=parameter_cache,
321
+ validator_cache_max_size=validator_cache,
322
+ )
323
+ self._cache_hits = 0
324
+ self._cache_misses = 0
325
+ self._parse_cache: OrderedDict[
326
+ str, tuple[exp.Expression | None, OperationType, dict[int, str], tuple[bool, bool]]
327
+ ] = OrderedDict()
328
+ self._parse_cache_hits = 0
329
+ self._parse_cache_misses = 0
330
+
331
+ def compile(
332
+ self, sql: str, parameters: Any = None, is_many: bool = False, expression: "exp.Expression | None" = None
333
+ ) -> CompiledSQL:
334
+ """Compile SQL statement.
335
+
336
+ Args:
337
+ sql: SQL string for compilation
338
+ parameters: Parameter values for substitution
339
+ is_many: Whether this is for execute_many operation
340
+ expression: Pre-parsed SQLGlot expression to reuse
341
+
342
+ Returns:
343
+ CompiledSQL with execution information
344
+ """
345
+ if not self._config.enable_caching or not self._cache_enabled:
346
+ return self._compile_uncached(sql, parameters, is_many, expression)
347
+
348
+ cache_key = self._make_cache_key(sql, parameters, is_many)
349
+
350
+ if cache_key in self._cache:
351
+ result = self._cache[cache_key]
352
+ del self._cache[cache_key]
353
+ self._cache[cache_key] = result
354
+ self._cache_hits += 1
355
+ return result
356
+
357
+ self._cache_misses += 1
358
+ result = self._compile_uncached(sql, parameters, is_many, expression)
359
+
360
+ if len(self._cache) >= self._max_cache_size:
361
+ self._cache.popitem(last=False)
362
+
363
+ self._cache[cache_key] = result
364
+ return result
365
+
366
+ def _prepare_parameters(
367
+ self, sql: str, parameters: Any, is_many: bool, dialect_str: "str | None"
368
+ ) -> "tuple[str, Any, ParameterProfile, str]":
369
+ """Process SQL parameters for compilation.
370
+
371
+ Args:
372
+ sql: SQL string.
373
+ parameters: Raw parameters.
374
+ is_many: Whether this is for execute_many.
375
+ dialect_str: Dialect name.
376
+
377
+ Returns:
378
+ Tuple of processed SQL, processed parameters, parameter profile, and SQLGlot SQL.
379
+ """
380
+ process_result = self._parameter_processor.process(
381
+ sql=sql,
382
+ parameters=parameters,
383
+ config=self._config.parameter_config,
384
+ dialect=dialect_str,
385
+ is_many=is_many,
386
+ wrap_types=self._config.enable_parameter_type_wrapping,
387
+ )
388
+ return (
389
+ process_result.sql,
390
+ process_result.parameters,
391
+ process_result.parameter_profile,
392
+ process_result.sqlglot_sql,
393
+ )
394
+
395
+ def _normalize_expression_override(
396
+ self, expression_override: "exp.Expression | None", sqlglot_sql: str, sql: str
397
+ ) -> "exp.Expression | None":
398
+ """Validate expression overrides against the input SQL.
399
+
400
+ Args:
401
+ expression_override: Pre-parsed SQLGlot expression.
402
+ sqlglot_sql: SQL passed to SQLGlot.
403
+ sql: Original SQL string.
404
+
405
+ Returns:
406
+ Expression override when it is safe to reuse.
407
+ """
408
+ if expression_override is None:
409
+ return None
410
+ if sqlglot_sql != sql:
411
+ return None
412
+ return expression_override
413
+
414
+ def _parse_expression_uncached(
415
+ self, sqlglot_sql: str, dialect_str: "str | None", expression_override: "exp.Expression | None"
416
+ ) -> "tuple[exp.Expression | None, OperationType, dict[int, str], OperationProfile]":
417
+ """Parse SQL into an expression without cache.
418
+
419
+ Args:
420
+ sqlglot_sql: SQL string for SQLGlot.
421
+ dialect_str: Dialect name.
422
+ expression_override: Pre-parsed SQLGlot expression.
423
+
424
+ Returns:
425
+ Expression details and derived metadata.
426
+ """
427
+ try:
428
+ if expression_override is not None:
429
+ expression = expression_override
430
+ else:
431
+ expression = sqlglot.parse_one(sqlglot_sql, dialect=dialect_str)
432
+ except ParseError:
433
+ return None, "EXECUTE", {}, OperationProfile.empty()
434
+ else:
435
+ operation_type = self._detect_operation_type(expression)
436
+ parameter_casts = self._detect_parameter_casts(expression)
437
+ operation_profile = self._build_operation_profile(expression, operation_type)
438
+ return expression, operation_type, parameter_casts, operation_profile
439
+
440
+ def _store_parse_cache(
441
+ self,
442
+ parse_cache_key: str,
443
+ expression: "exp.Expression | None",
444
+ operation_type: "OperationType",
445
+ parameter_casts: "dict[int, str]",
446
+ operation_profile: "OperationProfile",
447
+ ) -> None:
448
+ """Store parsed expression details in cache.
449
+
450
+ Args:
451
+ parse_cache_key: Cache key for the parsed SQL.
452
+ expression: Parsed SQLGlot expression.
453
+ operation_type: Detected operation type.
454
+ parameter_casts: Parameter cast mappings.
455
+ operation_profile: Operation metadata.
456
+ """
457
+ if len(self._parse_cache) >= self._parse_cache_max_size:
458
+ self._parse_cache.popitem(last=False)
459
+ cache_expression = expression.copy() if expression is not None else None
460
+ self._parse_cache[parse_cache_key] = (
461
+ cache_expression,
462
+ operation_type,
463
+ parameter_casts,
464
+ (operation_profile.returns_rows, operation_profile.modifies_rows),
465
+ )
466
+
467
+ def _unpack_parse_cache_entry(
468
+ self, parse_cache_entry: "ParseCacheEntry"
469
+ ) -> "tuple[exp.Expression | None, OperationType, dict[int, str], OperationProfile]":
470
+ """Expand cached parse results into runtime objects.
471
+
472
+ Args:
473
+ parse_cache_entry: Cached parse entry.
474
+
475
+ Returns:
476
+ Parsed expression metadata.
477
+ """
478
+ cached_expression, cached_operation, cached_casts, cached_profile = parse_cache_entry
479
+ expression = cached_expression.copy() if cached_expression is not None else None
480
+ operation_profile = OperationProfile(returns_rows=cached_profile[0], modifies_rows=cached_profile[1])
481
+ return expression, cached_operation, dict(cached_casts), operation_profile
482
+
483
+ def _resolve_expression(
484
+ self, sqlglot_sql: str, dialect_str: "str | None", expression_override: "exp.Expression | None"
485
+ ) -> "tuple[exp.Expression | None, OperationType, dict[int, str], OperationProfile, str | None, ParseCacheEntry | None]":
486
+ """Resolve an SQLGlot expression with caching.
487
+
488
+ Args:
489
+ sqlglot_sql: SQL string for SQLGlot.
490
+ dialect_str: Dialect name.
491
+ expression_override: Pre-parsed SQLGlot expression.
492
+
493
+ Returns:
494
+ Expression metadata and parse cache information.
495
+ """
496
+ parse_cache_key = None
497
+ parse_cache_entry = None
498
+ if self._config.enable_caching and self._parse_cache_max_size > 0:
499
+ parse_cache_key = self._make_parse_cache_key(sqlglot_sql, dialect_str)
500
+ parse_cache_entry = self._parse_cache.get(parse_cache_key)
501
+ if parse_cache_entry is not None:
502
+ self._parse_cache_hits += 1
503
+ self._parse_cache.move_to_end(parse_cache_key)
504
+ if parse_cache_entry is None:
505
+ self._parse_cache_misses += 1
506
+ expression, operation_type, parameter_casts, operation_profile = self._parse_expression_uncached(
507
+ sqlglot_sql, dialect_str, expression_override
508
+ )
509
+ if parse_cache_key is not None:
510
+ self._store_parse_cache(parse_cache_key, expression, operation_type, parameter_casts, operation_profile)
511
+ else:
512
+ expression, operation_type, parameter_casts, operation_profile = self._unpack_parse_cache_entry(
513
+ parse_cache_entry
514
+ )
515
+ return expression, operation_type, parameter_casts, operation_profile, parse_cache_key, parse_cache_entry
516
+
517
+ def _apply_ast_transformers(
518
+ self,
519
+ expression: "exp.Expression | None",
520
+ parameters: Any,
521
+ parameter_profile: "ParameterProfile",
522
+ operation_type: "OperationType",
523
+ parameter_casts: "dict[int, str]",
524
+ operation_profile: "OperationProfile",
525
+ parse_cache_key: "str | None",
526
+ parse_cache_entry: "ParseCacheEntry | None",
527
+ expression_override: "exp.Expression | None",
528
+ ) -> "tuple[exp.Expression | None, Any, bool, OperationType, dict[int, str], OperationProfile]":
529
+ """Apply AST transformers and update metadata.
530
+
531
+ Args:
532
+ expression: SQLGlot expression to transform.
533
+ parameters: Execution parameters.
534
+ parameter_profile: Parameter profile metadata.
535
+ operation_type: Current operation type.
536
+ parameter_casts: Current parameter cast mapping.
537
+ operation_profile: Current operation profile.
538
+ parse_cache_key: Parse cache key when used.
539
+ parse_cache_entry: Cached parse entry when available.
540
+ expression_override: Expression override reference.
541
+
542
+ Returns:
543
+ Updated expression metadata and transformation state.
544
+ """
545
+ statement_transformers = self._config.statement_transformers
546
+ ast_transformer = self._config.parameter_config.ast_transformer
547
+ if expression is None or (not statement_transformers and not ast_transformer):
548
+ return expression, parameters, False, operation_type, parameter_casts, operation_profile
549
+
550
+ should_copy = False
551
+ if parse_cache_key is not None and parse_cache_entry is None:
552
+ should_copy = True
553
+ if expression_override is not None and expression is expression_override:
554
+ should_copy = True
555
+ if should_copy:
556
+ expression = expression.copy()
557
+
558
+ ast_was_transformed = False
559
+ if statement_transformers:
560
+ for transformer in statement_transformers:
561
+ expression, parameters = transformer(expression, parameters)
562
+ ast_was_transformed = True
563
+ if ast_transformer:
564
+ expression, parameters = ast_transformer(expression, parameters, parameter_profile)
565
+ ast_was_transformed = True
566
+ if ast_was_transformed:
567
+ if expression is None:
568
+ return expression, parameters, ast_was_transformed, operation_type, parameter_casts, operation_profile
569
+ operation_type = self._detect_operation_type(expression)
570
+ parameter_casts = self._detect_parameter_casts(expression)
571
+ operation_profile = self._build_operation_profile(expression, operation_type)
572
+
573
+ return expression, parameters, ast_was_transformed, operation_type, parameter_casts, operation_profile
574
+
575
+ def _finalize_compilation(
576
+ self,
577
+ processed_sql: str,
578
+ processed_params: Any,
579
+ expression: "exp.Expression | None",
580
+ parameters: Any,
581
+ parameter_profile: "ParameterProfile",
582
+ is_many: bool,
583
+ dialect_str: "str | None",
584
+ ast_was_transformed: bool,
585
+ ) -> "tuple[str, Any, ParameterProfile]":
586
+ """Finalize SQL and parameter conversion for execution.
587
+
588
+ Args:
589
+ processed_sql: SQL after parameter processing.
590
+ processed_params: Parameters after initial processing.
591
+ expression: SQLGlot expression if available.
592
+ parameters: Parameters to compile for execution.
593
+ parameter_profile: Parameter profile metadata.
594
+ is_many: Whether this is for execute_many.
595
+ dialect_str: Dialect name.
596
+ ast_was_transformed: Whether AST transformations ran.
597
+
598
+ Returns:
599
+ Final SQL, execution parameters, and parameter profile.
600
+ """
601
+ if self._config.parameter_config.needs_static_script_compilation and processed_params is None:
602
+ return processed_sql, processed_params, parameter_profile
603
+ if ast_was_transformed and expression is not None:
604
+ transformed_result = self._parameter_processor.process_for_execution(
605
+ sql=expression.sql(dialect=dialect_str),
606
+ parameters=parameters,
607
+ config=self._config.parameter_config,
608
+ dialect=dialect_str,
609
+ is_many=is_many,
610
+ wrap_types=self._config.enable_parameter_type_wrapping,
611
+ )
612
+ final_sql = transformed_result.sql
613
+ final_params = transformed_result.parameters
614
+ parameter_profile = transformed_result.parameter_profile
615
+ output_transformer = self._config.output_transformer
616
+ if output_transformer:
617
+ final_sql, final_params = output_transformer(final_sql, final_params)
618
+ return final_sql, final_params, parameter_profile
619
+
620
+ final_sql, final_params = self._apply_final_transformations(expression, processed_sql, parameters, dialect_str)
621
+ return final_sql, final_params, parameter_profile
622
+
623
+ def _should_validate_parameters(self, final_params: Any, raw_parameters: Any, is_many: bool) -> bool:
624
+ """Determine if parameter alignment should be validated.
625
+
626
+ Args:
627
+ final_params: Parameters after compilation.
628
+ raw_parameters: Original parameters.
629
+ is_many: Whether this is for execute_many.
630
+
631
+ Returns:
632
+ True when validation should run.
633
+ """
634
+ if not self._config.enable_validation:
635
+ return False
636
+ return not (
637
+ _is_effectively_empty_parameters(final_params)
638
+ and _is_effectively_empty_parameters(raw_parameters)
639
+ and not is_many
640
+ )
641
+
642
+ def _validate_parameters(self, parameter_profile: "ParameterProfile", final_params: Any, is_many: bool) -> None:
643
+ """Validate parameter alignment and log failures.
644
+
645
+ Args:
646
+ parameter_profile: Parameter metadata.
647
+ final_params: Execution parameters.
648
+ is_many: Whether this is for execute_many.
649
+
650
+ Raises:
651
+ Exception: Re-raises validation errors from parameter alignment.
652
+ """
653
+ try:
654
+ validate_parameter_alignment(parameter_profile, final_params, is_many=is_many)
655
+ except Exception as exc:
656
+ log_with_context(logger, logging.ERROR, "sql.validate", error_type=type(exc).__name__)
657
+ raise
658
+
659
+ def _compile_uncached(
660
+ self, sql: str, parameters: Any, is_many: bool = False, expression_override: "exp.Expression | None" = None
661
+ ) -> CompiledSQL:
662
+ """Compile SQL without caching.
663
+
664
+ Args:
665
+ sql: SQL string
666
+ parameters: Parameter values
667
+ is_many: Whether this is for execute_many operation
668
+ expression_override: Pre-parsed SQLGlot expression to reuse
669
+
670
+ Returns:
671
+ CompiledSQL result
672
+ """
673
+ parameter_profile = ParameterProfile.empty()
674
+ operation_profile = OperationProfile.empty()
675
+
676
+ try:
677
+ dialect_str = str(self._config.dialect) if self._config.dialect else None
678
+ processed_sql, processed_params, parameter_profile, sqlglot_sql = self._prepare_parameters(
679
+ sql, parameters, is_many, dialect_str
680
+ )
681
+ expression_override = self._normalize_expression_override(expression_override, sqlglot_sql, sql)
682
+
683
+ final_parameters = processed_params
684
+ ast_was_transformed = False
685
+ expression = None
686
+ operation_type: OperationType = "EXECUTE"
687
+ parameter_casts: dict[int, str] = {}
688
+ parse_cache_key = None
689
+ parse_cache_entry = None
690
+
691
+ if self._config.enable_parsing:
692
+ (expression, operation_type, parameter_casts, operation_profile, parse_cache_key, parse_cache_entry) = (
693
+ self._resolve_expression(sqlglot_sql, dialect_str, expression_override)
694
+ )
695
+ (
696
+ expression,
697
+ final_parameters,
698
+ ast_was_transformed,
699
+ operation_type,
700
+ parameter_casts,
701
+ operation_profile,
702
+ ) = self._apply_ast_transformers(
703
+ expression,
704
+ final_parameters,
705
+ parameter_profile,
706
+ operation_type,
707
+ parameter_casts,
708
+ operation_profile,
709
+ parse_cache_key,
710
+ parse_cache_entry,
711
+ expression_override,
712
+ )
713
+
714
+ final_sql, final_params, parameter_profile = self._finalize_compilation(
715
+ processed_sql,
716
+ processed_params,
717
+ expression,
718
+ final_parameters,
719
+ parameter_profile,
720
+ is_many,
721
+ dialect_str,
722
+ ast_was_transformed,
723
+ )
724
+
725
+ if self._should_validate_parameters(final_params, parameters, is_many):
726
+ self._validate_parameters(parameter_profile, final_params, is_many)
727
+
728
+ return CompiledSQL(
729
+ compiled_sql=final_sql,
730
+ execution_parameters=final_params,
731
+ operation_type=operation_type,
732
+ expression=expression,
733
+ parameter_style=self._config.parameter_config.default_parameter_style.value,
734
+ supports_many=isinstance(final_params, list) and len(final_params) > 0,
735
+ parameter_casts=parameter_casts,
736
+ parameter_profile=parameter_profile,
737
+ operation_profile=operation_profile,
738
+ )
739
+
740
+ except sqlspec.exceptions.SQLSpecError:
741
+ raise
742
+ except Exception as exc:
743
+ log_with_context(logger, logging.DEBUG, "sql.compile", error_type=type(exc).__name__, status="fallback")
744
+ return CompiledSQL(
745
+ compiled_sql=sql,
746
+ execution_parameters=parameters,
747
+ operation_type="UNKNOWN",
748
+ parameter_casts={},
749
+ parameter_profile=parameter_profile,
750
+ operation_profile=operation_profile,
751
+ )
752
+
753
+ def _make_cache_key(self, sql: str, parameters: Any, is_many: bool = False) -> str:
754
+ """Generate cache key.
755
+
756
+ Args:
757
+ sql: SQL string
758
+ parameters: Parameter values
759
+ is_many: Whether this is for execute_many operation
760
+
761
+ Returns:
762
+ Cache key string
763
+ """
764
+
765
+ param_fingerprint = fingerprint_parameters(parameters)
766
+ dialect_str = str(self._config.dialect) if self._config.dialect else None
767
+ param_style = self._config.parameter_config.default_parameter_style.value
768
+
769
+ hash_data = (
770
+ sql,
771
+ param_fingerprint,
772
+ param_style,
773
+ dialect_str,
774
+ self._config.enable_parsing,
775
+ self._config.enable_transformations,
776
+ is_many,
777
+ )
778
+
779
+ hash_str = hashlib.blake2b(repr(hash_data).encode("utf-8"), digest_size=8).hexdigest()
780
+ return f"sql_{hash_str}"
781
+
782
+ def _detect_operation_type(self, expression: "exp.Expression") -> "OperationType":
783
+ """Detect operation type from AST.
784
+
785
+ Args:
786
+ expression: AST expression
787
+
788
+ Returns:
789
+ Operation type literal
790
+ """
791
+
792
+ expr_type = type(expression)
793
+ if expr_type in OPERATION_TYPE_MAP:
794
+ return OPERATION_TYPE_MAP[expr_type] # pyright: ignore
795
+
796
+ if isinstance(expression, exp.Copy):
797
+ copy_kind = expression.args.get("kind")
798
+ if copy_kind is True:
799
+ return "COPY_FROM"
800
+ if copy_kind is False:
801
+ return "COPY_TO"
802
+ return "COPY"
803
+
804
+ return "UNKNOWN"
805
+
806
+ def _detect_parameter_casts(self, expression: "exp.Expression | None") -> "dict[int, str]":
807
+ """Detect explicit type casts on parameters in the AST.
808
+
809
+ Args:
810
+ expression: SQLGlot AST expression to analyze
811
+
812
+ Returns:
813
+ Dict mapping parameter positions (1-based) to cast type names
814
+ """
815
+ if not expression:
816
+ return {}
817
+
818
+ cast_positions: dict[int, str] = {}
819
+ placeholder_positions: dict[str, int] = {}
820
+ placeholder_counter = [0]
821
+
822
+ # Walk all nodes in order to track parameter positions
823
+ for node in expression.walk():
824
+ if isinstance(node, exp.Placeholder):
825
+ _assign_placeholder_position(node, placeholder_positions, placeholder_counter)
826
+ # Check for cast nodes with parameter children
827
+ if isinstance(node, exp.Cast):
828
+ cast_target = node.this
829
+ position = None
830
+
831
+ if isinstance(cast_target, exp.Parameter):
832
+ # Handle $1, $2 style parameters
833
+ param_value = cast_target.this
834
+ if isinstance(param_value, exp.Literal):
835
+ position = int(param_value.this)
836
+ elif isinstance(cast_target, exp.Placeholder):
837
+ position = _assign_placeholder_position(cast_target, placeholder_positions, placeholder_counter)
838
+ elif isinstance(cast_target, exp.Column):
839
+ # Handle cases where $1 gets parsed as a column
840
+ column_name = str(cast_target.this) if cast_target.this else str(cast_target)
841
+ if column_name.startswith("$") and column_name[1:].isdigit():
842
+ position = int(column_name[1:])
843
+
844
+ if position is not None:
845
+ # Extract cast type
846
+ if isinstance(node.to, exp.DataType):
847
+ cast_type = str(get_value_attribute(node.to.this))
848
+ else:
849
+ cast_type = str(node.to)
850
+ cast_positions[position] = cast_type.upper()
851
+
852
+ return cast_positions
853
+
854
+ def _apply_final_transformations(
855
+ self, expression: "exp.Expression | None", sql: str, parameters: Any, dialect_str: "str | None"
856
+ ) -> "tuple[str, Any]":
857
+ """Apply final transformations.
858
+
859
+ Args:
860
+ expression: SQLGlot AST expression
861
+ sql: SQL string
862
+ parameters: Execution parameters
863
+ dialect_str: SQL dialect
864
+
865
+ Returns:
866
+ Tuple of (final_sql, final_parameters)
867
+ """
868
+ output_transformer = self._config.output_transformer
869
+ if output_transformer:
870
+ if expression is not None:
871
+ ast_sql = expression.sql(dialect=dialect_str)
872
+ return output_transformer(ast_sql, parameters)
873
+ return output_transformer(sql, parameters)
874
+
875
+ return sql, parameters
876
+
877
+ def _build_operation_profile(
878
+ self, expression: "exp.Expression | None", operation_type: "OperationType"
879
+ ) -> "OperationProfile":
880
+ if expression is None:
881
+ return OperationProfile.empty()
882
+
883
+ returns_rows = False
884
+ modifies_rows = False
885
+
886
+ expr = expression
887
+ if isinstance(
888
+ expr, (exp.Select, exp.Union, exp.Except, exp.Intersect, exp.Values, exp.Table, exp.TableSample, exp.With)
889
+ ):
890
+ returns_rows = True
891
+ elif isinstance(expr, (exp.Insert, exp.Update, exp.Delete, exp.Merge)):
892
+ modifies_rows = True
893
+ returns_rows = bool(expr.args.get("returning"))
894
+ elif isinstance(expr, exp.Copy):
895
+ copy_kind = expr.args.get("kind")
896
+ modifies_rows = copy_kind is True
897
+ returns_rows = copy_kind is False
898
+
899
+ if not returns_rows and operation_type in {"SELECT", "WITH", "VALUES", "TABLE"}:
900
+ returns_rows = True
901
+
902
+ if not modifies_rows and operation_type in {"INSERT", "UPDATE", "DELETE", "MERGE"}:
903
+ modifies_rows = True
904
+
905
+ return OperationProfile(returns_rows=returns_rows, modifies_rows=modifies_rows)
906
+
907
+ def clear_cache(self) -> None:
908
+ """Clear compilation cache and reset statistics."""
909
+ self._cache.clear()
910
+ self._cache_hits = 0
911
+ self._cache_misses = 0
912
+ self._parse_cache.clear()
913
+ self._parse_cache_hits = 0
914
+ self._parse_cache_misses = 0
915
+ self._parameter_processor.clear_cache()
916
+
917
+ def _make_parse_cache_key(self, sql: str, dialect: "str | None") -> str:
918
+ dialect_marker = dialect or "default"
919
+ hash_str = hashlib.sha256(f"{dialect_marker}:{sql}".encode()).hexdigest()[:16]
920
+ return f"parse_{hash_str}"
921
+
922
+ @property
923
+ def cache_stats(self) -> "dict[str, int]":
924
+ """Get cache statistics.
925
+
926
+ Returns:
927
+ Dictionary with cache statistics
928
+ """
929
+ total_requests = self._cache_hits + self._cache_misses
930
+ hit_rate_pct = int((self._cache_hits / total_requests) * 100) if total_requests > 0 else 0
931
+ parse_total = self._parse_cache_hits + self._parse_cache_misses
932
+ parse_hit_rate_pct = int((self._parse_cache_hits / parse_total) * 100) if parse_total > 0 else 0
933
+ parameter_stats = self._parameter_processor.cache_stats()
934
+
935
+ return {
936
+ "hits": self._cache_hits,
937
+ "misses": self._cache_misses,
938
+ "size": len(self._cache),
939
+ "max_size": self._max_cache_size,
940
+ "hit_rate_percent": hit_rate_pct,
941
+ "parse_hits": self._parse_cache_hits,
942
+ "parse_misses": self._parse_cache_misses,
943
+ "parse_size": len(self._parse_cache),
944
+ "parse_max_size": self._parse_cache_max_size,
945
+ "parse_hit_rate_percent": parse_hit_rate_pct,
946
+ "parameter_hits": parameter_stats["hits"],
947
+ "parameter_misses": parameter_stats["misses"],
948
+ "parameter_size": parameter_stats["size"],
949
+ "parameter_max_size": parameter_stats["max_size"],
950
+ "validator_hits": parameter_stats["validator_hits"],
951
+ "validator_misses": parameter_stats["validator_misses"],
952
+ "validator_size": parameter_stats["validator_size"],
953
+ "validator_max_size": parameter_stats["validator_max_size"],
954
+ }