Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions src/google/adk/sessions/sqlite_session_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,19 @@
# json_group_object writes a REAL with 15 significant digits, which rounds
# floats such as 0.1 + 0.2 for every key in the row. A REAL is written with 17
# digits when 15 do not read back as the same value, so floats round-trip.
#
# An integer outside the signed 64-bit range also comes out of json_each as a
# REAL (its type column still says 'integer'), so we can't rebuild it from
# value. The -> operator gives back the original JSON text of the element
# instead, which keeps those integers exact.
_MERGE_STATE_SQL = """
SELECT json_group_object(
key,
CASE
WHEN type IN ('object','array') THEN json(value)
WHEN type IN ('true','false') THEN json(type)
WHEN type = 'integer' AND typeof(value) = 'real'
THEN json(raw)
WHEN type = 'real' THEN json(
CASE
WHEN CAST(printf('%!.15g', value) AS REAL) = value
Expand All @@ -71,9 +78,11 @@
ELSE value
END)
FROM (
SELECT key, value, type FROM json_each({delta})
SELECT key, value, type, {delta} -> fullkey AS raw
FROM json_each({delta})
UNION ALL
SELECT key, value, type FROM json_each({state})
SELECT key, value, type, {state} -> fullkey AS raw
FROM json_each({state})
WHERE key NOT IN (SELECT key FROM json_each({delta}))
)
"""
Expand Down Expand Up @@ -675,10 +684,10 @@ async def _update_session_state_in_db(
delta_json = json.dumps(delta)
await db.execute(
"UPDATE sessions SET"
f" state=({_MERGE_STATE_SQL.format(delta='?', state='state')}),"
" update_time=? WHERE app_name=? AND user_id=? AND id=?",
# The delta is used several times in the merge, so bind it by number.
f" state=({_MERGE_STATE_SQL.format(delta='?1', state='state')}),"
" update_time=?2 WHERE app_name=?3 AND user_id=?4 AND id=?5",
(
delta_json,
delta_json,
now,
app_name,
Expand Down
4 changes: 3 additions & 1 deletion tests/unittests/sessions/test_session_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -1272,10 +1272,12 @@ async def test_user_state_none_valued_delta_is_stored_not_dropped(
assert session1.state.get('user:pref') is None


# Floats that need more than 15 significant digits to read back unchanged.
# Floats that need more than 15 significant digits to read back unchanged, plus
# an unsigned 64-bit hash that does not fit in a signed 64-bit integer.
_EXACT_NUMBERS = {
'ratio': 0.1 + 0.2,
'epoch_seconds': 1727500000.1234567,
'fingerprint': 0xFEDCBA9876543210,
}


Expand Down
Loading