mirror of
https://github.com/simonw/datasette.git
synced 2026-07-08 16:44:34 +02:00
Preserve SQLite defaults in bulk insert
Omit columns that are absent from pasted bulk insert data so SQLite defaults can fire during insert. Keep preview cells blank for omitted values while preserving explicit null rendering. Refs [https://github.com/simonw/datasette/pull/2813#issuecomment-4878063728](https://github.com/simonw/datasette/pull/2813#issuecomment-4878063728)
This commit is contained in:
parent
b759ea5486
commit
4bd9d41c43
2 changed files with 66 additions and 11 deletions
|
|
@ -5586,8 +5586,8 @@ function resetBulkInsertPreview(state) {
|
|||
syncRowEditInsertModeUi(state);
|
||||
}
|
||||
|
||||
function normalizeBulkInsertCell(column, value, isMissing) {
|
||||
if (isMissing || typeof value === "undefined") {
|
||||
function normalizeBulkInsertCell(column, value) {
|
||||
if (typeof value === "undefined") {
|
||||
return column.notnull ? "" : null;
|
||||
}
|
||||
if (value === null) {
|
||||
|
|
@ -5609,11 +5609,10 @@ function rowObjectForBulkInsert(valuesByColumn, columns) {
|
|||
valuesByColumn,
|
||||
column.name,
|
||||
);
|
||||
row[column.name] = normalizeBulkInsertCell(
|
||||
column,
|
||||
hasValue ? valuesByColumn[column.name] : undefined,
|
||||
!hasValue,
|
||||
);
|
||||
if (!hasValue) {
|
||||
return;
|
||||
}
|
||||
row[column.name] = normalizeBulkInsertCell(column, valuesByColumn[column.name]);
|
||||
});
|
||||
return row;
|
||||
}
|
||||
|
|
@ -5869,8 +5868,9 @@ function renderBulkInsertPreview(state, rows) {
|
|||
var tr = document.createElement("tr");
|
||||
state.bulkInsertColumnDetails.forEach(function (column) {
|
||||
var td = document.createElement("td");
|
||||
var value = row[column.name];
|
||||
td.textContent = bulkInsertPreviewValue(value);
|
||||
var hasValue = Object.prototype.hasOwnProperty.call(row, column.name);
|
||||
var value = hasValue ? row[column.name] : "";
|
||||
td.textContent = hasValue ? bulkInsertPreviewValue(value) : "";
|
||||
if (value === null) {
|
||||
td.className = "row-edit-bulk-preview-null";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,12 @@ def write_playwright_database(db_path):
|
|||
id integer primary key,
|
||||
created_ms integer default (CAST((julianday('now') - 2440587.5) * 86400000 AS INTEGER))
|
||||
);
|
||||
create table bulk_defaults (
|
||||
id integer primary key,
|
||||
title text not null,
|
||||
status text not null default 'todo',
|
||||
score integer default 5
|
||||
);
|
||||
insert into projects (title, metadata, logo, notes, score) values
|
||||
(
|
||||
'Build Datasette',
|
||||
|
|
@ -146,6 +152,11 @@ def write_playwright_config(config_path):
|
|||
"alter-table": True,
|
||||
},
|
||||
},
|
||||
"bulk_defaults": {
|
||||
"permissions": {
|
||||
"insert-row": True,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -279,6 +290,16 @@ def project_row(datasette_server, pk):
|
|||
return rows[0]
|
||||
|
||||
|
||||
def bulk_default_rows(datasette_server, **filters):
|
||||
params = {
|
||||
"_shape": "objects",
|
||||
**{key: str(value) for key, value in filters.items()},
|
||||
}
|
||||
response = httpx.get(f"{datasette_server}data/bulk_defaults.json", params=params)
|
||||
response.raise_for_status()
|
||||
return response.json()["rows"]
|
||||
|
||||
|
||||
def open_jump_menu(page):
|
||||
page.keyboard.press("/")
|
||||
page.locator("navigation-search .search-input").wait_for()
|
||||
|
|
@ -1007,7 +1028,8 @@ def test_insert_row_flow_uses_custom_column_field(page, datasette_server):
|
|||
assert "metadata" in preview_text
|
||||
assert "id" not in preview_text
|
||||
assert "From CSV" in preview_text
|
||||
assert "null" in preview_text
|
||||
assert "null" not in preview_text
|
||||
assert "undefined" not in preview_text
|
||||
preview_cell_style = dialog.locator(
|
||||
".row-edit-bulk-preview-table td"
|
||||
).first.evaluate(
|
||||
|
|
@ -1097,6 +1119,38 @@ def test_bulk_insert_preview_inserts_rows(page, datasette_server):
|
|||
assert project_rows(datasette_server, title="Bulk two")
|
||||
|
||||
|
||||
@pytest.mark.playwright
|
||||
def test_bulk_insert_omits_columns_absent_from_pasted_input(page, datasette_server):
|
||||
page.goto(f"{datasette_server}data/bulk_defaults")
|
||||
page.locator('button[data-table-action="insert-row"]').click()
|
||||
|
||||
dialog = page.locator("#row-edit-dialog")
|
||||
dialog.wait_for()
|
||||
dialog.locator(".row-edit-bulk-insert").click()
|
||||
dialog.locator(".row-edit-bulk-textarea").fill("title\nOnly title")
|
||||
dialog.locator(".row-edit-save").click()
|
||||
|
||||
assert dialog.locator(".row-edit-save").inner_text() == "Insert these rows"
|
||||
preview_text = dialog.locator(".row-edit-bulk-preview-table").inner_text()
|
||||
assert "Only title" in preview_text
|
||||
assert "undefined" not in preview_text
|
||||
|
||||
dialog.locator(".row-edit-save").click()
|
||||
dialog.locator(
|
||||
".row-edit-bulk-progress-status", has_text="1 row inserted."
|
||||
).wait_for()
|
||||
|
||||
rows = bulk_default_rows(datasette_server, title="Only title")
|
||||
assert rows == [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Only title",
|
||||
"status": "todo",
|
||||
"score": 5,
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.playwright
|
||||
def test_bulk_insert_preview_accepts_single_column_input(page, datasette_server):
|
||||
page.goto(f"{datasette_server}data/projects")
|
||||
|
|
@ -1116,7 +1170,8 @@ def test_bulk_insert_preview_accepts_single_column_input(page, datasette_server)
|
|||
assert "one" in preview_text
|
||||
assert "two" in preview_text
|
||||
assert "three" in preview_text
|
||||
assert "null" in preview_text
|
||||
assert "null" not in preview_text
|
||||
assert "undefined" not in preview_text
|
||||
|
||||
|
||||
@pytest.mark.playwright
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue