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,781 @@
1
+ """Oracle 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
+ from sqlspec.utils.sync_tools import async_
8
+ from sqlspec.utils.type_guards import is_async_readable, is_readable
9
+
10
+ if TYPE_CHECKING:
11
+ from sqlspec.adapters.oracledb.config import OracleAsyncConfig, OracleSyncConfig
12
+
13
+
14
+ ORACLE_SMALL_BLOB_LIMIT = 32000
15
+
16
+ __all__ = ("OracleAsyncStore", "OracleSyncStore")
17
+
18
+
19
+ def _coerce_bytes_payload(value: object) -> bytes:
20
+ """Coerce a payload into bytes for session storage."""
21
+ if value is None:
22
+ return b""
23
+ if isinstance(value, bytes):
24
+ return value
25
+ if isinstance(value, str):
26
+ return value.encode("utf-8")
27
+ return str(value).encode("utf-8")
28
+
29
+
30
+ async def _read_blob_async(value: object) -> bytes:
31
+ """Read LOB values from async connections into bytes."""
32
+ if is_async_readable(value):
33
+ return _coerce_bytes_payload(await value.read())
34
+ if is_readable(value):
35
+ return _coerce_bytes_payload(value.read())
36
+ return _coerce_bytes_payload(value)
37
+
38
+
39
+ def _read_blob_sync(value: object) -> bytes:
40
+ """Read LOB values from sync connections into bytes."""
41
+ if is_readable(value):
42
+ return _coerce_bytes_payload(value.read())
43
+ return _coerce_bytes_payload(value)
44
+
45
+
46
+ class OracleAsyncStore(BaseSQLSpecStore["OracleAsyncConfig"]):
47
+ """Oracle session store using async OracleDB driver.
48
+
49
+ Implements server-side session storage for Litestar using Oracle Database
50
+ via the async python-oracledb driver. Provides efficient session management with:
51
+ - Native async Oracle operations
52
+ - MERGE statement for atomic UPSERT
53
+ - Automatic expiration handling
54
+ - Efficient cleanup of expired sessions
55
+ - Optional In-Memory Column Store support (requires Oracle Database In-Memory license)
56
+
57
+ Args:
58
+ config: OracleAsyncConfig with extension_config["litestar"] settings.
59
+
60
+ Example:
61
+ from sqlspec.adapters.oracledb import OracleAsyncConfig
62
+ from sqlspec.adapters.oracledb.litestar.store import OracleAsyncStore
63
+
64
+ config = OracleAsyncConfig(
65
+ connection_config={"dsn": "oracle://..."},
66
+ extension_config={
67
+ "litestar": {
68
+ "session_table": "my_sessions",
69
+ "in_memory": True
70
+ }
71
+ }
72
+ )
73
+ store = OracleAsyncStore(config)
74
+ await store.create_table()
75
+
76
+ Notes:
77
+ Configuration is read from config.extension_config["litestar"]:
78
+ - session_table: Session table name (default: "litestar_session")
79
+ - in_memory: Enable INMEMORY PRIORITY HIGH clause (default: False, Oracle-specific)
80
+
81
+ When in_memory=True, the table is created with INMEMORY PRIORITY HIGH clause for
82
+ faster read operations. PRIORITY HIGH ensures the table is populated into the
83
+ In-Memory column store at database startup for immediate performance benefits.
84
+ This requires Oracle Database 12.1.0.2+ with the Database In-Memory option licensed.
85
+ If In-Memory is not available, the table creation will fail with ORA-00439 or ORA-62142.
86
+ """
87
+
88
+ __slots__ = ("_in_memory",)
89
+
90
+ def __init__(self, config: "OracleAsyncConfig") -> None:
91
+ """Initialize Oracle session store.
92
+
93
+ Args:
94
+ config: OracleAsyncConfig instance.
95
+
96
+ Notes:
97
+ Configuration is read from config.extension_config["litestar"]:
98
+ - session_table: Session table name (default: "litestar_session")
99
+ - in_memory: Enable INMEMORY clause (default: False)
100
+ """
101
+ super().__init__(config)
102
+
103
+ litestar_config = config.extension_config.get("litestar", {})
104
+ self._in_memory = bool(litestar_config.get("in_memory", False))
105
+
106
+ def _get_create_table_sql(self) -> str:
107
+ """Get Oracle CREATE TABLE SQL with optimized schema.
108
+
109
+ Returns:
110
+ SQL statement to create the sessions table with proper indexes.
111
+
112
+ Notes:
113
+ - Uses TIMESTAMP WITH TIME ZONE for timezone-aware expiration timestamps
114
+ - Index on expires_at for efficient cleanup queries
115
+ - BLOB type for data storage (Oracle native binary type)
116
+ - Audit columns (created_at, updated_at) help with debugging
117
+ - Table name is internally controlled, not user input (S608 suppressed)
118
+ - INMEMORY PRIORITY HIGH clause added when in_memory=True for faster reads
119
+ - HIGH priority ensures table population at database startup
120
+ """
121
+ inmemory_clause = "INMEMORY PRIORITY HIGH" if self._in_memory else ""
122
+ return f"""
123
+ BEGIN
124
+ EXECUTE IMMEDIATE 'CREATE TABLE {self._table_name} (
125
+ session_id VARCHAR2(255) PRIMARY KEY,
126
+ data BLOB NOT NULL,
127
+ expires_at TIMESTAMP WITH TIME ZONE,
128
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL,
129
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL
130
+ ) {inmemory_clause}';
131
+ EXCEPTION
132
+ WHEN OTHERS THEN
133
+ IF SQLCODE != -955 THEN
134
+ RAISE;
135
+ END IF;
136
+ END;
137
+
138
+ BEGIN
139
+ EXECUTE IMMEDIATE 'CREATE INDEX idx_{self._table_name}_expires_at
140
+ ON {self._table_name}(expires_at)';
141
+ EXCEPTION
142
+ WHEN OTHERS THEN
143
+ IF SQLCODE != -955 THEN
144
+ RAISE;
145
+ END IF;
146
+ END;
147
+ """
148
+
149
+ def _get_drop_table_sql(self) -> "list[str]":
150
+ """Get Oracle DROP TABLE SQL with PL/SQL error handling.
151
+
152
+ Returns:
153
+ List of SQL statements with exception handling for non-existent objects.
154
+ """
155
+ return [
156
+ f"""
157
+ BEGIN
158
+ EXECUTE IMMEDIATE 'DROP INDEX idx_{self._table_name}_expires_at';
159
+ EXCEPTION
160
+ WHEN OTHERS THEN
161
+ IF SQLCODE != -1418 THEN
162
+ RAISE;
163
+ END IF;
164
+ END;
165
+ """,
166
+ f"""
167
+ BEGIN
168
+ EXECUTE IMMEDIATE 'DROP TABLE {self._table_name}';
169
+ EXCEPTION
170
+ WHEN OTHERS THEN
171
+ IF SQLCODE != -942 THEN
172
+ RAISE;
173
+ END IF;
174
+ END;
175
+ """,
176
+ ]
177
+
178
+ async def create_table(self) -> None:
179
+ """Create the session table if it doesn't exist."""
180
+ sql = self._get_create_table_sql()
181
+ async with self._config.provide_session() as driver:
182
+ await driver.execute_script(sql)
183
+
184
+ self._log_table_created()
185
+
186
+ async def get(self, key: str, renew_for: "int | timedelta | None" = None) -> "bytes | None":
187
+ """Get a session value by key.
188
+
189
+ Args:
190
+ key: Session ID to retrieve.
191
+ renew_for: If given, renew the expiry time for this duration.
192
+
193
+ Returns:
194
+ Session data as bytes if found and not expired, None otherwise.
195
+
196
+ Notes:
197
+ Uses SYSTIMESTAMP for Oracle current timestamp.
198
+ The query uses the index for expires_at > SYSTIMESTAMP.
199
+ """
200
+ sql = f"""
201
+ SELECT data, expires_at FROM {self._table_name}
202
+ WHERE session_id = :session_id
203
+ AND (expires_at IS NULL OR expires_at > SYSTIMESTAMP)
204
+ """
205
+
206
+ conn_context = self._config.provide_connection()
207
+ async with conn_context as conn:
208
+ cursor = conn.cursor()
209
+ await cursor.execute(sql, {"session_id": key})
210
+ row = await cursor.fetchone()
211
+
212
+ if row is None:
213
+ return None
214
+
215
+ data_blob, expires_at = row
216
+
217
+ if renew_for is not None and expires_at is not None:
218
+ new_expires_at = self._calculate_expires_at(renew_for)
219
+ if new_expires_at is not None:
220
+ update_sql = f"""
221
+ UPDATE {self._table_name}
222
+ SET expires_at = :expires_at, updated_at = SYSTIMESTAMP
223
+ WHERE session_id = :session_id
224
+ """
225
+ await cursor.execute(update_sql, {"expires_at": new_expires_at, "session_id": key})
226
+ await conn.commit()
227
+
228
+ return await _read_blob_async(data_blob)
229
+
230
+ async def set(self, key: str, value: "str | bytes", expires_in: "int | timedelta | None" = None) -> None:
231
+ """Store a session value.
232
+
233
+ Args:
234
+ key: Session ID.
235
+ value: Session data.
236
+ expires_in: Time until expiration.
237
+
238
+ Notes:
239
+ Uses MERGE for atomic UPSERT operation in Oracle.
240
+ Updates updated_at timestamp on every write for audit trail.
241
+ For large BLOBs, uses empty_blob() and then writes data separately.
242
+ """
243
+ data = self._value_to_bytes(value)
244
+ expires_at = self._calculate_expires_at(expires_in)
245
+
246
+ conn_context = self._config.provide_connection()
247
+ async with conn_context as conn:
248
+ cursor = conn.cursor()
249
+
250
+ if len(data) > ORACLE_SMALL_BLOB_LIMIT:
251
+ merge_sql = f"""
252
+ MERGE INTO {self._table_name} t
253
+ USING (SELECT :session_id AS session_id FROM DUAL) s
254
+ ON (t.session_id = s.session_id)
255
+ WHEN MATCHED THEN
256
+ UPDATE SET
257
+ data = EMPTY_BLOB(),
258
+ expires_at = :expires_at,
259
+ updated_at = SYSTIMESTAMP
260
+ WHEN NOT MATCHED THEN
261
+ INSERT (session_id, data, expires_at, created_at, updated_at)
262
+ VALUES (:session_id, EMPTY_BLOB(), :expires_at, SYSTIMESTAMP, SYSTIMESTAMP)
263
+ """
264
+ await cursor.execute(merge_sql, {"session_id": key, "expires_at": expires_at})
265
+
266
+ select_sql = f"""
267
+ SELECT data FROM {self._table_name}
268
+ WHERE session_id = :session_id FOR UPDATE
269
+ """
270
+ await cursor.execute(select_sql, {"session_id": key})
271
+ row = await cursor.fetchone()
272
+ if row:
273
+ blob = row[0]
274
+ await blob.write(data)
275
+
276
+ await conn.commit()
277
+ else:
278
+ sql = f"""
279
+ MERGE INTO {self._table_name} t
280
+ USING (SELECT :session_id AS session_id FROM DUAL) s
281
+ ON (t.session_id = s.session_id)
282
+ WHEN MATCHED THEN
283
+ UPDATE SET
284
+ data = :data,
285
+ expires_at = :expires_at,
286
+ updated_at = SYSTIMESTAMP
287
+ WHEN NOT MATCHED THEN
288
+ INSERT (session_id, data, expires_at, created_at, updated_at)
289
+ VALUES (:session_id, :data, :expires_at, SYSTIMESTAMP, SYSTIMESTAMP)
290
+ """
291
+ await cursor.execute(sql, {"session_id": key, "data": data, "expires_at": expires_at})
292
+ await conn.commit()
293
+
294
+ async def delete(self, key: str) -> None:
295
+ """Delete a session by key.
296
+
297
+ Args:
298
+ key: Session ID to delete.
299
+ """
300
+ sql = f"DELETE FROM {self._table_name} WHERE session_id = :session_id"
301
+
302
+ conn_context = self._config.provide_connection()
303
+ async with conn_context as conn:
304
+ cursor = conn.cursor()
305
+ await cursor.execute(sql, {"session_id": key})
306
+ await conn.commit()
307
+
308
+ async def delete_all(self) -> None:
309
+ """Delete all sessions from the store."""
310
+ sql = f"DELETE FROM {self._table_name}"
311
+
312
+ conn_context = self._config.provide_connection()
313
+ async with conn_context as conn:
314
+ cursor = conn.cursor()
315
+ await cursor.execute(sql)
316
+ await conn.commit()
317
+ self._log_delete_all()
318
+
319
+ async def exists(self, key: str) -> bool:
320
+ """Check if a session key exists and is not expired.
321
+
322
+ Args:
323
+ key: Session ID to check.
324
+
325
+ Returns:
326
+ True if the session exists and is not expired.
327
+
328
+ Notes:
329
+ Uses SYSTIMESTAMP for consistency with get() method.
330
+ """
331
+ sql = f"""
332
+ SELECT 1 FROM {self._table_name}
333
+ WHERE session_id = :session_id
334
+ AND (expires_at IS NULL OR expires_at > SYSTIMESTAMP)
335
+ """
336
+
337
+ conn_context = self._config.provide_connection()
338
+ async with conn_context as conn:
339
+ cursor = conn.cursor()
340
+ await cursor.execute(sql, {"session_id": key})
341
+ result = await cursor.fetchone()
342
+ return result is not None
343
+
344
+ async def expires_in(self, key: str) -> "int | None":
345
+ """Get the time in seconds until the session expires.
346
+
347
+ Args:
348
+ key: Session ID to check.
349
+
350
+ Returns:
351
+ Seconds until expiration, or None if no expiry or key doesn't exist.
352
+ """
353
+ sql = f"""
354
+ SELECT expires_at FROM {self._table_name}
355
+ WHERE session_id = :session_id
356
+ """
357
+
358
+ conn_context = self._config.provide_connection()
359
+ async with conn_context as conn:
360
+ cursor = conn.cursor()
361
+ await cursor.execute(sql, {"session_id": key})
362
+ row = await cursor.fetchone()
363
+
364
+ if row is None or row[0] is None:
365
+ return None
366
+
367
+ expires_at = row[0]
368
+
369
+ if expires_at.tzinfo is None:
370
+ expires_at = expires_at.replace(tzinfo=timezone.utc)
371
+
372
+ now = datetime.now(timezone.utc)
373
+
374
+ if expires_at <= now:
375
+ return 0
376
+
377
+ delta = expires_at - now
378
+ return int(delta.total_seconds())
379
+
380
+ async def delete_expired(self) -> int:
381
+ """Delete all expired sessions.
382
+
383
+ Returns:
384
+ Number of sessions deleted.
385
+
386
+ Notes:
387
+ Uses SYSTIMESTAMP for consistency.
388
+ Oracle automatically commits DDL, so we explicitly commit for DML.
389
+ """
390
+ sql = f"DELETE FROM {self._table_name} WHERE expires_at <= SYSTIMESTAMP"
391
+
392
+ conn_context = self._config.provide_connection()
393
+ async with conn_context as conn:
394
+ cursor = conn.cursor()
395
+ await cursor.execute(sql)
396
+ count = cursor.rowcount if cursor.rowcount is not None else 0
397
+ await conn.commit()
398
+ if count > 0:
399
+ self._log_delete_expired(count)
400
+ return count
401
+
402
+
403
+ class OracleSyncStore(BaseSQLSpecStore["OracleSyncConfig"]):
404
+ """Oracle session store using sync OracleDB driver.
405
+
406
+ Implements server-side session storage for Litestar using Oracle Database
407
+ via the synchronous python-oracledb driver. Uses async_() wrapper to provide
408
+ an async interface compatible with the Store protocol.
409
+
410
+ Provides efficient session management with:
411
+ - Sync operations wrapped for async compatibility
412
+ - MERGE statement for atomic UPSERT
413
+ - Automatic expiration handling
414
+ - Efficient cleanup of expired sessions
415
+ - Optional In-Memory Column Store support (requires Oracle Database In-Memory license)
416
+
417
+ Note:
418
+ For high-concurrency applications, consider using OracleAsyncStore instead,
419
+ as it provides native async operations without threading overhead.
420
+
421
+ Args:
422
+ config: OracleSyncConfig with extension_config["litestar"] settings.
423
+
424
+ Example:
425
+ from sqlspec.adapters.oracledb import OracleSyncConfig
426
+ from sqlspec.adapters.oracledb.litestar.store import OracleSyncStore
427
+
428
+ config = OracleSyncConfig(
429
+ connection_config={"dsn": "oracle://..."},
430
+ extension_config={
431
+ "litestar": {
432
+ "session_table": "my_sessions",
433
+ "in_memory": True
434
+ }
435
+ }
436
+ )
437
+ store = OracleSyncStore(config)
438
+ await store.create_table()
439
+
440
+ Notes:
441
+ Configuration is read from config.extension_config["litestar"]:
442
+ - session_table: Session table name (default: "litestar_session")
443
+ - in_memory: Enable INMEMORY PRIORITY HIGH clause (default: False, Oracle-specific)
444
+
445
+ When in_memory=True, the table is created with INMEMORY PRIORITY HIGH clause for
446
+ faster read operations. PRIORITY HIGH ensures the table is populated into the
447
+ In-Memory column store at database startup for immediate performance benefits.
448
+ This requires Oracle Database 12.1.0.2+ with the Database In-Memory option licensed.
449
+ If In-Memory is not available, the table creation will fail with ORA-00439 or ORA-62142.
450
+ """
451
+
452
+ __slots__ = ("_in_memory",)
453
+
454
+ def __init__(self, config: "OracleSyncConfig") -> None:
455
+ """Initialize Oracle sync session store.
456
+
457
+ Args:
458
+ config: OracleSyncConfig instance.
459
+
460
+ Notes:
461
+ Configuration is read from config.extension_config["litestar"]:
462
+ - session_table: Session table name (default: "litestar_session")
463
+ - in_memory: Enable INMEMORY clause (default: False)
464
+ """
465
+ super().__init__(config)
466
+
467
+ litestar_config = config.extension_config.get("litestar", {})
468
+ self._in_memory = bool(litestar_config.get("in_memory", False))
469
+
470
+ def _get_create_table_sql(self) -> str:
471
+ """Get Oracle CREATE TABLE SQL with optimized schema.
472
+
473
+ Returns:
474
+ SQL statement to create the sessions table with proper indexes.
475
+
476
+ Notes:
477
+ - Uses TIMESTAMP WITH TIME ZONE for timezone-aware expiration timestamps
478
+ - Index on expires_at for efficient cleanup queries
479
+ - BLOB type for data storage (Oracle native binary type)
480
+ - Audit columns (created_at, updated_at) help with debugging
481
+ - Table name is internally controlled, not user input (S608 suppressed)
482
+ - INMEMORY PRIORITY HIGH clause added when in_memory=True for faster reads
483
+ - HIGH priority ensures table population at database startup
484
+ """
485
+ inmemory_clause = "INMEMORY PRIORITY HIGH" if self._in_memory else ""
486
+ return f"""
487
+ BEGIN
488
+ EXECUTE IMMEDIATE 'CREATE TABLE {self._table_name} (
489
+ session_id VARCHAR2(255) PRIMARY KEY,
490
+ data BLOB NOT NULL,
491
+ expires_at TIMESTAMP WITH TIME ZONE,
492
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL,
493
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL
494
+ ) {inmemory_clause}';
495
+ EXCEPTION
496
+ WHEN OTHERS THEN
497
+ IF SQLCODE != -955 THEN
498
+ RAISE;
499
+ END IF;
500
+ END;
501
+
502
+ BEGIN
503
+ EXECUTE IMMEDIATE 'CREATE INDEX idx_{self._table_name}_expires_at
504
+ ON {self._table_name}(expires_at)';
505
+ EXCEPTION
506
+ WHEN OTHERS THEN
507
+ IF SQLCODE != -955 THEN
508
+ RAISE;
509
+ END IF;
510
+ END;
511
+ """
512
+
513
+ def _get_drop_table_sql(self) -> "list[str]":
514
+ """Get Oracle DROP TABLE SQL with PL/SQL error handling.
515
+
516
+ Returns:
517
+ List of SQL statements with exception handling for non-existent objects.
518
+ """
519
+ return [
520
+ f"""
521
+ BEGIN
522
+ EXECUTE IMMEDIATE 'DROP INDEX idx_{self._table_name}_expires_at';
523
+ EXCEPTION
524
+ WHEN OTHERS THEN
525
+ IF SQLCODE != -1418 THEN
526
+ RAISE;
527
+ END IF;
528
+ END;
529
+ """,
530
+ f"""
531
+ BEGIN
532
+ EXECUTE IMMEDIATE 'DROP TABLE {self._table_name}';
533
+ EXCEPTION
534
+ WHEN OTHERS THEN
535
+ IF SQLCODE != -942 THEN
536
+ RAISE;
537
+ END IF;
538
+ END;
539
+ """,
540
+ ]
541
+
542
+ def _create_table(self) -> None:
543
+ """Synchronous implementation of create_table."""
544
+ sql = self._get_create_table_sql()
545
+ with self._config.provide_session() as driver:
546
+ driver.execute_script(sql)
547
+
548
+ self._log_table_created()
549
+
550
+ async def create_table(self) -> None:
551
+ """Create the session table if it doesn't exist."""
552
+ await async_(self._create_table)()
553
+
554
+ def _get(self, key: str, renew_for: "int | timedelta | None" = None) -> "bytes | None":
555
+ """Synchronous implementation of get.
556
+
557
+ Notes:
558
+ Uses SYSTIMESTAMP for Oracle current timestamp.
559
+ """
560
+ sql = f"""
561
+ SELECT data, expires_at FROM {self._table_name}
562
+ WHERE session_id = :session_id
563
+ AND (expires_at IS NULL OR expires_at > SYSTIMESTAMP)
564
+ """
565
+
566
+ with self._config.provide_connection() as conn:
567
+ cursor = conn.cursor()
568
+ cursor.execute(sql, {"session_id": key})
569
+ row = cursor.fetchone()
570
+
571
+ if row is None:
572
+ return None
573
+
574
+ data_blob, expires_at = row
575
+
576
+ if renew_for is not None and expires_at is not None:
577
+ new_expires_at = self._calculate_expires_at(renew_for)
578
+ if new_expires_at is not None:
579
+ update_sql = f"""
580
+ UPDATE {self._table_name}
581
+ SET expires_at = :expires_at, updated_at = SYSTIMESTAMP
582
+ WHERE session_id = :session_id
583
+ """
584
+ cursor.execute(update_sql, {"expires_at": new_expires_at, "session_id": key})
585
+ conn.commit()
586
+
587
+ return _read_blob_sync(data_blob)
588
+
589
+ async def get(self, key: str, renew_for: "int | timedelta | None" = None) -> "bytes | None":
590
+ """Get a session value by key.
591
+
592
+ Args:
593
+ key: Session ID to retrieve.
594
+ renew_for: If given, renew the expiry time for this duration.
595
+
596
+ Returns:
597
+ Session data as bytes if found and not expired, None otherwise.
598
+ """
599
+ return await async_(self._get)(key, renew_for)
600
+
601
+ def _set(self, key: str, value: "str | bytes", expires_in: "int | timedelta | None" = None) -> None:
602
+ """Synchronous implementation of set.
603
+
604
+ Notes:
605
+ Uses MERGE for atomic UPSERT operation in Oracle.
606
+ """
607
+ data = self._value_to_bytes(value)
608
+ expires_at = self._calculate_expires_at(expires_in)
609
+
610
+ with self._config.provide_connection() as conn:
611
+ cursor = conn.cursor()
612
+
613
+ if len(data) > ORACLE_SMALL_BLOB_LIMIT:
614
+ merge_sql = f"""
615
+ MERGE INTO {self._table_name} t
616
+ USING (SELECT :session_id AS session_id FROM DUAL) s
617
+ ON (t.session_id = s.session_id)
618
+ WHEN MATCHED THEN
619
+ UPDATE SET
620
+ data = EMPTY_BLOB(),
621
+ expires_at = :expires_at,
622
+ updated_at = SYSTIMESTAMP
623
+ WHEN NOT MATCHED THEN
624
+ INSERT (session_id, data, expires_at, created_at, updated_at)
625
+ VALUES (:session_id, EMPTY_BLOB(), :expires_at, SYSTIMESTAMP, SYSTIMESTAMP)
626
+ """
627
+ cursor.execute(merge_sql, {"session_id": key, "expires_at": expires_at})
628
+
629
+ select_sql = f"""
630
+ SELECT data FROM {self._table_name}
631
+ WHERE session_id = :session_id FOR UPDATE
632
+ """
633
+ cursor.execute(select_sql, {"session_id": key})
634
+ row = cursor.fetchone()
635
+ if row:
636
+ blob = row[0]
637
+ blob.write(data)
638
+
639
+ conn.commit()
640
+ else:
641
+ sql = f"""
642
+ MERGE INTO {self._table_name} t
643
+ USING (SELECT :session_id AS session_id FROM DUAL) s
644
+ ON (t.session_id = s.session_id)
645
+ WHEN MATCHED THEN
646
+ UPDATE SET
647
+ data = :data,
648
+ expires_at = :expires_at,
649
+ updated_at = SYSTIMESTAMP
650
+ WHEN NOT MATCHED THEN
651
+ INSERT (session_id, data, expires_at, created_at, updated_at)
652
+ VALUES (:session_id, :data, :expires_at, SYSTIMESTAMP, SYSTIMESTAMP)
653
+ """
654
+ cursor.execute(sql, {"session_id": key, "data": data, "expires_at": expires_at})
655
+ conn.commit()
656
+
657
+ async def set(self, key: str, value: "str | bytes", expires_in: "int | timedelta | None" = None) -> None:
658
+ """Store a session value.
659
+
660
+ Args:
661
+ key: Session ID.
662
+ value: Session data.
663
+ expires_in: Time until expiration.
664
+ """
665
+ await async_(self._set)(key, value, expires_in)
666
+
667
+ def _delete(self, key: str) -> None:
668
+ """Synchronous implementation of delete."""
669
+ sql = f"DELETE FROM {self._table_name} WHERE session_id = :session_id"
670
+
671
+ with self._config.provide_connection() as conn:
672
+ cursor = conn.cursor()
673
+ cursor.execute(sql, {"session_id": key})
674
+ conn.commit()
675
+
676
+ async def delete(self, key: str) -> None:
677
+ """Delete a session by key.
678
+
679
+ Args:
680
+ key: Session ID to delete.
681
+ """
682
+ await async_(self._delete)(key)
683
+
684
+ def _delete_all(self) -> None:
685
+ """Synchronous implementation of delete_all."""
686
+ sql = f"DELETE FROM {self._table_name}"
687
+
688
+ with self._config.provide_connection() as conn:
689
+ cursor = conn.cursor()
690
+ cursor.execute(sql)
691
+ conn.commit()
692
+ self._log_delete_all()
693
+
694
+ async def delete_all(self) -> None:
695
+ """Delete all sessions from the store."""
696
+ await async_(self._delete_all)()
697
+
698
+ def _exists(self, key: str) -> bool:
699
+ """Synchronous implementation of exists."""
700
+ sql = f"""
701
+ SELECT 1 FROM {self._table_name}
702
+ WHERE session_id = :session_id
703
+ AND (expires_at IS NULL OR expires_at > SYSTIMESTAMP)
704
+ """
705
+
706
+ with self._config.provide_connection() as conn:
707
+ cursor = conn.cursor()
708
+ cursor.execute(sql, {"session_id": key})
709
+ result = cursor.fetchone()
710
+ return result is not None
711
+
712
+ async def exists(self, key: str) -> bool:
713
+ """Check if a session key exists and is not expired.
714
+
715
+ Args:
716
+ key: Session ID to check.
717
+
718
+ Returns:
719
+ True if the session exists and is not expired.
720
+ """
721
+ return await async_(self._exists)(key)
722
+
723
+ def _expires_in(self, key: str) -> "int | None":
724
+ """Synchronous implementation of expires_in."""
725
+ sql = f"""
726
+ SELECT expires_at FROM {self._table_name}
727
+ WHERE session_id = :session_id
728
+ """
729
+
730
+ with self._config.provide_connection() as conn:
731
+ cursor = conn.cursor()
732
+ cursor.execute(sql, {"session_id": key})
733
+ row = cursor.fetchone()
734
+
735
+ if row is None or row[0] is None:
736
+ return None
737
+
738
+ expires_at = row[0]
739
+
740
+ if expires_at.tzinfo is None:
741
+ expires_at = expires_at.replace(tzinfo=timezone.utc)
742
+
743
+ now = datetime.now(timezone.utc)
744
+
745
+ if expires_at <= now:
746
+ return 0
747
+
748
+ delta = expires_at - now
749
+ return int(delta.total_seconds())
750
+
751
+ async def expires_in(self, key: str) -> "int | None":
752
+ """Get the time in seconds until the session expires.
753
+
754
+ Args:
755
+ key: Session ID to check.
756
+
757
+ Returns:
758
+ Seconds until expiration, or None if no expiry or key doesn't exist.
759
+ """
760
+ return await async_(self._expires_in)(key)
761
+
762
+ def _delete_expired(self) -> int:
763
+ """Synchronous implementation of delete_expired."""
764
+ sql = f"DELETE FROM {self._table_name} WHERE expires_at <= SYSTIMESTAMP"
765
+
766
+ with self._config.provide_connection() as conn:
767
+ cursor = conn.cursor()
768
+ cursor.execute(sql)
769
+ count = cursor.rowcount if cursor.rowcount is not None else 0
770
+ conn.commit()
771
+ if count > 0:
772
+ self._log_delete_expired(count)
773
+ return count
774
+
775
+ async def delete_expired(self) -> int:
776
+ """Delete all expired sessions.
777
+
778
+ Returns:
779
+ Number of sessions deleted.
780
+ """
781
+ return await async_(self._delete_expired)()