Add wiring_list_view: from-to wiring list over the conductor tables

Slice 3 of discussion #503, on top of slice 2 (#628). One row per
conductor, each endpoint resolved to its element label and terminal
name -- the `F1:4 -> M200:U1` shape from the original prototype.

The view deviates from the SQL sketched in the discussion in two ways,
both because the sketched version silently loses wires:

- **No join to the `element` table.** A terminal row already carries its
  `element_uuid`, so joining `element` back just to read the same uuid
  adds nothing. Worse, it filters: `populateElementTable()` only inserts
  elements matching `Simple|Terminal|Master|Thumbnail`, so `Slave`
  elements (relay contacts and the like -- extremely common at the end
  of a wire) and report elements are simply absent from that table after
  a project load, and an inner join through it drops their conductors.
- **`element_info` is LEFT joined** for the same reason. A wire whose
  endpoint element has no info row still belongs in a wiring list; it
  comes back with an empty label rather than vanishing. Losing a wire
  from a wiring list is a worse failure than showing one with a blank
  end.

Note this only bites after a save/reload. The incremental `addElement()`
path does not apply the type filter, so a slave element placed live is
present in `element`/`element_info` and an inner join looks fine -- it
is the bulk repopulate on project load that drops it. Testing only the
live-editing path would have missed this entirely.

Measured, comparing this view against an inner-join-through-element
variant built from the same tables in the same session:

| project | conductors | wiring_list_view | inner-join variant |
|---|---|---|---|
| Polonez MR'89 wiring diagram | 280 | 280 | 280 |
| two slave contacts, after save+reload | 1 | **1** | **0** |

Polonez happens to have no slave elements at conductor ends, so both
agree there and the problem is invisible. The second case is the
minimal reproduction: place two "Simple contact" elements
(`link_type="slave"`) so autoconnect wires them, save, reload -- the
sketched view returns zero rows for a project that plainly has a wire
in it.

Acceptance criterion held throughout: `wiring_list_view` row count
equals `conductor` row count, i.e. the view itself drops nothing.
Conductors already excluded upstream (legacy terminals without uuids,
see #628) stay excluded; that remains the only thing missing from the
list, and is what slice 4 should surface a count for.
This commit is contained in:
ispyisail
2026-08-02 12:43:21 +12:00
parent ab159404a3
commit 6061c63809
2 changed files with 52 additions and 0 deletions
+51
View File
@@ -505,6 +505,7 @@ bool projectDataBase::createDataBase()
createElementNomenclatureView();
createSummaryView();
createWiringListView();
prepareQuery();
updateDB();
return true;
@@ -622,6 +623,56 @@ void projectDataBase::createSummaryView()
}
}
/**
@brief projectDataBase::createWiringListView
A from-to wiring list: one row per conductor, each endpoint resolved to
its element label and terminal name.
Two deliberate differences from an ordinary inner-join view like
element_nomenclature_view:
- No join to the element table. A terminal row already carries its
element_uuid, so joining element back just to read the same uuid adds
nothing -- and would actively drop rows, because populateElementTable()
only inserts elements matching Simple|Terminal|Master|Thumbnail. Slave
elements (relay contacts and the like, extremely common at the end of a
wire) and report elements are absent from that table after a project
load, so an inner join through it silently loses their conductors.
- element_info is LEFT joined for the same reason. A wire whose endpoint
element carries no info row still belongs in a wiring list; it comes
back with an empty label rather than vanishing. Losing a wire from a
wiring list is a worse failure than showing one with a blank end.
The result is that this view returns exactly as many rows as the
conductor table holds -- what is already excluded upstream (conductors
on legacy terminals without uuids) stays excluded, and nothing new is
dropped here.
*/
void projectDataBase::createWiringListView()
{
QString create_view ("CREATE VIEW wiring_list_view AS SELECT "
"c.uuid AS conductor_uuid,"
"c.text AS wire_number,"
"t1.element_uuid AS from_element_uuid,"
"ei1.label AS from_element_label,"
"t1.name AS from_terminal,"
"t2.element_uuid AS to_element_uuid,"
"ei2.label AS to_element_label,"
"t2.name AS to_terminal,"
"d.pos AS diagram_position"
" FROM conductor c"
" JOIN terminal t1 ON c.terminal1_uuid = t1.uuid AND c.terminal1_element_uuid = t1.element_uuid"
" JOIN terminal t2 ON c.terminal2_uuid = t2.uuid AND c.terminal2_element_uuid = t2.element_uuid"
" LEFT JOIN element_info ei1 ON t1.element_uuid = ei1.element_uuid"
" LEFT JOIN element_info ei2 ON t2.element_uuid = ei2.element_uuid"
" JOIN diagram d ON c.diagram_uuid = d.uuid");
QSqlQuery query(m_data_base);
if (!query.exec(create_view)) {
qDebug() << query.lastError();
}
}
void projectDataBase::populateDiagramTable()
{
QSqlQuery query_(m_data_base);