mirror of
https://github.com/simonw/sqlite-utils.git
synced 2026-09-23 02:14:30 +02:00
Fix transform() corrupting ANY columns on STRICT tables to REAL
column_affinity() fell through all type checks for the SQLite-specific ANY column type and returned float, which then mapped to REAL in COLUMN_TYPE_MAPPING. This caused transform() on a STRICT table with ANY columns to either crash with IntegrityError (when existing rows held non-numeric values) or silently change the column type from ANY to REAL. Add ANY as an explicit case in column_affinity() so it passes through as the string "ANY", and register "ANY"/"any" in COLUMN_TYPE_MAPPING so create_table_sql() emits the correct column type. Fixes #790
This commit is contained in:
parent
6a456830ca
commit
7c182f5afa
3 changed files with 26 additions and 0 deletions
|
|
@ -343,6 +343,8 @@ COLUMN_TYPE_MAPPING: dict[Any, str] = {
|
||||||
"real": "REAL",
|
"real": "REAL",
|
||||||
"blob": "BLOB",
|
"blob": "BLOB",
|
||||||
"bytes": "BLOB",
|
"bytes": "BLOB",
|
||||||
|
"ANY": "ANY",
|
||||||
|
"any": "ANY",
|
||||||
}
|
}
|
||||||
# If numpy is available, add more types
|
# If numpy is available, add more types
|
||||||
if np:
|
if np:
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,8 @@ def column_affinity(column_type: str) -> type:
|
||||||
return bytes
|
return bytes
|
||||||
if "REAL" in column_type or "FLOA" in column_type or "DOUB" in column_type:
|
if "REAL" in column_type or "FLOA" in column_type or "DOUB" in column_type:
|
||||||
return float
|
return float
|
||||||
|
if column_type == "ANY":
|
||||||
|
return "ANY" # type: ignore[return-value]
|
||||||
# Default is 'NUMERIC', which we currently also treat as float
|
# Default is 'NUMERIC', which we currently also treat as float
|
||||||
return float
|
return float
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -785,6 +785,28 @@ def test_transform_to_strict_not_supported(fresh_db, method_name):
|
||||||
assert table.strict is False
|
assert table.strict is False
|
||||||
|
|
||||||
|
|
||||||
|
def test_transform_preserves_any_column_in_strict_table(fresh_db):
|
||||||
|
if not fresh_db.supports_strict:
|
||||||
|
pytest.skip("SQLite version does not support strict tables")
|
||||||
|
fresh_db.conn.execute(
|
||||||
|
"create table things (id integer primary key, data any) strict"
|
||||||
|
)
|
||||||
|
fresh_db.conn.execute("insert into things values (1, 42)")
|
||||||
|
fresh_db.conn.execute("insert into things values (2, 'text')")
|
||||||
|
fresh_db.conn.execute("insert into things values (3, 3.14)")
|
||||||
|
table = fresh_db["things"]
|
||||||
|
|
||||||
|
# transform() must preserve ANY columns without crashing or changing the type
|
||||||
|
table.transform()
|
||||||
|
assert table.strict is True
|
||||||
|
assert table.columns_dict == {"id": int, "data": "ANY"}
|
||||||
|
assert list(table.rows) == [
|
||||||
|
{"id": 1, "data": 42},
|
||||||
|
{"id": 2, "data": "text"},
|
||||||
|
{"id": 3, "data": 3.14},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"indexes, transform_params",
|
"indexes, transform_params",
|
||||||
[
|
[
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue