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,310 @@
1
+ """Psqlpy LISTEN/NOTIFY and hybrid event backends."""
2
+
3
+ # pyright: ignore=reportPrivateUsage
4
+ import asyncio
5
+ import contextlib
6
+ import logging
7
+ from datetime import datetime, timezone
8
+ from typing import TYPE_CHECKING, Any, cast
9
+
10
+ from sqlspec.core import SQL
11
+ from sqlspec.exceptions import ImproperConfigurationError
12
+ from sqlspec.extensions.events import (
13
+ AsyncTableEventQueue,
14
+ EventMessage,
15
+ build_queue_backend,
16
+ decode_notify_payload,
17
+ encode_notify_payload,
18
+ )
19
+ from sqlspec.extensions.events import normalize_event_channel_name as _normalize_channel
20
+ from sqlspec.protocols import NotificationProtocol
21
+ from sqlspec.utils.logging import get_logger, log_with_context
22
+ from sqlspec.utils.serializers import to_json
23
+ from sqlspec.utils.uuids import uuid4
24
+
25
+ if TYPE_CHECKING:
26
+ from psqlpy import Listener
27
+
28
+ from sqlspec.adapters.psqlpy.config import PsqlpyConfig
29
+
30
+
31
+ logger = get_logger("sqlspec.events.psqlpy")
32
+
33
+ __all__ = ("PsqlpyEventsBackend", "PsqlpyHybridEventsBackend", "create_event_backend")
34
+
35
+ _PSQLPY_CALLBACK_MIN_ARGS = 3
36
+
37
+
38
+ class _PsqlpyNotifyCapture:
39
+ __slots__ = ("_channel", "_event", "payload")
40
+
41
+ def __init__(self, channel: str, event: asyncio.Event) -> None:
42
+ self._channel = channel
43
+ self._event = event
44
+ self.payload: str | None = None
45
+
46
+ async def __call__(self, *args: Any) -> None:
47
+ if not args:
48
+ return
49
+
50
+ notified_channel: str | None = None
51
+ payload: str | None = None
52
+
53
+ if len(args) == 1:
54
+ message = args[0]
55
+ if isinstance(message, NotificationProtocol):
56
+ notified_channel = message.channel
57
+ payload = message.payload
58
+ elif len(args) >= _PSQLPY_CALLBACK_MIN_ARGS:
59
+ value1 = cast("str", args[1])
60
+ value2 = cast("str", args[2])
61
+ if value1 == self._channel:
62
+ notified_channel = value1
63
+ payload = value2
64
+ elif value2 == self._channel:
65
+ notified_channel = value2
66
+ payload = value1
67
+ else:
68
+ return
69
+
70
+ if notified_channel == self._channel and payload is not None and self.payload is None:
71
+ self.payload = payload
72
+ self._event.set()
73
+
74
+
75
+ class _PsqlpyNotifySignal:
76
+ __slots__ = ("_channel", "_event")
77
+
78
+ def __init__(self, channel: str, event: asyncio.Event) -> None:
79
+ self._channel = channel
80
+ self._event = event
81
+
82
+ async def __call__(self, *args: Any) -> None:
83
+ if not args:
84
+ return
85
+
86
+ notified_channel: str | None = None
87
+ if len(args) == 1:
88
+ message = args[0]
89
+ if isinstance(message, NotificationProtocol):
90
+ notified_channel = message.channel
91
+ elif len(args) >= _PSQLPY_CALLBACK_MIN_ARGS:
92
+ value1 = cast("str", args[1])
93
+ value2 = cast("str", args[2])
94
+ if value1 == self._channel:
95
+ notified_channel = value1
96
+ elif value2 == self._channel:
97
+ notified_channel = value2
98
+
99
+ if notified_channel == self._channel:
100
+ self._event.set()
101
+
102
+
103
+ class PsqlpyEventsBackend:
104
+ """Native LISTEN/NOTIFY backend for psqlpy adapters.
105
+
106
+ Uses psqlpy's Listener API which provides a dedicated connection for
107
+ receiving PostgreSQL NOTIFY messages via callbacks or async iteration.
108
+ """
109
+
110
+ __slots__ = ("_config", "_listener", "_listener_started", "_runtime")
111
+
112
+ supports_sync = False
113
+ supports_async = True
114
+ backend_name = "listen_notify"
115
+
116
+ def __init__(self, config: "PsqlpyConfig") -> None:
117
+ if "psqlpy" not in type(config).__module__:
118
+ msg = "Psqlpy events backend requires a Psqlpy adapter"
119
+ raise ImproperConfigurationError(msg)
120
+ self._config = config
121
+ self._runtime = config.get_observability_runtime()
122
+ self._listener: Any | None = None
123
+ self._listener_started: bool = False
124
+ log_with_context(
125
+ logger,
126
+ logging.DEBUG,
127
+ "event.listen",
128
+ adapter_name="psqlpy",
129
+ backend_name=self.backend_name,
130
+ mode="async",
131
+ status="backend_ready",
132
+ )
133
+
134
+ async def publish(self, channel: str, payload: "dict[str, Any]", metadata: "dict[str, Any] | None" = None) -> str:
135
+ event_id = uuid4().hex
136
+ async with self._config.provide_session() as driver:
137
+ await driver.execute_script(
138
+ SQL("SELECT pg_notify($1, $2)", channel, encode_notify_payload(event_id, payload, metadata))
139
+ )
140
+ await driver.commit()
141
+ self._runtime.increment_metric("events.publish.native")
142
+ return event_id
143
+
144
+ async def dequeue(self, channel: str, poll_interval: float) -> EventMessage | None:
145
+ listener = await self._ensure_listener(channel)
146
+ event = asyncio.Event()
147
+ callback = _PsqlpyNotifyCapture(channel, event)
148
+ await listener.add_callback(channel=channel, callback=callback.__call__)
149
+
150
+ if not self._listener_started:
151
+ listener.listen()
152
+ self._listener_started = True
153
+ await asyncio.sleep(0.05)
154
+
155
+ with contextlib.suppress(asyncio.TimeoutError):
156
+ await asyncio.wait_for(event.wait(), timeout=poll_interval)
157
+
158
+ await listener.clear_channel_callbacks(channel=channel)
159
+ return decode_notify_payload(channel, callback.payload) if callback.payload is not None else None
160
+
161
+ async def ack(self, _event_id: str) -> None:
162
+ self._runtime.increment_metric("events.ack")
163
+
164
+ async def nack(self, _event_id: str) -> None:
165
+ """Return an event to the queue (no-op for native LISTEN/NOTIFY)."""
166
+
167
+ async def shutdown(self) -> None:
168
+ """Shutdown the listener and release resources."""
169
+ if self._listener is not None:
170
+ if self._listener_started:
171
+ self._listener.abort_listen()
172
+ self._listener_started = False
173
+ await self._listener.shutdown()
174
+ self._listener = None
175
+
176
+ async def _ensure_listener(self, channel: str) -> "Listener":
177
+ """Ensure a listener is created for receiving notifications."""
178
+ _normalize_channel(channel)
179
+ if self._listener is None:
180
+ pool = await self._config.provide_pool()
181
+ self._listener = pool.listener()
182
+ await self._listener.startup()
183
+ return self._listener
184
+
185
+
186
+ class PsqlpyHybridEventsBackend:
187
+ """Durable hybrid backend combining queue storage with LISTEN/NOTIFY wakeups.
188
+
189
+ Uses psqlpy's Listener API for real-time notifications while persisting
190
+ events to a durable queue table.
191
+ """
192
+
193
+ __slots__ = ("_config", "_listener", "_listener_started", "_queue", "_runtime")
194
+
195
+ supports_sync = False
196
+ supports_async = True
197
+ backend_name = "listen_notify_durable"
198
+
199
+ def __init__(self, config: "PsqlpyConfig", queue: "AsyncTableEventQueue") -> None:
200
+ if "psqlpy" not in type(config).__module__:
201
+ msg = "Psqlpy hybrid backend requires a Psqlpy adapter"
202
+ raise ImproperConfigurationError(msg)
203
+ self._config = config
204
+ self._queue = queue
205
+ self._runtime = config.get_observability_runtime()
206
+ self._listener: Any | None = None
207
+ self._listener_started: bool = False
208
+ log_with_context(
209
+ logger,
210
+ logging.DEBUG,
211
+ "event.listen",
212
+ adapter_name="psqlpy",
213
+ backend_name=self.backend_name,
214
+ mode="async",
215
+ status="backend_ready",
216
+ )
217
+
218
+ async def publish(self, channel: str, payload: "dict[str, Any]", metadata: "dict[str, Any] | None" = None) -> str:
219
+ event_id = uuid4().hex
220
+ await self._publish_durable(channel, event_id, payload, metadata)
221
+ self._runtime.increment_metric("events.publish.native")
222
+ return event_id
223
+
224
+ async def dequeue(self, channel: str, poll_interval: float) -> EventMessage | None:
225
+ listener = await self._ensure_listener(channel)
226
+ event = asyncio.Event()
227
+ callback = _PsqlpyNotifySignal(channel, event)
228
+ await listener.add_callback(channel=channel, callback=callback.__call__)
229
+
230
+ if not self._listener_started:
231
+ listener.listen()
232
+ self._listener_started = True
233
+ await asyncio.sleep(0.05)
234
+
235
+ with contextlib.suppress(asyncio.TimeoutError):
236
+ await asyncio.wait_for(event.wait(), timeout=poll_interval)
237
+
238
+ await listener.clear_channel_callbacks(channel=channel)
239
+ return await self._queue.dequeue(channel, poll_interval)
240
+
241
+ async def ack(self, event_id: str) -> None:
242
+ await self._queue.ack(event_id)
243
+ self._runtime.increment_metric("events.ack")
244
+
245
+ async def nack(self, event_id: str) -> None:
246
+ await self._queue.nack(event_id)
247
+ self._runtime.increment_metric("events.nack")
248
+
249
+ async def shutdown(self) -> None:
250
+ """Shutdown the listener and release resources."""
251
+ if self._listener is not None:
252
+ if self._listener_started:
253
+ self._listener.abort_listen()
254
+ self._listener_started = False
255
+ await self._listener.shutdown()
256
+ self._listener = None
257
+
258
+ async def _ensure_listener(self, channel: str) -> "Listener":
259
+ """Ensure a listener is created for receiving notifications."""
260
+ _normalize_channel(channel)
261
+ if self._listener is None:
262
+ pool = await self._config.provide_pool()
263
+ self._listener = pool.listener()
264
+ await self._listener.startup()
265
+ return self._listener
266
+
267
+ async def _publish_durable(
268
+ self, channel: str, event_id: str, payload: "dict[str, Any]", metadata: "dict[str, Any] | None"
269
+ ) -> None:
270
+ now = datetime.now(timezone.utc)
271
+ async with self._config.provide_session() as driver:
272
+ await driver.execute(
273
+ SQL(
274
+ self._queue._upsert_sql, # pyright: ignore[reportPrivateUsage]
275
+ {
276
+ "event_id": event_id,
277
+ "channel": channel,
278
+ "payload_json": payload,
279
+ "metadata_json": metadata,
280
+ "status": "pending",
281
+ "available_at": now,
282
+ "lease_expires_at": None,
283
+ "attempts": 0,
284
+ "created_at": now,
285
+ },
286
+ statement_config=self._queue._statement_config, # pyright: ignore[reportPrivateUsage]
287
+ )
288
+ )
289
+ await driver.execute_script(SQL("SELECT pg_notify($1, $2)", channel, to_json({"event_id": event_id})))
290
+ await driver.commit()
291
+
292
+
293
+ def create_event_backend(
294
+ config: "PsqlpyConfig", backend_name: str, extension_settings: "dict[str, Any]"
295
+ ) -> PsqlpyEventsBackend | PsqlpyHybridEventsBackend | None:
296
+ """Factory used by EventChannel to create the native psqlpy backend."""
297
+ match backend_name:
298
+ case "listen_notify":
299
+ try:
300
+ return PsqlpyEventsBackend(config)
301
+ except ImproperConfigurationError:
302
+ return None
303
+ case "listen_notify_durable":
304
+ queue = cast("AsyncTableEventQueue", build_queue_backend(config, extension_settings, adapter_name="psqlpy"))
305
+ try:
306
+ return PsqlpyHybridEventsBackend(config, queue)
307
+ except ImproperConfigurationError:
308
+ return None
309
+ case _:
310
+ return None
@@ -0,0 +1,20 @@
1
+ """Psqlpy event queue store."""
2
+
3
+ from sqlspec.adapters.psqlpy.config import PsqlpyConfig
4
+ from sqlspec.extensions.events import BaseEventQueueStore
5
+
6
+ __all__ = ("PsqlpyEventQueueStore",)
7
+
8
+
9
+ class PsqlpyEventQueueStore(BaseEventQueueStore[PsqlpyConfig]):
10
+ """Provide PostgreSQL column mappings for the queue table.
11
+
12
+ PostgreSQL uses JSONB for efficient binary JSON storage with indexing support,
13
+ and TIMESTAMPTZ for timezone-aware timestamps.
14
+ """
15
+
16
+ __slots__ = ()
17
+
18
+ def _column_types(self) -> "tuple[str, str, str]":
19
+ """Return PostgreSQL-optimized column types for the event queue."""
20
+ return "JSONB", "JSONB", "TIMESTAMPTZ"
@@ -0,0 +1,5 @@
1
+ """Litestar integration for psqlpy adapter."""
2
+
3
+ from sqlspec.adapters.psqlpy.litestar.store import PsqlpyStore
4
+
5
+ __all__ = ("PsqlpyStore",)
@@ -0,0 +1,270 @@
1
+ """Psqlpy session store for Litestar integration."""
2
+
3
+ from datetime import datetime, timedelta, timezone
4
+ from typing import TYPE_CHECKING
5
+
6
+ from sqlspec.extensions.litestar.store import BaseSQLSpecStore
7
+
8
+ if TYPE_CHECKING:
9
+ from sqlspec.adapters.psqlpy.config import PsqlpyConfig
10
+
11
+
12
+ __all__ = ("PsqlpyStore",)
13
+
14
+
15
+ class PsqlpyStore(BaseSQLSpecStore["PsqlpyConfig"]):
16
+ """PostgreSQL session store using Psqlpy driver.
17
+
18
+ Implements server-side session storage for Litestar using PostgreSQL
19
+ via the Psqlpy driver (Rust-based async driver). Provides efficient
20
+ session management with:
21
+ - Native async PostgreSQL operations via Rust
22
+ - UPSERT support using ON CONFLICT
23
+ - Automatic expiration handling
24
+ - Efficient cleanup of expired sessions
25
+
26
+ Args:
27
+ config: PsqlpyConfig instance.
28
+
29
+ Example:
30
+ from sqlspec.adapters.psqlpy import PsqlpyConfig
31
+ from sqlspec.adapters.psqlpy.litestar.store import PsqlpyStore
32
+
33
+ config = PsqlpyConfig(connection_config={"dsn": "postgresql://..."})
34
+ store = PsqlpyStore(config)
35
+ await store.create_table()
36
+ """
37
+
38
+ __slots__ = ()
39
+
40
+ def __init__(self, config: "PsqlpyConfig") -> None:
41
+ """Initialize Psqlpy session store.
42
+
43
+ Args:
44
+ config: PsqlpyConfig instance.
45
+
46
+ Notes:
47
+ Table name is read from config.extension_config["litestar"]["session_table"].
48
+ """
49
+ super().__init__(config)
50
+
51
+ def _get_create_table_sql(self) -> str:
52
+ """Get PostgreSQL CREATE TABLE SQL with optimized schema.
53
+
54
+ Returns:
55
+ SQL statement to create the sessions table with proper indexes.
56
+
57
+ Notes:
58
+ - Uses TIMESTAMPTZ for timezone-aware expiration timestamps
59
+ - Partial index WHERE expires_at IS NOT NULL reduces index size/maintenance
60
+ - FILLFACTOR 80 leaves space for HOT updates, reducing table bloat
61
+ - Audit columns (created_at, updated_at) help with debugging
62
+ - Table name is internally controlled, not user input (S608 suppressed)
63
+ """
64
+ return f"""
65
+ CREATE TABLE IF NOT EXISTS {self._table_name} (
66
+ session_id TEXT PRIMARY KEY,
67
+ data BYTEA NOT NULL,
68
+ expires_at TIMESTAMPTZ,
69
+ created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
70
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
71
+ ) WITH (fillfactor = 80);
72
+
73
+ CREATE INDEX IF NOT EXISTS idx_{self._table_name}_expires_at
74
+ ON {self._table_name}(expires_at) WHERE expires_at IS NOT NULL;
75
+
76
+ ALTER TABLE {self._table_name} SET (
77
+ autovacuum_vacuum_scale_factor = 0.05,
78
+ autovacuum_analyze_scale_factor = 0.02
79
+ );
80
+ """
81
+
82
+ def _get_drop_table_sql(self) -> "list[str]":
83
+ """Get PostgreSQL DROP TABLE SQL statements.
84
+
85
+ Returns:
86
+ List of SQL statements to drop indexes and table.
87
+ """
88
+ return [f"DROP INDEX IF EXISTS idx_{self._table_name}_expires_at", f"DROP TABLE IF EXISTS {self._table_name}"]
89
+
90
+ async def create_table(self) -> None:
91
+ """Create the session table if it doesn't exist."""
92
+ sql = self._get_create_table_sql()
93
+ async with self._config.provide_session() as driver:
94
+ await driver.execute_script(sql)
95
+ self._log_table_created()
96
+
97
+ async def get(self, key: str, renew_for: "int | timedelta | None" = None) -> "bytes | None":
98
+ """Get a session value by key.
99
+
100
+ Args:
101
+ key: Session ID to retrieve.
102
+ renew_for: If given, renew the expiry time for this duration.
103
+
104
+ Returns:
105
+ Session data as bytes if found and not expired, None otherwise.
106
+
107
+ Notes:
108
+ Uses CURRENT_TIMESTAMP instead of NOW() for SQL standard compliance.
109
+ The query planner can use the partial index for expires_at > CURRENT_TIMESTAMP.
110
+ """
111
+ sql = f"""
112
+ SELECT data, expires_at FROM {self._table_name}
113
+ WHERE session_id = $1
114
+ AND (expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP)
115
+ """
116
+
117
+ async with self._config.provide_connection() as conn:
118
+ query_result = await conn.fetch(sql, [key])
119
+ rows = query_result.result()
120
+
121
+ if not rows:
122
+ return None
123
+
124
+ row = rows[0]
125
+
126
+ if renew_for is not None and row["expires_at"] is not None:
127
+ new_expires_at = self._calculate_expires_at(renew_for)
128
+ if new_expires_at is not None:
129
+ update_sql = f"""
130
+ UPDATE {self._table_name}
131
+ SET expires_at = $1, updated_at = CURRENT_TIMESTAMP
132
+ WHERE session_id = $2
133
+ """
134
+ await conn.execute(update_sql, [new_expires_at, key])
135
+
136
+ return bytes(row["data"])
137
+
138
+ async def set(self, key: str, value: "str | bytes", expires_in: "int | timedelta | None" = None) -> None:
139
+ """Store a session value.
140
+
141
+ Args:
142
+ key: Session ID.
143
+ value: Session data.
144
+ expires_in: Time until expiration.
145
+
146
+ Notes:
147
+ Uses EXCLUDED to reference the proposed insert values in ON CONFLICT.
148
+ Updates updated_at timestamp on every write for audit trail.
149
+ """
150
+ data = self._value_to_bytes(value)
151
+ expires_at = self._calculate_expires_at(expires_in)
152
+
153
+ sql = f"""
154
+ INSERT INTO {self._table_name} (session_id, data, expires_at)
155
+ VALUES ($1, $2, $3)
156
+ ON CONFLICT (session_id)
157
+ DO UPDATE SET
158
+ data = EXCLUDED.data,
159
+ expires_at = EXCLUDED.expires_at,
160
+ updated_at = CURRENT_TIMESTAMP
161
+ """
162
+
163
+ async with self._config.provide_connection() as conn:
164
+ await conn.execute(sql, [key, data, expires_at])
165
+
166
+ async def delete(self, key: str) -> None:
167
+ """Delete a session by key.
168
+
169
+ Args:
170
+ key: Session ID to delete.
171
+ """
172
+ sql = f"DELETE FROM {self._table_name} WHERE session_id = $1"
173
+
174
+ async with self._config.provide_connection() as conn:
175
+ await conn.execute(sql, [key])
176
+
177
+ async def delete_all(self) -> None:
178
+ """Delete all sessions from the store."""
179
+ sql = f"DELETE FROM {self._table_name}"
180
+
181
+ async with self._config.provide_connection() as conn:
182
+ await conn.execute(sql)
183
+ self._log_delete_all()
184
+
185
+ async def exists(self, key: str) -> bool:
186
+ """Check if a session key exists and is not expired.
187
+
188
+ Args:
189
+ key: Session ID to check.
190
+
191
+ Returns:
192
+ True if the session exists and is not expired.
193
+
194
+ Notes:
195
+ Uses CURRENT_TIMESTAMP for consistency with get() method.
196
+ Uses fetch() instead of fetch_val() to handle zero-row case.
197
+ """
198
+ sql = f"""
199
+ SELECT 1 FROM {self._table_name}
200
+ WHERE session_id = $1
201
+ AND (expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP)
202
+ """
203
+
204
+ async with self._config.provide_connection() as conn:
205
+ query_result = await conn.fetch(sql, [key])
206
+ rows = query_result.result()
207
+ return len(rows) > 0
208
+
209
+ async def expires_in(self, key: str) -> "int | None":
210
+ """Get the time in seconds until the session expires.
211
+
212
+ Args:
213
+ key: Session ID to check.
214
+
215
+ Returns:
216
+ Seconds until expiration, or None if no expiry or key doesn't exist.
217
+
218
+ Notes:
219
+ Uses fetch() to handle the case where the key doesn't exist.
220
+ """
221
+ sql = f"""
222
+ SELECT expires_at FROM {self._table_name}
223
+ WHERE session_id = $1
224
+ """
225
+
226
+ async with self._config.provide_connection() as conn:
227
+ query_result = await conn.fetch(sql, [key])
228
+ rows = query_result.result()
229
+
230
+ if not rows:
231
+ return None
232
+
233
+ expires_at = rows[0]["expires_at"]
234
+
235
+ if expires_at is None:
236
+ return None
237
+
238
+ now = datetime.now(timezone.utc)
239
+ if expires_at <= now:
240
+ return 0
241
+
242
+ delta = expires_at - now
243
+ return int(delta.total_seconds())
244
+
245
+ async def delete_expired(self) -> int:
246
+ """Delete all expired sessions.
247
+
248
+ Returns:
249
+ Number of sessions deleted.
250
+
251
+ Notes:
252
+ Uses CURRENT_TIMESTAMP for consistency.
253
+ Uses RETURNING to get deleted row count since psqlpy QueryResult
254
+ doesn't expose command tags.
255
+ For very large tables (10M+ rows), consider batching deletes
256
+ to avoid holding locks too long.
257
+ """
258
+ sql = f"""
259
+ DELETE FROM {self._table_name}
260
+ WHERE expires_at <= CURRENT_TIMESTAMP
261
+ RETURNING session_id
262
+ """
263
+
264
+ async with self._config.provide_connection() as conn:
265
+ query_result = await conn.fetch(sql, [])
266
+ rows = query_result.result()
267
+ count = len(rows)
268
+ if count > 0:
269
+ self._log_delete_expired(count)
270
+ return count