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,187 @@
1
+ """Spanner event queue store with GoogleSQL-optimized DDL.
2
+
3
+ Spanner requires:
4
+ - STRING instead of VARCHAR
5
+ - INT64 instead of INTEGER
6
+ - No DEFAULT clause for non-computed columns
7
+ - Separate index creation statements (no IF NOT EXISTS)
8
+ - PRIMARY KEY declared inline in CREATE TABLE
9
+ """
10
+
11
+ import logging
12
+
13
+ from sqlspec.adapters.spanner.config import SpannerSyncConfig
14
+ from sqlspec.extensions.events import BaseEventQueueStore
15
+ from sqlspec.utils.logging import get_logger, log_with_context
16
+
17
+ __all__ = ("SpannerSyncEventQueueStore",)
18
+
19
+ logger = get_logger("sqlspec.adapters.spanner.events.store")
20
+
21
+
22
+ class SpannerSyncEventQueueStore(BaseEventQueueStore["SpannerSyncConfig"]):
23
+ """Spanner-specific event queue store with GoogleSQL DDL.
24
+
25
+ Generates optimized DDL for Google Cloud Spanner using GoogleSQL dialect.
26
+ Spanner does not support IF NOT EXISTS, so statements must be executed
27
+ with proper error handling for existing objects.
28
+
29
+ Args:
30
+ config: SpannerSyncConfig with extension_config["events"] settings.
31
+
32
+ Notes:
33
+ Configuration is read from config.extension_config["events"]:
34
+ - queue_table: Table name (default: "sqlspec_event_queue")
35
+
36
+ Example:
37
+ from sqlspec.adapters.spanner import SpannerSyncConfig
38
+ from sqlspec.adapters.spanner.events import SpannerSyncEventQueueStore
39
+
40
+ config = SpannerSyncConfig(
41
+ connection_config={"project": "my-project", "instance": "my-instance", "database": "my-db"},
42
+ extension_config={"events": {"queue_table": "my_events"}}
43
+ )
44
+ store = SpannerSyncEventQueueStore(config)
45
+ store.create_table()
46
+ """
47
+
48
+ __slots__ = ()
49
+
50
+ def _column_types(self) -> "tuple[str, str, str]":
51
+ """Return Spanner-specific column types."""
52
+ return "JSON", "JSON", "TIMESTAMP"
53
+
54
+ def _string_type(self, length: int) -> str:
55
+ """Return Spanner STRING(N) type syntax."""
56
+ return f"STRING({length})"
57
+
58
+ def _integer_type(self) -> str:
59
+ """Return Spanner INT64 type."""
60
+ return "INT64"
61
+
62
+ def _primary_key_syntax(self) -> str:
63
+ """Return Spanner inline PRIMARY KEY clause."""
64
+ return " PRIMARY KEY (event_id)"
65
+
66
+ def _build_create_table_sql(self) -> str:
67
+ """Build Spanner CREATE TABLE with PRIMARY KEY inline.
68
+
69
+ Spanner does not support DEFAULT clauses on non-computed columns,
70
+ so we omit them entirely. Values must be provided at insert time.
71
+ """
72
+ payload_type, metadata_type, timestamp_type = self._column_types()
73
+ string_64 = self._string_type(64)
74
+ string_128 = self._string_type(128)
75
+ string_32 = self._string_type(32)
76
+ integer_type = self._integer_type()
77
+ pk_inline = self._primary_key_syntax()
78
+
79
+ return (
80
+ f"CREATE TABLE {self.table_name} ("
81
+ f"event_id {string_64} NOT NULL,"
82
+ f" channel {string_128} NOT NULL,"
83
+ f" payload_json {payload_type} NOT NULL,"
84
+ f" metadata_json {metadata_type},"
85
+ f" status {string_32} NOT NULL,"
86
+ f" available_at {timestamp_type} NOT NULL,"
87
+ f" lease_expires_at {timestamp_type},"
88
+ f" attempts {integer_type} NOT NULL,"
89
+ f" created_at {timestamp_type} NOT NULL,"
90
+ f" acknowledged_at {timestamp_type}"
91
+ f"){pk_inline}"
92
+ )
93
+
94
+ def _build_index_sql(self) -> str | None:
95
+ """Build Spanner secondary index for queue operations."""
96
+ index_name = self._index_name()
97
+ return f"CREATE INDEX {index_name} ON {self.table_name}(channel, status, available_at)"
98
+
99
+ def _wrap_create_statement(self, statement: str, object_type: str) -> str:
100
+ """Return statement unchanged - Spanner does not support IF NOT EXISTS.
101
+
102
+ Args:
103
+ statement: The DDL statement.
104
+ object_type: Type of object (table, index).
105
+
106
+ Returns:
107
+ The statement unchanged.
108
+ """
109
+ del object_type
110
+ return statement
111
+
112
+ def _wrap_drop_statement(self, statement: str) -> str:
113
+ """Return statement unchanged - Spanner does not support IF EXISTS."""
114
+ return statement
115
+
116
+ def create_statements(self) -> "list[str]":
117
+ """Return separate statements for table and index creation.
118
+
119
+ Spanner requires DDL statements to be executed individually.
120
+ The caller should handle errors for already-existing objects.
121
+ """
122
+ statements = [self._build_create_table_sql()]
123
+ index_sql = self._build_index_sql()
124
+ if index_sql:
125
+ statements.append(index_sql)
126
+ return statements
127
+
128
+ def drop_statements(self) -> "list[str]":
129
+ """Return drop statements in reverse dependency order.
130
+
131
+ Spanner requires index to be dropped before the table.
132
+ The caller should handle errors for non-existent objects.
133
+ """
134
+ index_name = self._index_name()
135
+ return [f"DROP INDEX {index_name}", f"DROP TABLE {self.table_name}"]
136
+
137
+ def create_table(self) -> None:
138
+ """Create the event queue table and index.
139
+
140
+ Executes DDL statements via database.update_ddl() which is the
141
+ recommended approach for Spanner schema changes.
142
+
143
+ Raises:
144
+ google.api_core.exceptions.AlreadyExists: If table or index exists.
145
+ """
146
+ config = self._config
147
+ if not isinstance(config, SpannerSyncConfig):
148
+ msg = "create_table requires SpannerSyncConfig"
149
+ raise TypeError(msg)
150
+
151
+ database = config.get_database()
152
+ statements = self.create_statements()
153
+ log_with_context(
154
+ logger,
155
+ logging.DEBUG,
156
+ "events.queue.create",
157
+ adapter_name="spanner",
158
+ table_name=self.table_name,
159
+ statement_count=len(statements),
160
+ )
161
+ database.update_ddl(statements).result() # type: ignore[no-untyped-call]
162
+
163
+ def drop_table(self) -> None:
164
+ """Drop the event queue table and index.
165
+
166
+ Executes DDL statements via database.update_ddl() which is the
167
+ recommended approach for Spanner schema changes.
168
+
169
+ Raises:
170
+ google.api_core.exceptions.NotFound: If table or index does not exist.
171
+ """
172
+ config = self._config
173
+ if not isinstance(config, SpannerSyncConfig):
174
+ msg = "drop_table requires SpannerSyncConfig"
175
+ raise TypeError(msg)
176
+
177
+ database = config.get_database()
178
+ statements = self.drop_statements()
179
+ log_with_context(
180
+ logger,
181
+ logging.DEBUG,
182
+ "events.queue.drop",
183
+ adapter_name="spanner",
184
+ table_name=self.table_name,
185
+ statement_count=len(statements),
186
+ )
187
+ database.update_ddl(statements).result() # type: ignore[no-untyped-call]
@@ -0,0 +1,5 @@
1
+ """Litestar integration for Spanner adapter."""
2
+
3
+ from sqlspec.adapters.spanner.litestar.store import SpannerSyncStore
4
+
5
+ __all__ = ("SpannerSyncStore",)
@@ -0,0 +1,291 @@
1
+ """Spanner session store for Litestar integration."""
2
+
3
+ from datetime import datetime, timedelta, timezone
4
+ from typing import TYPE_CHECKING, Any, cast
5
+
6
+ from google.cloud.spanner_v1 import param_types
7
+
8
+ from sqlspec.adapters.spanner.type_converter import bytes_to_spanner, spanner_to_bytes
9
+ from sqlspec.extensions.litestar.store import BaseSQLSpecStore
10
+ from sqlspec.utils.sync_tools import async_
11
+
12
+ if TYPE_CHECKING:
13
+ from collections.abc import Callable
14
+ from typing import Protocol
15
+
16
+ from google.cloud.spanner_v1.transaction import Transaction
17
+
18
+ from sqlspec.adapters.spanner.config import SpannerSyncConfig
19
+
20
+ class _DatabaseProtocol(Protocol):
21
+ def run_in_transaction(self, func: "Callable[[Transaction], Any]") -> Any: ...
22
+
23
+ def update_ddl(self, ddl_statements: "list[str]") -> Any: ...
24
+
25
+ def list_tables(self) -> Any: ...
26
+
27
+
28
+ __all__ = ("SpannerSyncStore",)
29
+
30
+
31
+ class _SpannerExecuteUpdateJob:
32
+ __slots__ = ("_params", "_sql", "_types")
33
+
34
+ def __init__(self, sql: str, params: "dict[str, Any] | None" = None, types: "dict[str, Any] | None" = None) -> None:
35
+ self._sql = sql
36
+ self._params = params
37
+ self._types = types
38
+
39
+ def __call__(self, transaction: "Transaction") -> None:
40
+ if self._params is None and self._types is None:
41
+ transaction.execute_update(self._sql) # type: ignore[no-untyped-call]
42
+ return
43
+ transaction.execute_update(self._sql, params=self._params or {}, param_types=self._types) # type: ignore[no-untyped-call]
44
+
45
+
46
+ class _SpannerUpsertJob:
47
+ __slots__ = ("_insert_sql", "_params", "_types", "_update_sql")
48
+
49
+ def __init__(self, update_sql: str, insert_sql: str, params: "dict[str, Any]", types: "dict[str, Any]") -> None:
50
+ self._update_sql = update_sql
51
+ self._insert_sql = insert_sql
52
+ self._params = params
53
+ self._types = types
54
+
55
+ def __call__(self, transaction: "Transaction") -> None:
56
+ row_ct = transaction.execute_update(self._update_sql, params=self._params, param_types=self._types) # type: ignore[no-untyped-call]
57
+ if row_ct == 0:
58
+ transaction.execute_update(self._insert_sql, params=self._params, param_types=self._types) # type: ignore[no-untyped-call]
59
+
60
+
61
+ class _SpannerExecuteUpdateCountJob:
62
+ __slots__ = ("_sql",)
63
+
64
+ def __init__(self, sql: str) -> None:
65
+ self._sql = sql
66
+
67
+ def __call__(self, transaction: "Transaction") -> int:
68
+ return int(transaction.execute_update(self._sql)) # type: ignore[no-untyped-call]
69
+
70
+
71
+ class SpannerSyncStore(BaseSQLSpecStore["SpannerSyncConfig"]):
72
+ """Spanner-backed Litestar session store using sync driver wrapped as async."""
73
+
74
+ __slots__ = ("_index_options", "_shard_count", "_table_options")
75
+
76
+ def __init__(self, config: "SpannerSyncConfig") -> None:
77
+ super().__init__(config)
78
+ litestar_cfg = cast("dict[str, Any]", config.extension_config.get("litestar", {}))
79
+ self._shard_count: int = int(litestar_cfg.get("shard_count", 0)) if litestar_cfg.get("shard_count") else 0
80
+ self._table_options: str | None = litestar_cfg.get("table_options")
81
+ self._index_options: str | None = litestar_cfg.get("index_options")
82
+
83
+ def _database(self) -> "_DatabaseProtocol":
84
+ return cast("_DatabaseProtocol", self._config.get_database())
85
+
86
+ def _datetime_to_timestamp(self, dt: "datetime | None") -> "datetime | None":
87
+ if dt is None:
88
+ return None
89
+ if dt.tzinfo is None:
90
+ return dt.replace(tzinfo=timezone.utc)
91
+ return dt
92
+
93
+ def _timestamp_to_datetime(self, ts: "datetime | None") -> "datetime | None":
94
+ if ts is None:
95
+ return None
96
+ if ts.tzinfo is None:
97
+ return ts.replace(tzinfo=timezone.utc)
98
+ return ts
99
+
100
+ def _build_params(
101
+ self, key: str, expires_at: "datetime | None" = None, data: "bytes | None" = None
102
+ ) -> "dict[str, Any]":
103
+ return {
104
+ "session_id": key,
105
+ "data": bytes_to_spanner(data),
106
+ "expires_at": self._datetime_to_timestamp(expires_at),
107
+ }
108
+
109
+ def _get_param_types(
110
+ self, session_id: bool = True, expires_at: bool = False, data: bool = False
111
+ ) -> "dict[str, Any]":
112
+ types: dict[str, Any] = {}
113
+ if session_id:
114
+ types["session_id"] = param_types.STRING
115
+ if expires_at:
116
+ types["expires_at"] = param_types.TIMESTAMP
117
+ if data:
118
+ types["data"] = param_types.BYTES
119
+ return types
120
+
121
+ async def get(self, key: str, renew_for: "int | timedelta | None" = None) -> "bytes | None":
122
+ return await async_(self._get)(key, renew_for)
123
+
124
+ def _get(self, key: str, renew_for: "int | timedelta | None" = None) -> "bytes | None":
125
+ sql = f"""
126
+ SELECT data, expires_at
127
+ FROM {self._table_name}
128
+ WHERE session_id = @session_id
129
+ AND (expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP())
130
+ """
131
+ if self._shard_count > 1:
132
+ sql = f"""
133
+ SELECT data, expires_at
134
+ FROM {self._table_name}
135
+ WHERE shard_id = MOD(FARM_FINGERPRINT(@session_id), {self._shard_count})
136
+ AND session_id = @session_id
137
+ AND (expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP())
138
+ """
139
+
140
+ with self._config.provide_session() as driver:
141
+ result = driver.select_one_or_none(sql, {"session_id": key})
142
+
143
+ if result is None:
144
+ return None
145
+
146
+ data = result.get("data")
147
+ expires_at = self._timestamp_to_datetime(result.get("expires_at"))
148
+
149
+ if renew_for is not None and expires_at is not None:
150
+ new_expires = self._calculate_expires_at(renew_for)
151
+ update_sql = f"""
152
+ UPDATE {self._table_name}
153
+ SET expires_at = @expires_at, updated_at = PENDING_COMMIT_TIMESTAMP()
154
+ WHERE session_id = @session_id
155
+ """
156
+ if self._shard_count > 1:
157
+ update_sql = f"{update_sql} AND shard_id = MOD(FARM_FINGERPRINT(@session_id), {self._shard_count})"
158
+ params = self._build_params(key, new_expires)
159
+ types = self._get_param_types(expires_at=True)
160
+ self._database().run_in_transaction(_SpannerExecuteUpdateJob(update_sql, params, types))
161
+
162
+ return spanner_to_bytes(data)
163
+
164
+ async def set(self, key: str, value: "str | bytes", expires_in: "int | timedelta | None" = None) -> None:
165
+ await async_(self._set)(key, value, expires_in)
166
+
167
+ def _set(self, key: str, value: "str | bytes", expires_in: "int | timedelta | None" = None) -> None:
168
+ data = self._value_to_bytes(value)
169
+ expires_at = self._calculate_expires_at(expires_in)
170
+ params = self._build_params(key, expires_at, data)
171
+ types = self._get_param_types(session_id=True, expires_at=True, data=True)
172
+
173
+ update_sql = f"""
174
+ UPDATE {self._table_name}
175
+ SET data = @data,
176
+ expires_at = @expires_at,
177
+ updated_at = PENDING_COMMIT_TIMESTAMP()
178
+ WHERE session_id = @session_id
179
+ """
180
+ if self._shard_count > 1:
181
+ update_sql = f"{update_sql} AND shard_id = MOD(FARM_FINGERPRINT(@session_id), {self._shard_count})"
182
+ insert_sql = f"""
183
+ INSERT {self._table_name} (session_id, data, expires_at, created_at, updated_at)
184
+ VALUES (@session_id, @data, @expires_at, PENDING_COMMIT_TIMESTAMP(), PENDING_COMMIT_TIMESTAMP())
185
+ """
186
+ self._database().run_in_transaction(_SpannerUpsertJob(update_sql, insert_sql, params, types))
187
+
188
+ async def delete(self, key: str) -> None:
189
+ await async_(self._delete)(key)
190
+
191
+ def _delete(self, key: str) -> None:
192
+ sql = f"DELETE FROM {self._table_name} WHERE session_id = @session_id"
193
+ if self._shard_count > 1:
194
+ sql = f"{sql} AND shard_id = MOD(FARM_FINGERPRINT(@session_id), {self._shard_count})"
195
+ params = {"session_id": key}
196
+ types = self._get_param_types(session_id=True)
197
+ self._database().run_in_transaction(_SpannerExecuteUpdateJob(sql, params, types))
198
+
199
+ async def delete_all(self) -> None:
200
+ await async_(self._delete_all)()
201
+
202
+ def _delete_all(self) -> None:
203
+ sql = f"DELETE FROM {self._table_name} WHERE TRUE"
204
+ self._database().run_in_transaction(_SpannerExecuteUpdateJob(sql))
205
+
206
+ async def exists(self, key: str) -> bool:
207
+ return await async_(self._exists)(key)
208
+
209
+ def _exists(self, key: str) -> bool:
210
+ sql = f"""
211
+ SELECT 1 FROM {self._table_name}
212
+ WHERE session_id = @session_id
213
+ AND (expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP())
214
+ LIMIT 1
215
+ """
216
+ with self._config.provide_session() as driver:
217
+ row = driver.select_one_or_none(sql, {"session_id": key})
218
+ return row is not None
219
+
220
+ async def expires_in(self, key: str) -> "int | None":
221
+ return await async_(self._expires_in)(key)
222
+
223
+ def _expires_in(self, key: str) -> "int | None":
224
+ sql = f"""
225
+ SELECT expires_at FROM {self._table_name}
226
+ WHERE session_id = @session_id
227
+ """
228
+ if self._shard_count > 1:
229
+ sql = f"{sql} AND shard_id = MOD(FARM_FINGERPRINT(@session_id), {self._shard_count})"
230
+ with self._config.provide_session() as driver:
231
+ row = driver.select_one_or_none(sql, {"session_id": key})
232
+ if row is None:
233
+ return None
234
+ expires_at = self._timestamp_to_datetime(row.get("expires_at"))
235
+ if expires_at is None:
236
+ return None
237
+ delta = expires_at - datetime.now(timezone.utc)
238
+ return max(int(delta.total_seconds()), 0)
239
+
240
+ async def delete_expired(self) -> int:
241
+ return await async_(self._delete_expired)()
242
+
243
+ def _delete_expired(self) -> int:
244
+ sql = f"""
245
+ DELETE FROM {self._table_name}
246
+ WHERE expires_at IS NOT NULL AND expires_at <= CURRENT_TIMESTAMP()
247
+ """
248
+ result = self._database().run_in_transaction(_SpannerExecuteUpdateCountJob(sql))
249
+ return cast("int", result)
250
+
251
+ async def create_table(self) -> None:
252
+ await async_(self._create_table)()
253
+
254
+ def _create_table(self) -> None:
255
+ database = self._config.get_database()
256
+ existing_tables = {t.table_id for t in database.list_tables()} # type: ignore[no-untyped-call]
257
+
258
+ if self._table_name not in existing_tables:
259
+ ddl_statements = [self._get_create_table_sql(), self._get_create_index_sql()]
260
+ database.update_ddl(ddl_statements).result(300) # type: ignore[no-untyped-call]
261
+
262
+ def _get_create_table_sql(self) -> str:
263
+ shard_column = ""
264
+ pk = "PRIMARY KEY (session_id)"
265
+ if self._shard_count > 1:
266
+ shard_column = f",\n shard_id INT64 AS (MOD(FARM_FINGERPRINT(session_id), {self._shard_count})) STORED"
267
+ pk = "PRIMARY KEY (shard_id, session_id)"
268
+ options = ""
269
+ if self._table_options:
270
+ options = f"\nOPTIONS ({self._table_options})"
271
+ return f"""
272
+ CREATE TABLE {self._table_name} (
273
+ session_id STRING(128) NOT NULL,
274
+ data BYTES(MAX) NOT NULL,
275
+ expires_at TIMESTAMP,
276
+ created_at TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true),
277
+ updated_at TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true){shard_column}
278
+ ) {pk}{options}
279
+ """
280
+
281
+ def _get_create_index_sql(self) -> str:
282
+ leading = "expires_at"
283
+ if self._shard_count > 1:
284
+ leading = "shard_id, expires_at"
285
+ opts = ""
286
+ if self._index_options:
287
+ opts = f" OPTIONS ({self._index_options})"
288
+ return f"CREATE INDEX idx_{self._table_name}_expires_at ON {self._table_name}({leading}){opts}"
289
+
290
+ def _get_drop_table_sql(self) -> "list[str]":
291
+ return [f"DROP INDEX idx_{self._table_name}_expires_at", f"DROP TABLE {self._table_name}"]