sqlspec 0.47.0__cp314-cp314-win_amd64.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 (621) hide show
  1. f68e0789eb443ecb1c2c__mypyc.cp314-win_amd64.pyd +0 -0
  2. sqlspec/__init__.py +167 -0
  3. sqlspec/__main__.py +12 -0
  4. sqlspec/__metadata__.py +14 -0
  5. sqlspec/_typing.py +714 -0
  6. sqlspec/adapters/__init__.py +0 -0
  7. sqlspec/adapters/adbc/__init__.py +13 -0
  8. sqlspec/adapters/adbc/_typing.py +106 -0
  9. sqlspec/adapters/adbc/adk/__init__.py +5 -0
  10. sqlspec/adapters/adbc/adk/store.py +1280 -0
  11. sqlspec/adapters/adbc/config.py +378 -0
  12. sqlspec/adapters/adbc/core.cp314-win_amd64.pyd +0 -0
  13. sqlspec/adapters/adbc/core.py +922 -0
  14. sqlspec/adapters/adbc/data_dictionary.py +339 -0
  15. sqlspec/adapters/adbc/driver.py +534 -0
  16. sqlspec/adapters/adbc/events/__init__.py +5 -0
  17. sqlspec/adapters/adbc/events/store.py +285 -0
  18. sqlspec/adapters/adbc/litestar/__init__.py +5 -0
  19. sqlspec/adapters/adbc/litestar/store.py +534 -0
  20. sqlspec/adapters/adbc/type_converter.cp314-win_amd64.pyd +0 -0
  21. sqlspec/adapters/adbc/type_converter.py +142 -0
  22. sqlspec/adapters/aiomysql/__init__.py +21 -0
  23. sqlspec/adapters/aiomysql/_typing.py +137 -0
  24. sqlspec/adapters/aiomysql/adk/__init__.py +5 -0
  25. sqlspec/adapters/aiomysql/adk/store.py +678 -0
  26. sqlspec/adapters/aiomysql/config.py +305 -0
  27. sqlspec/adapters/aiomysql/core.cp314-win_amd64.pyd +0 -0
  28. sqlspec/adapters/aiomysql/core.py +536 -0
  29. sqlspec/adapters/aiomysql/data_dictionary.py +121 -0
  30. sqlspec/adapters/aiomysql/driver.py +386 -0
  31. sqlspec/adapters/aiomysql/events/__init__.py +5 -0
  32. sqlspec/adapters/aiomysql/events/store.py +104 -0
  33. sqlspec/adapters/aiomysql/litestar/__init__.py +5 -0
  34. sqlspec/adapters/aiomysql/litestar/store.py +314 -0
  35. sqlspec/adapters/aiosqlite/__init__.py +26 -0
  36. sqlspec/adapters/aiosqlite/_typing.py +109 -0
  37. sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
  38. sqlspec/adapters/aiosqlite/adk/store.py +829 -0
  39. sqlspec/adapters/aiosqlite/config.py +315 -0
  40. sqlspec/adapters/aiosqlite/core.cp314-win_amd64.pyd +0 -0
  41. sqlspec/adapters/aiosqlite/core.py +315 -0
  42. sqlspec/adapters/aiosqlite/data_dictionary.py +202 -0
  43. sqlspec/adapters/aiosqlite/driver.py +311 -0
  44. sqlspec/adapters/aiosqlite/events/__init__.py +5 -0
  45. sqlspec/adapters/aiosqlite/events/store.py +20 -0
  46. sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
  47. sqlspec/adapters/aiosqlite/litestar/store.py +279 -0
  48. sqlspec/adapters/aiosqlite/pool.cp314-win_amd64.pyd +0 -0
  49. sqlspec/adapters/aiosqlite/pool.py +734 -0
  50. sqlspec/adapters/asyncmy/__init__.py +21 -0
  51. sqlspec/adapters/asyncmy/_typing.py +113 -0
  52. sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
  53. sqlspec/adapters/asyncmy/adk/store.py +644 -0
  54. sqlspec/adapters/asyncmy/config.py +307 -0
  55. sqlspec/adapters/asyncmy/core.cp314-win_amd64.pyd +0 -0
  56. sqlspec/adapters/asyncmy/core.py +538 -0
  57. sqlspec/adapters/asyncmy/data_dictionary.py +122 -0
  58. sqlspec/adapters/asyncmy/driver.py +391 -0
  59. sqlspec/adapters/asyncmy/events/__init__.py +5 -0
  60. sqlspec/adapters/asyncmy/events/store.py +104 -0
  61. sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
  62. sqlspec/adapters/asyncmy/litestar/store.py +296 -0
  63. sqlspec/adapters/asyncpg/__init__.py +26 -0
  64. sqlspec/adapters/asyncpg/_typing.py +103 -0
  65. sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
  66. sqlspec/adapters/asyncpg/adk/store.py +483 -0
  67. sqlspec/adapters/asyncpg/config.py +575 -0
  68. sqlspec/adapters/asyncpg/core.cp314-win_amd64.pyd +0 -0
  69. sqlspec/adapters/asyncpg/core.py +480 -0
  70. sqlspec/adapters/asyncpg/data_dictionary.py +157 -0
  71. sqlspec/adapters/asyncpg/driver.py +487 -0
  72. sqlspec/adapters/asyncpg/events/__init__.py +6 -0
  73. sqlspec/adapters/asyncpg/events/_hub.py +181 -0
  74. sqlspec/adapters/asyncpg/events/backend.py +210 -0
  75. sqlspec/adapters/asyncpg/events/store.py +40 -0
  76. sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
  77. sqlspec/adapters/asyncpg/litestar/store.py +251 -0
  78. sqlspec/adapters/bigquery/__init__.py +15 -0
  79. sqlspec/adapters/bigquery/_typing.py +108 -0
  80. sqlspec/adapters/bigquery/config.py +362 -0
  81. sqlspec/adapters/bigquery/core.cp314-win_amd64.pyd +0 -0
  82. sqlspec/adapters/bigquery/core.py +768 -0
  83. sqlspec/adapters/bigquery/data_dictionary.py +120 -0
  84. sqlspec/adapters/bigquery/driver.py +542 -0
  85. sqlspec/adapters/bigquery/events/__init__.py +5 -0
  86. sqlspec/adapters/bigquery/events/store.py +139 -0
  87. sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
  88. sqlspec/adapters/bigquery/litestar/store.py +325 -0
  89. sqlspec/adapters/bigquery/type_converter.cp314-win_amd64.pyd +0 -0
  90. sqlspec/adapters/bigquery/type_converter.py +107 -0
  91. sqlspec/adapters/cockroach_asyncpg/__init__.py +26 -0
  92. sqlspec/adapters/cockroach_asyncpg/_typing.py +73 -0
  93. sqlspec/adapters/cockroach_asyncpg/adk/__init__.py +3 -0
  94. sqlspec/adapters/cockroach_asyncpg/adk/store.py +465 -0
  95. sqlspec/adapters/cockroach_asyncpg/config.py +248 -0
  96. sqlspec/adapters/cockroach_asyncpg/core.cp314-win_amd64.pyd +0 -0
  97. sqlspec/adapters/cockroach_asyncpg/core.py +55 -0
  98. sqlspec/adapters/cockroach_asyncpg/data_dictionary.py +110 -0
  99. sqlspec/adapters/cockroach_asyncpg/driver.py +142 -0
  100. sqlspec/adapters/cockroach_asyncpg/events/__init__.py +3 -0
  101. sqlspec/adapters/cockroach_asyncpg/events/store.py +20 -0
  102. sqlspec/adapters/cockroach_asyncpg/litestar/__init__.py +3 -0
  103. sqlspec/adapters/cockroach_asyncpg/litestar/store.py +142 -0
  104. sqlspec/adapters/cockroach_psycopg/__init__.py +39 -0
  105. sqlspec/adapters/cockroach_psycopg/_typing.py +137 -0
  106. sqlspec/adapters/cockroach_psycopg/adk/__init__.py +13 -0
  107. sqlspec/adapters/cockroach_psycopg/adk/store.py +1039 -0
  108. sqlspec/adapters/cockroach_psycopg/config.py +511 -0
  109. sqlspec/adapters/cockroach_psycopg/core.cp314-win_amd64.pyd +0 -0
  110. sqlspec/adapters/cockroach_psycopg/core.py +63 -0
  111. sqlspec/adapters/cockroach_psycopg/data_dictionary.py +220 -0
  112. sqlspec/adapters/cockroach_psycopg/driver.py +273 -0
  113. sqlspec/adapters/cockroach_psycopg/events/__init__.py +6 -0
  114. sqlspec/adapters/cockroach_psycopg/events/store.py +34 -0
  115. sqlspec/adapters/cockroach_psycopg/litestar/__init__.py +3 -0
  116. sqlspec/adapters/cockroach_psycopg/litestar/store.py +327 -0
  117. sqlspec/adapters/duckdb/__init__.py +29 -0
  118. sqlspec/adapters/duckdb/_typing.py +104 -0
  119. sqlspec/adapters/duckdb/adk/__init__.py +14 -0
  120. sqlspec/adapters/duckdb/adk/store.py +935 -0
  121. sqlspec/adapters/duckdb/config.py +386 -0
  122. sqlspec/adapters/duckdb/core.cp314-win_amd64.pyd +0 -0
  123. sqlspec/adapters/duckdb/core.py +332 -0
  124. sqlspec/adapters/duckdb/data_dictionary.py +140 -0
  125. sqlspec/adapters/duckdb/driver.py +426 -0
  126. sqlspec/adapters/duckdb/events/__init__.py +5 -0
  127. sqlspec/adapters/duckdb/events/store.py +57 -0
  128. sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
  129. sqlspec/adapters/duckdb/litestar/store.py +330 -0
  130. sqlspec/adapters/duckdb/pool.cp314-win_amd64.pyd +0 -0
  131. sqlspec/adapters/duckdb/pool.py +350 -0
  132. sqlspec/adapters/duckdb/type_converter.cp314-win_amd64.pyd +0 -0
  133. sqlspec/adapters/duckdb/type_converter.py +118 -0
  134. sqlspec/adapters/mysqlconnector/__init__.py +39 -0
  135. sqlspec/adapters/mysqlconnector/_typing.py +186 -0
  136. sqlspec/adapters/mysqlconnector/adk/__init__.py +15 -0
  137. sqlspec/adapters/mysqlconnector/adk/store.py +1183 -0
  138. sqlspec/adapters/mysqlconnector/config.py +421 -0
  139. sqlspec/adapters/mysqlconnector/core.cp314-win_amd64.pyd +0 -0
  140. sqlspec/adapters/mysqlconnector/core.py +472 -0
  141. sqlspec/adapters/mysqlconnector/data_dictionary.py +230 -0
  142. sqlspec/adapters/mysqlconnector/driver.py +516 -0
  143. sqlspec/adapters/mysqlconnector/events/__init__.py +8 -0
  144. sqlspec/adapters/mysqlconnector/events/store.py +98 -0
  145. sqlspec/adapters/mysqlconnector/litestar/__init__.py +5 -0
  146. sqlspec/adapters/mysqlconnector/litestar/store.py +426 -0
  147. sqlspec/adapters/oracledb/__init__.py +39 -0
  148. sqlspec/adapters/oracledb/_json_handlers.cp314-win_amd64.pyd +0 -0
  149. sqlspec/adapters/oracledb/_json_handlers.py +196 -0
  150. sqlspec/adapters/oracledb/_param_types.cp314-win_amd64.pyd +0 -0
  151. sqlspec/adapters/oracledb/_param_types.py +46 -0
  152. sqlspec/adapters/oracledb/_typing.py +258 -0
  153. sqlspec/adapters/oracledb/_uuid_handlers.cp314-win_amd64.pyd +0 -0
  154. sqlspec/adapters/oracledb/_uuid_handlers.py +163 -0
  155. sqlspec/adapters/oracledb/_vector_handlers.cp314-win_amd64.pyd +0 -0
  156. sqlspec/adapters/oracledb/_vector_handlers.py +228 -0
  157. sqlspec/adapters/oracledb/adk/__init__.py +21 -0
  158. sqlspec/adapters/oracledb/adk/store.py +2453 -0
  159. sqlspec/adapters/oracledb/config.py +575 -0
  160. sqlspec/adapters/oracledb/core.cp314-win_amd64.pyd +0 -0
  161. sqlspec/adapters/oracledb/core.py +820 -0
  162. sqlspec/adapters/oracledb/data_dictionary.py +404 -0
  163. sqlspec/adapters/oracledb/driver.py +1277 -0
  164. sqlspec/adapters/oracledb/events/__init__.py +16 -0
  165. sqlspec/adapters/oracledb/events/_hub.py +345 -0
  166. sqlspec/adapters/oracledb/events/backend.py +300 -0
  167. sqlspec/adapters/oracledb/events/store.py +420 -0
  168. sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
  169. sqlspec/adapters/oracledb/litestar/store.py +781 -0
  170. sqlspec/adapters/oracledb/migrations.py +539 -0
  171. sqlspec/adapters/oracledb/type_converter.cp314-win_amd64.pyd +0 -0
  172. sqlspec/adapters/oracledb/type_converter.py +211 -0
  173. sqlspec/adapters/psqlpy/__init__.py +18 -0
  174. sqlspec/adapters/psqlpy/_typing.py +121 -0
  175. sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
  176. sqlspec/adapters/psqlpy/adk/store.py +591 -0
  177. sqlspec/adapters/psqlpy/config.py +376 -0
  178. sqlspec/adapters/psqlpy/core.cp314-win_amd64.pyd +0 -0
  179. sqlspec/adapters/psqlpy/core.py +694 -0
  180. sqlspec/adapters/psqlpy/data_dictionary.py +121 -0
  181. sqlspec/adapters/psqlpy/driver.py +411 -0
  182. sqlspec/adapters/psqlpy/events/__init__.py +6 -0
  183. sqlspec/adapters/psqlpy/events/_hub.py +204 -0
  184. sqlspec/adapters/psqlpy/events/backend.py +210 -0
  185. sqlspec/adapters/psqlpy/events/store.py +20 -0
  186. sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
  187. sqlspec/adapters/psqlpy/litestar/store.py +270 -0
  188. sqlspec/adapters/psqlpy/type_converter.cp314-win_amd64.pyd +0 -0
  189. sqlspec/adapters/psqlpy/type_converter.py +113 -0
  190. sqlspec/adapters/psycopg/__init__.py +38 -0
  191. sqlspec/adapters/psycopg/_typing.py +218 -0
  192. sqlspec/adapters/psycopg/adk/__init__.py +10 -0
  193. sqlspec/adapters/psycopg/adk/store.py +1106 -0
  194. sqlspec/adapters/psycopg/config.py +695 -0
  195. sqlspec/adapters/psycopg/core.cp314-win_amd64.pyd +0 -0
  196. sqlspec/adapters/psycopg/core.py +520 -0
  197. sqlspec/adapters/psycopg/data_dictionary.py +278 -0
  198. sqlspec/adapters/psycopg/driver.py +1033 -0
  199. sqlspec/adapters/psycopg/events/__init__.py +20 -0
  200. sqlspec/adapters/psycopg/events/_hub.py +388 -0
  201. sqlspec/adapters/psycopg/events/backend.py +398 -0
  202. sqlspec/adapters/psycopg/events/store.py +42 -0
  203. sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
  204. sqlspec/adapters/psycopg/litestar/store.py +554 -0
  205. sqlspec/adapters/psycopg/type_converter.cp314-win_amd64.pyd +0 -0
  206. sqlspec/adapters/psycopg/type_converter.py +93 -0
  207. sqlspec/adapters/pymysql/__init__.py +21 -0
  208. sqlspec/adapters/pymysql/_typing.py +92 -0
  209. sqlspec/adapters/pymysql/adk/__init__.py +5 -0
  210. sqlspec/adapters/pymysql/adk/store.py +657 -0
  211. sqlspec/adapters/pymysql/config.py +176 -0
  212. sqlspec/adapters/pymysql/core.cp314-win_amd64.pyd +0 -0
  213. sqlspec/adapters/pymysql/core.py +469 -0
  214. sqlspec/adapters/pymysql/data_dictionary.py +120 -0
  215. sqlspec/adapters/pymysql/driver.py +271 -0
  216. sqlspec/adapters/pymysql/events/__init__.py +5 -0
  217. sqlspec/adapters/pymysql/events/store.py +50 -0
  218. sqlspec/adapters/pymysql/litestar/__init__.py +5 -0
  219. sqlspec/adapters/pymysql/litestar/store.py +232 -0
  220. sqlspec/adapters/pymysql/pool.cp314-win_amd64.pyd +0 -0
  221. sqlspec/adapters/pymysql/pool.py +184 -0
  222. sqlspec/adapters/spanner/__init__.py +33 -0
  223. sqlspec/adapters/spanner/_typing.py +102 -0
  224. sqlspec/adapters/spanner/adk/__init__.py +5 -0
  225. sqlspec/adapters/spanner/adk/store.py +758 -0
  226. sqlspec/adapters/spanner/config.py +355 -0
  227. sqlspec/adapters/spanner/core.cp314-win_amd64.pyd +0 -0
  228. sqlspec/adapters/spanner/core.py +263 -0
  229. sqlspec/adapters/spanner/data_dictionary.py +120 -0
  230. sqlspec/adapters/spanner/driver.py +407 -0
  231. sqlspec/adapters/spanner/events/__init__.py +5 -0
  232. sqlspec/adapters/spanner/events/store.py +187 -0
  233. sqlspec/adapters/spanner/litestar/__init__.py +5 -0
  234. sqlspec/adapters/spanner/litestar/store.py +291 -0
  235. sqlspec/adapters/spanner/type_converter.cp314-win_amd64.pyd +0 -0
  236. sqlspec/adapters/spanner/type_converter.py +342 -0
  237. sqlspec/adapters/sqlite/__init__.py +19 -0
  238. sqlspec/adapters/sqlite/_typing.py +123 -0
  239. sqlspec/adapters/sqlite/adk/__init__.py +5 -0
  240. sqlspec/adapters/sqlite/adk/store.py +992 -0
  241. sqlspec/adapters/sqlite/config.py +240 -0
  242. sqlspec/adapters/sqlite/core.cp314-win_amd64.pyd +0 -0
  243. sqlspec/adapters/sqlite/core.py +357 -0
  244. sqlspec/adapters/sqlite/data_dictionary.py +198 -0
  245. sqlspec/adapters/sqlite/driver.py +527 -0
  246. sqlspec/adapters/sqlite/events/__init__.py +5 -0
  247. sqlspec/adapters/sqlite/events/store.py +20 -0
  248. sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
  249. sqlspec/adapters/sqlite/litestar/store.py +316 -0
  250. sqlspec/adapters/sqlite/pool.cp314-win_amd64.pyd +0 -0
  251. sqlspec/adapters/sqlite/pool.py +237 -0
  252. sqlspec/adapters/sqlite/type_converter.cp314-win_amd64.pyd +0 -0
  253. sqlspec/adapters/sqlite/type_converter.py +114 -0
  254. sqlspec/base.py +832 -0
  255. sqlspec/builder/__init__.py +181 -0
  256. sqlspec/builder/_base.cp314-win_amd64.pyd +0 -0
  257. sqlspec/builder/_base.py +1071 -0
  258. sqlspec/builder/_column.cp314-win_amd64.pyd +0 -0
  259. sqlspec/builder/_column.py +521 -0
  260. sqlspec/builder/_ddl.cp314-win_amd64.pyd +0 -0
  261. sqlspec/builder/_ddl.py +1691 -0
  262. sqlspec/builder/_delete.cp314-win_amd64.pyd +0 -0
  263. sqlspec/builder/_delete.py +95 -0
  264. sqlspec/builder/_dml.cp314-win_amd64.pyd +0 -0
  265. sqlspec/builder/_dml.py +386 -0
  266. sqlspec/builder/_explain.cp314-win_amd64.pyd +0 -0
  267. sqlspec/builder/_explain.py +579 -0
  268. sqlspec/builder/_expression_wrappers.cp314-win_amd64.pyd +0 -0
  269. sqlspec/builder/_expression_wrappers.py +46 -0
  270. sqlspec/builder/_factory.cp314-win_amd64.pyd +0 -0
  271. sqlspec/builder/_factory.py +1884 -0
  272. sqlspec/builder/_insert.cp314-win_amd64.pyd +0 -0
  273. sqlspec/builder/_insert.py +405 -0
  274. sqlspec/builder/_join.cp314-win_amd64.pyd +0 -0
  275. sqlspec/builder/_join.py +489 -0
  276. sqlspec/builder/_merge.cp314-win_amd64.pyd +0 -0
  277. sqlspec/builder/_merge.py +823 -0
  278. sqlspec/builder/_parsing_utils.cp314-win_amd64.pyd +0 -0
  279. sqlspec/builder/_parsing_utils.py +295 -0
  280. sqlspec/builder/_select.cp314-win_amd64.pyd +0 -0
  281. sqlspec/builder/_select.py +1666 -0
  282. sqlspec/builder/_temporal.cp314-win_amd64.pyd +0 -0
  283. sqlspec/builder/_temporal.py +167 -0
  284. sqlspec/builder/_update.cp314-win_amd64.pyd +0 -0
  285. sqlspec/builder/_update.py +173 -0
  286. sqlspec/builder/_vector_distance.cp314-win_amd64.pyd +0 -0
  287. sqlspec/builder/_vector_distance.py +330 -0
  288. sqlspec/cli.py +1095 -0
  289. sqlspec/config.py +2383 -0
  290. sqlspec/core/__init__.py +372 -0
  291. sqlspec/core/_correlation.cp314-win_amd64.pyd +0 -0
  292. sqlspec/core/_correlation.py +176 -0
  293. sqlspec/core/_pagination.py +42 -0
  294. sqlspec/core/_pool.cp314-win_amd64.pyd +0 -0
  295. sqlspec/core/_pool.py +76 -0
  296. sqlspec/core/cache.cp314-win_amd64.pyd +0 -0
  297. sqlspec/core/cache.py +1085 -0
  298. sqlspec/core/compiler.cp314-win_amd64.pyd +0 -0
  299. sqlspec/core/compiler.py +1090 -0
  300. sqlspec/core/config_runtime.cp314-win_amd64.pyd +0 -0
  301. sqlspec/core/config_runtime.py +174 -0
  302. sqlspec/core/explain.cp314-win_amd64.pyd +0 -0
  303. sqlspec/core/explain.py +275 -0
  304. sqlspec/core/filters.cp314-win_amd64.pyd +0 -0
  305. sqlspec/core/filters.py +969 -0
  306. sqlspec/core/hashing.cp314-win_amd64.pyd +0 -0
  307. sqlspec/core/hashing.py +266 -0
  308. sqlspec/core/metrics.cp314-win_amd64.pyd +0 -0
  309. sqlspec/core/metrics.py +83 -0
  310. sqlspec/core/parameters/__init__.py +72 -0
  311. sqlspec/core/parameters/_alignment.cp314-win_amd64.pyd +0 -0
  312. sqlspec/core/parameters/_alignment.py +283 -0
  313. sqlspec/core/parameters/_converter.cp314-win_amd64.pyd +0 -0
  314. sqlspec/core/parameters/_converter.py +554 -0
  315. sqlspec/core/parameters/_processor.cp314-win_amd64.pyd +0 -0
  316. sqlspec/core/parameters/_processor.py +1182 -0
  317. sqlspec/core/parameters/_registry.cp314-win_amd64.pyd +0 -0
  318. sqlspec/core/parameters/_registry.py +206 -0
  319. sqlspec/core/parameters/_transformers.cp314-win_amd64.pyd +0 -0
  320. sqlspec/core/parameters/_transformers.py +324 -0
  321. sqlspec/core/parameters/_types.cp314-win_amd64.pyd +0 -0
  322. sqlspec/core/parameters/_types.py +536 -0
  323. sqlspec/core/parameters/_validator.cp314-win_amd64.pyd +0 -0
  324. sqlspec/core/parameters/_validator.py +171 -0
  325. sqlspec/core/pipeline.cp314-win_amd64.pyd +0 -0
  326. sqlspec/core/pipeline.py +333 -0
  327. sqlspec/core/query_modifiers.cp314-win_amd64.pyd +0 -0
  328. sqlspec/core/query_modifiers.py +508 -0
  329. sqlspec/core/result/__init__.py +25 -0
  330. sqlspec/core/result/_base.cp314-win_amd64.pyd +0 -0
  331. sqlspec/core/result/_base.py +1232 -0
  332. sqlspec/core/result/_io.cp314-win_amd64.pyd +0 -0
  333. sqlspec/core/result/_io.py +28 -0
  334. sqlspec/core/splitter.cp314-win_amd64.pyd +0 -0
  335. sqlspec/core/splitter.py +1021 -0
  336. sqlspec/core/sqlcommenter.cp314-win_amd64.pyd +0 -0
  337. sqlspec/core/sqlcommenter.py +249 -0
  338. sqlspec/core/stack.cp314-win_amd64.pyd +0 -0
  339. sqlspec/core/stack.py +163 -0
  340. sqlspec/core/statement.cp314-win_amd64.pyd +0 -0
  341. sqlspec/core/statement.py +1865 -0
  342. sqlspec/core/type_converter.cp314-win_amd64.pyd +0 -0
  343. sqlspec/core/type_converter.py +340 -0
  344. sqlspec/data_dictionary/__init__.py +22 -0
  345. sqlspec/data_dictionary/_loader.cp314-win_amd64.pyd +0 -0
  346. sqlspec/data_dictionary/_loader.py +138 -0
  347. sqlspec/data_dictionary/_registry.cp314-win_amd64.pyd +0 -0
  348. sqlspec/data_dictionary/_registry.py +74 -0
  349. sqlspec/data_dictionary/_types.cp314-win_amd64.pyd +0 -0
  350. sqlspec/data_dictionary/_types.py +121 -0
  351. sqlspec/data_dictionary/dialects/__init__.py +21 -0
  352. sqlspec/data_dictionary/dialects/bigquery.cp314-win_amd64.pyd +0 -0
  353. sqlspec/data_dictionary/dialects/bigquery.py +81 -0
  354. sqlspec/data_dictionary/dialects/cockroachdb.cp314-win_amd64.pyd +0 -0
  355. sqlspec/data_dictionary/dialects/cockroachdb.py +54 -0
  356. sqlspec/data_dictionary/dialects/duckdb.cp314-win_amd64.pyd +0 -0
  357. sqlspec/data_dictionary/dialects/duckdb.py +47 -0
  358. sqlspec/data_dictionary/dialects/mysql.cp314-win_amd64.pyd +0 -0
  359. sqlspec/data_dictionary/dialects/mysql.py +53 -0
  360. sqlspec/data_dictionary/dialects/oracle.cp314-win_amd64.pyd +0 -0
  361. sqlspec/data_dictionary/dialects/oracle.py +197 -0
  362. sqlspec/data_dictionary/dialects/postgres.cp314-win_amd64.pyd +0 -0
  363. sqlspec/data_dictionary/dialects/postgres.py +69 -0
  364. sqlspec/data_dictionary/dialects/spanner.cp314-win_amd64.pyd +0 -0
  365. sqlspec/data_dictionary/dialects/spanner.py +37 -0
  366. sqlspec/data_dictionary/dialects/sqlite.cp314-win_amd64.pyd +0 -0
  367. sqlspec/data_dictionary/dialects/sqlite.py +59 -0
  368. sqlspec/data_dictionary/sql/.gitkeep +0 -0
  369. sqlspec/data_dictionary/sql/bigquery/columns.sql +23 -0
  370. sqlspec/data_dictionary/sql/bigquery/foreign_keys.sql +34 -0
  371. sqlspec/data_dictionary/sql/bigquery/indexes.sql +19 -0
  372. sqlspec/data_dictionary/sql/bigquery/tables.sql +33 -0
  373. sqlspec/data_dictionary/sql/bigquery/version.sql +3 -0
  374. sqlspec/data_dictionary/sql/cockroachdb/columns.sql +34 -0
  375. sqlspec/data_dictionary/sql/cockroachdb/foreign_keys.sql +40 -0
  376. sqlspec/data_dictionary/sql/cockroachdb/indexes.sql +32 -0
  377. sqlspec/data_dictionary/sql/cockroachdb/tables.sql +44 -0
  378. sqlspec/data_dictionary/sql/cockroachdb/version.sql +3 -0
  379. sqlspec/data_dictionary/sql/duckdb/columns.sql +23 -0
  380. sqlspec/data_dictionary/sql/duckdb/foreign_keys.sql +36 -0
  381. sqlspec/data_dictionary/sql/duckdb/indexes.sql +19 -0
  382. sqlspec/data_dictionary/sql/duckdb/tables.sql +38 -0
  383. sqlspec/data_dictionary/sql/duckdb/version.sql +3 -0
  384. sqlspec/data_dictionary/sql/mysql/columns.sql +23 -0
  385. sqlspec/data_dictionary/sql/mysql/foreign_keys.sql +28 -0
  386. sqlspec/data_dictionary/sql/mysql/indexes.sql +26 -0
  387. sqlspec/data_dictionary/sql/mysql/tables.sql +33 -0
  388. sqlspec/data_dictionary/sql/mysql/version.sql +3 -0
  389. sqlspec/data_dictionary/sql/oracle/columns.sql +23 -0
  390. sqlspec/data_dictionary/sql/oracle/foreign_keys.sql +48 -0
  391. sqlspec/data_dictionary/sql/oracle/indexes.sql +44 -0
  392. sqlspec/data_dictionary/sql/oracle/tables.sql +25 -0
  393. sqlspec/data_dictionary/sql/oracle/version.sql +20 -0
  394. sqlspec/data_dictionary/sql/postgres/columns.sql +34 -0
  395. sqlspec/data_dictionary/sql/postgres/foreign_keys.sql +40 -0
  396. sqlspec/data_dictionary/sql/postgres/indexes.sql +56 -0
  397. sqlspec/data_dictionary/sql/postgres/tables.sql +44 -0
  398. sqlspec/data_dictionary/sql/postgres/version.sql +3 -0
  399. sqlspec/data_dictionary/sql/spanner/columns.sql +23 -0
  400. sqlspec/data_dictionary/sql/spanner/foreign_keys.sql +70 -0
  401. sqlspec/data_dictionary/sql/spanner/indexes.sql +30 -0
  402. sqlspec/data_dictionary/sql/spanner/tables.sql +9 -0
  403. sqlspec/data_dictionary/sql/spanner/version.sql +3 -0
  404. sqlspec/data_dictionary/sql/sqlite/columns.sql +23 -0
  405. sqlspec/data_dictionary/sql/sqlite/foreign_keys.sql +22 -0
  406. sqlspec/data_dictionary/sql/sqlite/indexes.sql +7 -0
  407. sqlspec/data_dictionary/sql/sqlite/tables.sql +28 -0
  408. sqlspec/data_dictionary/sql/sqlite/version.sql +3 -0
  409. sqlspec/dialects/__init__.py +22 -0
  410. sqlspec/dialects/_compat.cp314-win_amd64.pyd +0 -0
  411. sqlspec/dialects/_compat.py +14 -0
  412. sqlspec/dialects/postgres/__init__.py +9 -0
  413. sqlspec/dialects/postgres/_generators.cp314-win_amd64.pyd +0 -0
  414. sqlspec/dialects/postgres/_generators.py +57 -0
  415. sqlspec/dialects/postgres/_operators.cp314-win_amd64.pyd +0 -0
  416. sqlspec/dialects/postgres/_operators.py +81 -0
  417. sqlspec/dialects/postgres/_paradedb.py +50 -0
  418. sqlspec/dialects/postgres/_pgvector.py +36 -0
  419. sqlspec/dialects/spanner/__init__.py +6 -0
  420. sqlspec/dialects/spanner/_generators.cp314-win_amd64.pyd +0 -0
  421. sqlspec/dialects/spanner/_generators.py +206 -0
  422. sqlspec/dialects/spanner/_spangres.py +77 -0
  423. sqlspec/dialects/spanner/_spanner.py +179 -0
  424. sqlspec/driver/__init__.py +49 -0
  425. sqlspec/driver/_async.cp314-win_amd64.pyd +0 -0
  426. sqlspec/driver/_async.py +1830 -0
  427. sqlspec/driver/_common.cp314-win_amd64.pyd +0 -0
  428. sqlspec/driver/_common.py +2292 -0
  429. sqlspec/driver/_exception_handler.cp314-win_amd64.pyd +0 -0
  430. sqlspec/driver/_exception_handler.py +108 -0
  431. sqlspec/driver/_query_cache.cp314-win_amd64.pyd +0 -0
  432. sqlspec/driver/_query_cache.py +96 -0
  433. sqlspec/driver/_sql_helpers.cp314-win_amd64.pyd +0 -0
  434. sqlspec/driver/_sql_helpers.py +139 -0
  435. sqlspec/driver/_storage_helpers.cp314-win_amd64.pyd +0 -0
  436. sqlspec/driver/_storage_helpers.py +153 -0
  437. sqlspec/driver/_sync.cp314-win_amd64.pyd +0 -0
  438. sqlspec/driver/_sync.py +1817 -0
  439. sqlspec/exceptions.cp314-win_amd64.pyd +0 -0
  440. sqlspec/exceptions.py +480 -0
  441. sqlspec/extensions/__init__.py +0 -0
  442. sqlspec/extensions/adk/__init__.py +84 -0
  443. sqlspec/extensions/adk/_config_utils.py +199 -0
  444. sqlspec/extensions/adk/_types.cp314-win_amd64.pyd +0 -0
  445. sqlspec/extensions/adk/_types.py +41 -0
  446. sqlspec/extensions/adk/artifact/__init__.py +57 -0
  447. sqlspec/extensions/adk/artifact/_types.cp314-win_amd64.pyd +0 -0
  448. sqlspec/extensions/adk/artifact/_types.py +32 -0
  449. sqlspec/extensions/adk/artifact/service.py +508 -0
  450. sqlspec/extensions/adk/artifact/store.py +361 -0
  451. sqlspec/extensions/adk/converters.py +212 -0
  452. sqlspec/extensions/adk/memory/__init__.py +69 -0
  453. sqlspec/extensions/adk/memory/_types.cp314-win_amd64.pyd +0 -0
  454. sqlspec/extensions/adk/memory/_types.py +30 -0
  455. sqlspec/extensions/adk/memory/converters.py +225 -0
  456. sqlspec/extensions/adk/memory/service.py +316 -0
  457. sqlspec/extensions/adk/memory/store.py +525 -0
  458. sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +184 -0
  459. sqlspec/extensions/adk/migrations/__init__.py +0 -0
  460. sqlspec/extensions/adk/service.py +279 -0
  461. sqlspec/extensions/adk/store.py +590 -0
  462. sqlspec/extensions/events/__init__.py +51 -0
  463. sqlspec/extensions/events/_channel.py +703 -0
  464. sqlspec/extensions/events/_hints.cp314-win_amd64.pyd +0 -0
  465. sqlspec/extensions/events/_hints.py +45 -0
  466. sqlspec/extensions/events/_models.py +23 -0
  467. sqlspec/extensions/events/_payload.cp314-win_amd64.pyd +0 -0
  468. sqlspec/extensions/events/_payload.py +69 -0
  469. sqlspec/extensions/events/_protocols.py +134 -0
  470. sqlspec/extensions/events/_queue.py +462 -0
  471. sqlspec/extensions/events/_store.py +209 -0
  472. sqlspec/extensions/events/migrations/0001_create_event_queue.py +59 -0
  473. sqlspec/extensions/events/migrations/__init__.py +3 -0
  474. sqlspec/extensions/fastapi/__init__.py +22 -0
  475. sqlspec/extensions/fastapi/extension.py +391 -0
  476. sqlspec/extensions/fastapi/providers.cp314-win_amd64.pyd +0 -0
  477. sqlspec/extensions/fastapi/providers.py +712 -0
  478. sqlspec/extensions/flask/__init__.py +38 -0
  479. sqlspec/extensions/flask/_state.py +87 -0
  480. sqlspec/extensions/flask/_utils.py +71 -0
  481. sqlspec/extensions/flask/extension.py +539 -0
  482. sqlspec/extensions/litestar/__init__.py +31 -0
  483. sqlspec/extensions/litestar/_utils.py +52 -0
  484. sqlspec/extensions/litestar/channels.py +165 -0
  485. sqlspec/extensions/litestar/cli.py +102 -0
  486. sqlspec/extensions/litestar/config.py +90 -0
  487. sqlspec/extensions/litestar/handlers.py +316 -0
  488. sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
  489. sqlspec/extensions/litestar/migrations/__init__.py +3 -0
  490. sqlspec/extensions/litestar/plugin.py +1066 -0
  491. sqlspec/extensions/litestar/providers.cp314-win_amd64.pyd +0 -0
  492. sqlspec/extensions/litestar/providers.py +784 -0
  493. sqlspec/extensions/litestar/store.py +298 -0
  494. sqlspec/extensions/otel/__init__.py +58 -0
  495. sqlspec/extensions/prometheus/__init__.py +113 -0
  496. sqlspec/extensions/sanic/__init__.py +19 -0
  497. sqlspec/extensions/sanic/_state.py +43 -0
  498. sqlspec/extensions/sanic/_utils.py +127 -0
  499. sqlspec/extensions/sanic/extension.py +647 -0
  500. sqlspec/extensions/starlette/__init__.py +22 -0
  501. sqlspec/extensions/starlette/_state.py +42 -0
  502. sqlspec/extensions/starlette/_utils.py +96 -0
  503. sqlspec/extensions/starlette/extension.py +374 -0
  504. sqlspec/extensions/starlette/middleware.py +281 -0
  505. sqlspec/loader.cp314-win_amd64.pyd +0 -0
  506. sqlspec/loader.py +727 -0
  507. sqlspec/migrations/__init__.py +39 -0
  508. sqlspec/migrations/base.cp314-win_amd64.pyd +0 -0
  509. sqlspec/migrations/base.py +862 -0
  510. sqlspec/migrations/commands.py +2151 -0
  511. sqlspec/migrations/context.cp314-win_amd64.pyd +0 -0
  512. sqlspec/migrations/context.py +157 -0
  513. sqlspec/migrations/fix.cp314-win_amd64.pyd +0 -0
  514. sqlspec/migrations/fix.py +204 -0
  515. sqlspec/migrations/loaders.cp314-win_amd64.pyd +0 -0
  516. sqlspec/migrations/loaders.py +443 -0
  517. sqlspec/migrations/runner.cp314-win_amd64.pyd +0 -0
  518. sqlspec/migrations/runner.py +1195 -0
  519. sqlspec/migrations/squash.cp314-win_amd64.pyd +0 -0
  520. sqlspec/migrations/squash.py +490 -0
  521. sqlspec/migrations/templates.cp314-win_amd64.pyd +0 -0
  522. sqlspec/migrations/templates.py +234 -0
  523. sqlspec/migrations/tracker.cp314-win_amd64.pyd +0 -0
  524. sqlspec/migrations/tracker.py +792 -0
  525. sqlspec/migrations/utils.cp314-win_amd64.pyd +0 -0
  526. sqlspec/migrations/utils.py +256 -0
  527. sqlspec/migrations/validation.cp314-win_amd64.pyd +0 -0
  528. sqlspec/migrations/validation.py +359 -0
  529. sqlspec/migrations/version.cp314-win_amd64.pyd +0 -0
  530. sqlspec/migrations/version.py +446 -0
  531. sqlspec/observability/__init__.py +57 -0
  532. sqlspec/observability/_common.cp314-win_amd64.pyd +0 -0
  533. sqlspec/observability/_common.py +77 -0
  534. sqlspec/observability/_config.cp314-win_amd64.pyd +0 -0
  535. sqlspec/observability/_config.py +364 -0
  536. sqlspec/observability/_diagnostics.cp314-win_amd64.pyd +0 -0
  537. sqlspec/observability/_diagnostics.py +74 -0
  538. sqlspec/observability/_dispatcher.cp314-win_amd64.pyd +0 -0
  539. sqlspec/observability/_dispatcher.py +200 -0
  540. sqlspec/observability/_formatters/__init__.py +13 -0
  541. sqlspec/observability/_formatters/_aws.cp314-win_amd64.pyd +0 -0
  542. sqlspec/observability/_formatters/_aws.py +102 -0
  543. sqlspec/observability/_formatters/_azure.cp314-win_amd64.pyd +0 -0
  544. sqlspec/observability/_formatters/_azure.py +96 -0
  545. sqlspec/observability/_formatters/_base.cp314-win_amd64.pyd +0 -0
  546. sqlspec/observability/_formatters/_base.py +57 -0
  547. sqlspec/observability/_formatters/_gcp.cp314-win_amd64.pyd +0 -0
  548. sqlspec/observability/_formatters/_gcp.py +131 -0
  549. sqlspec/observability/_formatting.py +58 -0
  550. sqlspec/observability/_observer.cp314-win_amd64.pyd +0 -0
  551. sqlspec/observability/_observer.py +361 -0
  552. sqlspec/observability/_runtime.cp314-win_amd64.pyd +0 -0
  553. sqlspec/observability/_runtime.py +461 -0
  554. sqlspec/observability/_sampling.cp314-win_amd64.pyd +0 -0
  555. sqlspec/observability/_sampling.py +188 -0
  556. sqlspec/observability/_spans.cp314-win_amd64.pyd +0 -0
  557. sqlspec/observability/_spans.py +161 -0
  558. sqlspec/protocols.py +955 -0
  559. sqlspec/py.typed +0 -0
  560. sqlspec/service.py +433 -0
  561. sqlspec/storage/__init__.py +48 -0
  562. sqlspec/storage/_arrow_payload.py +68 -0
  563. sqlspec/storage/_paths.cp314-win_amd64.pyd +0 -0
  564. sqlspec/storage/_paths.py +58 -0
  565. sqlspec/storage/_utils.py +46 -0
  566. sqlspec/storage/backends/__init__.py +1 -0
  567. sqlspec/storage/backends/base.cp314-win_amd64.pyd +0 -0
  568. sqlspec/storage/backends/base.py +374 -0
  569. sqlspec/storage/backends/fsspec.py +574 -0
  570. sqlspec/storage/backends/local.py +468 -0
  571. sqlspec/storage/backends/obstore.py +956 -0
  572. sqlspec/storage/errors.cp314-win_amd64.pyd +0 -0
  573. sqlspec/storage/errors.py +102 -0
  574. sqlspec/storage/pipeline.cp314-win_amd64.pyd +0 -0
  575. sqlspec/storage/pipeline.py +628 -0
  576. sqlspec/storage/registry.cp314-win_amd64.pyd +0 -0
  577. sqlspec/storage/registry.py +329 -0
  578. sqlspec/typing.py +405 -0
  579. sqlspec/utils/__init__.py +7 -0
  580. sqlspec/utils/arrow_helpers.py +384 -0
  581. sqlspec/utils/config_tools.cp314-win_amd64.pyd +0 -0
  582. sqlspec/utils/config_tools.py +314 -0
  583. sqlspec/utils/correlation.cp314-win_amd64.pyd +0 -0
  584. sqlspec/utils/correlation.py +134 -0
  585. sqlspec/utils/deprecation.cp314-win_amd64.pyd +0 -0
  586. sqlspec/utils/deprecation.py +157 -0
  587. sqlspec/utils/dispatch.cp314-win_amd64.pyd +0 -0
  588. sqlspec/utils/dispatch.py +101 -0
  589. sqlspec/utils/fixtures.cp314-win_amd64.pyd +0 -0
  590. sqlspec/utils/fixtures.py +260 -0
  591. sqlspec/utils/logging.cp314-win_amd64.pyd +0 -0
  592. sqlspec/utils/logging.py +251 -0
  593. sqlspec/utils/module_loader.py +306 -0
  594. sqlspec/utils/portal.cp314-win_amd64.pyd +0 -0
  595. sqlspec/utils/portal.py +377 -0
  596. sqlspec/utils/schema.cp314-win_amd64.pyd +0 -0
  597. sqlspec/utils/schema.py +1040 -0
  598. sqlspec/utils/serializers/__init__.py +30 -0
  599. sqlspec/utils/serializers/_json.cp314-win_amd64.pyd +0 -0
  600. sqlspec/utils/serializers/_json.py +415 -0
  601. sqlspec/utils/serializers/_numpy.cp314-win_amd64.pyd +0 -0
  602. sqlspec/utils/serializers/_numpy.py +65 -0
  603. sqlspec/utils/serializers/_schema.cp314-win_amd64.pyd +0 -0
  604. sqlspec/utils/serializers/_schema.py +285 -0
  605. sqlspec/utils/singleton.cp314-win_amd64.pyd +0 -0
  606. sqlspec/utils/singleton.py +41 -0
  607. sqlspec/utils/sync_tools.cp314-win_amd64.pyd +0 -0
  608. sqlspec/utils/sync_tools.py +316 -0
  609. sqlspec/utils/text.cp314-win_amd64.pyd +0 -0
  610. sqlspec/utils/text.py +109 -0
  611. sqlspec/utils/type_converters.cp314-win_amd64.pyd +0 -0
  612. sqlspec/utils/type_converters.py +216 -0
  613. sqlspec/utils/type_guards.cp314-win_amd64.pyd +0 -0
  614. sqlspec/utils/type_guards.py +1508 -0
  615. sqlspec/utils/uuids.cp314-win_amd64.pyd +0 -0
  616. sqlspec/utils/uuids.py +241 -0
  617. sqlspec-0.47.0.dist-info/METADATA +202 -0
  618. sqlspec-0.47.0.dist-info/RECORD +621 -0
  619. sqlspec-0.47.0.dist-info/WHEEL +4 -0
  620. sqlspec-0.47.0.dist-info/entry_points.txt +6 -0
  621. sqlspec-0.47.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,829 @@
1
+ """Aiosqlite async ADK store for Google Agent Development Kit session/event storage."""
2
+
3
+ import sqlite3
4
+ from datetime import datetime, timezone
5
+ from typing import TYPE_CHECKING, Any, Final, cast
6
+
7
+ from sqlspec.extensions.adk import BaseAsyncADKStore, EventRecord, SessionRecord
8
+ from sqlspec.extensions.adk.memory.store import BaseAsyncADKMemoryStore
9
+ from sqlspec.utils.serializers import from_json, to_json
10
+
11
+ if TYPE_CHECKING:
12
+ from sqlspec.adapters.aiosqlite.config import AiosqliteConfig
13
+ from sqlspec.extensions.adk import MemoryRecord
14
+
15
+
16
+ SECONDS_PER_DAY = 86400.0
17
+ JULIAN_EPOCH = 2440587.5
18
+ SQLITE_TABLE_NOT_FOUND_ERROR: Final = "no such table"
19
+
20
+ __all__ = ("AiosqliteADKMemoryStore", "AiosqliteADKStore")
21
+
22
+
23
+ def _datetime_to_julian(dt: datetime) -> float:
24
+ """Convert datetime to Julian Day number for SQLite storage.
25
+
26
+ Args:
27
+ dt: Datetime to convert (must be UTC-aware).
28
+
29
+ Returns:
30
+ Julian Day number as REAL.
31
+
32
+ Notes:
33
+ Julian Day number is days since November 24, 4714 BCE (proleptic Gregorian).
34
+ This enables direct comparison with julianday('now') in SQL queries.
35
+ """
36
+ if dt.tzinfo is None:
37
+ dt = dt.replace(tzinfo=timezone.utc)
38
+ epoch = datetime(1970, 1, 1, tzinfo=timezone.utc)
39
+ delta_days = (dt - epoch).total_seconds() / SECONDS_PER_DAY
40
+ return JULIAN_EPOCH + delta_days
41
+
42
+
43
+ def _julian_to_datetime(julian: float) -> datetime:
44
+ """Convert Julian Day number back to datetime.
45
+
46
+ Args:
47
+ julian: Julian Day number.
48
+
49
+ Returns:
50
+ UTC-aware datetime.
51
+ """
52
+ days_since_epoch = julian - JULIAN_EPOCH
53
+ timestamp = days_since_epoch * SECONDS_PER_DAY
54
+ return datetime.fromtimestamp(timestamp, tz=timezone.utc)
55
+
56
+
57
+ class AiosqliteADKStore(BaseAsyncADKStore["AiosqliteConfig"]):
58
+ """Aiosqlite ADK store using asynchronous SQLite driver.
59
+
60
+ Implements session and event storage for Google Agent Development Kit
61
+ using SQLite via the asynchronous aiosqlite driver.
62
+
63
+ Provides:
64
+ - Session state management with JSON storage (as TEXT)
65
+ - Event history tracking with full-event JSON storage
66
+ - Julian Day timestamps (REAL) for efficient date operations
67
+ - Foreign key constraints with cascade delete
68
+ - Atomic event+state writes via append_event_and_update_state
69
+ - PRAGMA optimization profile for file-based databases
70
+
71
+ Args:
72
+ config: AiosqliteConfig with extension_config["adk"] settings.
73
+
74
+ Example:
75
+ from sqlspec.adapters.aiosqlite import AiosqliteConfig
76
+ from sqlspec.adapters.aiosqlite.adk import AiosqliteADKStore
77
+
78
+ config = AiosqliteConfig(
79
+ connection_config={"database": ":memory:"},
80
+ extension_config={
81
+ "adk": {
82
+ "session_table": "my_sessions",
83
+ "events_table": "my_events"
84
+ }
85
+ }
86
+ )
87
+ store = AiosqliteADKStore(config)
88
+ await store.ensure_tables()
89
+
90
+ Notes:
91
+ - JSON stored as TEXT with SQLSpec serializers (msgspec/orjson/stdlib)
92
+ - Timestamps as REAL (Julian day: julianday('now'))
93
+ - Full event stored as JSON TEXT in event_data column
94
+ - PRAGMA foreign_keys = ON (enable per connection)
95
+ - Configuration is read from config.extension_config["adk"]
96
+ """
97
+
98
+ __slots__ = ()
99
+
100
+ def __init__(self, config: "AiosqliteConfig") -> None:
101
+ """Initialize Aiosqlite ADK store.
102
+
103
+ Args:
104
+ config: AiosqliteConfig instance.
105
+
106
+ Notes:
107
+ Configuration is read from config.extension_config["adk"]:
108
+ - session_table: Sessions table name (default: "adk_sessions")
109
+ - events_table: Events table name (default: "adk_events")
110
+ """
111
+ super().__init__(config)
112
+
113
+ async def _apply_pragmas(self, connection: Any) -> None:
114
+ """Apply PRAGMA optimization profile for this connection.
115
+
116
+ Args:
117
+ connection: Aiosqlite connection.
118
+
119
+ Notes:
120
+ Enables foreign keys and applies performance PRAGMAs.
121
+ For file-based databases, adds cache_size, mmap_size,
122
+ and journal_size_limit optimizations.
123
+ """
124
+ await connection.execute("PRAGMA foreign_keys = ON")
125
+ await connection.execute("PRAGMA cache_size = -64000")
126
+ await connection.execute("PRAGMA mmap_size = 30000000")
127
+ await connection.execute("PRAGMA journal_size_limit = 67108864")
128
+
129
+ async def _get_create_sessions_table_sql(self) -> str:
130
+ """Get SQLite CREATE TABLE SQL for sessions.
131
+
132
+ Returns:
133
+ SQL statement to create adk_sessions table with indexes.
134
+
135
+ Notes:
136
+ - TEXT for IDs, names, and JSON state
137
+ - REAL for Julian Day timestamps
138
+ - Optional owner ID column for multi-tenant scenarios
139
+ - Composite index on (app_name, user_id)
140
+ - Index on update_time DESC for recent session queries
141
+ """
142
+ owner_id_line = ""
143
+ if self._owner_id_column_ddl:
144
+ owner_id_line = f",\n {self._owner_id_column_ddl}"
145
+
146
+ return f"""
147
+ CREATE TABLE IF NOT EXISTS {self._session_table} (
148
+ id TEXT PRIMARY KEY,
149
+ app_name TEXT NOT NULL,
150
+ user_id TEXT NOT NULL{owner_id_line},
151
+ state TEXT NOT NULL DEFAULT '{{}}',
152
+ create_time REAL NOT NULL,
153
+ update_time REAL NOT NULL
154
+ );
155
+ CREATE INDEX IF NOT EXISTS idx_{self._session_table}_app_user
156
+ ON {self._session_table}(app_name, user_id);
157
+ CREATE INDEX IF NOT EXISTS idx_{self._session_table}_update_time
158
+ ON {self._session_table}(update_time DESC);
159
+ """
160
+
161
+ async def _get_create_events_table_sql(self) -> str:
162
+ """Get SQLite CREATE TABLE SQL for events.
163
+
164
+ Returns:
165
+ SQL statement to create adk_events table with indexes.
166
+
167
+ Notes:
168
+ - TEXT for IDs and indexed scalars
169
+ - TEXT for full event JSON (event_data)
170
+ - REAL for Julian Day timestamps
171
+ - Foreign key to sessions with CASCADE delete
172
+ - Index on (session_id, timestamp ASC)
173
+ """
174
+ return f"""
175
+ CREATE TABLE IF NOT EXISTS {self._events_table} (
176
+ id TEXT PRIMARY KEY,
177
+ session_id TEXT NOT NULL,
178
+ invocation_id TEXT,
179
+ author TEXT,
180
+ timestamp REAL NOT NULL,
181
+ event_data TEXT NOT NULL,
182
+ FOREIGN KEY (session_id) REFERENCES {self._session_table}(id) ON DELETE CASCADE
183
+ );
184
+ CREATE INDEX IF NOT EXISTS idx_{self._events_table}_session
185
+ ON {self._events_table}(session_id, timestamp ASC);
186
+ """
187
+
188
+ def _get_drop_tables_sql(self) -> "list[str]":
189
+ """Get SQLite DROP TABLE SQL statements.
190
+
191
+ Returns:
192
+ List of SQL statements to drop tables and indexes.
193
+
194
+ Notes:
195
+ Order matters: drop events table (child) before sessions (parent).
196
+ SQLite automatically drops indexes when dropping tables.
197
+ """
198
+ return [f"DROP TABLE IF EXISTS {self._events_table}", f"DROP TABLE IF EXISTS {self._session_table}"]
199
+
200
+ async def create_tables(self) -> None:
201
+ """Create both sessions and events tables if they don't exist."""
202
+ async with self._config.provide_session() as driver:
203
+ await self._apply_pragmas(driver.connection)
204
+ await driver.execute_script(await self._get_create_sessions_table_sql())
205
+ await driver.execute_script(await self._get_create_events_table_sql())
206
+
207
+ async def create_session(
208
+ self, session_id: str, app_name: str, user_id: str, state: "dict[str, Any]", owner_id: "Any | None" = None
209
+ ) -> SessionRecord:
210
+ """Create a new session.
211
+
212
+ Args:
213
+ session_id: Unique session identifier.
214
+ app_name: Application name.
215
+ user_id: User identifier.
216
+ state: Initial session state.
217
+ owner_id: Optional owner ID value for owner_id_column.
218
+
219
+ Returns:
220
+ Created session record.
221
+
222
+ Notes:
223
+ Uses Julian Day for create_time and update_time.
224
+ State is always JSON-serialized (empty dict becomes '{}', never NULL).
225
+ """
226
+ now = datetime.now(timezone.utc)
227
+ now_julian = _datetime_to_julian(now)
228
+ state_json = to_json(state)
229
+
230
+ params: tuple[Any, ...]
231
+ if self._owner_id_column_name:
232
+ sql = f"""
233
+ INSERT INTO {self._session_table}
234
+ (id, app_name, user_id, {self._owner_id_column_name}, state, create_time, update_time)
235
+ VALUES (?, ?, ?, ?, ?, ?, ?)
236
+ """
237
+ params = (session_id, app_name, user_id, owner_id, state_json, now_julian, now_julian)
238
+ else:
239
+ sql = f"""
240
+ INSERT INTO {self._session_table} (id, app_name, user_id, state, create_time, update_time)
241
+ VALUES (?, ?, ?, ?, ?, ?)
242
+ """
243
+ params = (session_id, app_name, user_id, state_json, now_julian, now_julian)
244
+
245
+ async with self._config.provide_connection() as conn:
246
+ await self._apply_pragmas(conn)
247
+ await conn.execute(sql, params)
248
+ await conn.commit()
249
+
250
+ return SessionRecord(
251
+ id=session_id, app_name=app_name, user_id=user_id, state=state, create_time=now, update_time=now
252
+ )
253
+
254
+ async def get_session(self, session_id: str) -> "SessionRecord | None":
255
+ """Get session by ID.
256
+
257
+ Args:
258
+ session_id: Session identifier.
259
+
260
+ Returns:
261
+ Session record or None if not found.
262
+
263
+ Notes:
264
+ SQLite returns Julian Day (REAL) for timestamps.
265
+ JSON is parsed from TEXT storage.
266
+ """
267
+ sql = f"""
268
+ SELECT id, app_name, user_id, state, create_time, update_time
269
+ FROM {self._session_table}
270
+ WHERE id = ?
271
+ """
272
+
273
+ try:
274
+ async with self._config.provide_connection() as conn:
275
+ await self._apply_pragmas(conn)
276
+ cursor = await conn.execute(sql, (session_id,))
277
+ row = await cursor.fetchone()
278
+
279
+ if row is None:
280
+ return None
281
+
282
+ return SessionRecord(
283
+ id=row[0],
284
+ app_name=row[1],
285
+ user_id=row[2],
286
+ state=from_json(row[3]) if row[3] else {},
287
+ create_time=_julian_to_datetime(row[4]),
288
+ update_time=_julian_to_datetime(row[5]),
289
+ )
290
+ except sqlite3.OperationalError as exc:
291
+ if SQLITE_TABLE_NOT_FOUND_ERROR in str(exc):
292
+ return None
293
+ raise
294
+
295
+ async def update_session_state(self, session_id: str, state: "dict[str, Any]") -> None:
296
+ """Update session state.
297
+
298
+ Args:
299
+ session_id: Session identifier.
300
+ state: New state dictionary (replaces existing state).
301
+
302
+ Notes:
303
+ This replaces the entire state dictionary.
304
+ Updates update_time to current Julian Day.
305
+ Empty dict is serialized as '{}', never NULL.
306
+ """
307
+ now_julian = _datetime_to_julian(datetime.now(timezone.utc))
308
+ state_json = to_json(state)
309
+
310
+ sql = f"""
311
+ UPDATE {self._session_table}
312
+ SET state = ?, update_time = ?
313
+ WHERE id = ?
314
+ """
315
+
316
+ async with self._config.provide_connection() as conn:
317
+ await self._apply_pragmas(conn)
318
+ await conn.execute(sql, (state_json, now_julian, session_id))
319
+ await conn.commit()
320
+
321
+ async def list_sessions(self, app_name: str, user_id: str | None = None) -> "list[SessionRecord]":
322
+ """List sessions for an app, optionally filtered by user.
323
+
324
+ Args:
325
+ app_name: Application name.
326
+ user_id: User identifier. If None, lists all sessions for the app.
327
+
328
+ Returns:
329
+ List of session records ordered by update_time DESC.
330
+
331
+ Notes:
332
+ Uses composite index on (app_name, user_id) when user_id is provided.
333
+ """
334
+ if user_id is None:
335
+ sql = f"""
336
+ SELECT id, app_name, user_id, state, create_time, update_time
337
+ FROM {self._session_table}
338
+ WHERE app_name = ?
339
+ ORDER BY update_time DESC
340
+ """
341
+ params: tuple[str, ...] = (app_name,)
342
+ else:
343
+ sql = f"""
344
+ SELECT id, app_name, user_id, state, create_time, update_time
345
+ FROM {self._session_table}
346
+ WHERE app_name = ? AND user_id = ?
347
+ ORDER BY update_time DESC
348
+ """
349
+ params = (app_name, user_id)
350
+
351
+ try:
352
+ async with self._config.provide_connection() as conn:
353
+ await self._apply_pragmas(conn)
354
+ cursor = await conn.execute(sql, params)
355
+ rows = await cursor.fetchall()
356
+
357
+ return [
358
+ SessionRecord(
359
+ id=row[0],
360
+ app_name=row[1],
361
+ user_id=row[2],
362
+ state=from_json(row[3]) if row[3] else {},
363
+ create_time=_julian_to_datetime(row[4]),
364
+ update_time=_julian_to_datetime(row[5]),
365
+ )
366
+ for row in rows
367
+ ]
368
+ except sqlite3.OperationalError as exc:
369
+ if SQLITE_TABLE_NOT_FOUND_ERROR in str(exc):
370
+ return []
371
+ raise
372
+
373
+ async def delete_session(self, session_id: str) -> None:
374
+ """Delete session and all associated events (cascade).
375
+
376
+ Args:
377
+ session_id: Session identifier.
378
+
379
+ Notes:
380
+ Foreign key constraint ensures events are cascade-deleted.
381
+ """
382
+ sql = f"DELETE FROM {self._session_table} WHERE id = ?"
383
+
384
+ async with self._config.provide_connection() as conn:
385
+ await self._apply_pragmas(conn)
386
+ await conn.execute(sql, (session_id,))
387
+ await conn.commit()
388
+
389
+ async def append_event(self, event_record: EventRecord) -> None:
390
+ """Append an event to a session.
391
+
392
+ Args:
393
+ event_record: Event record with 5 keys: session_id, invocation_id,
394
+ author, timestamp, event_json.
395
+
396
+ Notes:
397
+ Uses Julian Day for timestamp.
398
+ event_json dict is serialized to TEXT as event_data column.
399
+ """
400
+ import uuid
401
+
402
+ timestamp_julian = _datetime_to_julian(event_record["timestamp"])
403
+ event_data_json = to_json(event_record["event_json"])
404
+ event_id = str(uuid.uuid4())
405
+
406
+ sql = f"""
407
+ INSERT INTO {self._events_table} (
408
+ id, session_id, invocation_id, author, timestamp, event_data
409
+ ) VALUES (?, ?, ?, ?, ?, ?)
410
+ """
411
+
412
+ async with self._config.provide_connection() as conn:
413
+ await self._apply_pragmas(conn)
414
+ await conn.execute(
415
+ sql,
416
+ (
417
+ event_id,
418
+ event_record["session_id"],
419
+ event_record["invocation_id"],
420
+ event_record["author"],
421
+ timestamp_julian,
422
+ event_data_json,
423
+ ),
424
+ )
425
+ await conn.commit()
426
+
427
+ async def append_event_and_update_state(
428
+ self, event_record: EventRecord, session_id: str, state: "dict[str, Any]"
429
+ ) -> SessionRecord:
430
+ """Atomically append an event and update the session's durable state.
431
+
432
+ Inserts the event and updates the session state + update_time in a
433
+ single transaction. Both operations succeed or fail together. Returns
434
+ the updated SessionRecord via SQLite RETURNING (3.35+).
435
+
436
+ Args:
437
+ event_record: Event record to store.
438
+ session_id: Session identifier whose state should be updated.
439
+ state: Post-append durable state snapshot (temp: keys already
440
+ stripped by the service layer).
441
+ """
442
+ import uuid
443
+
444
+ timestamp_julian = _datetime_to_julian(event_record["timestamp"])
445
+ event_data_json = to_json(event_record["event_json"])
446
+ now_julian = _datetime_to_julian(datetime.now(timezone.utc))
447
+ state_json = to_json(state)
448
+ event_id = str(uuid.uuid4())
449
+
450
+ insert_sql = f"""
451
+ INSERT INTO {self._events_table} (
452
+ id, session_id, invocation_id, author, timestamp, event_data
453
+ ) VALUES (?, ?, ?, ?, ?, ?)
454
+ """
455
+
456
+ update_sql = f"""
457
+ UPDATE {self._session_table}
458
+ SET state = ?, update_time = ?
459
+ WHERE id = ?
460
+ RETURNING id, app_name, user_id, state, create_time, update_time
461
+ """
462
+
463
+ async with self._config.provide_connection() as conn:
464
+ await self._apply_pragmas(conn)
465
+ await conn.execute(
466
+ insert_sql,
467
+ (
468
+ event_id,
469
+ event_record["session_id"],
470
+ event_record["invocation_id"],
471
+ event_record["author"],
472
+ timestamp_julian,
473
+ event_data_json,
474
+ ),
475
+ )
476
+ cursor = await conn.execute(update_sql, (state_json, now_julian, session_id))
477
+ row = await cursor.fetchone()
478
+ await conn.commit()
479
+
480
+ if row is None:
481
+ msg = f"Session {session_id} not found during append_event_and_update_state."
482
+ raise ValueError(msg)
483
+
484
+ return SessionRecord(
485
+ id=row[0],
486
+ app_name=row[1],
487
+ user_id=row[2],
488
+ state=from_json(row[3]) if row[3] else {},
489
+ create_time=_julian_to_datetime(row[4]),
490
+ update_time=_julian_to_datetime(row[5]),
491
+ )
492
+
493
+ async def get_events(
494
+ self, session_id: str, after_timestamp: "datetime | None" = None, limit: "int | None" = None
495
+ ) -> "list[EventRecord]":
496
+ """Get events for a session.
497
+
498
+ Args:
499
+ session_id: Session identifier.
500
+ after_timestamp: Only return events after this time.
501
+ limit: Maximum number of events to return.
502
+
503
+ Returns:
504
+ List of event records ordered by timestamp ASC.
505
+
506
+ Notes:
507
+ Uses index on (session_id, timestamp ASC).
508
+ Parses event_data TEXT back to dict for event_json field.
509
+ """
510
+ where_clauses = ["session_id = ?"]
511
+ params: list[Any] = [session_id]
512
+
513
+ if after_timestamp is not None:
514
+ where_clauses.append("timestamp > ?")
515
+ params.append(_datetime_to_julian(after_timestamp))
516
+
517
+ where_clause = " AND ".join(where_clauses)
518
+ limit_clause = f" LIMIT {limit}" if limit else ""
519
+
520
+ sql = f"""
521
+ SELECT id, session_id, invocation_id, author, timestamp, event_data
522
+ FROM {self._events_table}
523
+ WHERE {where_clause}
524
+ ORDER BY timestamp ASC{limit_clause}
525
+ """
526
+
527
+ try:
528
+ async with self._config.provide_connection() as conn:
529
+ await self._apply_pragmas(conn)
530
+ cursor = await conn.execute(sql, params)
531
+ rows = await cursor.fetchall()
532
+
533
+ return [
534
+ EventRecord(
535
+ session_id=row[1],
536
+ invocation_id=row[2],
537
+ author=row[3],
538
+ timestamp=_julian_to_datetime(row[4]),
539
+ event_json=from_json(row[5]) if row[5] else {},
540
+ )
541
+ for row in rows
542
+ ]
543
+ except sqlite3.OperationalError as exc:
544
+ if SQLITE_TABLE_NOT_FOUND_ERROR in str(exc):
545
+ return []
546
+ raise
547
+
548
+
549
+ class AiosqliteADKMemoryStore(BaseAsyncADKMemoryStore["AiosqliteConfig"]):
550
+ """Aiosqlite ADK memory store using asynchronous SQLite driver.
551
+
552
+ Implements memory entry storage for Google Agent Development Kit
553
+ using SQLite via the asynchronous aiosqlite driver. Provides:
554
+ - Session memory storage with JSON as TEXT
555
+ - Simple LIKE search (simple strategy)
556
+ - Optional FTS5 full-text search (sqlite_fts5 strategy)
557
+ - Julian Day timestamps (REAL) for efficient date operations
558
+ - Deduplication via event_id unique constraint
559
+ - Efficient upserts using INSERT OR IGNORE
560
+
561
+ Args:
562
+ config: AiosqliteConfig with extension_config["adk"] settings.
563
+
564
+ Example:
565
+ from sqlspec.adapters.aiosqlite import AiosqliteConfig
566
+ from sqlspec.adapters.aiosqlite.adk import AiosqliteADKMemoryStore
567
+
568
+ config = AiosqliteConfig(
569
+ connection_config={"database": ":memory:"},
570
+ extension_config={
571
+ "adk": {
572
+ "memory_table": "adk_memory_entries",
573
+ "memory_use_fts": False,
574
+ "memory_max_results": 20,
575
+ }
576
+ }
577
+ )
578
+ store = AiosqliteADKMemoryStore(config)
579
+ await store.ensure_tables()
580
+
581
+ Notes:
582
+ - JSON stored as TEXT with SQLSpec serializers
583
+ - REAL for Julian Day timestamps
584
+ - event_id UNIQUE constraint for deduplication
585
+ - Composite index on (app_name, user_id, timestamp DESC)
586
+ - Optional FTS5 virtual table for full-text search
587
+ - Configuration is read from config.extension_config["adk"]
588
+ """
589
+
590
+ __slots__ = ()
591
+
592
+ def __init__(self, config: "AiosqliteConfig") -> None:
593
+ """Initialize Aiosqlite ADK memory store.
594
+
595
+ Args:
596
+ config: AiosqliteConfig instance.
597
+
598
+ Notes:
599
+ Configuration is read from config.extension_config["adk"]:
600
+ - memory_table: Memory table name (default: "adk_memory_entries")
601
+ - memory_use_fts: Enable full-text search when supported (default: False)
602
+ - memory_max_results: Max search results (default: 20)
603
+ - owner_id_column: Optional owner FK column DDL (default: None)
604
+ - enable_memory: Whether memory is enabled (default: True)
605
+ """
606
+ super().__init__(config)
607
+
608
+ async def _get_create_memory_table_sql(self) -> str:
609
+ """Get SQLite CREATE TABLE SQL for memory entries.
610
+
611
+ Returns:
612
+ SQL statement to create memory table with indexes.
613
+
614
+ Notes:
615
+ - TEXT for IDs, names, and JSON content
616
+ - REAL for Julian Day timestamps
617
+ - UNIQUE constraint on event_id for deduplication
618
+ - Composite index on (app_name, user_id, timestamp DESC)
619
+ - Optional owner ID column for multi-tenancy
620
+ - Optional FTS5 virtual table for full-text search
621
+ """
622
+ owner_id_line = ""
623
+ if self._owner_id_column_ddl:
624
+ owner_id_line = f",\n {self._owner_id_column_ddl}"
625
+
626
+ fts_table = ""
627
+ if self._use_fts:
628
+ fts_table = f"""
629
+ CREATE VIRTUAL TABLE IF NOT EXISTS {self._memory_table}_fts USING fts5(
630
+ content_text,
631
+ content={self._memory_table},
632
+ content_rowid=rowid
633
+ );
634
+
635
+ CREATE TRIGGER IF NOT EXISTS {self._memory_table}_ai AFTER INSERT ON {self._memory_table} BEGIN
636
+ INSERT INTO {self._memory_table}_fts(rowid, content_text) VALUES (new.rowid, new.content_text);
637
+ END;
638
+
639
+ CREATE TRIGGER IF NOT EXISTS {self._memory_table}_ad AFTER DELETE ON {self._memory_table} BEGIN
640
+ INSERT INTO {self._memory_table}_fts({self._memory_table}_fts, rowid, content_text)
641
+ VALUES('delete', old.rowid, old.content_text);
642
+ END;
643
+
644
+ CREATE TRIGGER IF NOT EXISTS {self._memory_table}_au AFTER UPDATE ON {self._memory_table} BEGIN
645
+ INSERT INTO {self._memory_table}_fts({self._memory_table}_fts, rowid, content_text)
646
+ VALUES('delete', old.rowid, old.content_text);
647
+ INSERT INTO {self._memory_table}_fts(rowid, content_text) VALUES (new.rowid, new.content_text);
648
+ END;
649
+ """
650
+
651
+ return f"""
652
+ CREATE TABLE IF NOT EXISTS {self._memory_table} (
653
+ id TEXT PRIMARY KEY,
654
+ session_id TEXT NOT NULL,
655
+ app_name TEXT NOT NULL,
656
+ user_id TEXT NOT NULL,
657
+ event_id TEXT NOT NULL UNIQUE,
658
+ author TEXT{owner_id_line},
659
+ timestamp REAL NOT NULL,
660
+ content_json TEXT NOT NULL,
661
+ content_text TEXT NOT NULL,
662
+ metadata_json TEXT,
663
+ inserted_at REAL NOT NULL
664
+ );
665
+
666
+ CREATE INDEX IF NOT EXISTS idx_{self._memory_table}_app_user_time
667
+ ON {self._memory_table}(app_name, user_id, timestamp DESC);
668
+
669
+ CREATE INDEX IF NOT EXISTS idx_{self._memory_table}_session
670
+ ON {self._memory_table}(session_id);
671
+ {fts_table}
672
+ """
673
+
674
+ def _get_drop_memory_table_sql(self) -> "list[str]":
675
+ """Get SQLite DROP TABLE SQL statements."""
676
+ statements = [f"DROP TABLE IF EXISTS {self._memory_table}"]
677
+ if self._use_fts:
678
+ statements.extend([
679
+ f"DROP TABLE IF EXISTS {self._memory_table}_fts",
680
+ f"DROP TRIGGER IF EXISTS {self._memory_table}_ai",
681
+ f"DROP TRIGGER IF EXISTS {self._memory_table}_ad",
682
+ f"DROP TRIGGER IF EXISTS {self._memory_table}_au",
683
+ ])
684
+ return statements
685
+
686
+ async def create_tables(self) -> None:
687
+ """Create the memory table and indexes if they don't exist.
688
+
689
+ Skips table creation if memory store is disabled.
690
+ """
691
+ if not self._enabled:
692
+ return
693
+
694
+ async with self._config.provide_session() as driver:
695
+ await driver.execute_script(await self._get_create_memory_table_sql())
696
+
697
+ async def insert_memory_entries(self, entries: "list[MemoryRecord]", owner_id: "object | None" = None) -> int:
698
+ """Bulk insert memory entries with deduplication.
699
+
700
+ Uses INSERT OR IGNORE to skip duplicates based on event_id unique constraint.
701
+ """
702
+ if not self._enabled:
703
+ msg = "Memory store is disabled"
704
+ raise RuntimeError(msg)
705
+
706
+ if not entries:
707
+ return 0
708
+
709
+ inserted_count = 0
710
+ async with self._config.provide_connection() as conn:
711
+ for entry in entries:
712
+ params: tuple[Any, ...]
713
+ if self._owner_id_column_name:
714
+ sql = f"""
715
+ INSERT OR IGNORE INTO {self._memory_table}
716
+ (id, session_id, app_name, user_id, event_id, author,
717
+ {self._owner_id_column_name}, timestamp, content_json,
718
+ content_text, metadata_json, inserted_at)
719
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
720
+ """
721
+ params = (
722
+ entry["id"],
723
+ entry["session_id"],
724
+ entry["app_name"],
725
+ entry["user_id"],
726
+ entry["event_id"],
727
+ entry["author"],
728
+ owner_id,
729
+ _datetime_to_julian(entry["timestamp"]),
730
+ to_json(entry["content_json"]),
731
+ entry["content_text"],
732
+ to_json(entry["metadata_json"]),
733
+ _datetime_to_julian(entry["inserted_at"]),
734
+ )
735
+ else:
736
+ sql = f"""
737
+ INSERT OR IGNORE INTO {self._memory_table}
738
+ (id, session_id, app_name, user_id, event_id, author,
739
+ timestamp, content_json, content_text, metadata_json, inserted_at)
740
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
741
+ """
742
+ params = (
743
+ entry["id"],
744
+ entry["session_id"],
745
+ entry["app_name"],
746
+ entry["user_id"],
747
+ entry["event_id"],
748
+ entry["author"],
749
+ _datetime_to_julian(entry["timestamp"]),
750
+ to_json(entry["content_json"]),
751
+ entry["content_text"],
752
+ to_json(entry["metadata_json"]),
753
+ _datetime_to_julian(entry["inserted_at"]),
754
+ )
755
+ cursor = await conn.execute(sql, params)
756
+ inserted_count += cursor.rowcount
757
+ await cursor.close()
758
+ await conn.commit()
759
+ return inserted_count
760
+
761
+ async def search_entries(
762
+ self, query: str, app_name: str, user_id: str, limit: "int | None" = None
763
+ ) -> "list[MemoryRecord]":
764
+ """Search memory entries by text query."""
765
+ if not self._enabled:
766
+ msg = "Memory store is disabled"
767
+ raise RuntimeError(msg)
768
+
769
+ if not query:
770
+ return []
771
+
772
+ limit_value = limit or self._max_results
773
+ if self._use_fts:
774
+ sql = f"""
775
+ SELECT m.* FROM {self._memory_table} AS m
776
+ JOIN {self._memory_table}_fts AS fts ON m.rowid = fts.rowid
777
+ WHERE m.app_name = ? AND m.user_id = ? AND fts.content_text MATCH ?
778
+ ORDER BY m.timestamp DESC
779
+ LIMIT ?
780
+ """
781
+ params = (app_name, user_id, query, limit_value)
782
+ else:
783
+ sql = f"""
784
+ SELECT * FROM {self._memory_table}
785
+ WHERE app_name = ? AND user_id = ? AND content_text LIKE ?
786
+ ORDER BY timestamp DESC
787
+ LIMIT ?
788
+ """
789
+ params = (app_name, user_id, f"%{query}%", limit_value)
790
+
791
+ async with self._config.provide_connection() as conn:
792
+ cursor = await conn.execute(sql, params)
793
+ rows = await cursor.fetchall()
794
+ columns = [col[0] for col in cursor.description or []]
795
+ await cursor.close()
796
+ records: list[MemoryRecord] = []
797
+ for row in rows:
798
+ raw = dict(zip(columns, row, strict=False))
799
+ raw["timestamp"] = _julian_to_datetime(raw["timestamp"])
800
+ raw["inserted_at"] = _julian_to_datetime(raw["inserted_at"])
801
+ raw["content_json"] = from_json(raw["content_json"])
802
+ raw["metadata_json"] = from_json(raw["metadata_json"]) if raw["metadata_json"] else None
803
+ records.append(cast("MemoryRecord", raw))
804
+ return records
805
+
806
+ async def delete_entries_by_session(self, session_id: str) -> int:
807
+ """Delete all memory entries for a specific session."""
808
+ if not self._enabled:
809
+ msg = "Memory store is disabled"
810
+ raise RuntimeError(msg)
811
+
812
+ sql = f"DELETE FROM {self._memory_table} WHERE session_id = ?"
813
+ async with self._config.provide_connection() as conn:
814
+ cursor = await conn.execute(sql, (session_id,))
815
+ await conn.commit()
816
+ return cursor.rowcount
817
+
818
+ async def delete_entries_older_than(self, days: int) -> int:
819
+ """Delete memory entries older than specified days."""
820
+ if not self._enabled:
821
+ msg = "Memory store is disabled"
822
+ raise RuntimeError(msg)
823
+
824
+ cutoff = _datetime_to_julian(datetime.now(timezone.utc)) - days
825
+ sql = f"DELETE FROM {self._memory_table} WHERE inserted_at < ?"
826
+ async with self._config.provide_connection() as conn:
827
+ cursor = await conn.execute(sql, (cutoff,))
828
+ await conn.commit()
829
+ return cursor.rowcount