Fix KeyError when passing an unrecognized string type to create_table or add_column

Passing a valid SQLite type string that is not in COLUMN_TYPE_MAPPING, such as
NUMERIC or ANY, raised KeyError instead of being used as-is. The fix falls back
to the raw string value when the type is a string not present in the mapping,
matching the documented behaviour: col_type accepts Python types or SQLite type
strings.
This commit is contained in:
ikatyal2110 2026-07-27 14:42:17 +00:00
commit 5d812b920f
No known key found for this signature in database
2 changed files with 25 additions and 2 deletions

View file

@ -1480,7 +1480,9 @@ class Database:
column_extras.append( column_extras.append(
f"REFERENCES {quote_identifier(fk.other_table)}({quote_identifier(cast(str, fk.other_column))}){_fk_actions_sql(fk)}" f"REFERENCES {quote_identifier(fk.other_table)}({quote_identifier(cast(str, fk.other_column))}){_fk_actions_sql(fk)}"
) )
column_type_str = COLUMN_TYPE_MAPPING[column_type] column_type_str = COLUMN_TYPE_MAPPING.get(column_type) or (
column_type if isinstance(column_type, str) else COLUMN_TYPE_MAPPING[column_type]
)
# Special case for strict tables to map FLOAT to REAL # Special case for strict tables to map FLOAT to REAL
# Refs https://github.com/simonw/sqlite-utils/issues/644 # Refs https://github.com/simonw/sqlite-utils/issues/644
if strict and column_type_str == "FLOAT": if strict and column_type_str == "FLOAT":
@ -3121,7 +3123,9 @@ class Table(Queryable):
sql = "ALTER TABLE {} ADD COLUMN {} {col_type}{not_null_default};".format( sql = "ALTER TABLE {} ADD COLUMN {} {col_type}{not_null_default};".format(
quote_identifier(self.name), quote_identifier(self.name),
quote_identifier(col_name), quote_identifier(col_name),
col_type=fk_col_type or COLUMN_TYPE_MAPPING[col_type], col_type=fk_col_type or COLUMN_TYPE_MAPPING.get(col_type) or (
col_type if isinstance(col_type, str) else COLUMN_TYPE_MAPPING[col_type]
),
not_null_default=(" " + not_null_sql) if not_null_sql else "", not_null_default=(" " + not_null_sql) if not_null_sql else "",
) )
self.db.execute(sql) self.db.execute(sql)

View file

@ -110,6 +110,13 @@ def test_create_table_with_defaults(fresh_db):
) == table.schema ) == table.schema
def test_create_table_with_unknown_string_type(fresh_db):
table = fresh_db.create_table("t", {"id": int, "value": "NUMERIC"}, pk="id")
assert table.schema == 'CREATE TABLE "t" (\n "id" INTEGER PRIMARY KEY,\n "value" NUMERIC\n)'
table2 = fresh_db.create_table("t2", {"id": int, "misc": "ANY"}, pk="id")
assert table2.schema == 'CREATE TABLE "t2" (\n "id" INTEGER PRIMARY KEY,\n "misc" ANY\n)'
def test_create_table_with_bad_not_null(fresh_db): def test_create_table_with_bad_not_null(fresh_db):
with pytest.raises(ValueError): with pytest.raises(ValueError):
fresh_db.create_table( fresh_db.create_table(
@ -375,6 +382,18 @@ def test_create_error_if_invalid_self_referential_foreign_keys(fresh_db):
'CREATE TABLE "dogs" (\n "name" TEXT\n, "float" FLOAT)', 'CREATE TABLE "dogs" (\n "name" TEXT\n, "float" FLOAT)',
), ),
("blob", "blob", None, 'CREATE TABLE "dogs" (\n "name" TEXT\n, "blob" BLOB)'), ("blob", "blob", None, 'CREATE TABLE "dogs" (\n "name" TEXT\n, "blob" BLOB)'),
(
"score",
"NUMERIC",
None,
'CREATE TABLE "dogs" (\n "name" TEXT\n, "score" NUMERIC)',
),
(
"misc",
"ANY",
None,
'CREATE TABLE "dogs" (\n "name" TEXT\n, "misc" ANY)',
),
( (
"default_str", "default_str",
None, None,