insert/upsert --csv no longer rewrites column types of existing tables

Type detection is the 4.0 default for CSV/TSV data, and the detected-type
transform ran even when the target table already existed - inserting a
CSV into a table with a TEXT zip column converted the column to INTEGER,
corrupting values with leading zeros ('01234' became 1234) with no
warning. Detected types now only apply to tables the command created.

Refs https://github.com/simonw/sqlite-utils/issues/769#issuecomment-4900034150

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Simon Willison 2026-07-06 21:44:56 -07:00
commit 884574685f
4 changed files with 62 additions and 1 deletions

View file

@ -1165,6 +1165,9 @@ def insert_upsert_implementation(
db.conn.cursor().executemany(bulk_sql, doc_chunk)
return
# table_names() rather than db.table(), which raises NoTable for
# views before the error handling below can deal with them
table_existed_before_insert = table in db.table_names()
try:
db.table(table).insert_all(
docs, pk=pk, batch_size=batch_size, alter=alter, **extra_kwargs
@ -1194,7 +1197,14 @@ def insert_upsert_implementation(
)
else:
raise
if tracker is not None and db.table(table).exists():
# Apply detected types only to a table this command created -
# transforming a pre-existing table would rewrite its column types
# and corrupt values such as TEXT zip codes with leading zeros
if (
tracker is not None
and not table_existed_before_insert
and db.table(table).exists()
):
db.table(table).transform(types=tracker.types)
# Clean up open file-like objects