Changes for version 0.003.1 - 2026-08-26

  • Enhancements
    • Allow files to be removed from the recently opened and recently saved lists
  • Bug Fixes
    • Drag-and-dropped files now appear in "Recently opened" under their original filesystem location, not the temporary .uploads/ copy. The drop handler now extracts the file:// URI from the DataTransfer text/uri-list item (provided by desktop file managers such as Nautilus and Finder) and stashes it in sessionStorage before starting the upload. The dashboard page then reads that stash and records the real path. If no file:// URI is available (browser drag, email attachment, etc.), the entry is omitted entirely so a useless temp path never
    • Dragging and dropping the same file more than once no longer creates duplicate entries in the "Recently opened" section on the home page. Each upload creates a new random .uploads/<tempdir>/ subdirectory, so the href changed on every drop even for the same file, bypassing the existing href-based deduplication. The dedup key is now normalised: upload entries are keyed by display name ("upload:<filename>"); all other entries (browser-opened files, URL imports) continue to be keyed by their full href so that two different files with the same name from different directories can both appear in the list.
    • Opening a file whose name has a mixed-case stem (e.g. AccountHistory.csv) now works correctly on case-sensitive Linux filesystems. The controller was lowercasing the stem before calling open_table, causing DataSource to look for "accounthistory.csv" which does not exist. The stem is now passed verbatim from the filesystem path; URL-sourced names (from /view/:table and table: join specs) are still normalised to lowercase as before because data/ files are lowercase by convention.
    • CSV files whose first column header is not a valid SQL identifier (e.g. "Account Number" from a bank export) now open without error. DataSource::_detect_file_info previously passed the first column name directly to Database::Abstraction as the id parameter; D::A validates id against $SAFE_IDENTIFIER and croaked "unsafe id column name". _detect_file_info now scans the header and picks the first column name that IS a safe identifier.
    • CSV files where the first safe-identifier column is always empty (e.g. "Check" in a US bank statement) now show all rows. Database::Abstraction uses empty_is_undef => 1, so an empty Check cell becomes undef and the row-existence sentinel grep discards every row where Check is blank. _detect_file_info now reads the first data row and skips safe-identifier columns whose value there is empty, landing on a reliably populated column (e.g. "Description") as the id.
    • If no column header in a CSV satisfies the safe-identifier constraint, DataSource now croaks error_no_safe_id with a clear message asking the user to rename at least one column, rather than silently returning 0 rows.
  • Test Improvements
    • Added targeted tests in t/function.t, t/path.t, and t/domain.t that would have caught all three bugs above before they reached production: unit-level _detect_file_info subtests for each id-selection scenario, new CFG paths G-J in path.t, and end-to-end HTTP domain subtests that assert all rows are visible for mixed-case stems, spaced column headers, and empty sentinel columns.

Documentation

Modules

Web-based Business Intelligence viewer for flat data files
Home picker, filesystem browser, table viewer, left-join engine, result filter, export, and file upload
Table-agnostic adapter around Database::Abstraction