Open
Description
I found a bug where calls to upsert()
and upsert_all()
don't write rows if:
- There's a
not_null
kwarg on the table definition, and - You don't pass
not_null
in theupsert()
call
This doesn't affect insert()
or insert_all()
.
Repro example
from sqlite_utils import Database
db = Database(":memory:")
db["birds"].create(
{"id": int, "name": str},
pk="id",
not_null={"name"},
)
db["birds"].insert({"id": 1, "name": "flamingo"})
print("insert: ", len(list(db["birds"].rows)))
db["birds"].insert({"id": 2, "name": "goldfinch"}, not_null={"name"})
print("insert, not_null: ", len(list(db["birds"].rows)))
db["birds"].upsert({"id": 3, "name": "loon"}, pk="id")
print("upsert: ", len(list(db["birds"].rows)))
db["birds"].upsert({"id": 4, "name": "stork"}, pk="id", not_null={"name"})
print("upsert, not_null: ", len(list(db["birds"].rows)))
db["birds"].insert_all([{"id": 5, "name": "magpie"}])
print("insert_all: ", len(list(db["birds"].rows)))
db["birds"].insert_all([{"id": 6, "name": "gull"}], not_null={"name"})
print("insert_all, not_null: ", len(list(db["birds"].rows)))
db["birds"].upsert_all([{"id": 7, "name": "dodo"}], pk="id")
print("upsert_all: ", len(list(db["birds"].rows)))
db["birds"].upsert_all([{"id": 8, "name": "crow"}], pk="id", not_null={"name"})
print("upsert_all, not_null: ", len(list(db["birds"].rows)))
Here's the output (with my comments on the right)
sqlite-utils, version 3.36
insert: 1
insert, not_null: 2
upsert: 2 <-- no write
upsert, not_null: 3
insert_all: 4
insert_all, not_null: 5
upsert_all: 5 <-- no write
upsert_all, not_null: 6
So calling upsert()
and upsert_all()
without passing not_null
isn't actually inserting a record.
This problem goes away if:
- I add the
not_null
argument to theupsert()
calls, or - Remove the
not_null
from the table definition
Version info
- Python:
3.12.0
- sqlite-utils:
3.36
- sqlite:
3.39.5 2022-10-14
Related issues
It seems very likely that this is related to #538, which was also about upsert()
and the not_null
flag.
Metadata
Metadata
Assignees
Labels
No labels