diff --git a/apps/desktop/src/lib/__tests__/dataGrid/dataGridCellCoercion.spec.ts b/apps/desktop/src/lib/__tests__/dataGrid/dataGridCellCoercion.spec.ts index 85485aa86..088ebf1bd 100644 --- a/apps/desktop/src/lib/__tests__/dataGrid/dataGridCellCoercion.spec.ts +++ b/apps/desktop/src/lib/__tests__/dataGrid/dataGridCellCoercion.spec.ts @@ -34,6 +34,26 @@ describe("dataGridCellDisplayText", () => { }); describe("coerceDataGridCellValue", () => { + it.each(["null", "NULL", "Null", "nUlL"])("preserves literal %s input as text", (value) => { + expect( + coerceDataGridCellValue({ + value, + oldValue: null, + databaseType: "mysql", + columnInfo: { data_type: "varchar(255)" }, + }), + ).toBe(value); + + expect( + coerceDataGridCellValue({ + value, + oldValue: "previous", + databaseType: "postgres", + columnInfo: { data_type: "text" }, + }), + ).toBe(value); + }); + it("preserves an explicitly generated empty string for a null cell", () => { const options = { value: "", diff --git a/apps/desktop/src/lib/dataGrid/dataGridCellCoercion.ts b/apps/desktop/src/lib/dataGrid/dataGridCellCoercion.ts index d60d95b71..b9c946887 100644 --- a/apps/desktop/src/lib/dataGrid/dataGridCellCoercion.ts +++ b/apps/desktop/src/lib/dataGrid/dataGridCellCoercion.ts @@ -11,7 +11,6 @@ export interface CoerceDataGridCellValueOptions { export function coerceDataGridCellValue(options: CoerceDataGridCellValueOptions): GridCellValue { const { value, oldValue } = options; - if (value.toUpperCase() === "NULL") return null; if (value === "" && oldValue === null && !options.preserveEmptyString) return null; const postgresArrayValue = coercePostgresArrayValue(options); if (postgresArrayValue !== undefined) return postgresArrayValue; diff --git a/packages/app-tests/dataGridEditor.test.ts b/packages/app-tests/dataGridEditor.test.ts index aab888fa6..12c462c97 100644 --- a/packages/app-tests/dataGridEditor.test.ts +++ b/packages/app-tests/dataGridEditor.test.ts @@ -618,6 +618,23 @@ test("undo and redo restore pending cell edits before save", () => { assert.deepEqual(editor.rowDataWithChanges(result.value.rows[0], 0), [1, "Ada Lovelace"]); }); +test("typing NULL preserves the literal string value", async () => { + setActivePinia(createPinia()); + installBrowserTestGlobals(); + + const result = computed(() => ({ + columns: ["id", "name"], + rows: [[1, "Ada"] as CellValue[]], + })); + const editor = createPeopleGridEditor(result); + + editor.applyCellValue(0, 1, "NULL"); + + assert.equal(editor.dirtyRows.value.get(0)?.get(1), "NULL"); + assert.deepEqual(editor.rowDataWithChanges(result.value.rows[0], 0), [1, "NULL"]); + assert.deepEqual(await editor.previewChanges(), [`UPDATE "people" SET "name" = 'NULL' WHERE "id" = 1;`]); +}); + test("setting a cell to NULL records pending SQL and supports undo and redo", async () => { setActivePinia(createPinia()); installBrowserTestGlobals();