diff --git a/sources/qetgraphicsitem/element.cpp b/sources/qetgraphicsitem/element.cpp index 125c069a0..565688059 100644 --- a/sources/qetgraphicsitem/element.cpp +++ b/sources/qetgraphicsitem/element.cpp @@ -2568,21 +2568,20 @@ void Element::setUpFormula(bool code_letter, QUndoCommand *parent_undo) if (diagram()) { - QString formula = diagram() - ->project() - ->elementAutoNumCurrentFormula(); + QETProject *autonum_project = diagram()->project(); + QString element_currentAutoNum = autonum_project->elementCurrentAutoNum(); + //One query for the scheme's rows, read once and reused below -- + //elementAutoNumCurrentFormula()+elementAutoNum() each re-fetched + //the same rows separately (2b-3: every numbering read is now a + //database query, so a second fetch is a second round trip). + NumerotationContext nc = autonum_project->elementAutoNum(element_currentAutoNum); + QString formula = autonum::numerotationContextToFormula(nc); m_data.m_informations.addValue(QStringLiteral("formula"), formula); storeInformation(); - QString element_currentAutoNum = diagram() - ->project() - ->elementCurrentAutoNum(); - const QUuid scheme_id = diagram()->project()->elementAutoNumId(element_currentAutoNum); + const QUuid scheme_id = autonum_project->elementAutoNumId(element_currentAutoNum); setFormulaSchemeId(formula.isEmpty() ? QUuid() : scheme_id); - NumerotationContext nc = diagram() - ->project() - ->elementAutoNum(element_currentAutoNum); //The number given is the first whose label no other element of //the project carries: a counter set back, or an element which diff --git a/sources/qetproject.cpp b/sources/qetproject.cpp index 91ce3d1e5..c8dd66df0 100644 --- a/sources/qetproject.cpp +++ b/sources/qetproject.cpp @@ -1886,13 +1886,16 @@ void QETProject::linkElementsToElementAutoNums() void QETProject::linkElementsToElementAutoNums(Diagram *folio) { const QHash titles_by_formula = elementAutoNumTitlesByFormula(); + QHash title_cache; + QHash id_cache; { const auto items = folio->items(); for (QGraphicsItem *it : items) { auto *el = qgraphicsitem_cast(it); if (!el) continue; if (const auto id = elementAutoNumIdToLink(el->elementInformations(), - titles_by_formula)) { + titles_by_formula, + &title_cache, &id_cache)) { el->setFormulaSchemeId(*id); } } @@ -1922,7 +1925,9 @@ QHash QETProject::elementAutoNumTitlesByFormula() const */ std::optional QETProject::elementAutoNumIdToLink( const DiagramContext &information, - const QHash &titles_by_formula) const + const QHash &titles_by_formula, + QHash *title_cache, + QHash *id_cache) const { const QString formula = information.value(QETInformation::ELMT_FORMULA).toString(); const bool has_id = information.contains(QETInformation::ELMT_FORMULA_ID); @@ -1932,14 +1937,36 @@ std::optional QETProject::elementAutoNumIdToLink( if (has_id) return QUuid(); return std::nullopt; } - if (!elementAutoNumTitle(id).isEmpty()) { + //Every symbol following the same scheme repeats the same id/title + //lookup; a project database query per symbol is the ASan-visible + //cost (F134-adjacent, 2b-3), so a caller walking many symbols may + //pass caches that live only for that one walk -- never persisted. + QString title; + if (title_cache && title_cache->contains(id)) { + title = title_cache->value(id); + } else { + title = elementAutoNumTitle(id); + if (title_cache) title_cache->insert(id, title); + } + if (!title.isEmpty()) { return std::nullopt; } if (!has_id && !m_legacy_element_autonums) { return std::nullopt; //A formula typed by hand } const QStringList matches = titles_by_formula.value(formula); - return matches.size() == 1 ? elementAutoNumId(matches.first()) : QUuid(); + if (matches.size() != 1) { + return QUuid(); + } + const QString &match = matches.first(); + if (id_cache) { + auto it = id_cache->find(match); + if (it == id_cache->end()) { + it = id_cache->insert(match, elementAutoNumId(match)); + } + return it.value(); + } + return elementAutoNumId(match); } /** @@ -1986,13 +2013,18 @@ QList QETProject::symbolNumbering() const for (Diagram *d : m_diagrams_list) if (!d->isLoaded()) unbuilt_in_order << d->uuid(); const QHash titles_by_formula = elementAutoNumTitlesByFormula(); + //Every symbol on an unbuilt folio following the same scheme repeats + //the same title/id lookup; cache both directions for this one walk + //(never persisted -- a scheme rename between calls must see it). + QHash title_cache; + QHash id_cache; for (const projectDataBase::FolioSymbol &row : m_data_base.symbolsOnFolios(unbuilt_in_order)) { const DiagramContext info = m_data_base.elementInformation(row.uuid); SymbolNumbering symbol; symbol.label = info.value(QETInformation::ELMT_LABEL).toString(); symbol.formula = info.value(QETInformation::ELMT_FORMULA).toString(); - const auto linked = elementAutoNumIdToLink(info, titles_by_formula); + const auto linked = elementAutoNumIdToLink(info, titles_by_formula, &title_cache, &id_cache); symbol.scheme = linked ? *linked : QUuid(info.value(QETInformation::ELMT_FORMULA_ID).toString()); symbol.sequence = row.sequence; diff --git a/sources/qetproject.h b/sources/qetproject.h index 73c27415f..1675f2627 100644 --- a/sources/qetproject.h +++ b/sources/qetproject.h @@ -537,7 +537,9 @@ class QETProject : public QObject QHash elementAutoNumTitlesByFormula() const; std::optional elementAutoNumIdToLink( const DiagramContext &information, - const QHash &titles_by_formula) const; + const QHash &titles_by_formula, + QHash *title_cache = nullptr, + QHash *id_cache = nullptr) const; bool m_deferring_folios = false; /// Opening with folios built only when needed: QET_LAZY_FOLIOS /// is set and the database can be filled from the document