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,868 @@
1
+ """CockroachDB ADK store for Google Agent Development Kit session/event storage (psycopg)."""
2
+
3
+ from typing import TYPE_CHECKING, Any, cast
4
+
5
+ from psycopg import errors
6
+ from psycopg import sql as pg_sql
7
+ from psycopg.types.json import Jsonb
8
+
9
+ from sqlspec.extensions.adk import BaseAsyncADKStore, BaseSyncADKStore, EventRecord, SessionRecord
10
+ from sqlspec.extensions.adk.memory.store import BaseAsyncADKMemoryStore, BaseSyncADKMemoryStore
11
+ from sqlspec.utils.logging import get_logger
12
+
13
+ if TYPE_CHECKING:
14
+ from sqlspec.adapters.cockroach_psycopg.config import CockroachPsycopgAsyncConfig, CockroachPsycopgSyncConfig
15
+ from sqlspec.extensions.adk import MemoryRecord
16
+
17
+
18
+ __all__ = (
19
+ "CockroachPsycopgAsyncADKMemoryStore",
20
+ "CockroachPsycopgAsyncADKStore",
21
+ "CockroachPsycopgSyncADKMemoryStore",
22
+ "CockroachPsycopgSyncADKStore",
23
+ )
24
+
25
+ logger = get_logger("sqlspec.adapters.cockroach_psycopg.adk.store")
26
+
27
+
28
+ def _build_insert_params(entry: "MemoryRecord") -> "tuple[object, ...]":
29
+ return (
30
+ entry["id"],
31
+ entry["session_id"],
32
+ entry["app_name"],
33
+ entry["user_id"],
34
+ entry["event_id"],
35
+ entry["author"],
36
+ entry["timestamp"],
37
+ Jsonb(entry["content_json"]),
38
+ entry["content_text"],
39
+ Jsonb(entry["metadata_json"]) if entry["metadata_json"] is not None else None,
40
+ entry["inserted_at"],
41
+ )
42
+
43
+
44
+ def _build_insert_params_with_owner(entry: "MemoryRecord", owner_id: "object | None") -> "tuple[object, ...]":
45
+ return (
46
+ entry["id"],
47
+ entry["session_id"],
48
+ entry["app_name"],
49
+ entry["user_id"],
50
+ entry["event_id"],
51
+ entry["author"],
52
+ owner_id,
53
+ entry["timestamp"],
54
+ Jsonb(entry["content_json"]),
55
+ entry["content_text"],
56
+ Jsonb(entry["metadata_json"]) if entry["metadata_json"] is not None else None,
57
+ entry["inserted_at"],
58
+ )
59
+
60
+
61
+ class CockroachPsycopgAsyncADKStore(BaseAsyncADKStore["CockroachPsycopgAsyncConfig"]):
62
+ """CockroachDB ADK store using psycopg async driver."""
63
+
64
+ __slots__ = ()
65
+
66
+ def __init__(self, config: "CockroachPsycopgAsyncConfig") -> None:
67
+ super().__init__(config)
68
+
69
+ async def _get_create_sessions_table_sql(self) -> str:
70
+ """Get CockroachDB CREATE TABLE SQL for sessions."""
71
+ owner_id_line = ""
72
+ if self._owner_id_column_ddl:
73
+ owner_id_line = f",\n {self._owner_id_column_ddl}"
74
+
75
+ return f"""
76
+ CREATE TABLE IF NOT EXISTS {self._session_table} (
77
+ id VARCHAR(128) PRIMARY KEY,
78
+ app_name VARCHAR(128) NOT NULL,
79
+ user_id VARCHAR(128) NOT NULL{owner_id_line},
80
+ state JSONB NOT NULL DEFAULT '{{}}'::jsonb,
81
+ create_time TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
82
+ update_time TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
83
+ );
84
+
85
+ CREATE INDEX IF NOT EXISTS idx_{self._session_table}_app_user
86
+ ON {self._session_table}(app_name, user_id);
87
+
88
+ CREATE INDEX IF NOT EXISTS idx_{self._session_table}_update_time
89
+ ON {self._session_table}(update_time DESC);
90
+ """
91
+
92
+ async def _get_create_events_table_sql(self) -> str:
93
+ """Get CockroachDB CREATE TABLE SQL for events."""
94
+ return f"""
95
+ CREATE TABLE IF NOT EXISTS {self._events_table} (
96
+ id VARCHAR(128) PRIMARY KEY,
97
+ session_id VARCHAR(128) NOT NULL,
98
+ app_name VARCHAR(128) NOT NULL,
99
+ user_id VARCHAR(128) NOT NULL,
100
+ invocation_id VARCHAR(256) NOT NULL,
101
+ author VARCHAR(256) NOT NULL,
102
+ actions BYTEA NOT NULL,
103
+ long_running_tool_ids_json JSONB,
104
+ branch VARCHAR(256),
105
+ timestamp TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
106
+ content JSONB,
107
+ grounding_metadata JSONB,
108
+ custom_metadata JSONB,
109
+ partial BOOLEAN,
110
+ turn_complete BOOLEAN,
111
+ interrupted BOOLEAN,
112
+ error_code VARCHAR(256),
113
+ error_message VARCHAR(1024),
114
+ FOREIGN KEY (session_id) REFERENCES {self._session_table}(id) ON DELETE CASCADE
115
+ );
116
+
117
+ CREATE INDEX IF NOT EXISTS idx_{self._events_table}_session
118
+ ON {self._events_table}(session_id, timestamp ASC);
119
+ """
120
+
121
+ def _get_drop_tables_sql(self) -> "list[str]":
122
+ return [f"DROP TABLE IF EXISTS {self._events_table}", f"DROP TABLE IF EXISTS {self._session_table}"]
123
+
124
+ async def create_tables(self) -> None:
125
+ async with self._config.provide_session() as driver:
126
+ await driver.execute_script(await self._get_create_sessions_table_sql())
127
+ await driver.execute_script(await self._get_create_events_table_sql())
128
+
129
+ async def create_session(
130
+ self, session_id: str, app_name: str, user_id: str, state: "dict[str, Any]", owner_id: "Any | None" = None
131
+ ) -> SessionRecord:
132
+ state_json = Jsonb(state)
133
+
134
+ params: tuple[Any, ...]
135
+ if self._owner_id_column_name:
136
+ sql = f"""
137
+ INSERT INTO {self._session_table} (id, app_name, user_id, {self._owner_id_column_name}, state, create_time, update_time)
138
+ VALUES (%s, %s, %s, %s, %s, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
139
+ """
140
+ params = (session_id, app_name, user_id, owner_id, state_json)
141
+ else:
142
+ sql = f"""
143
+ INSERT INTO {self._session_table} (id, app_name, user_id, state, create_time, update_time)
144
+ VALUES (%s, %s, %s, %s, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
145
+ """
146
+ params = (session_id, app_name, user_id, state_json)
147
+
148
+ async with self._config.provide_connection() as conn, conn.cursor() as cur:
149
+ await cur.execute(sql.encode(), params)
150
+ await conn.commit()
151
+
152
+ result = await self.get_session(session_id)
153
+ if result is None:
154
+ msg = "Session creation failed"
155
+ raise RuntimeError(msg)
156
+ return result
157
+
158
+ async def get_session(self, session_id: str) -> "SessionRecord | None":
159
+ sql = f"""
160
+ SELECT id, app_name, user_id, state, create_time, update_time
161
+ FROM {self._session_table}
162
+ WHERE id = %s
163
+ """
164
+
165
+ try:
166
+ async with self._config.provide_connection() as conn, conn.cursor() as cur:
167
+ await cur.execute(sql.encode(), (session_id,))
168
+ row = await cur.fetchone()
169
+
170
+ if row is None:
171
+ return None
172
+
173
+ return SessionRecord(
174
+ id=row["id"],
175
+ app_name=row["app_name"],
176
+ user_id=row["user_id"],
177
+ state=row["state"],
178
+ create_time=row["create_time"],
179
+ update_time=row["update_time"],
180
+ )
181
+ except errors.UndefinedTable:
182
+ return None
183
+
184
+ async def update_session_state(self, session_id: str, state: "dict[str, Any]") -> None:
185
+ sql = f"""
186
+ UPDATE {self._session_table}
187
+ SET state = %s, update_time = CURRENT_TIMESTAMP
188
+ WHERE id = %s
189
+ """
190
+
191
+ async with self._config.provide_connection() as conn, conn.cursor() as cur:
192
+ await cur.execute(sql.encode(), (Jsonb(state), session_id))
193
+ await conn.commit()
194
+
195
+ async def delete_session(self, session_id: str) -> None:
196
+ sql = f"DELETE FROM {self._session_table} WHERE id = %s"
197
+
198
+ async with self._config.provide_connection() as conn, conn.cursor() as cur:
199
+ await cur.execute(sql.encode(), (session_id,))
200
+ await conn.commit()
201
+
202
+ async def list_sessions(self, app_name: str, user_id: str | None = None) -> "list[SessionRecord]":
203
+ if user_id is None:
204
+ sql = f"""
205
+ SELECT id, app_name, user_id, state, create_time, update_time
206
+ FROM {self._session_table}
207
+ WHERE app_name = %s
208
+ ORDER BY update_time DESC
209
+ """
210
+ params: tuple[str, ...] = (app_name,)
211
+ else:
212
+ sql = f"""
213
+ SELECT id, app_name, user_id, state, create_time, update_time
214
+ FROM {self._session_table}
215
+ WHERE app_name = %s AND user_id = %s
216
+ ORDER BY update_time DESC
217
+ """
218
+ params = (app_name, user_id)
219
+
220
+ try:
221
+ async with self._config.provide_connection() as conn, conn.cursor() as cur:
222
+ await cur.execute(sql.encode(), params)
223
+ rows = await cur.fetchall()
224
+
225
+ return [
226
+ SessionRecord(
227
+ id=row["id"],
228
+ app_name=row["app_name"],
229
+ user_id=row["user_id"],
230
+ state=row["state"],
231
+ create_time=row["create_time"],
232
+ update_time=row["update_time"],
233
+ )
234
+ for row in rows
235
+ ]
236
+ except errors.UndefinedTable:
237
+ return []
238
+
239
+ async def append_event(self, event_record: EventRecord) -> None:
240
+ sql = f"""
241
+ INSERT INTO {self._events_table} (
242
+ id, session_id, app_name, user_id, invocation_id, author, actions,
243
+ long_running_tool_ids_json, branch, timestamp, content,
244
+ grounding_metadata, custom_metadata, partial, turn_complete,
245
+ interrupted, error_code, error_message
246
+ ) VALUES (
247
+ %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
248
+ )
249
+ """
250
+
251
+ async with self._config.provide_connection() as conn, conn.cursor() as cur:
252
+ await cur.execute(
253
+ sql.encode(),
254
+ (
255
+ event_record["id"],
256
+ event_record["session_id"],
257
+ event_record["app_name"],
258
+ event_record["user_id"],
259
+ event_record["invocation_id"],
260
+ event_record["author"],
261
+ event_record["actions"],
262
+ event_record.get("long_running_tool_ids_json"),
263
+ event_record.get("branch"),
264
+ event_record["timestamp"],
265
+ event_record.get("content"),
266
+ event_record.get("grounding_metadata"),
267
+ event_record.get("custom_metadata"),
268
+ event_record.get("partial"),
269
+ event_record.get("turn_complete"),
270
+ event_record.get("interrupted"),
271
+ event_record.get("error_code"),
272
+ event_record.get("error_message"),
273
+ ),
274
+ )
275
+ await conn.commit()
276
+
277
+ async def list_events(self, session_id: str) -> "list[EventRecord]":
278
+ sql = f"""
279
+ SELECT id, session_id, app_name, user_id, invocation_id, author, actions,
280
+ long_running_tool_ids_json, branch, timestamp, content,
281
+ grounding_metadata, custom_metadata, partial, turn_complete,
282
+ interrupted, error_code, error_message
283
+ FROM {self._events_table}
284
+ WHERE session_id = %s
285
+ ORDER BY timestamp ASC
286
+ """
287
+
288
+ try:
289
+ async with self._config.provide_connection() as conn, conn.cursor() as cur:
290
+ await cur.execute(sql.encode(), (session_id,))
291
+ rows = await cur.fetchall()
292
+
293
+ return [
294
+ EventRecord(
295
+ id=row["id"],
296
+ session_id=row["session_id"],
297
+ app_name=row["app_name"],
298
+ user_id=row["user_id"],
299
+ invocation_id=row["invocation_id"],
300
+ author=row["author"],
301
+ actions=bytes(row["actions"]),
302
+ long_running_tool_ids_json=row["long_running_tool_ids_json"],
303
+ branch=row["branch"],
304
+ timestamp=row["timestamp"],
305
+ content=row["content"],
306
+ grounding_metadata=row["grounding_metadata"],
307
+ custom_metadata=row["custom_metadata"],
308
+ partial=row["partial"],
309
+ turn_complete=row["turn_complete"],
310
+ interrupted=row["interrupted"],
311
+ error_code=row["error_code"],
312
+ error_message=row["error_message"],
313
+ )
314
+ for row in rows
315
+ ]
316
+ except errors.UndefinedTable:
317
+ return []
318
+
319
+
320
+ class CockroachPsycopgSyncADKStore(BaseSyncADKStore["CockroachPsycopgSyncConfig"]):
321
+ """CockroachDB ADK store using psycopg sync driver."""
322
+
323
+ __slots__ = ()
324
+
325
+ def __init__(self, config: "CockroachPsycopgSyncConfig") -> None:
326
+ super().__init__(config)
327
+
328
+ def _get_create_sessions_table_sql(self) -> str:
329
+ owner_id_line = ""
330
+ if self._owner_id_column_ddl:
331
+ owner_id_line = f",\n {self._owner_id_column_ddl}"
332
+
333
+ return f"""
334
+ CREATE TABLE IF NOT EXISTS {self._session_table} (
335
+ id VARCHAR(128) PRIMARY KEY,
336
+ app_name VARCHAR(128) NOT NULL,
337
+ user_id VARCHAR(128) NOT NULL{owner_id_line},
338
+ state JSONB NOT NULL DEFAULT '{{}}'::jsonb,
339
+ create_time TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
340
+ update_time TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
341
+ );
342
+
343
+ CREATE INDEX IF NOT EXISTS idx_{self._session_table}_app_user
344
+ ON {self._session_table}(app_name, user_id);
345
+
346
+ CREATE INDEX IF NOT EXISTS idx_{self._session_table}_update_time
347
+ ON {self._session_table}(update_time DESC);
348
+ """
349
+
350
+ def _get_create_events_table_sql(self) -> str:
351
+ return f"""
352
+ CREATE TABLE IF NOT EXISTS {self._events_table} (
353
+ id VARCHAR(128) PRIMARY KEY,
354
+ session_id VARCHAR(128) NOT NULL,
355
+ app_name VARCHAR(128) NOT NULL,
356
+ user_id VARCHAR(128) NOT NULL,
357
+ invocation_id VARCHAR(256) NOT NULL,
358
+ author VARCHAR(256) NOT NULL,
359
+ actions BYTEA NOT NULL,
360
+ long_running_tool_ids_json JSONB,
361
+ branch VARCHAR(256),
362
+ timestamp TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
363
+ content JSONB,
364
+ grounding_metadata JSONB,
365
+ custom_metadata JSONB,
366
+ partial BOOLEAN,
367
+ turn_complete BOOLEAN,
368
+ interrupted BOOLEAN,
369
+ error_code VARCHAR(256),
370
+ error_message VARCHAR(1024),
371
+ FOREIGN KEY (session_id) REFERENCES {self._session_table}(id) ON DELETE CASCADE
372
+ );
373
+
374
+ CREATE INDEX IF NOT EXISTS idx_{self._events_table}_session
375
+ ON {self._events_table}(session_id, timestamp ASC);
376
+ """
377
+
378
+ def _get_drop_tables_sql(self) -> "list[str]":
379
+ return [f"DROP TABLE IF EXISTS {self._events_table}", f"DROP TABLE IF EXISTS {self._session_table}"]
380
+
381
+ def create_tables(self) -> None:
382
+ with self._config.provide_session() as driver:
383
+ driver.execute_script(self._get_create_sessions_table_sql())
384
+ driver.execute_script(self._get_create_events_table_sql())
385
+
386
+ def create_session(
387
+ self, session_id: str, app_name: str, user_id: str, state: "dict[str, Any]", owner_id: "Any | None" = None
388
+ ) -> SessionRecord:
389
+ state_json = Jsonb(state)
390
+
391
+ params: tuple[Any, ...]
392
+ if self._owner_id_column_name:
393
+ sql = f"""
394
+ INSERT INTO {self._session_table} (id, app_name, user_id, {self._owner_id_column_name}, state, create_time, update_time)
395
+ VALUES (%s, %s, %s, %s, %s, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
396
+ """
397
+ params = (session_id, app_name, user_id, owner_id, state_json)
398
+ else:
399
+ sql = f"""
400
+ INSERT INTO {self._session_table} (id, app_name, user_id, state, create_time, update_time)
401
+ VALUES (%s, %s, %s, %s, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
402
+ """
403
+ params = (session_id, app_name, user_id, state_json)
404
+
405
+ with self._config.provide_connection() as conn, conn.cursor() as cur:
406
+ cur.execute(sql.encode(), params)
407
+ conn.commit()
408
+
409
+ result = self.get_session(session_id)
410
+ if result is None:
411
+ msg = "Session creation failed"
412
+ raise RuntimeError(msg)
413
+ return result
414
+
415
+ def get_session(self, session_id: str) -> "SessionRecord | None":
416
+ sql = f"""
417
+ SELECT id, app_name, user_id, state, create_time, update_time
418
+ FROM {self._session_table}
419
+ WHERE id = %s
420
+ """
421
+
422
+ try:
423
+ with self._config.provide_connection() as conn, conn.cursor() as cur:
424
+ cur.execute(sql.encode(), (session_id,))
425
+ row = cur.fetchone()
426
+
427
+ if row is None:
428
+ return None
429
+
430
+ return SessionRecord(
431
+ id=row["id"],
432
+ app_name=row["app_name"],
433
+ user_id=row["user_id"],
434
+ state=row["state"],
435
+ create_time=row["create_time"],
436
+ update_time=row["update_time"],
437
+ )
438
+ except errors.UndefinedTable:
439
+ return None
440
+
441
+ def update_session_state(self, session_id: str, state: "dict[str, Any]") -> None:
442
+ sql = f"""
443
+ UPDATE {self._session_table}
444
+ SET state = %s, update_time = CURRENT_TIMESTAMP
445
+ WHERE id = %s
446
+ """
447
+
448
+ with self._config.provide_connection() as conn, conn.cursor() as cur:
449
+ cur.execute(sql.encode(), (Jsonb(state), session_id))
450
+ conn.commit()
451
+
452
+ def delete_session(self, session_id: str) -> None:
453
+ sql = f"DELETE FROM {self._session_table} WHERE id = %s"
454
+
455
+ with self._config.provide_connection() as conn, conn.cursor() as cur:
456
+ cur.execute(sql.encode(), (session_id,))
457
+ conn.commit()
458
+
459
+ def list_sessions(self, app_name: str, user_id: str | None = None) -> "list[SessionRecord]":
460
+ if user_id is None:
461
+ sql = f"""
462
+ SELECT id, app_name, user_id, state, create_time, update_time
463
+ FROM {self._session_table}
464
+ WHERE app_name = %s
465
+ ORDER BY update_time DESC
466
+ """
467
+ params: tuple[str, ...] = (app_name,)
468
+ else:
469
+ sql = f"""
470
+ SELECT id, app_name, user_id, state, create_time, update_time
471
+ FROM {self._session_table}
472
+ WHERE app_name = %s AND user_id = %s
473
+ ORDER BY update_time DESC
474
+ """
475
+ params = (app_name, user_id)
476
+
477
+ try:
478
+ with self._config.provide_connection() as conn, conn.cursor() as cur:
479
+ cur.execute(sql.encode(), params)
480
+ rows = cur.fetchall()
481
+
482
+ return [
483
+ SessionRecord(
484
+ id=row["id"],
485
+ app_name=row["app_name"],
486
+ user_id=row["user_id"],
487
+ state=row["state"],
488
+ create_time=row["create_time"],
489
+ update_time=row["update_time"],
490
+ )
491
+ for row in rows
492
+ ]
493
+ except errors.UndefinedTable:
494
+ return []
495
+
496
+ def append_event(self, event_record: EventRecord) -> None:
497
+ sql = f"""
498
+ INSERT INTO {self._events_table} (
499
+ id, session_id, app_name, user_id, invocation_id, author, actions,
500
+ long_running_tool_ids_json, branch, timestamp, content,
501
+ grounding_metadata, custom_metadata, partial, turn_complete,
502
+ interrupted, error_code, error_message
503
+ ) VALUES (
504
+ %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
505
+ )
506
+ """
507
+
508
+ with self._config.provide_connection() as conn, conn.cursor() as cur:
509
+ cur.execute(
510
+ sql.encode(),
511
+ (
512
+ event_record["id"],
513
+ event_record["session_id"],
514
+ event_record["app_name"],
515
+ event_record["user_id"],
516
+ event_record["invocation_id"],
517
+ event_record["author"],
518
+ event_record["actions"],
519
+ event_record.get("long_running_tool_ids_json"),
520
+ event_record.get("branch"),
521
+ event_record["timestamp"],
522
+ event_record.get("content"),
523
+ event_record.get("grounding_metadata"),
524
+ event_record.get("custom_metadata"),
525
+ event_record.get("partial"),
526
+ event_record.get("turn_complete"),
527
+ event_record.get("interrupted"),
528
+ event_record.get("error_code"),
529
+ event_record.get("error_message"),
530
+ ),
531
+ )
532
+ conn.commit()
533
+
534
+ def list_events(self, session_id: str) -> "list[EventRecord]":
535
+ sql = f"""
536
+ SELECT id, session_id, app_name, user_id, invocation_id, author, actions,
537
+ long_running_tool_ids_json, branch, timestamp, content,
538
+ grounding_metadata, custom_metadata, partial, turn_complete,
539
+ interrupted, error_code, error_message
540
+ FROM {self._events_table}
541
+ WHERE session_id = %s
542
+ ORDER BY timestamp ASC
543
+ """
544
+
545
+ try:
546
+ with self._config.provide_connection() as conn, conn.cursor() as cur:
547
+ cur.execute(sql.encode(), (session_id,))
548
+ rows = cur.fetchall()
549
+
550
+ return [
551
+ EventRecord(
552
+ id=row["id"],
553
+ session_id=row["session_id"],
554
+ app_name=row["app_name"],
555
+ user_id=row["user_id"],
556
+ invocation_id=row["invocation_id"],
557
+ author=row["author"],
558
+ actions=bytes(row["actions"]),
559
+ long_running_tool_ids_json=row["long_running_tool_ids_json"],
560
+ branch=row["branch"],
561
+ timestamp=row["timestamp"],
562
+ content=row["content"],
563
+ grounding_metadata=row["grounding_metadata"],
564
+ custom_metadata=row["custom_metadata"],
565
+ partial=row["partial"],
566
+ turn_complete=row["turn_complete"],
567
+ interrupted=row["interrupted"],
568
+ error_code=row["error_code"],
569
+ error_message=row["error_message"],
570
+ )
571
+ for row in rows
572
+ ]
573
+ except errors.UndefinedTable:
574
+ return []
575
+
576
+
577
+ class CockroachPsycopgAsyncADKMemoryStore(BaseAsyncADKMemoryStore["CockroachPsycopgAsyncConfig"]):
578
+ """CockroachDB ADK memory store using psycopg async driver."""
579
+
580
+ __slots__ = ()
581
+
582
+ def __init__(self, config: "CockroachPsycopgAsyncConfig") -> None:
583
+ super().__init__(config)
584
+
585
+ async def _get_create_memory_table_sql(self) -> str:
586
+ owner_id_line = ""
587
+ if self._owner_id_column_ddl:
588
+ owner_id_line = f",\n {self._owner_id_column_ddl}"
589
+
590
+ return f"""
591
+ CREATE TABLE IF NOT EXISTS {self._memory_table} (
592
+ id VARCHAR(128) PRIMARY KEY,
593
+ session_id VARCHAR(128) NOT NULL,
594
+ app_name VARCHAR(128) NOT NULL,
595
+ user_id VARCHAR(128) NOT NULL,
596
+ event_id VARCHAR(128) NOT NULL UNIQUE,
597
+ author VARCHAR(256){owner_id_line},
598
+ timestamp TIMESTAMPTZ NOT NULL,
599
+ content_json JSONB NOT NULL,
600
+ content_text TEXT NOT NULL,
601
+ metadata_json JSONB,
602
+ inserted_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
603
+ );
604
+
605
+ CREATE INDEX IF NOT EXISTS idx_{self._memory_table}_app_user_time
606
+ ON {self._memory_table}(app_name, user_id, timestamp DESC);
607
+
608
+ CREATE INDEX IF NOT EXISTS idx_{self._memory_table}_session
609
+ ON {self._memory_table}(session_id);
610
+ """
611
+
612
+ def _get_drop_memory_table_sql(self) -> "list[str]":
613
+ return [f"DROP TABLE IF EXISTS {self._memory_table}"]
614
+
615
+ async def create_tables(self) -> None:
616
+ if not self._enabled:
617
+ return
618
+
619
+ async with self._config.provide_session() as driver:
620
+ await driver.execute_script(await self._get_create_memory_table_sql())
621
+
622
+ async def insert_memory_entries(self, entries: "list[MemoryRecord]", owner_id: "object | None" = None) -> int:
623
+ if not self._enabled:
624
+ msg = "Memory store is disabled"
625
+ raise RuntimeError(msg)
626
+
627
+ if not entries:
628
+ return 0
629
+
630
+ inserted_count = 0
631
+ if self._owner_id_column_name:
632
+ query = pg_sql.SQL("""
633
+ INSERT INTO {table} (
634
+ id, session_id, app_name, user_id, event_id, author,
635
+ {owner_id_col}, timestamp, content_json, content_text,
636
+ metadata_json, inserted_at
637
+ ) VALUES (
638
+ %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
639
+ )
640
+ ON CONFLICT (event_id) DO NOTHING
641
+ """).format(
642
+ table=pg_sql.Identifier(self._memory_table), owner_id_col=pg_sql.Identifier(self._owner_id_column_name)
643
+ )
644
+ else:
645
+ query = pg_sql.SQL("""
646
+ INSERT INTO {table} (
647
+ id, session_id, app_name, user_id, event_id, author,
648
+ timestamp, content_json, content_text, metadata_json, inserted_at
649
+ ) VALUES (
650
+ %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
651
+ )
652
+ ON CONFLICT (event_id) DO NOTHING
653
+ """).format(table=pg_sql.Identifier(self._memory_table))
654
+
655
+ async with self._config.provide_connection() as conn, conn.cursor() as cur:
656
+ for entry in entries:
657
+ if self._owner_id_column_name:
658
+ await cur.execute(query, _build_insert_params_with_owner(entry, owner_id))
659
+ else:
660
+ await cur.execute(query, _build_insert_params(entry))
661
+ if cur.rowcount and cur.rowcount > 0:
662
+ inserted_count += cur.rowcount
663
+ await conn.commit()
664
+
665
+ return inserted_count
666
+
667
+ async def search_entries(
668
+ self, query: str, app_name: str, user_id: str, limit: "int | None" = None
669
+ ) -> "list[MemoryRecord]":
670
+ if not self._enabled:
671
+ msg = "Memory store is disabled"
672
+ raise RuntimeError(msg)
673
+
674
+ if not query:
675
+ return []
676
+
677
+ effective_limit = limit if limit is not None else self._max_results
678
+ if self._use_fts:
679
+ logger.debug("CockroachDB full-text search not supported; using simple search")
680
+
681
+ sql = f"""
682
+ SELECT * FROM {self._memory_table}
683
+ WHERE app_name = %s AND user_id = %s AND content_text ILIKE %s
684
+ ORDER BY timestamp DESC
685
+ LIMIT %s
686
+ """
687
+ params = (app_name, user_id, f"%{query}%", effective_limit)
688
+
689
+ try:
690
+ async with self._config.provide_connection() as conn, conn.cursor() as cur:
691
+ await cur.execute(sql.encode(), params)
692
+ rows = await cur.fetchall()
693
+ columns = [col[0] for col in cur.description or []]
694
+ except errors.UndefinedTable:
695
+ return []
696
+
697
+ return [cast("MemoryRecord", dict(zip(columns, row, strict=False))) for row in rows]
698
+
699
+ async def delete_entries_by_session(self, session_id: str) -> int:
700
+ if not self._enabled:
701
+ msg = "Memory store is disabled"
702
+ raise RuntimeError(msg)
703
+
704
+ sql = f"DELETE FROM {self._memory_table} WHERE session_id = %s"
705
+ async with self._config.provide_connection() as conn, conn.cursor() as cur:
706
+ await cur.execute(sql.encode(), (session_id,))
707
+ await conn.commit()
708
+ return cur.rowcount if cur.rowcount and cur.rowcount > 0 else 0
709
+
710
+ async def delete_entries_older_than(self, days: int) -> int:
711
+ if not self._enabled:
712
+ msg = "Memory store is disabled"
713
+ raise RuntimeError(msg)
714
+
715
+ sql = f"""
716
+ DELETE FROM {self._memory_table}
717
+ WHERE inserted_at < (CURRENT_TIMESTAMP - INTERVAL %s DAY)
718
+ """
719
+ async with self._config.provide_connection() as conn, conn.cursor() as cur:
720
+ await cur.execute(sql.encode(), (days,))
721
+ await conn.commit()
722
+ return cur.rowcount if cur.rowcount and cur.rowcount > 0 else 0
723
+
724
+
725
+ class CockroachPsycopgSyncADKMemoryStore(BaseSyncADKMemoryStore["CockroachPsycopgSyncConfig"]):
726
+ """CockroachDB ADK memory store using psycopg sync driver."""
727
+
728
+ __slots__ = ()
729
+
730
+ def __init__(self, config: "CockroachPsycopgSyncConfig") -> None:
731
+ super().__init__(config)
732
+
733
+ def _get_create_memory_table_sql(self) -> str:
734
+ owner_id_line = ""
735
+ if self._owner_id_column_ddl:
736
+ owner_id_line = f",\n {self._owner_id_column_ddl}"
737
+
738
+ return f"""
739
+ CREATE TABLE IF NOT EXISTS {self._memory_table} (
740
+ id VARCHAR(128) PRIMARY KEY,
741
+ session_id VARCHAR(128) NOT NULL,
742
+ app_name VARCHAR(128) NOT NULL,
743
+ user_id VARCHAR(128) NOT NULL,
744
+ event_id VARCHAR(128) NOT NULL UNIQUE,
745
+ author VARCHAR(256){owner_id_line},
746
+ timestamp TIMESTAMPTZ NOT NULL,
747
+ content_json JSONB NOT NULL,
748
+ content_text TEXT NOT NULL,
749
+ metadata_json JSONB,
750
+ inserted_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
751
+ );
752
+
753
+ CREATE INDEX IF NOT EXISTS idx_{self._memory_table}_app_user_time
754
+ ON {self._memory_table}(app_name, user_id, timestamp DESC);
755
+
756
+ CREATE INDEX IF NOT EXISTS idx_{self._memory_table}_session
757
+ ON {self._memory_table}(session_id);
758
+ """
759
+
760
+ def _get_drop_memory_table_sql(self) -> "list[str]":
761
+ return [f"DROP TABLE IF EXISTS {self._memory_table}"]
762
+
763
+ def create_tables(self) -> None:
764
+ if not self._enabled:
765
+ return
766
+
767
+ with self._config.provide_session() as driver:
768
+ driver.execute_script(self._get_create_memory_table_sql())
769
+
770
+ def insert_memory_entries(self, entries: "list[MemoryRecord]", owner_id: "object | None" = None) -> int:
771
+ if not self._enabled:
772
+ msg = "Memory store is disabled"
773
+ raise RuntimeError(msg)
774
+
775
+ if not entries:
776
+ return 0
777
+
778
+ inserted_count = 0
779
+ if self._owner_id_column_name:
780
+ query = pg_sql.SQL("""
781
+ INSERT INTO {table} (
782
+ id, session_id, app_name, user_id, event_id, author,
783
+ {owner_id_col}, timestamp, content_json, content_text,
784
+ metadata_json, inserted_at
785
+ ) VALUES (
786
+ %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
787
+ )
788
+ ON CONFLICT (event_id) DO NOTHING
789
+ """).format(
790
+ table=pg_sql.Identifier(self._memory_table), owner_id_col=pg_sql.Identifier(self._owner_id_column_name)
791
+ )
792
+ else:
793
+ query = pg_sql.SQL("""
794
+ INSERT INTO {table} (
795
+ id, session_id, app_name, user_id, event_id, author,
796
+ timestamp, content_json, content_text, metadata_json, inserted_at
797
+ ) VALUES (
798
+ %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
799
+ )
800
+ ON CONFLICT (event_id) DO NOTHING
801
+ """).format(table=pg_sql.Identifier(self._memory_table))
802
+
803
+ with self._config.provide_connection() as conn, conn.cursor() as cur:
804
+ for entry in entries:
805
+ if self._owner_id_column_name:
806
+ cur.execute(query, _build_insert_params_with_owner(entry, owner_id))
807
+ else:
808
+ cur.execute(query, _build_insert_params(entry))
809
+ if cur.rowcount and cur.rowcount > 0:
810
+ inserted_count += cur.rowcount
811
+ return inserted_count
812
+
813
+ def search_entries(
814
+ self, query: str, app_name: str, user_id: str, limit: "int | None" = None
815
+ ) -> "list[MemoryRecord]":
816
+ if not self._enabled:
817
+ msg = "Memory store is disabled"
818
+ raise RuntimeError(msg)
819
+
820
+ if not query:
821
+ return []
822
+
823
+ effective_limit = limit if limit is not None else self._max_results
824
+ if self._use_fts:
825
+ logger.debug("CockroachDB full-text search not supported; using simple search")
826
+
827
+ sql = f"""
828
+ SELECT * FROM {self._memory_table}
829
+ WHERE app_name = %s AND user_id = %s AND content_text ILIKE %s
830
+ ORDER BY timestamp DESC
831
+ LIMIT %s
832
+ """
833
+ params = (app_name, user_id, f"%{query}%", effective_limit)
834
+
835
+ try:
836
+ with self._config.provide_connection() as conn, conn.cursor() as cur:
837
+ cur.execute(sql.encode(), params)
838
+ rows = cur.fetchall()
839
+ columns = [col[0] for col in cur.description or []]
840
+ except errors.UndefinedTable:
841
+ return []
842
+
843
+ return [cast("MemoryRecord", dict(zip(columns, row, strict=False))) for row in rows]
844
+
845
+ def delete_entries_by_session(self, session_id: str) -> int:
846
+ if not self._enabled:
847
+ msg = "Memory store is disabled"
848
+ raise RuntimeError(msg)
849
+
850
+ sql = f"DELETE FROM {self._memory_table} WHERE session_id = %s"
851
+ with self._config.provide_connection() as conn, conn.cursor() as cur:
852
+ cur.execute(sql.encode(), (session_id,))
853
+ conn.commit()
854
+ return cur.rowcount if cur.rowcount and cur.rowcount > 0 else 0
855
+
856
+ def delete_entries_older_than(self, days: int) -> int:
857
+ if not self._enabled:
858
+ msg = "Memory store is disabled"
859
+ raise RuntimeError(msg)
860
+
861
+ sql = f"""
862
+ DELETE FROM {self._memory_table}
863
+ WHERE inserted_at < (CURRENT_TIMESTAMP - INTERVAL %s DAY)
864
+ """
865
+ with self._config.provide_connection() as conn, conn.cursor() as cur:
866
+ cur.execute(sql.encode(), (days,))
867
+ conn.commit()
868
+ return cur.rowcount if cur.rowcount and cur.rowcount > 0 else 0