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 |