Split Tables Problem

If I save a plain False to a simple object column in a table using Faster Storage, it gets stored as NULL and I get None back the next time I fetch the row.

Here’s an MWE:

clone link

The server code boils down to this, with a settings table that has a name (text) and a value (simple object) column:

from anvil.tables import app_tables

row = app_tables.settings.add_row(name="flag", value=True)
row["value"] = False
print(row["value"])                                   # False
print(app_tables.settings.get(name="flag")["value"])  # None

app_tables.settings.add_row(name="flag2", value=False)
print(app_tables.settings.get(name="flag2")["value"]) # None

I’d expect both of those fresh reads to give False.

The row object I wrote through still shows False. It’s only a fresh get that comes back with None. True, 0 and {"x": False} all round-trip fine, so it seems to be just a bare False.

Here’s the full output from the MWE:

add_row(value=True): expected True, row['value'] -> True (bool), re-read -> True (bool)
row['value'] = False: expected False, row['value'] -> False (bool), re-read -> None (NoneType)  <-- MISMATCH
row['value'] = 0: expected 0, row['value'] -> 0 (int), re-read -> 0 (int)
row['value'] = {'x': False}: expected {'x': False}, row['value'] -> {'x': False} (dict), re-read -> {'x': False} (dict)
add_row(value=False): expected False, row['value'] -> False (bool), re-read -> None (NoneType)  <-- MISMATCH

I get exactly the same on the open source app server (1.18.0 with an external PostgreSQL database) with enable_v2: true and enable_split: true in the tables service config. Looking in the database there, the column holds SQL NULL rather than JSON false. With enable_split: false, or with neither flag set, everything comes back as written.

I have a fix ready to roll if a PR to GitHub - anvil-works/anvil-runtime: The runtime engine for hosting Anvil web apps · GitHub would be of use.