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,1060 @@
1
+ """MysqlConnector ADK store for Google Agent Development Kit session/event storage."""
2
+
3
+ import re
4
+ from typing import TYPE_CHECKING, Any, Final, cast
5
+
6
+ import mysql.connector
7
+
8
+ from sqlspec.extensions.adk import BaseAsyncADKStore, BaseSyncADKStore, EventRecord, SessionRecord
9
+ from sqlspec.extensions.adk.memory.store import BaseAsyncADKMemoryStore, BaseSyncADKMemoryStore
10
+ from sqlspec.utils.serializers import from_json, to_json
11
+
12
+ if TYPE_CHECKING:
13
+ from datetime import datetime
14
+
15
+ from sqlspec.adapters.mysqlconnector.config import MysqlConnectorAsyncConfig, MysqlConnectorSyncConfig
16
+ from sqlspec.extensions.adk import MemoryRecord
17
+
18
+
19
+ __all__ = (
20
+ "MysqlConnectorAsyncADKMemoryStore",
21
+ "MysqlConnectorAsyncADKStore",
22
+ "MysqlConnectorSyncADKMemoryStore",
23
+ "MysqlConnectorSyncADKStore",
24
+ )
25
+
26
+ MYSQL_TABLE_NOT_FOUND_ERROR: Final = 1146
27
+
28
+
29
+ def _parse_owner_id_column_for_mysql(column_ddl: str) -> "tuple[str, str]":
30
+ references_match = re.search(r"\s+REFERENCES\s+(.+)", column_ddl, re.IGNORECASE)
31
+ if not references_match:
32
+ return (column_ddl.strip(), "")
33
+
34
+ col_def = column_ddl[: references_match.start()].strip()
35
+ fk_clause = references_match.group(1).strip()
36
+ col_name = col_def.split()[0]
37
+ fk_constraint = f"FOREIGN KEY ({col_name}) REFERENCES {fk_clause}"
38
+ return (col_def, fk_constraint)
39
+
40
+
41
+ class MysqlConnectorAsyncADKStore(BaseAsyncADKStore["MysqlConnectorAsyncConfig"]):
42
+ """MySQL/MariaDB ADK store using mysql-connector async driver."""
43
+
44
+ __slots__ = ()
45
+
46
+ def __init__(self, config: "MysqlConnectorAsyncConfig") -> None:
47
+ super().__init__(config)
48
+
49
+ def _parse_owner_id_column_for_mysql(self, column_ddl: str) -> "tuple[str, str]":
50
+ return _parse_owner_id_column_for_mysql(column_ddl)
51
+
52
+ async def _get_create_sessions_table_sql(self) -> str:
53
+ owner_id_col = ""
54
+ fk_constraint = ""
55
+
56
+ if self._owner_id_column_ddl:
57
+ col_def, fk_def = self._parse_owner_id_column_for_mysql(self._owner_id_column_ddl)
58
+ owner_id_col = f"{col_def},"
59
+ if fk_def:
60
+ fk_constraint = f",\n {fk_def}"
61
+
62
+ return f"""
63
+ CREATE TABLE IF NOT EXISTS {self._session_table} (
64
+ id VARCHAR(128) PRIMARY KEY,
65
+ app_name VARCHAR(128) NOT NULL,
66
+ user_id VARCHAR(128) NOT NULL,
67
+ {owner_id_col}
68
+ state JSON NOT NULL,
69
+ create_time TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
70
+ update_time TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
71
+ INDEX idx_{self._session_table}_app_user (app_name, user_id),
72
+ INDEX idx_{self._session_table}_update_time (update_time DESC){fk_constraint}
73
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
74
+ """
75
+
76
+ async def _get_create_events_table_sql(self) -> str:
77
+ return f"""
78
+ CREATE TABLE IF NOT EXISTS {self._events_table} (
79
+ id VARCHAR(128) PRIMARY KEY,
80
+ session_id VARCHAR(128) NOT NULL,
81
+ app_name VARCHAR(128) NOT NULL,
82
+ user_id VARCHAR(128) NOT NULL,
83
+ invocation_id VARCHAR(256) NOT NULL,
84
+ author VARCHAR(256) NOT NULL,
85
+ actions BLOB NOT NULL,
86
+ long_running_tool_ids_json JSON,
87
+ branch VARCHAR(256),
88
+ timestamp TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
89
+ content JSON,
90
+ grounding_metadata JSON,
91
+ custom_metadata JSON,
92
+ partial BOOLEAN,
93
+ turn_complete BOOLEAN,
94
+ interrupted BOOLEAN,
95
+ error_code VARCHAR(256),
96
+ error_message VARCHAR(1024),
97
+ FOREIGN KEY (session_id) REFERENCES {self._session_table}(id) ON DELETE CASCADE,
98
+ INDEX idx_{self._events_table}_session (session_id, timestamp ASC)
99
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
100
+ """
101
+
102
+ def _get_drop_tables_sql(self) -> "list[str]":
103
+ return [f"DROP TABLE IF EXISTS {self._events_table}", f"DROP TABLE IF EXISTS {self._session_table}"]
104
+
105
+ async def create_tables(self) -> None:
106
+ async with self._config.provide_session() as driver:
107
+ await driver.execute_script(await self._get_create_sessions_table_sql())
108
+ await driver.execute_script(await self._get_create_events_table_sql())
109
+
110
+ async def create_session(
111
+ self, session_id: str, app_name: str, user_id: str, state: "dict[str, Any]", owner_id: "Any | None" = None
112
+ ) -> SessionRecord:
113
+ state_json = to_json(state)
114
+
115
+ params: tuple[Any, ...]
116
+ if self._owner_id_column_name:
117
+ sql = f"""
118
+ INSERT INTO {self._session_table} (id, app_name, user_id, {self._owner_id_column_name}, state, create_time, update_time)
119
+ VALUES (%s, %s, %s, %s, %s, UTC_TIMESTAMP(6), UTC_TIMESTAMP(6))
120
+ """
121
+ params = (session_id, app_name, user_id, owner_id, state_json)
122
+ else:
123
+ sql = f"""
124
+ INSERT INTO {self._session_table} (id, app_name, user_id, state, create_time, update_time)
125
+ VALUES (%s, %s, %s, %s, UTC_TIMESTAMP(6), UTC_TIMESTAMP(6))
126
+ """
127
+ params = (session_id, app_name, user_id, state_json)
128
+
129
+ async with self._config.provide_connection() as conn:
130
+ cursor = await conn.cursor()
131
+ try:
132
+ await cursor.execute(sql, params)
133
+ finally:
134
+ await cursor.close()
135
+ await conn.commit()
136
+
137
+ return await self.get_session(session_id) # type: ignore[return-value]
138
+
139
+ async def get_session(self, session_id: str) -> "SessionRecord | None":
140
+ sql = f"""
141
+ SELECT id, app_name, user_id, state, create_time, update_time
142
+ FROM {self._session_table}
143
+ WHERE id = %s
144
+ """
145
+
146
+ try:
147
+ async with self._config.provide_connection() as conn:
148
+ cursor = await conn.cursor()
149
+ try:
150
+ await cursor.execute(sql, (session_id,))
151
+ row = await cursor.fetchone()
152
+ finally:
153
+ await cursor.close()
154
+
155
+ if row is None:
156
+ return None
157
+
158
+ session_id_val, app_name_val, user_id_val, state_json, create_time_val, update_time_val = row
159
+
160
+ return SessionRecord(
161
+ id=cast("str", session_id_val),
162
+ app_name=cast("str", app_name_val),
163
+ user_id=cast("str", user_id_val),
164
+ state=from_json(state_json) if isinstance(state_json, str) else cast("dict[str, Any]", state_json),
165
+ create_time=cast("datetime", create_time_val),
166
+ update_time=cast("datetime", update_time_val),
167
+ )
168
+ except mysql.connector.Error as exc:
169
+ if "doesn't exist" in str(exc) or getattr(exc, "errno", None) == MYSQL_TABLE_NOT_FOUND_ERROR:
170
+ return None
171
+ raise
172
+
173
+ async def update_session_state(self, session_id: str, state: "dict[str, Any]") -> None:
174
+ state_json = to_json(state)
175
+
176
+ sql = f"""
177
+ UPDATE {self._session_table}
178
+ SET state = %s
179
+ WHERE id = %s
180
+ """
181
+
182
+ async with self._config.provide_connection() as conn:
183
+ cursor = await conn.cursor()
184
+ try:
185
+ await cursor.execute(sql, (state_json, session_id))
186
+ finally:
187
+ await cursor.close()
188
+ await conn.commit()
189
+
190
+ async def delete_session(self, session_id: str) -> None:
191
+ sql = f"DELETE FROM {self._session_table} WHERE id = %s"
192
+
193
+ async with self._config.provide_connection() as conn:
194
+ cursor = await conn.cursor()
195
+ try:
196
+ await cursor.execute(sql, (session_id,))
197
+ finally:
198
+ await cursor.close()
199
+ await conn.commit()
200
+
201
+ async def list_sessions(self, app_name: str, user_id: str | None = None) -> "list[SessionRecord]":
202
+ if user_id is None:
203
+ sql = f"""
204
+ SELECT id, app_name, user_id, state, create_time, update_time
205
+ FROM {self._session_table}
206
+ WHERE app_name = %s
207
+ ORDER BY update_time DESC
208
+ """
209
+ params: tuple[str, ...] = (app_name,)
210
+ else:
211
+ sql = f"""
212
+ SELECT id, app_name, user_id, state, create_time, update_time
213
+ FROM {self._session_table}
214
+ WHERE app_name = %s AND user_id = %s
215
+ ORDER BY update_time DESC
216
+ """
217
+ params = (app_name, user_id)
218
+
219
+ try:
220
+ async with self._config.provide_connection() as conn:
221
+ cursor = await conn.cursor()
222
+ try:
223
+ await cursor.execute(sql, params)
224
+ rows = await cursor.fetchall()
225
+ finally:
226
+ await cursor.close()
227
+
228
+ return [
229
+ SessionRecord(
230
+ id=cast("str", row[0]),
231
+ app_name=cast("str", row[1]),
232
+ user_id=cast("str", row[2]),
233
+ state=from_json(row[3]) if isinstance(row[3], str) else cast("dict[str, Any]", row[3]),
234
+ create_time=cast("datetime", row[4]),
235
+ update_time=cast("datetime", row[5]),
236
+ )
237
+ for row in rows
238
+ ]
239
+ except mysql.connector.Error as exc:
240
+ if "doesn't exist" in str(exc) or getattr(exc, "errno", None) == MYSQL_TABLE_NOT_FOUND_ERROR:
241
+ return []
242
+ raise
243
+
244
+ async def append_event(self, event_record: EventRecord) -> None:
245
+ content_json = to_json(event_record.get("content")) if event_record.get("content") else None
246
+ grounding_metadata_json = (
247
+ to_json(event_record.get("grounding_metadata")) if event_record.get("grounding_metadata") else None
248
+ )
249
+ custom_metadata_json = (
250
+ to_json(event_record.get("custom_metadata")) if event_record.get("custom_metadata") else None
251
+ )
252
+
253
+ sql = f"""
254
+ INSERT INTO {self._events_table} (
255
+ id, session_id, app_name, user_id, invocation_id, author, actions,
256
+ long_running_tool_ids_json, branch, timestamp, content,
257
+ grounding_metadata, custom_metadata, partial, turn_complete,
258
+ interrupted, error_code, error_message
259
+ ) VALUES (
260
+ %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
261
+ )
262
+ """
263
+
264
+ async with self._config.provide_connection() as conn:
265
+ cursor = await conn.cursor()
266
+ try:
267
+ await cursor.execute(
268
+ sql,
269
+ (
270
+ event_record["id"],
271
+ event_record["session_id"],
272
+ event_record["app_name"],
273
+ event_record["user_id"],
274
+ event_record["invocation_id"],
275
+ event_record["author"],
276
+ event_record["actions"],
277
+ event_record.get("long_running_tool_ids_json"),
278
+ event_record.get("branch"),
279
+ event_record["timestamp"],
280
+ content_json,
281
+ grounding_metadata_json,
282
+ custom_metadata_json,
283
+ event_record.get("partial"),
284
+ event_record.get("turn_complete"),
285
+ event_record.get("interrupted"),
286
+ event_record.get("error_code"),
287
+ event_record.get("error_message"),
288
+ ),
289
+ )
290
+ finally:
291
+ await cursor.close()
292
+ await conn.commit()
293
+
294
+ async def get_events(
295
+ self, session_id: str, after_timestamp: "datetime | None" = None, limit: "int | None" = None
296
+ ) -> "list[EventRecord]":
297
+ where_clauses = ["session_id = %s"]
298
+ params: list[Any] = [session_id]
299
+
300
+ if after_timestamp is not None:
301
+ where_clauses.append("timestamp > %s")
302
+ params.append(after_timestamp)
303
+
304
+ where_clause = " AND ".join(where_clauses)
305
+ limit_clause = f" LIMIT {limit}" if limit else ""
306
+
307
+ sql = f"""
308
+ SELECT id, session_id, app_name, user_id, invocation_id, author, actions,
309
+ long_running_tool_ids_json, branch, timestamp, content,
310
+ grounding_metadata, custom_metadata, partial, turn_complete,
311
+ interrupted, error_code, error_message
312
+ FROM {self._events_table}
313
+ WHERE {where_clause}
314
+ ORDER BY timestamp ASC{limit_clause}
315
+ """
316
+
317
+ try:
318
+ async with self._config.provide_connection() as conn:
319
+ cursor = await conn.cursor()
320
+ try:
321
+ await cursor.execute(sql, params)
322
+ rows = await cursor.fetchall()
323
+ finally:
324
+ await cursor.close()
325
+
326
+ return [
327
+ EventRecord(
328
+ id=cast("str", row[0]),
329
+ session_id=cast("str", row[1]),
330
+ app_name=cast("str", row[2]),
331
+ user_id=cast("str", row[3]),
332
+ invocation_id=cast("str", row[4]),
333
+ author=cast("str", row[5]),
334
+ actions=bytes(cast("bytes", row[6])),
335
+ long_running_tool_ids_json=cast("str | None", row[7]),
336
+ branch=cast("str | None", row[8]),
337
+ timestamp=cast("datetime", row[9]),
338
+ content=from_json(row[10])
339
+ if row[10] and isinstance(row[10], str)
340
+ else cast("dict[str, Any] | None", row[10]),
341
+ grounding_metadata=from_json(row[11])
342
+ if row[11] and isinstance(row[11], str)
343
+ else cast("dict[str, Any] | None", row[11]),
344
+ custom_metadata=from_json(row[12])
345
+ if row[12] and isinstance(row[12], str)
346
+ else cast("dict[str, Any] | None", row[12]),
347
+ partial=cast("bool | None", row[13]),
348
+ turn_complete=cast("bool | None", row[14]),
349
+ interrupted=cast("bool | None", row[15]),
350
+ error_code=cast("str | None", row[16]),
351
+ error_message=cast("str | None", row[17]),
352
+ )
353
+ for row in rows
354
+ ]
355
+ except mysql.connector.Error as exc:
356
+ if "doesn't exist" in str(exc) or getattr(exc, "errno", None) == MYSQL_TABLE_NOT_FOUND_ERROR:
357
+ return []
358
+ raise
359
+
360
+
361
+ class MysqlConnectorSyncADKStore(BaseSyncADKStore["MysqlConnectorSyncConfig"]):
362
+ """MySQL/MariaDB ADK store using mysql-connector sync driver."""
363
+
364
+ __slots__ = ()
365
+
366
+ def __init__(self, config: "MysqlConnectorSyncConfig") -> None:
367
+ super().__init__(config)
368
+
369
+ def _parse_owner_id_column_for_mysql(self, column_ddl: str) -> "tuple[str, str]":
370
+ return _parse_owner_id_column_for_mysql(column_ddl)
371
+
372
+ def _get_create_sessions_table_sql(self) -> str:
373
+ owner_id_col = ""
374
+ fk_constraint = ""
375
+
376
+ if self._owner_id_column_ddl:
377
+ col_def, fk_def = self._parse_owner_id_column_for_mysql(self._owner_id_column_ddl)
378
+ owner_id_col = f"{col_def},"
379
+ if fk_def:
380
+ fk_constraint = f",\n {fk_def}"
381
+
382
+ return f"""
383
+ CREATE TABLE IF NOT EXISTS {self._session_table} (
384
+ id VARCHAR(128) PRIMARY KEY,
385
+ app_name VARCHAR(128) NOT NULL,
386
+ user_id VARCHAR(128) NOT NULL,
387
+ {owner_id_col}
388
+ state JSON NOT NULL,
389
+ create_time TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
390
+ update_time TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
391
+ INDEX idx_{self._session_table}_app_user (app_name, user_id),
392
+ INDEX idx_{self._session_table}_update_time (update_time DESC){fk_constraint}
393
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
394
+ """
395
+
396
+ def _get_create_events_table_sql(self) -> str:
397
+ return f"""
398
+ CREATE TABLE IF NOT EXISTS {self._events_table} (
399
+ id VARCHAR(128) PRIMARY KEY,
400
+ session_id VARCHAR(128) NOT NULL,
401
+ app_name VARCHAR(128) NOT NULL,
402
+ user_id VARCHAR(128) NOT NULL,
403
+ invocation_id VARCHAR(256) NOT NULL,
404
+ author VARCHAR(256) NOT NULL,
405
+ actions BLOB NOT NULL,
406
+ long_running_tool_ids_json JSON,
407
+ branch VARCHAR(256),
408
+ timestamp TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
409
+ content JSON,
410
+ grounding_metadata JSON,
411
+ custom_metadata JSON,
412
+ partial BOOLEAN,
413
+ turn_complete BOOLEAN,
414
+ interrupted BOOLEAN,
415
+ error_code VARCHAR(256),
416
+ error_message VARCHAR(1024),
417
+ FOREIGN KEY (session_id) REFERENCES {self._session_table}(id) ON DELETE CASCADE,
418
+ INDEX idx_{self._events_table}_session (session_id, timestamp ASC)
419
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
420
+ """
421
+
422
+ def _get_drop_tables_sql(self) -> "list[str]":
423
+ return [f"DROP TABLE IF EXISTS {self._events_table}", f"DROP TABLE IF EXISTS {self._session_table}"]
424
+
425
+ def create_tables(self) -> None:
426
+ with self._config.provide_session() as driver:
427
+ driver.execute_script(self._get_create_sessions_table_sql())
428
+ driver.execute_script(self._get_create_events_table_sql())
429
+
430
+ def create_session(
431
+ self, session_id: str, app_name: str, user_id: str, state: "dict[str, Any]", owner_id: "Any | None" = None
432
+ ) -> SessionRecord:
433
+ state_json = to_json(state)
434
+
435
+ params: tuple[Any, ...]
436
+ if self._owner_id_column_name:
437
+ sql = f"""
438
+ INSERT INTO {self._session_table} (id, app_name, user_id, {self._owner_id_column_name}, state, create_time, update_time)
439
+ VALUES (%s, %s, %s, %s, %s, UTC_TIMESTAMP(6), UTC_TIMESTAMP(6))
440
+ """
441
+ params = (session_id, app_name, user_id, owner_id, state_json)
442
+ else:
443
+ sql = f"""
444
+ INSERT INTO {self._session_table} (id, app_name, user_id, state, create_time, update_time)
445
+ VALUES (%s, %s, %s, %s, UTC_TIMESTAMP(6), UTC_TIMESTAMP(6))
446
+ """
447
+ params = (session_id, app_name, user_id, state_json)
448
+
449
+ with self._config.provide_connection() as conn:
450
+ cursor = conn.cursor()
451
+ try:
452
+ cursor.execute(sql, params)
453
+ finally:
454
+ cursor.close()
455
+ conn.commit()
456
+
457
+ result = self.get_session(session_id)
458
+ if result is None:
459
+ msg = "Failed to fetch created session"
460
+ raise RuntimeError(msg)
461
+ return result
462
+
463
+ def get_session(self, session_id: str) -> "SessionRecord | None":
464
+ sql = f"""
465
+ SELECT id, app_name, user_id, state, create_time, update_time
466
+ FROM {self._session_table}
467
+ WHERE id = %s
468
+ """
469
+
470
+ try:
471
+ with self._config.provide_connection() as conn:
472
+ cursor = conn.cursor()
473
+ try:
474
+ cursor.execute(sql, (session_id,))
475
+ row = cursor.fetchone()
476
+ finally:
477
+ cursor.close()
478
+
479
+ if row is None:
480
+ return None
481
+
482
+ session_id_val, app_name_val, user_id_val, state_json, create_time_val, update_time_val = row
483
+
484
+ return SessionRecord(
485
+ id=cast("str", session_id_val),
486
+ app_name=cast("str", app_name_val),
487
+ user_id=cast("str", user_id_val),
488
+ state=from_json(state_json) if isinstance(state_json, str) else cast("dict[str, Any]", state_json),
489
+ create_time=cast("datetime", create_time_val),
490
+ update_time=cast("datetime", update_time_val),
491
+ )
492
+ except mysql.connector.Error as exc:
493
+ if "doesn't exist" in str(exc) or getattr(exc, "errno", None) == MYSQL_TABLE_NOT_FOUND_ERROR:
494
+ return None
495
+ raise
496
+
497
+ def update_session_state(self, session_id: str, state: "dict[str, Any]") -> None:
498
+ state_json = to_json(state)
499
+
500
+ sql = f"""
501
+ UPDATE {self._session_table}
502
+ SET state = %s
503
+ WHERE id = %s
504
+ """
505
+
506
+ with self._config.provide_connection() as conn:
507
+ cursor = conn.cursor()
508
+ try:
509
+ cursor.execute(sql, (state_json, session_id))
510
+ finally:
511
+ cursor.close()
512
+ conn.commit()
513
+
514
+ def delete_session(self, session_id: str) -> None:
515
+ sql = f"DELETE FROM {self._session_table} WHERE id = %s"
516
+
517
+ with self._config.provide_connection() as conn:
518
+ cursor = conn.cursor()
519
+ try:
520
+ cursor.execute(sql, (session_id,))
521
+ finally:
522
+ cursor.close()
523
+ conn.commit()
524
+
525
+ def list_sessions(self, app_name: str, user_id: str | None = None) -> "list[SessionRecord]":
526
+ if user_id is None:
527
+ sql = f"""
528
+ SELECT id, app_name, user_id, state, create_time, update_time
529
+ FROM {self._session_table}
530
+ WHERE app_name = %s
531
+ ORDER BY update_time DESC
532
+ """
533
+ params: tuple[str, ...] = (app_name,)
534
+ else:
535
+ sql = f"""
536
+ SELECT id, app_name, user_id, state, create_time, update_time
537
+ FROM {self._session_table}
538
+ WHERE app_name = %s AND user_id = %s
539
+ ORDER BY update_time DESC
540
+ """
541
+ params = (app_name, user_id)
542
+
543
+ try:
544
+ with self._config.provide_connection() as conn:
545
+ cursor = conn.cursor()
546
+ try:
547
+ cursor.execute(sql, params)
548
+ rows = cursor.fetchall()
549
+ finally:
550
+ cursor.close()
551
+
552
+ return [
553
+ SessionRecord(
554
+ id=cast("str", row[0]),
555
+ app_name=cast("str", row[1]),
556
+ user_id=cast("str", row[2]),
557
+ state=from_json(row[3]) if isinstance(row[3], str) else cast("dict[str, Any]", row[3]),
558
+ create_time=cast("datetime", row[4]),
559
+ update_time=cast("datetime", row[5]),
560
+ )
561
+ for row in rows
562
+ ]
563
+ except mysql.connector.Error as exc:
564
+ if "doesn't exist" in str(exc) or getattr(exc, "errno", None) == MYSQL_TABLE_NOT_FOUND_ERROR:
565
+ return []
566
+ raise
567
+
568
+ def append_event(self, event_record: EventRecord) -> None:
569
+ content_json = to_json(event_record.get("content")) if event_record.get("content") else None
570
+ grounding_metadata_json = (
571
+ to_json(event_record.get("grounding_metadata")) if event_record.get("grounding_metadata") else None
572
+ )
573
+ custom_metadata_json = (
574
+ to_json(event_record.get("custom_metadata")) if event_record.get("custom_metadata") else None
575
+ )
576
+
577
+ sql = f"""
578
+ INSERT INTO {self._events_table} (
579
+ id, session_id, app_name, user_id, invocation_id, author, actions,
580
+ long_running_tool_ids_json, branch, timestamp, content,
581
+ grounding_metadata, custom_metadata, partial, turn_complete,
582
+ interrupted, error_code, error_message
583
+ ) VALUES (
584
+ %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
585
+ )
586
+ """
587
+
588
+ with self._config.provide_connection() as conn:
589
+ cursor = conn.cursor()
590
+ try:
591
+ cursor.execute(
592
+ sql,
593
+ (
594
+ event_record["id"],
595
+ event_record["session_id"],
596
+ event_record["app_name"],
597
+ event_record["user_id"],
598
+ event_record["invocation_id"],
599
+ event_record["author"],
600
+ event_record["actions"],
601
+ event_record.get("long_running_tool_ids_json"),
602
+ event_record.get("branch"),
603
+ event_record["timestamp"],
604
+ content_json,
605
+ grounding_metadata_json,
606
+ custom_metadata_json,
607
+ event_record.get("partial"),
608
+ event_record.get("turn_complete"),
609
+ event_record.get("interrupted"),
610
+ event_record.get("error_code"),
611
+ event_record.get("error_message"),
612
+ ),
613
+ )
614
+ finally:
615
+ cursor.close()
616
+ conn.commit()
617
+
618
+ def get_events(
619
+ self, session_id: str, after_timestamp: "datetime | None" = None, limit: "int | None" = None
620
+ ) -> "list[EventRecord]":
621
+ where_clauses = ["session_id = %s"]
622
+ params: list[Any] = [session_id]
623
+
624
+ if after_timestamp is not None:
625
+ where_clauses.append("timestamp > %s")
626
+ params.append(after_timestamp)
627
+
628
+ where_clause = " AND ".join(where_clauses)
629
+ limit_clause = f" LIMIT {limit}" if limit else ""
630
+
631
+ sql = f"""
632
+ SELECT id, session_id, app_name, user_id, invocation_id, author, actions,
633
+ long_running_tool_ids_json, branch, timestamp, content,
634
+ grounding_metadata, custom_metadata, partial, turn_complete,
635
+ interrupted, error_code, error_message
636
+ FROM {self._events_table}
637
+ WHERE {where_clause}
638
+ ORDER BY timestamp ASC{limit_clause}
639
+ """
640
+
641
+ try:
642
+ with self._config.provide_connection() as conn:
643
+ cursor = conn.cursor()
644
+ try:
645
+ cursor.execute(sql, params)
646
+ rows = cursor.fetchall()
647
+ finally:
648
+ cursor.close()
649
+
650
+ return [
651
+ EventRecord(
652
+ id=cast("str", row[0]),
653
+ session_id=cast("str", row[1]),
654
+ app_name=cast("str", row[2]),
655
+ user_id=cast("str", row[3]),
656
+ invocation_id=cast("str", row[4]),
657
+ author=cast("str", row[5]),
658
+ actions=bytes(cast("bytes", row[6])),
659
+ long_running_tool_ids_json=cast("str | None", row[7]),
660
+ branch=cast("str | None", row[8]),
661
+ timestamp=cast("datetime", row[9]),
662
+ content=from_json(row[10])
663
+ if row[10] and isinstance(row[10], str)
664
+ else cast("dict[str, Any] | None", row[10]),
665
+ grounding_metadata=from_json(row[11])
666
+ if row[11] and isinstance(row[11], str)
667
+ else cast("dict[str, Any] | None", row[11]),
668
+ custom_metadata=from_json(row[12])
669
+ if row[12] and isinstance(row[12], str)
670
+ else cast("dict[str, Any] | None", row[12]),
671
+ partial=cast("bool | None", row[13]),
672
+ turn_complete=cast("bool | None", row[14]),
673
+ interrupted=cast("bool | None", row[15]),
674
+ error_code=cast("str | None", row[16]),
675
+ error_message=cast("str | None", row[17]),
676
+ )
677
+ for row in rows
678
+ ]
679
+ except mysql.connector.Error as exc:
680
+ if "doesn't exist" in str(exc) or getattr(exc, "errno", None) == MYSQL_TABLE_NOT_FOUND_ERROR:
681
+ return []
682
+ raise
683
+
684
+
685
+ class MysqlConnectorAsyncADKMemoryStore(BaseAsyncADKMemoryStore["MysqlConnectorAsyncConfig"]):
686
+ """MySQL/MariaDB ADK memory store using mysql-connector async driver."""
687
+
688
+ __slots__ = ()
689
+
690
+ def __init__(self, config: "MysqlConnectorAsyncConfig") -> None:
691
+ super().__init__(config)
692
+
693
+ async def _get_create_memory_table_sql(self) -> str:
694
+ owner_id_line = ""
695
+ fk_constraint = ""
696
+ if self._owner_id_column_ddl:
697
+ col_def, fk_def = _parse_owner_id_column_for_mysql(self._owner_id_column_ddl)
698
+ owner_id_line = f",\n {col_def}"
699
+ if fk_def:
700
+ fk_constraint = f",\n {fk_def}"
701
+
702
+ fts_index = ""
703
+ if self._use_fts:
704
+ fts_index = f",\n FULLTEXT INDEX idx_{self._memory_table}_fts (content_text)"
705
+
706
+ return f"""
707
+ CREATE TABLE IF NOT EXISTS {self._memory_table} (
708
+ id VARCHAR(128) PRIMARY KEY,
709
+ session_id VARCHAR(128) NOT NULL,
710
+ app_name VARCHAR(128) NOT NULL,
711
+ user_id VARCHAR(128) NOT NULL,
712
+ event_id VARCHAR(128) NOT NULL UNIQUE,
713
+ author VARCHAR(256){owner_id_line},
714
+ timestamp TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
715
+ content_json JSON NOT NULL,
716
+ content_text TEXT NOT NULL,
717
+ metadata_json JSON,
718
+ inserted_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
719
+ INDEX idx_{self._memory_table}_app_user_time (app_name, user_id, timestamp),
720
+ INDEX idx_{self._memory_table}_session (session_id){fts_index}{fk_constraint}
721
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
722
+ """
723
+
724
+ def _get_drop_memory_table_sql(self) -> "list[str]":
725
+ return [f"DROP TABLE IF EXISTS {self._memory_table}"]
726
+
727
+ async def create_tables(self) -> None:
728
+ if not self._enabled:
729
+ return
730
+
731
+ async with self._config.provide_session() as driver:
732
+ await driver.execute_script(await self._get_create_memory_table_sql())
733
+
734
+ async def insert_memory_entries(self, entries: "list[MemoryRecord]", owner_id: "object | None" = None) -> int:
735
+ if not self._enabled:
736
+ msg = "Memory store is disabled"
737
+ raise RuntimeError(msg)
738
+
739
+ if not entries:
740
+ return 0
741
+
742
+ inserted_count = 0
743
+ if self._owner_id_column_name:
744
+ sql = f"""
745
+ INSERT IGNORE INTO {self._memory_table} (
746
+ id, session_id, app_name, user_id, event_id, author,
747
+ {self._owner_id_column_name}, timestamp, content_json,
748
+ content_text, metadata_json, inserted_at
749
+ ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
750
+ """
751
+ else:
752
+ sql = f"""
753
+ INSERT IGNORE INTO {self._memory_table} (
754
+ id, session_id, app_name, user_id, event_id, author,
755
+ timestamp, content_json, content_text, metadata_json, inserted_at
756
+ ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
757
+ """
758
+
759
+ async with self._config.provide_connection() as conn:
760
+ cursor = await conn.cursor()
761
+ try:
762
+ for entry in entries:
763
+ params: tuple[Any, ...]
764
+ if self._owner_id_column_name:
765
+ params = (
766
+ entry["id"],
767
+ entry["session_id"],
768
+ entry["app_name"],
769
+ entry["user_id"],
770
+ entry["event_id"],
771
+ entry["author"],
772
+ owner_id,
773
+ entry["timestamp"],
774
+ to_json(entry["content_json"]),
775
+ entry["content_text"],
776
+ to_json(entry["metadata_json"]),
777
+ entry["inserted_at"],
778
+ )
779
+ else:
780
+ params = (
781
+ entry["id"],
782
+ entry["session_id"],
783
+ entry["app_name"],
784
+ entry["user_id"],
785
+ entry["event_id"],
786
+ entry["author"],
787
+ entry["timestamp"],
788
+ to_json(entry["content_json"]),
789
+ entry["content_text"],
790
+ to_json(entry["metadata_json"]),
791
+ entry["inserted_at"],
792
+ )
793
+ await cursor.execute(sql, params)
794
+ inserted_count += cursor.rowcount
795
+ finally:
796
+ await cursor.close()
797
+ await conn.commit()
798
+ return inserted_count
799
+
800
+ async def search_entries(
801
+ self, query: str, app_name: str, user_id: str, limit: "int | None" = None
802
+ ) -> "list[MemoryRecord]":
803
+ if not self._enabled:
804
+ msg = "Memory store is disabled"
805
+ raise RuntimeError(msg)
806
+
807
+ if not query:
808
+ return []
809
+
810
+ limit_value = limit or self._max_results
811
+ if self._use_fts:
812
+ sql = f"""
813
+ SELECT * FROM {self._memory_table}
814
+ WHERE app_name = %s AND user_id = %s
815
+ AND MATCH(content_text) AGAINST (%s IN NATURAL LANGUAGE MODE)
816
+ ORDER BY timestamp DESC
817
+ LIMIT %s
818
+ """
819
+ params = (app_name, user_id, query, limit_value)
820
+ else:
821
+ sql = f"""
822
+ SELECT * FROM {self._memory_table}
823
+ WHERE app_name = %s AND user_id = %s AND content_text LIKE %s
824
+ ORDER BY timestamp DESC
825
+ LIMIT %s
826
+ """
827
+ params = (app_name, user_id, f"%{query}%", limit_value)
828
+
829
+ async with self._config.provide_connection() as conn:
830
+ cursor = await conn.cursor()
831
+ try:
832
+ await cursor.execute(sql, params)
833
+ rows = await cursor.fetchall()
834
+ columns = [col[0] for col in cursor.description or []]
835
+ finally:
836
+ await cursor.close()
837
+
838
+ return [cast("MemoryRecord", dict(zip(columns, row, strict=False))) for row in rows]
839
+
840
+ async def delete_entries_by_session(self, session_id: str) -> int:
841
+ if not self._enabled:
842
+ msg = "Memory store is disabled"
843
+ raise RuntimeError(msg)
844
+
845
+ sql = f"DELETE FROM {self._memory_table} WHERE session_id = %s"
846
+ async with self._config.provide_connection() as conn:
847
+ cursor = await conn.cursor()
848
+ try:
849
+ await cursor.execute(sql, (session_id,))
850
+ await conn.commit()
851
+ return cursor.rowcount if cursor.rowcount and cursor.rowcount > 0 else 0
852
+ finally:
853
+ await cursor.close()
854
+
855
+ async def delete_entries_older_than(self, days: int) -> int:
856
+ if not self._enabled:
857
+ msg = "Memory store is disabled"
858
+ raise RuntimeError(msg)
859
+
860
+ sql = f"""
861
+ DELETE FROM {self._memory_table}
862
+ WHERE inserted_at < (UTC_TIMESTAMP(6) - INTERVAL %s DAY)
863
+ """
864
+ async with self._config.provide_connection() as conn:
865
+ cursor = await conn.cursor()
866
+ try:
867
+ await cursor.execute(sql, (days,))
868
+ await conn.commit()
869
+ return cursor.rowcount if cursor.rowcount and cursor.rowcount > 0 else 0
870
+ finally:
871
+ await cursor.close()
872
+
873
+
874
+ class MysqlConnectorSyncADKMemoryStore(BaseSyncADKMemoryStore["MysqlConnectorSyncConfig"]):
875
+ """MySQL/MariaDB ADK memory store using mysql-connector sync driver."""
876
+
877
+ __slots__ = ()
878
+
879
+ def __init__(self, config: "MysqlConnectorSyncConfig") -> None:
880
+ super().__init__(config)
881
+
882
+ def _get_create_memory_table_sql(self) -> str:
883
+ owner_id_line = ""
884
+ fk_constraint = ""
885
+ if self._owner_id_column_ddl:
886
+ col_def, fk_def = _parse_owner_id_column_for_mysql(self._owner_id_column_ddl)
887
+ owner_id_line = f",\n {col_def}"
888
+ if fk_def:
889
+ fk_constraint = f",\n {fk_def}"
890
+
891
+ fts_index = ""
892
+ if self._use_fts:
893
+ fts_index = f",\n FULLTEXT INDEX idx_{self._memory_table}_fts (content_text)"
894
+
895
+ return f"""
896
+ CREATE TABLE IF NOT EXISTS {self._memory_table} (
897
+ id VARCHAR(128) PRIMARY KEY,
898
+ session_id VARCHAR(128) NOT NULL,
899
+ app_name VARCHAR(128) NOT NULL,
900
+ user_id VARCHAR(128) NOT NULL,
901
+ event_id VARCHAR(128) NOT NULL UNIQUE,
902
+ author VARCHAR(256){owner_id_line},
903
+ timestamp TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
904
+ content_json JSON NOT NULL,
905
+ content_text TEXT NOT NULL,
906
+ metadata_json JSON,
907
+ inserted_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
908
+ INDEX idx_{self._memory_table}_app_user_time (app_name, user_id, timestamp),
909
+ INDEX idx_{self._memory_table}_session (session_id){fts_index}{fk_constraint}
910
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
911
+ """
912
+
913
+ def _get_drop_memory_table_sql(self) -> "list[str]":
914
+ return [f"DROP TABLE IF EXISTS {self._memory_table}"]
915
+
916
+ def create_tables(self) -> None:
917
+ if not self._enabled:
918
+ return
919
+
920
+ with self._config.provide_session() as driver:
921
+ driver.execute_script(self._get_create_memory_table_sql())
922
+
923
+ def insert_memory_entries(self, entries: "list[MemoryRecord]", owner_id: "object | None" = None) -> int:
924
+ if not self._enabled:
925
+ msg = "Memory store is disabled"
926
+ raise RuntimeError(msg)
927
+
928
+ if not entries:
929
+ return 0
930
+
931
+ inserted_count = 0
932
+ if self._owner_id_column_name:
933
+ sql = f"""
934
+ INSERT IGNORE INTO {self._memory_table} (
935
+ id, session_id, app_name, user_id, event_id, author,
936
+ {self._owner_id_column_name}, timestamp, content_json,
937
+ content_text, metadata_json, inserted_at
938
+ ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
939
+ """
940
+ else:
941
+ sql = f"""
942
+ INSERT IGNORE INTO {self._memory_table} (
943
+ id, session_id, app_name, user_id, event_id, author,
944
+ timestamp, content_json, content_text, metadata_json, inserted_at
945
+ ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
946
+ """
947
+
948
+ with self._config.provide_connection() as conn:
949
+ cursor = conn.cursor()
950
+ try:
951
+ for entry in entries:
952
+ params: tuple[Any, ...]
953
+ if self._owner_id_column_name:
954
+ params = (
955
+ entry["id"],
956
+ entry["session_id"],
957
+ entry["app_name"],
958
+ entry["user_id"],
959
+ entry["event_id"],
960
+ entry["author"],
961
+ owner_id,
962
+ entry["timestamp"],
963
+ to_json(entry["content_json"]),
964
+ entry["content_text"],
965
+ to_json(entry["metadata_json"]),
966
+ entry["inserted_at"],
967
+ )
968
+ else:
969
+ params = (
970
+ entry["id"],
971
+ entry["session_id"],
972
+ entry["app_name"],
973
+ entry["user_id"],
974
+ entry["event_id"],
975
+ entry["author"],
976
+ entry["timestamp"],
977
+ to_json(entry["content_json"]),
978
+ entry["content_text"],
979
+ to_json(entry["metadata_json"]),
980
+ entry["inserted_at"],
981
+ )
982
+ cursor.execute(sql, cast("tuple[Any, ...]", params))
983
+ inserted_count += cursor.rowcount
984
+ finally:
985
+ cursor.close()
986
+ conn.commit()
987
+ return inserted_count
988
+
989
+ def search_entries(
990
+ self, query: str, app_name: str, user_id: str, limit: "int | None" = None
991
+ ) -> "list[MemoryRecord]":
992
+ if not self._enabled:
993
+ msg = "Memory store is disabled"
994
+ raise RuntimeError(msg)
995
+
996
+ if not query:
997
+ return []
998
+
999
+ limit_value = limit or self._max_results
1000
+ if self._use_fts:
1001
+ sql = f"""
1002
+ SELECT * FROM {self._memory_table}
1003
+ WHERE app_name = %s AND user_id = %s
1004
+ AND MATCH(content_text) AGAINST (%s IN NATURAL LANGUAGE MODE)
1005
+ ORDER BY timestamp DESC
1006
+ LIMIT %s
1007
+ """
1008
+ params = (app_name, user_id, query, limit_value)
1009
+ else:
1010
+ sql = f"""
1011
+ SELECT * FROM {self._memory_table}
1012
+ WHERE app_name = %s AND user_id = %s AND content_text LIKE %s
1013
+ ORDER BY timestamp DESC
1014
+ LIMIT %s
1015
+ """
1016
+ params = (app_name, user_id, f"%{query}%", limit_value)
1017
+
1018
+ with self._config.provide_connection() as conn:
1019
+ cursor = conn.cursor()
1020
+ try:
1021
+ cursor.execute(sql, params)
1022
+ rows = cursor.fetchall()
1023
+ columns = [col[0] for col in cursor.description or []]
1024
+ finally:
1025
+ cursor.close()
1026
+
1027
+ return [cast("MemoryRecord", dict(zip(columns, row, strict=False))) for row in rows]
1028
+
1029
+ def delete_entries_by_session(self, session_id: str) -> int:
1030
+ if not self._enabled:
1031
+ msg = "Memory store is disabled"
1032
+ raise RuntimeError(msg)
1033
+
1034
+ sql = f"DELETE FROM {self._memory_table} WHERE session_id = %s"
1035
+ with self._config.provide_connection() as conn:
1036
+ cursor = conn.cursor()
1037
+ try:
1038
+ cursor.execute(sql, (session_id,))
1039
+ conn.commit()
1040
+ return cursor.rowcount if cursor.rowcount and cursor.rowcount > 0 else 0
1041
+ finally:
1042
+ cursor.close()
1043
+
1044
+ def delete_entries_older_than(self, days: int) -> int:
1045
+ if not self._enabled:
1046
+ msg = "Memory store is disabled"
1047
+ raise RuntimeError(msg)
1048
+
1049
+ sql = f"""
1050
+ DELETE FROM {self._memory_table}
1051
+ WHERE inserted_at < (UTC_TIMESTAMP(6) - INTERVAL %s DAY)
1052
+ """
1053
+ with self._config.provide_connection() as conn:
1054
+ cursor = conn.cursor()
1055
+ try:
1056
+ cursor.execute(sql, (days,))
1057
+ conn.commit()
1058
+ return cursor.rowcount if cursor.rowcount and cursor.rowcount > 0 else 0
1059
+ finally:
1060
+ cursor.close()