|
21 | 21 | {"types": {"age": int}}, |
22 | 22 | [ |
23 | 23 | 'CREATE TABLE "dogs_new_suffix" (\n "id" INTEGER PRIMARY KEY,\n "name" TEXT,\n "age" INTEGER\n);', |
24 | | - 'INSERT INTO "dogs_new_suffix" ("rowid", "id", "name", "age")\n SELECT "rowid", "id", "name", "age" FROM "dogs";', |
| 24 | + 'INSERT INTO "dogs_new_suffix" ("rowid", "id", "name", "age")\n SELECT "rowid", "id", "name", NULLIF("age", \'\') FROM "dogs";', |
25 | 25 | 'DROP TABLE "dogs";', |
26 | 26 | 'ALTER TABLE "dogs_new_suffix" RENAME TO "dogs";', |
27 | 27 | ], |
|
51 | 51 | {"types": {"age": int}, "rename": {"age": "dog_age"}}, |
52 | 52 | [ |
53 | 53 | 'CREATE TABLE "dogs_new_suffix" (\n "id" INTEGER PRIMARY KEY,\n "name" TEXT,\n "dog_age" INTEGER\n);', |
54 | | - 'INSERT INTO "dogs_new_suffix" ("rowid", "id", "name", "dog_age")\n SELECT "rowid", "id", "name", "age" FROM "dogs";', |
| 54 | + 'INSERT INTO "dogs_new_suffix" ("rowid", "id", "name", "dog_age")\n SELECT "rowid", "id", "name", NULLIF("age", \'\') FROM "dogs";', |
55 | 55 | 'DROP TABLE "dogs";', |
56 | 56 | 'ALTER TABLE "dogs_new_suffix" RENAME TO "dogs";', |
57 | 57 | ], |
@@ -144,7 +144,7 @@ def tracer(sql, params): |
144 | 144 | {"types": {"age": int}}, |
145 | 145 | [ |
146 | 146 | 'CREATE TABLE "dogs_new_suffix" (\n "id" INTEGER,\n "name" TEXT,\n "age" INTEGER\n);', |
147 | | - 'INSERT INTO "dogs_new_suffix" ("rowid", "id", "name", "age")\n SELECT "rowid", "id", "name", "age" FROM "dogs";', |
| 147 | + 'INSERT INTO "dogs_new_suffix" ("rowid", "id", "name", "age")\n SELECT "rowid", "id", "name", NULLIF("age", \'\') FROM "dogs";', |
148 | 148 | 'DROP TABLE "dogs";', |
149 | 149 | 'ALTER TABLE "dogs_new_suffix" RENAME TO "dogs";', |
150 | 150 | ], |
@@ -659,3 +659,32 @@ def test_transform_with_unique_constraint_implicit_index(fresh_db): |
659 | 659 | "You must manually drop this index prior to running this transformation and manually recreate the new index after running this transformation." |
660 | 660 | in str(excinfo.value) |
661 | 661 | ) |
| 662 | + |
| 663 | + |
| 664 | +def test_transform_empty_string_to_null_for_numeric_types(fresh_db): |
| 665 | + # Issue #488: converting a text column to integer/float should turn |
| 666 | + # empty-string values into NULLs instead of leaving them as ''. |
| 667 | + rows = fresh_db["rows"] |
| 668 | + rows.insert_all( |
| 669 | + [ |
| 670 | + {"id": 1, "weight": "12.5", "count": "3"}, |
| 671 | + {"id": 2, "weight": "", "count": ""}, |
| 672 | + {"id": 3, "weight": "0", "count": "0"}, |
| 673 | + ], |
| 674 | + pk="id", |
| 675 | + ) |
| 676 | + rows.transform(types={"weight": float, "count": int}) |
| 677 | + assert rows.columns_dict == {"id": int, "weight": float, "count": int} |
| 678 | + assert list(rows.rows) == [ |
| 679 | + {"id": 1, "weight": 12.5, "count": 3}, |
| 680 | + {"id": 2, "weight": None, "count": None}, |
| 681 | + {"id": 3, "weight": 0.0, "count": 0}, |
| 682 | + ] |
| 683 | + |
| 684 | + |
| 685 | +def test_transform_does_not_nullify_text_columns(fresh_db): |
| 686 | + # Empty strings in text columns must be preserved (issue #488). |
| 687 | + rows = fresh_db["rows"] |
| 688 | + rows.insert_all([{"id": 1, "name": ""}, {"id": 2, "name": "x"}], pk="id") |
| 689 | + rows.transform(types={"name": str}) |
| 690 | + assert list(rows.rows) == [{"id": 1, "name": ""}, {"id": 2, "name": "x"}] |
0 commit comments