GCC Code Coverage Report


Directory: libimgdoc2/
File: libimgdoc2/src/doc/documentReadBase.cpp
Date: 2025-02-03 12:41:04
Exec Total Coverage
Lines: 95 97 97.9%
Functions: 7 7 100.0%
Branches: 109 196 55.6%

Line Branch Exec Source
1 // SPDX-FileCopyrightText: 2023 Carl Zeiss Microscopy GmbH
2 //
3 // SPDX-License-Identifier: MIT
4
5 #include "documentReadBase.h"
6 #include <algorithm>
7 #include <vector>
8 #include <string>
9 #include <gsl/assert>
10 #include <gsl/narrow>
11
12 using namespace std;
13 using namespace imgdoc2;
14
15 14 /*static*/void DocumentReadBase::GetEntityDimensionsInternal(const unordered_set<imgdoc2::Dimension>& tile_dimensions, imgdoc2::Dimension* dimensions, std::uint32_t& count)
16 {
17
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 if (dimensions != nullptr)
18 {
19
2/4
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
8 copy_n(tile_dimensions.cbegin(), min(count, gsl::narrow<uint32_t>(tile_dimensions.size())), dimensions);
20 }
21
22 14 count = gsl::narrow<uint32_t>(tile_dimensions.size());
23 14 }
24
25 12 std::map<imgdoc2::Dimension, imgdoc2::Int32Interval> DocumentReadBase::GetMinMaxForTileDimensionInternal(
26 const std::vector<imgdoc2::Dimension>& dimensions_to_query_for,
27 const std::function<bool(imgdoc2::Dimension)>& func_is_dimension_valid,
28 const std::function<void(std::ostringstream&, imgdoc2::Dimension)>& func_add_dimension_table_name,
29 const std::string& table_name) const
30 {
31
2/2
✓ Branch 5 taken 16 times.
✓ Branch 6 taken 10 times.
26 for (const auto dimension : dimensions_to_query_for)
32 {
33
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 const bool is_valid = func_is_dimension_valid(dimension);
34
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (!is_valid)
35 {
36
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 ostringstream string_stream;
37
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
2 string_stream << "The dimension '" << dimension << "' is not valid.";
38
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
2 throw invalid_argument_exception(string_stream.str().c_str());
39 2 }
40 }
41
42
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 8 times.
10 if (dimensions_to_query_for.empty())
43 {
44 2 return {};
45 }
46
47
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 const auto query_statement = this->CreateQueryMinMaxStatement(dimensions_to_query_for, func_add_dimension_table_name, table_name);
48
49 8 map<imgdoc2::Dimension, imgdoc2::Int32Interval> result;
50
51 // we expect exactly "2 * dimensions_to_query_for.size()" results
52
1/2
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
8 const bool is_done = this->GetDocument()->GetDatabase_connection()->StepStatement(query_statement.get());
53
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!is_done)
54 {
55 throw internal_error_exception("database-query gave no result, this is unexpected.");
56 }
57
58
3/4
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 8 times.
22 for (int i = 0; i < gsl::narrow<int>(dimensions_to_query_for.size()); ++i)
59 {
60 14 Int32Interval coordinate_bounds;
61
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 auto min = query_statement->GetResultInt32OrNull(i * 2);
62
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 auto max = query_statement->GetResultInt32OrNull(i * 2 + 1);
63
5/6
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 2 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 2 times.
14 if (min.has_value() && max.has_value())
64 {
65
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 coordinate_bounds.minimum_value = min.value();
66
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 coordinate_bounds.maximum_value = max.value();
67 }
68
69
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 result[dimensions_to_query_for[i]] = coordinate_bounds;
70 }
71
72 8 return result;
73 8 }
74
75 8 std::shared_ptr<IDbStatement> DocumentReadBase::CreateQueryMinMaxStatement(
76 const std::vector<imgdoc2::Dimension>& dimensions,
77 const std::function<void(std::ostringstream&, imgdoc2::Dimension)>& func_add_dimension_table_name,
78 const std::string& table_name) const
79 {
80 // preconditions:
81 // - the dimensions specified must be valid
82 // - the collection must not be empty
83
84
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 ostringstream string_stream;
85
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 string_stream << "SELECT ";
86 8 bool first_iteration = true;
87
2/2
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 8 times.
22 for (const auto dimension : dimensions)
88 {
89
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
14 if (!first_iteration)
90 {
91
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 string_stream << ',';
92 }
93
94
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 string_stream << "MIN([";
95
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 func_add_dimension_table_name(string_stream, dimension);
96
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 string_stream << "]),";
97
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 string_stream << "MAX([";
98
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 func_add_dimension_table_name(string_stream, dimension);
99
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 string_stream << "])";
100 14 first_iteration = false;
101 }
102
103
4/8
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
8 string_stream << " FROM " << "[" << table_name << "];";
104
105
2/4
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
8 auto statement = this->GetDocument()->GetDatabase_connection()->PrepareStatement(string_stream.str());
106 16 return statement;
107 8 }
108
109 22 std::shared_ptr<IDbStatement> DocumentReadBase::CreateQueryMinMaxForXyz(const std::string& table_name, const std::vector<QueryMinMaxForXyzInfo>& query_info) const
110 {
111
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 Expects(!query_info.empty());
112
113
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
22 ostringstream string_stream;
114
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
22 string_stream << "SELECT ";
115 22 bool first_iteration = true;
116
2/2
✓ Branch 4 taken 32 times.
✓ Branch 5 taken 22 times.
54 for (const auto& info : query_info)
117 {
118
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 22 times.
32 if (!first_iteration)
119 {
120
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 string_stream << ',';
121 }
122
123
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 string_stream << "MIN([";
124
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 string_stream << info.column_name_coordinate;
125
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 string_stream << "]),";
126
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 string_stream << "MAX([";
127
3/6
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 32 times.
✗ Branch 8 not taken.
32 string_stream << info.column_name_coordinate << "]+[" << info.column_name_coordinate_extent;
128
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 string_stream << "])";
129
130 32 first_iteration = false;
131 }
132
133
3/6
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 22 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 22 times.
✗ Branch 8 not taken.
22 string_stream << " FROM [" << table_name << "];";
134
135
2/4
✓ Branch 5 taken 22 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 22 times.
✗ Branch 9 not taken.
22 auto statement = this->GetDocument()->GetDatabase_connection()->PrepareStatement(string_stream.str());
136
137 44 return statement;
138 22 }
139
140 52 /*static*/int DocumentReadBase::SetCoordinateBoundsValueIfNonNull(imgdoc2::DoubleInterval* interval, IDbStatement* statement, int result_index)
141 {
142
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 20 times.
52 if (interval != nullptr)
143 {
144
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 const auto min = statement->GetResultDoubleOrNull(result_index++);
145
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 const auto max = statement->GetResultDoubleOrNull(result_index++);
146
5/6
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 4 times.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 28 times.
✓ Branch 7 taken 4 times.
32 if (min.has_value() && max.has_value())
147 {
148
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 interval->minimum_value = min.value();
149
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 interval->maximum_value = max.value();
150 }
151 else
152 {
153 4 *interval = DoubleInterval{};
154 }
155 }
156
157 52 return result_index;
158 }
159
160 32 std::uint64_t DocumentReadBase::GetTotalTileCount(const std::string& table_name)
161 {
162
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 ostringstream string_stream;
163
3/6
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 32 times.
✗ Branch 8 not taken.
32 string_stream << "SELECT COUNT(*) FROM [" << table_name << "];";
164
2/4
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 32 times.
✗ Branch 9 not taken.
32 const auto statement = this->GetDocument()->GetDatabase_connection()->PrepareStatement(string_stream.str());
165
166
1/2
✓ Branch 6 taken 32 times.
✗ Branch 7 not taken.
32 const bool is_done = this->GetDocument()->GetDatabase_connection()->StepStatement(statement.get());
167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!is_done)
168 {
169 throw internal_error_exception("database-query gave no result, this is unexpected.");
170 }
171
172
1/2
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
32 const auto result = statement->GetResultInt64(0);
173 32 return result;
174 32 }
175
176 14 std::map<int, std::uint64_t> DocumentReadBase::GetTileCountPerLayer(const std::string& table_name, const std::string& pyramid_level_column_name)
177 {
178
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 ostringstream string_stream;
179
7/14
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 14 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 14 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 14 times.
✗ Branch 20 not taken.
14 string_stream << "SELECT [" << pyramid_level_column_name << "], COUNT(*) FROM [" << table_name << "] GROUP BY [" << pyramid_level_column_name << "];";
180
2/4
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
14 const auto statement = this->GetDocument()->GetDatabase_connection()->PrepareStatement(string_stream.str());
181
182 14 map<int, uint64_t> result;
183
3/4
✓ Branch 6 taken 50 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 36 times.
✓ Branch 9 taken 14 times.
50 while (this->GetDocument()->GetDatabase_connection()->StepStatement(statement.get()))
184 {
185
1/2
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
36 const auto layer = statement->GetResultInt32(0);
186
1/2
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
36 const auto count = statement->GetResultInt64(1);
187
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 result[layer] = count;
188 }
189
190 28 return result;
191 14 }
192