fix(sql-browser): rank the row-selector candidate so a date-only column is a last resort (Driver.Sql.Browser-001)
PreferredTimestampColumn nominated the first column mapping to DriverDataType .DateTime, and that set includes date-only types (SQL Server / PostgreSQL 'date'). A table whose first date/time column is a 'date' committed rowSelector.topByTimestamp = <date>, making the wide-row read ORDER BY <date> DESC LIMIT 1 - which ties for every row written that day, so 'the newest row' became storage order among the ties. Time-bearing candidates now outrank date-only ones; a date-only column is still stated when it is all the table has, so such a table stays bindable. Oracle's DATE carries a time of day and is exempt - pinned by a control dialect that differs from the SQLite one only in the Provider it reports.
This commit is contained in:
+12
-3
@@ -190,14 +190,23 @@ commit writes as `rowSelector.topByTimestamp` ("read the newest row"). Before th
|
||||
a selector-less blob that `SqlEquipmentTagParser` and the authoring gate both refuse, so no
|
||||
browse-committed Sql tag was ever readable.
|
||||
|
||||
Two properties of the choice are deliberate:
|
||||
Three properties of the choice are deliberate:
|
||||
|
||||
- **Candidacy is by declared TYPE, never by column name.** The session asks
|
||||
`ISqlDialect.MapColumnType` for `DriverDataType.DateTime` — the same metadata the browse tree already
|
||||
renders per column. A name heuristic (`*_ts`, `*time*`) would happily order a wide-row read by a
|
||||
*string* column called `timestamp`, binding the tag to whichever row sorts last lexically.
|
||||
- **The tie-break is first in catalog order** (every dialect's column query orders by ordinal
|
||||
position), so the pick is stable across calls, connections and servers. On a
|
||||
- **Candidates are RANKED: a time-bearing type beats a date-only one.** `MapColumnType` reports
|
||||
`DriverDataType.DateTime` for SQL Server's and PostgreSQL's `date` too, and ordering a single-row read
|
||||
by a date-only column ties for *every row written on the same day* — "the newest row" quietly becomes
|
||||
storage order among the ties, and the reader cannot warn about it because the server has already
|
||||
discarded the others. So a `datetime2`/`timestamptz`/… column wins over a `date` one wherever both
|
||||
exist, regardless of declaration order. A date-only column is still stated when it is **all** the table
|
||||
has, so such a table stays bindable by browse rather than becoming un-committable.
|
||||
**Oracle's `DATE` is exempt** — it carries a time-of-day component (which is why `OracleDialect` maps
|
||||
it faithfully rather than as a widening), so it is not demoted there.
|
||||
- **The tie-break within a rank is first in catalog order** (every dialect's column query orders by
|
||||
ordinal position), so the pick is stable across calls, connections and servers. On a
|
||||
`CreatedUtc`/`ModifiedUtc` pair it takes the earlier-declared one. It is a **visible, editable
|
||||
default**: the typed editor shows the selector and the operator can change it — to the other
|
||||
timestamp, or to a `whereColumn`/`whereValue` pair entirely.
|
||||
|
||||
Reference in New Issue
Block a user