Comments (3)
I don't know if this is a clue, but while testing this I noticed that insert()
seems to be completely ignoring the not_null
parameter if it doesn't have to create the table, whereas upsert()
doesn't. Here's another 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"}, not_null={"wingspan"})
print("insert complete!")
db["birds"].upsert({"id": 2, "name": "goldfinch"}, pk="id", not_null={"wingspan"})
print("upsert complete!")
In this case the insert()
completes, but the upsert()
fails with sqlite3.OperationalError: table birds has no column named wingspan
.
The only way to make the insert()
fail is to let it auto-create the table:
from sqlite_utils import Database
db = Database(":memory:")
db["birds"].insert({"id": 1, "name": "flamingo"}, not_null={"wingspan"})
print("insert complete!")
db["birds"].upsert({"id": 2, "name": "goldfinch"}, pk="id", not_null={"wingspan"})
print("upsert complete!")
at which point I get an error AssertionError: not_null set {'wingspan'} includes items not in columns {'id', 'name'}
.
from sqlite-utils.
A further, potentially interesting observation: this only seems to apply when you're inserting new rows. If your upsert is modifying an existing row, it works without supplying the not_null
list.
Another example:
from sqlite_utils import Database
db = Database(":memory:")
db["birds"].create(
{"id": int, "name": str, "color": str},
pk="id",
not_null={"name"},
)
db["birds"].insert({"id": 1, "name": "flamingo"})
print(next(db["birds"].rows))
# initial insert
# {'id': 1, 'name': 'flamingo', 'color': None}
db["birds"].upsert({"id": 1, "name": "goldfinch"}, pk="id")
print(next(db["birds"].rows))
# modifying the existing row
# {'id': 1, 'name': 'goldfinch', 'color': None}
db["birds"].upsert({"id": 1, "color": "blue"}, pk="id")
print(next(db["birds"].rows))
# modifying a column which is allowed to be non-null
# {'id': 1, 'name': 'goldfinch', 'color': 'blue'}
(That second case is how I spotted it – I was upserting into a table with not-null columns, but modifying a nullable column on an existing row.)
from sqlite-utils.
i can confirm all of the above.
upserts do not work on tables where there are not-null columns, but only the inserts do not work - updates work fine.
i am not sure if there would be a better fix, but one possible fix would be to query sqlite_master
if not_null
is DEFAULT
, and if the table already exists, use its own reckoning of which columns are not_null
. I am going to implement this fix in our fork.
One other thing worth noting - the documentation asserts that the pk
argument is not necessary for upserts if you are certain that the table has already been created. However, that is not the case - upsert will raise an exception if you do not provide pk
. My proposed fix of using sqlite_master
to get the actual 'values' for not_null
would also work as a way of filling in pk
for existing tables, to match the documentation.
from sqlite-utils.
Related Issues (20)
- Move plugin directory into documentation
- `sqlite-utils transform` removes the `AUTOINCREMENT` keyword
- Pyhton 3.12 Bug report HOT 2
- Insert fails with `Error: Python int too large to convert to SQLite INTEGER`; can we use `NUMERIC` here? HOT 1
- str and int as aliases for text and integer HOT 2
- pyright and mypy showing access error messages for basic sqlite-utils usage
- Attached database tables representable by `Table`
- `.transform()` effect on triggers and indices
- Automatic JSON de-serialization
- Windows: Correct way to initialize spatialite?
- sqlite-utils command fails when used with xargs HOT 2
- Drop support for Python 3.7 HOT 1
- create-table command does not handle compound primary keys HOT 2
- insert-files accept multiple --pk HOT 1
- Command to generate a visual schema diagram?
- Query with duplicate output column names drop/overwrites duplicate colums
- Doublebyte content is unicode-escaped in JSON output
- Allow an index to be dropped
- Allow mytable.create_index() to ignore an already existing index
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from sqlite-utils.