Skip to content

Commit 613f50c

Browse files
authored
Merge pull request #804 from mcserep/efficient-pagination
Query paginated metrics efficiently
2 parents 049cb5e + 7d12a1c commit 613f50c

File tree

3 files changed

+82
-48
lines changed

3 files changed

+82
-48
lines changed

plugins/cpp_metrics/service/cxxmetrics.thrift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ service CppMetricsService
109109
map<common.AstNodeId, list<CppMetricsAstNodeSingle>> getPagedCppAstNodeMetricsForPath(
110110
1:string path
111111
2:i32 pageSize,
112-
3:i32 pageNumber)
112+
3:common.AstNodeId previousId)
113113

114114
/**
115115
* This function returns all available C++ metrics
@@ -129,7 +129,7 @@ service CppMetricsService
129129
map<common.AstNodeId, CppMetricsAstNodeDetailed> getPagedCppAstNodeMetricsDetailedForPath(
130130
1:string path,
131131
2:i32 pageSize,
132-
3:i32 pageNumber)
132+
3:common.AstNodeId previousId)
133133

134134
/**
135135
* This function returns all available C++ metrics
@@ -149,7 +149,7 @@ service CppMetricsService
149149
map<common.FileId, list<CppMetricsModuleSingle>> getPagedCppFileMetricsForPath(
150150
1:string path,
151151
2:i32 pageSize,
152-
3:i32 pageNumber)
152+
3:common.FileId previousId)
153153

154154
/**
155155
* This function returns the names of the AST node-level C++ metrics.

plugins/cpp_metrics/service/include/service/cppmetricsservice.h

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class CppMetricsServiceHandler : virtual public CppMetricsServiceIf
5757
std::map<core::AstNodeId, std::vector<CppMetricsAstNodeSingle>>& _return,
5858
const std::string& path_,
5959
const std::int32_t pageSize_,
60-
const std::int32_t pageNumber_) override;
60+
const core::AstNodeId& previousId_) override;
6161

6262
void getCppAstNodeMetricsDetailedForPath(
6363
std::map<core::AstNodeId, CppMetricsAstNodeDetailed>& _return,
@@ -67,7 +67,7 @@ class CppMetricsServiceHandler : virtual public CppMetricsServiceIf
6767
std::map<core::AstNodeId, CppMetricsAstNodeDetailed>& _return,
6868
const std::string& path_,
6969
const std::int32_t pageSize_,
70-
const std::int32_t pageNumber_) override;
70+
const core::AstNodeId& previousId_) override;
7171

7272
void getCppFileMetricsForPath(
7373
std::map<core::FileId, std::vector<CppMetricsModuleSingle>>& _return,
@@ -77,7 +77,7 @@ class CppMetricsServiceHandler : virtual public CppMetricsServiceIf
7777
std::map<core::FileId, std::vector<CppMetricsModuleSingle>>& _return,
7878
const std::string& path_,
7979
const std::int32_t pageSize_,
80-
const std::int32_t pageNumber_) override;
80+
const core::FileId& previousId_) override;
8181

8282
void getCppAstNodeMetricsTypeNames(
8383
std::vector<CppAstNodeMetricsTypeName>& _return) override;
@@ -91,33 +91,17 @@ class CppMetricsServiceHandler : virtual public CppMetricsServiceIf
9191

9292
const boost::program_options::variables_map& _config;
9393

94-
std::string getPagingQuery(
94+
std::string getLimitQuery(const std::int32_t pageSize_);
95+
96+
std::vector<model::CppAstNodeId> pageAstNodeMetrics(
97+
const std::string& path_,
9598
const std::int32_t pageSize_,
96-
const std::int32_t pageNumber_);
99+
const model::CppAstNodeId previousId_);
97100

98-
template <typename TID, typename TView>
99-
std::vector<TID> pageMetrics(
101+
std::vector<model::FileId> pageFileMetrics(
100102
const std::string& path_,
101103
const std::int32_t pageSize_,
102-
const std::int32_t pageNumber_)
103-
{
104-
return _transaction([&, this](){
105-
odb::result<TView> paged_nodes = _db->query<TView>(
106-
odb::query<TView>::File::path.like(path_ + '%') + getPagingQuery(pageSize_, pageNumber_));
107-
108-
std::vector<TID> paged_ids(paged_nodes.size());
109-
std::transform(paged_nodes.begin(), paged_nodes.end(), paged_ids.begin(),
110-
[](const TView& e){
111-
if constexpr (std::is_same<TView, model::CppAstNodeMetricsDistinctView>::value) {
112-
return e.astNodeId;
113-
} else if constexpr (std::is_same<TView, model::CppModuleMetricsDistinctView>::value) {
114-
return e.fileId;
115-
}
116-
});
117-
118-
return paged_ids;
119-
});
120-
}
104+
const model::FileId previousId_);
121105

122106
void queryCppAstNodeMetricsForPath(
123107
std::map<core::AstNodeId, std::vector<CppMetricsAstNodeSingle>>& _return,

plugins/cpp_metrics/service/src/cppmetricsservice.cpp

Lines changed: 69 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,10 @@ void CppMetricsServiceHandler::getPagedCppAstNodeMetricsForPath(
187187
std::map<core::AstNodeId, std::vector<CppMetricsAstNodeSingle>>& _return,
188188
const std::string& path_,
189189
const std::int32_t pageSize_,
190-
const std::int32_t pageNumber_)
190+
const core::AstNodeId& previousId_)
191191
{
192-
std::vector<model::CppAstNodeId> paged_nodes = pageMetrics<model::CppAstNodeId, model::CppAstNodeMetricsDistinctView>(
193-
path_, pageSize_, pageNumber_);
192+
std::vector<model::CppAstNodeId> paged_nodes = pageAstNodeMetrics(
193+
path_, pageSize_, previousId_.empty() ? 0 : std::stoull(previousId_));
194194

195195
queryCppAstNodeMetricsForPath(_return,
196196
CppNodeMetricsQuery::CppAstNodeMetrics::astNodeId.in_range(paged_nodes.begin(), paged_nodes.end()));
@@ -241,10 +241,10 @@ void CppMetricsServiceHandler::getPagedCppAstNodeMetricsDetailedForPath(
241241
std::map<core::AstNodeId, CppMetricsAstNodeDetailed>& _return,
242242
const std::string& path_,
243243
const std::int32_t pageSize_,
244-
const std::int32_t pageNumber_)
244+
const core::AstNodeId& previousId_)
245245
{
246-
std::vector<model::CppAstNodeId> paged_nodes = pageMetrics<model::CppAstNodeId, model::CppAstNodeMetricsDistinctView>(
247-
path_, pageSize_, pageNumber_);
246+
std::vector<model::CppAstNodeId> paged_nodes = pageAstNodeMetrics(
247+
path_, pageSize_, previousId_.empty() ? 0 : std::stoull(previousId_));
248248

249249
queryCppAstNodeMetricsDetailedForPath(_return,
250250
CppNodeMetricsQuery::CppAstNodeMetrics::astNodeId.in_range(paged_nodes.begin(), paged_nodes.end()));
@@ -290,16 +290,16 @@ void CppMetricsServiceHandler::getPagedCppFileMetricsForPath(
290290
std::map<core::FileId, std::vector<CppMetricsModuleSingle>>& _return,
291291
const std::string& path_,
292292
const std::int32_t pageSize_,
293-
const std::int32_t pageNumber_)
293+
const core::FileId& previousId_)
294294
{
295-
std::vector<model::FileId> paged_files = pageMetrics<model::FileId, model::CppModuleMetricsDistinctView>(path_, pageSize_, pageNumber_);
295+
std::vector<model::FileId> paged_files = pageFileMetrics(
296+
path_, pageSize_, previousId_.empty() ? 0 : std::stoull(previousId_));
296297
queryCppFileMetricsForPath(_return,
297298
CppModuleMetricsQuery::CppFileMetrics::file.in_range(paged_files.begin(), paged_files.end()));
298299
}
299300

300-
std::string CppMetricsServiceHandler::getPagingQuery(
301-
const std::int32_t pageSize_,
302-
const std::int32_t pageNumber_)
301+
std::string CppMetricsServiceHandler::getLimitQuery(
302+
const std::int32_t pageSize_)
303303
{
304304
if (pageSize_ <= 0)
305305
{
@@ -308,15 +308,65 @@ std::string CppMetricsServiceHandler::getPagingQuery(
308308
throw ex;
309309
}
310310

311-
if (pageNumber_ <= 0)
312-
{
313-
core::InvalidInput ex;
314-
ex.__set_msg("Invalid page number: " + std::to_string(pageNumber_));
315-
throw ex;
316-
}
311+
return " LIMIT " + std::to_string(pageSize_);
312+
}
313+
314+
std::vector<model::CppAstNodeId> CppMetricsServiceHandler::pageAstNodeMetrics(
315+
const std::string& path_,
316+
const std::int32_t pageSize_,
317+
const model::CppAstNodeId previousId_)
318+
{
319+
typedef odb::query<model::CppAstNodeMetricsDistinctView> MetricQuery;
320+
typedef odb::result<model::CppAstNodeMetricsDistinctView> MetricResult;
321+
322+
return _transaction([&, this](){
323+
MetricQuery condition = MetricQuery::File::path.like(path_ + '%');
324+
if (previousId_ != 0) {
325+
condition = condition && (MetricQuery::CppAstNodeMetrics::astNodeId > previousId_);
326+
}
327+
328+
MetricResult paged_nodes = _db->query<model::CppAstNodeMetricsDistinctView>(
329+
condition +
330+
("ORDER BY" + odb::query<model::CppAstNodeMetrics>::astNodeId) +
331+
getLimitQuery(pageSize_));
317332

318-
const std::int32_t offset = (pageNumber_ - 1) * pageSize_;
319-
return " LIMIT " + std::to_string(pageSize_) + " OFFSET " + std::to_string(offset);
333+
std::vector<model::CppAstNodeId> paged_ids(paged_nodes.size());
334+
std::transform(paged_nodes.begin(), paged_nodes.end(), paged_ids.begin(),
335+
[](const model::CppAstNodeMetricsDistinctView& e){
336+
return e.astNodeId;
337+
});
338+
339+
return paged_ids;
340+
});
341+
}
342+
343+
std::vector<model::FileId> CppMetricsServiceHandler::pageFileMetrics(
344+
const std::string& path_,
345+
const std::int32_t pageSize_,
346+
const model::FileId previousId_)
347+
{
348+
typedef odb::query<model::CppModuleMetricsDistinctView> MetricQuery;
349+
typedef odb::result<model::CppModuleMetricsDistinctView> MetricResult;
350+
351+
return _transaction([&, this](){
352+
MetricQuery condition = MetricQuery::File::path.like(path_ + '%');
353+
if (previousId_ != 0) {
354+
condition = condition && (MetricQuery::CppFileMetrics::file > previousId_);
355+
}
356+
357+
MetricResult paged_nodes = _db->query<model::CppModuleMetricsDistinctView>(
358+
condition +
359+
("ORDER BY" + odb::query<model::CppFileMetrics>::file) +
360+
getLimitQuery(pageSize_));
361+
362+
std::vector<model::FileId> paged_ids(paged_nodes.size());
363+
std::transform(paged_nodes.begin(), paged_nodes.end(), paged_ids.begin(),
364+
[](const model::CppModuleMetricsDistinctView& e){
365+
return e.fileId;
366+
});
367+
368+
return paged_ids;
369+
});
320370
}
321371

322372
} // cppmetrics

0 commit comments

Comments
 (0)