From 7ba19f9834fddd3473bcc9e77a3a6e96bf6759c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=BCkki=20D=C3=A1niel?= <64849783+dbukki@users.noreply.github.com> Date: Wed, 8 May 2024 15:17:16 +0200 Subject: [PATCH] Incremental parsing issue fixes (#736) Fix segmentation fault due to access of file ID on non-loaded file. Eliminated use of size() on ODB query result in SourceManager. Added isSingletonResult instead to dbutil. --- parser/src/sourcemanager.cpp | 5 +-- .../model/include/model/cppastnodemetrics.h | 13 +++++++ .../parser/src/cppmetricsparser.cpp | 8 ++--- util/include/util/dbutil.h | 34 +++++++++++++++++++ 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/parser/src/sourcemanager.cpp b/parser/src/sourcemanager.cpp index 114db9661..73868e859 100644 --- a/parser/src/sourcemanager.cpp +++ b/parser/src/sourcemanager.cpp @@ -5,6 +5,7 @@ #include #include +#include #include @@ -238,9 +239,9 @@ void SourceManager::removeFile(const model::File& file_) _transaction([&]() { if(file_.content) { - auto relFiles = _db->query( + odb::result relFiles = _db->query( odb::query::content == file_.content.object_id()); - if (relFiles.size() == 1) + if (util::isSingleResult(relFiles)) { removeContent = true; _db->erase(file_.content.object_id()); diff --git a/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h b/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h index 5c2f5b452..6b53bfd0b 100644 --- a/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h +++ b/plugins/cpp_metrics/model/include/model/cppastnodemetrics.h @@ -45,6 +45,19 @@ struct CppRecordMetricsView double value; }; +#pragma db view \ + object(CppAstNodeMetrics) \ + object(CppAstNode : CppAstNodeMetrics::astNodeId == CppAstNode::id) \ + object(File : CppAstNode::location.file) +struct CppAstNodeMetricsFileView +{ + #pragma db column(CppAstNode::id) + CppAstNodeId astNodeId; + + #pragma db column(File::id) + FileId fileId; +}; + #pragma db view \ object(CppAstNodeMetrics) \ object(CppAstNode : CppAstNodeMetrics::astNodeId == CppAstNode::id) \ diff --git a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp index eace3bfc6..c7404d437 100644 --- a/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp +++ b/plugins/cpp_metrics/parser/src/cppmetricsparser.cpp @@ -39,12 +39,10 @@ CppMetricsParser::CppMetricsParser(ParserContext& ctx_): AbstractParser(ctx_) _fileIdCache.insert(fm.file); } - for (const model::CppAstNodeMetrics& anm - : _ctx.db->query()) + for (const model::CppAstNodeMetricsFileView& anm + : _ctx.db->query()) { - auto node = _ctx.db->query_one( - odb::query::id == anm.astNodeId); - _astNodeIdCache.insert({anm.astNodeId, node->location.file->id}); + _astNodeIdCache.emplace(anm.astNodeId, anm.fileId); } }); } diff --git a/util/include/util/dbutil.h b/util/include/util/dbutil.h index 4a3d27514..5d1c331d5 100644 --- a/util/include/util/dbutil.h +++ b/util/include/util/dbutil.h @@ -97,6 +97,40 @@ inline std::string getDbDriver() #endif } +/// @brief Determines if the specified ODB query result only contains +/// a single entity. That single entity is then stored in 'single_'. +/// @tparam TEntity The type of entities in the query result. +/// @param result_ The ODB query result in question. +/// @param single_ The variable that receives the first entity (if any). +/// @return Returns true if 'result_' only contained 'single_'; +/// otherwise false. +template +bool isSingleResult(odb::result& result_, TEntity& single_) +{ + auto it_b = result_.begin(); + const auto it_e = result_.end(); + if (it_b != it_e) + { + single_ = *it_b; + return ++it_b == it_e; + } + else return false; +} + +/// @brief Determines if the specified ODB query result only contains +/// a single entity. +/// @tparam TEntity The type of entities in the query result. +/// @param result_ The ODB query result in question. +/// @return Returns true if 'result_' only contained a single entity; +/// otherwise false. +template +bool isSingleResult(odb::result& result_) +{ + auto it_b = result_.begin(); + const auto it_e = result_.end(); + return (it_b != it_e) && (++it_b == it_e); +} + } // util } // cc