From bbae6d83c6d7ea25f17965fd68062f0cab3da5e4 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 23 Aug 2023 00:26:20 +0100 Subject: Cache the Hook name/column relation for non-subclass multi-row selects --- slicer/db/sqlSelectDeserializer.cpp | 78 ++++++++++++++++++++++++++++++------- slicer/db/sqlSelectDeserializer.h | 13 +++++-- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/slicer/db/sqlSelectDeserializer.cpp b/slicer/db/sqlSelectDeserializer.cpp index e11493e..8081d76 100644 --- a/slicer/db/sqlSelectDeserializer.cpp +++ b/slicer/db/sqlSelectDeserializer.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -58,10 +59,53 @@ namespace Slicer { } } + void + SqlSelectDeserializer::fillLowerColumnNameCache() + { + BOOST_ASSERT(lowerColumnNames.empty()); + lowerColumnNames.reserve(columnCount); + orderedColumns.reserve(columnCount); + for (auto col = 0U; col < columnCount; col += 1) { + const DB::Column & c = (*cmd)[col]; + lowerColumnNames.emplace_back(to_lower_copy(c.name)); + } + } + + const DB::Column * + SqlSelectDeserializer::searchOrFilleColumnCache(size_t idx, const HookCommon * hook) + { + if (idx < orderedColumns.size()) { + return orderedColumns[idx]; + } + BOOST_ASSERT(idx == orderedColumns.size()); + if (const auto itr = std::find(lowerColumnNames.begin(), lowerColumnNames.end(), hook->nameLower); + itr != lowerColumnNames.end()) { + return orderedColumns.emplace_back(&(*cmd)[static_cast(itr - lowerColumnNames.begin())]); + } + else { + return orderedColumns.emplace_back(nullptr); + } + } + + namespace { + void + assignFromColumn(ModelPartParam fmp, const DB::Column & c) + { + BOOST_ASSERT(fmp); + BOOST_ASSERT(!c.isNull()); + fmp->Create(); + fmp->SetValue(SqlSource(c)); + fmp->Complete(); + } + } + void SqlSelectDeserializer::DeserializeSequence(ModelPartParam omp) { omp->OnAnonChild([this](auto && mp, auto &&) { + if (!typeIdColIdx && lowerColumnNames.empty()) { + fillLowerColumnNameCache(); + } while (cmd->fetch()) { DeserializeRow(mp); } @@ -92,20 +136,26 @@ namespace Slicer { case Slicer::ModelPartType::Complex: { auto apply = [this](auto && rcmp) { rcmp->Create(); - for (auto col = 0U; col < columnCount; col += 1) { - const DB::Column & c = (*cmd)[col]; - if (!c.isNull()) { - rcmp->OnChild( - [&c](auto && fmp, auto &&) { - if (fmp) { - fmp->Create(); - fmp->SetValue(SqlSource(c)); - fmp->Complete(); - } - }, - c.name, nullptr, false); + if (typeIdColIdx || lowerColumnNames.empty()) { + for (auto col = 0U; col < columnCount; col += 1) { + const DB::Column & c = (*cmd)[col]; + if (!c.isNull()) { + rcmp->OnChild( + [&c](auto && fmp, auto &&) { + assignFromColumn(fmp, c); + }, + c.name, nullptr, false); + } } } + else { + rcmp->OnEachChild([idx = 0U, this](auto &&, auto && fmp, auto && hook) mutable { + if (auto c = searchOrFilleColumnCache(idx, hook); c && !c->isNull()) { + assignFromColumn(fmp, *c); + } + ++idx; + }); + } rcmp->Complete(); }; if (typeIdColIdx) { @@ -116,12 +166,10 @@ namespace Slicer { apply(rmp); } break; case Slicer::ModelPartType::Simple: { - rmp->Create(); const DB::Column & c = (*cmd)[0]; if (!c.isNull()) { - rmp->SetValue(SqlSource(c)); + assignFromColumn(rmp, c); } - rmp->Complete(); } break; default: throw UnsupportedModelType(); diff --git a/slicer/db/sqlSelectDeserializer.h b/slicer/db/sqlSelectDeserializer.h index f8fce08..b911fb1 100644 --- a/slicer/db/sqlSelectDeserializer.h +++ b/slicer/db/sqlSelectDeserializer.h @@ -9,6 +9,7 @@ namespace DB { class SelectCommand; + class Column; } namespace Slicer { @@ -20,15 +21,19 @@ namespace Slicer { void Deserialize(ModelPartForRootParam) override; protected: - void DLL_PRIVATE DeserializeSimple(ModelPartParam); - void DLL_PRIVATE DeserializeObject(ModelPartParam); - void DLL_PRIVATE DeserializeSequence(ModelPartParam); - void DLL_PRIVATE DeserializeRow(ModelPartParam); + DLL_PRIVATE void DeserializeSimple(ModelPartParam); + DLL_PRIVATE void DeserializeObject(ModelPartParam); + DLL_PRIVATE void DeserializeSequence(ModelPartParam); + DLL_PRIVATE void DeserializeRow(ModelPartParam); + DLL_PRIVATE void fillLowerColumnNameCache(); + DLL_PRIVATE inline const DB::Column * searchOrFilleColumnCache(size_t idx, const HookCommon * hook); DB::SelectCommand * cmd; unsigned int columnCount; std::optional typeIdColName; std::optional typeIdColIdx; + std::vector lowerColumnNames; + std::vector orderedColumns; }; } -- cgit v1.2.3