GCC Code Coverage Report


Directory: libimgdoc2/
File: libimgdoc2/src/doc/documentMetadataReader.cpp
Date: 2025-02-03 12:41:04
Exec Total Coverage
Lines: 174 183 95.1%
Functions: 9 9 100.0%
Branches: 518 980 52.9%

Line Branch Exec Source
1 // SPDX-FileCopyrightText: 2023 Carl Zeiss Microscopy GmbH
2 //
3 // SPDX-License-Identifier: MIT
4
5 #include "documentMetadataReader.h"
6 #include <string>
7
8 using namespace std;
9 using namespace imgdoc2;
10
11 120 /*virtual*/imgdoc2::DocumentMetadataItem DocumentMetadataReader::GetItem(imgdoc2::dbIndex primary_key, imgdoc2::DocumentMetadataItemFlags flags)
12 {
13 120 DocumentMetadataItem item;
14
15 // special case: if no flags are specified, we should just check if the item exists
16
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 108 times.
120 if (flags == DocumentMetadataItemFlags::None)
17 {
18
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 const bool exists = this->CheckIfItemExists(primary_key);
19
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
12 if (!exists)
20 {
21
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 ostringstream ss;
22
3/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
4 ss << "The requested item (with pk=" << primary_key << ") does not exist";
23
2/4
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
4 throw non_existing_item_exception(ss.str(), primary_key);
24 4 }
25
26 8 return item;
27 }
28
29 // check if we have to "retrieve data from the item" (i.e. if the caller wants to have the name, the type, or the value of the item)
30
2/2
✓ Branch 3 taken 90 times.
✓ Branch 4 taken 18 times.
108 if ((flags & (DocumentMetadataItemFlags::kPrimaryKeyValid | DocumentMetadataItemFlags::kNameValid | DocumentMetadataItemFlags::kDocumentMetadataTypeAndValueValid)) != DocumentMetadataItemFlags::None)
31 {
32
1/2
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
90 const auto statement = this->CreateStatementForRetrievingItem(flags);
33
1/2
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
90 statement->BindInt64(1, primary_key);
34
35
3/4
✓ Branch 6 taken 90 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 26 times.
✓ Branch 9 taken 64 times.
90 if (!this->GetDocument()->GetDatabase_connection()->StepStatement(statement.get()))
36 {
37 // this means that the tile with the specified index ('primary_key') was not found
38
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 ostringstream ss;
39
3/6
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 26 times.
✗ Branch 8 not taken.
26 ss << "Request for reading a non-existing item (with pk=" << primary_key << ")";
40
2/4
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 26 times.
✗ Branch 6 not taken.
26 throw non_existing_item_exception(ss.str(), primary_key);
41 26 }
42
43 // Note that "CreateStatementForRetrievingItem" does not retrieve the "complete path" of the item, we need to do this separately
44 // for the time being, so we need to remove the "kCompletePath" flag from the flags parameter
45
2/4
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 64 times.
✗ Branch 7 not taken.
64 item = this->RetrieveDocumentMetadataItemFromStatement(statement, flags & ~DocumentMetadataItemFlags::kCompletePath, "");
46 90 }
47
48 // check if we have to "retrieve the complete path" (i.e. if the caller wants to have the complete path of the item)
49
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 54 times.
82 if ((flags & DocumentMetadataItemFlags::kCompletePath) == DocumentMetadataItemFlags::kCompletePath)
50 {
51
3/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 24 times.
28 if (!this->GetPathForNode(primary_key, item.complete_path))
52 {
53
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 ostringstream ss;
54
3/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
4 ss << "Request for reading the path of a non-existing item (with pk=" << primary_key << ")";
55
2/4
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
4 throw non_existing_item_exception(ss.str(), primary_key);
56 4 }
57
58 24 item.flags = item.flags | DocumentMetadataItemFlags::kCompletePath;
59 }
60
61 78 return item;
62 34 }
63
64 86 /*virtual*/imgdoc2::DocumentMetadataItem DocumentMetadataReader::GetItemForPath(const std::string& path, imgdoc2::DocumentMetadataItemFlags flags)
65 {
66 86 optional<imgdoc2::dbIndex> idx;
67
2/2
✓ Branch 1 taken 74 times.
✓ Branch 2 taken 12 times.
86 const bool success = this->TryMapPathAndGetTerminalNode(path, &idx);
68
6/6
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 18 times.
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 42 times.
✓ Branch 6 taken 32 times.
74 if (success && idx.has_value())
69 {
70 // note: we require to have a valid node-id here, an "empty" optional (which would mean "empty path") is not valid in this method
71
2/4
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
84 return this->GetItem(idx.value(), flags);
72 }
73
74
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 ostringstream string_stream;
75
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 << "The path '" << path << "' does not exist.";
76
2/4
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
32 throw invalid_path_exception(string_stream.str());
77 32 }
78
79 64 void DocumentMetadataReader::EnumerateItems(
80 std::optional<imgdoc2::dbIndex> parent,
81 bool recursive,
82 DocumentMetadataItemFlags flags,
83 const std::function<bool(imgdoc2::dbIndex, const DocumentMetadataItem& item)>& func)
84 {
85 64 string path_of_parent_node;
86
87 // if we are to retrieve to first retrieve the path to the 'parent'-node
88
6/6
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 8 times.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 36 times.
✓ Branch 6 taken 20 times.
✓ Branch 7 taken 44 times.
64 if (parent.has_value() && (flags & DocumentMetadataItemFlags::kCompletePath) == DocumentMetadataItemFlags::kCompletePath)
89 {
90
4/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 12 times.
20 if (!this->GetPathForNode(parent.value(), path_of_parent_node))
91 {
92
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 ostringstream ss;
93
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 ss << "Request for reading the path of a non-existing item (with pk=" << parent.value() << ")";
94
3/6
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
8 throw non_existing_item_exception(ss.str(), parent.value());
95 8 }
96
97
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 path_of_parent_node += DocumentMetadataBase::kPathDelimiter_;
98 }
99
100
2/2
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 20 times.
56 this->InternalEnumerateItems(parent, path_of_parent_node, recursive, flags, func);
101 64 }
102
103 8 void DocumentMetadataReader::EnumerateItemsForPath(
104 const std::string& path,
105 bool recursive,
106 DocumentMetadataItemFlags flags,
107 const std::function<bool(imgdoc2::dbIndex, const DocumentMetadataItem& item)>& func)
108 {
109 8 optional<imgdoc2::dbIndex> idx;
110
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 const bool success = this->TryMapPathAndGetTerminalNode(path, &idx);
111
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if (success)
112 {
113
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 this->InternalEnumerateItems(idx, path, recursive, flags, func);
114 6 return;
115 }
116
117
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 ostringstream string_stream;
118
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 path '" << path << "' does not exist.";
119
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 throw invalid_path_exception(string_stream.str());
120 2 }
121
122 62 void DocumentMetadataReader::InternalEnumerateItems(
123 std::optional<imgdoc2::dbIndex> parent,
124 const std::string& path_of_parent,
125 bool recursive,
126 imgdoc2::DocumentMetadataItemFlags flags,
127 const std::function<bool(imgdoc2::dbIndex, const imgdoc2::DocumentMetadataItem& item)>& func)
128 {
129 const auto statement = this->CreateStatementForEnumerateAllItemsWithAncestorAndDataBind(
130 recursive,
131 62 (flags & DocumentMetadataItemFlags::kCompletePath) == DocumentMetadataItemFlags::kCompletePath,
132
1/2
✓ Branch 1 taken 62 times.
✗ Branch 2 not taken.
62 parent);
133
134 62 bool at_least_one_item_found = false;
135
3/4
✓ Branch 6 taken 208 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 146 times.
✓ Branch 9 taken 62 times.
208 while (this->GetDocument()->GetDatabase_connection()->StepStatement(statement.get()))
136 {
137 146 at_least_one_item_found = true;
138
1/2
✓ Branch 2 taken 146 times.
✗ Branch 3 not taken.
146 const imgdoc2::dbIndex index = statement->GetResultInt64(0);
139
1/2
✓ Branch 1 taken 146 times.
✗ Branch 2 not taken.
146 DocumentMetadataItem document_metadata_item = this->RetrieveDocumentMetadataItemFromStatement(statement, flags, path_of_parent);
140
1/2
✓ Branch 1 taken 146 times.
✗ Branch 2 not taken.
146 const bool continue_operation = func(index, document_metadata_item);
141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
146 if (!continue_operation)
142 {
143 break;
144 }
145
1/2
✓ Branch 1 taken 146 times.
✗ Branch 2 not taken.
146 }
146
147
5/6
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 42 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
✓ Branch 6 taken 42 times.
62 if (!at_least_one_item_found && parent.has_value())
148 {
149 // Unfortunately, we cannot distinguish between "no items found because parent does have a child" and "no items found because the parent does not exist".
150 // Maybe there is a more clever way to check whether the parent exists, but for now we have to execute an additional query.
151 // Note that if we query for the root node, we do not need to check whether the parent exists, because the root node always exists.
152
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
20 const bool parent_exists = this->CheckIfItemExists(parent.value());
153
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (!parent_exists)
154 {
155
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ostringstream string_stream;
156
4/8
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 20 times.
✗ Branch 11 not taken.
20 string_stream << "The parent with pk=" << parent.value() << " does not exist.";
157
3/6
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 20 times.
✗ Branch 9 not taken.
20 throw non_existing_item_exception(string_stream.str(), parent.value());
158 20 }
159 }
160 62 }
161
162 90 std::shared_ptr<IDbStatement> DocumentMetadataReader::CreateStatementForRetrievingItem(imgdoc2::DocumentMetadataItemFlags flags)
163 {
164
1/2
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
90 ostringstream string_stream;
165 string_stream << "SELECT " <<
166
2/4
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 90 times.
✗ Branch 6 not taken.
90 this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_Pk) << ", " <<
167
2/4
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 90 times.
✗ Branch 6 not taken.
180 this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_Name) << ", " <<
168
2/4
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 90 times.
✗ Branch 6 not taken.
180 this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_TypeDiscriminator) << ", " <<
169
2/4
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 90 times.
✗ Branch 6 not taken.
180 this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_ValueDouble) << ", " <<
170
2/4
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 90 times.
✗ Branch 6 not taken.
180 this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_ValueInteger) << ", " <<
171
2/4
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 90 times.
✗ Branch 6 not taken.
180 this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_ValueString) << " " <<
172
2/4
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 90 times.
✗ Branch 6 not taken.
180 "FROM [" << this->GetDocument()->GetDataBaseConfigurationCommon()->GetTableNameForMetadataTableOrThrow() << "] WHERE " <<
173
21/42
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 90 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 90 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 90 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 90 times.
✗ Branch 16 not taken.
✓ Branch 19 taken 90 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 90 times.
✗ Branch 23 not taken.
✓ Branch 26 taken 90 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 90 times.
✗ Branch 30 not taken.
✓ Branch 33 taken 90 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 90 times.
✗ Branch 37 not taken.
✓ Branch 40 taken 90 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 90 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 90 times.
✗ Branch 47 not taken.
✓ Branch 50 taken 90 times.
✗ Branch 51 not taken.
✓ Branch 53 taken 90 times.
✗ Branch 54 not taken.
✓ Branch 56 taken 90 times.
✗ Branch 57 not taken.
✓ Branch 61 taken 90 times.
✗ Branch 62 not taken.
✓ Branch 64 taken 90 times.
✗ Branch 65 not taken.
✓ Branch 67 taken 90 times.
✗ Branch 68 not taken.
✓ Branch 70 taken 90 times.
✗ Branch 71 not taken.
720 "[" << this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_Pk) << "]=?1;";
174
2/4
✓ Branch 5 taken 90 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 90 times.
✗ Branch 9 not taken.
90 auto statement = this->GetDocument()->GetDatabase_connection()->PrepareStatement(string_stream.str());
175 180 return statement;
176 90 }
177
178 62 std::shared_ptr<IDbStatement> DocumentMetadataReader::CreateStatementForEnumerateAllItemsWithAncestorAndDataBind(bool recursive, bool include_path, std::optional<imgdoc2::dbIndex> parent)
179 {
180 /* If we want to create "full-path" (include_path=true) for the items, we use a query like this:
181
182 WITH RECURSIVE
183 [cte](Pk,Name,AncestorId,TypeDiscriminator,ValueDouble,ValueInteger,ValueString,Path) AS(
184 SELECT
185 [Pk],
186 [Name],
187 [AncestorId],
188 [TypeDiscriminator],
189 [ValueDouble],
190 [ValueInteger],
191 [ValueString],
192 [Name] As Path
193 FROM [METADATA]
194 WHERE [AncestorId] IS NULL
195 UNION ALL
196 SELECT
197 [c].[Pk],
198 [c].[Name],
199 [c].[AncestorId],
200 [c].[TypeDiscriminator],
201 [c].[ValueDouble],
202 [c].[ValueInteger],
203 [c].[ValueString],
204 [cte].Path || '/' ||c.Name
205 FROM [METADATA] [c]
206 JOIN [cte] ON [c].[AncestorId] = [cte].[Pk]
207 )
208 SELECT
209 [Pk],
210 [Name],
211 [TypeDiscriminator],
212 [ValueDouble],
213 [ValueInteger],
214 [ValueString],
215 [Path]
216 FROM [cte];
217
218 If the path is not required, we can use a simpler query:
219
220 WITH RECURSIVE
221 [cte] AS(
222 SELECT
223 [Pk],
224 [Name],
225 [AncestorId],
226 [TypeDiscriminator],
227 [ValueDouble],
228 [ValueInteger],
229 [ValueString],
230 FROM [METADATA]
231 WHERE [AncestorId] IS NULL
232 UNION ALL
233 SELECT
234 [c].[Pk],
235 [c].[Name],
236 [c].[AncestorId],
237 [c].[TypeDiscriminator],
238 [c].[ValueDouble],
239 [c].[ValueInteger],
240 [c].[ValueString],
241 FROM [METADATA] [c]
242 JOIN [cte] ON [c].[AncestorId] = [cte].[Pk]
243 )
244 SELECT
245 [Pk],
246 [Name],
247 [TypeDiscriminator],
248 [ValueDouble],
249 [ValueInteger],
250 [ValueString],
251 FROM [cte];
252
253 */
254 62 const bool parent_has_value = parent.has_value();
255
1/2
✓ Branch 1 taken 62 times.
✗ Branch 2 not taken.
62 ostringstream string_stream;
256
257
2/4
✓ Branch 3 taken 62 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 62 times.
✗ Branch 7 not taken.
62 const auto metadata_table_name = this->GetDocument()->GetDataBaseConfigurationCommon()->GetTableNameForMetadataTableOrThrow();
258
2/4
✓ Branch 3 taken 62 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 62 times.
✗ Branch 7 not taken.
62 const auto column_name_pk = this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_Pk);
259
2/4
✓ Branch 3 taken 62 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 62 times.
✗ Branch 7 not taken.
62 const auto column_name_name = this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_Name);
260
2/4
✓ Branch 3 taken 62 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 62 times.
✗ Branch 7 not taken.
62 const auto column_name_ancestor_id = this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_AncestorId);
261
2/4
✓ Branch 3 taken 62 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 62 times.
✗ Branch 7 not taken.
62 const auto column_name_type_discriminator = this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_TypeDiscriminator);
262
2/4
✓ Branch 3 taken 62 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 62 times.
✗ Branch 7 not taken.
62 const auto column_name_value_double = this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_ValueDouble);
263
2/4
✓ Branch 3 taken 62 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 62 times.
✗ Branch 7 not taken.
62 const auto column_name_value_integer = this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_ValueInteger);
264
2/4
✓ Branch 3 taken 62 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 62 times.
✗ Branch 7 not taken.
62 const auto column_name_value_string = this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_ValueString);
265
266
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 36 times.
62 if (recursive)
267 {
268
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 16 times.
26 if (include_path)
269 {
270 string_stream << "WITH RECURSIVE [cte](" <<
271 column_name_pk << "," << column_name_name << "," << column_name_ancestor_id << "," << column_name_type_discriminator << "," << column_name_value_double << "," << column_name_value_integer << "," << column_name_value_string << ",Path) AS(" <<
272 "SELECT [" << column_name_pk << "],[" << column_name_name << "],[" << column_name_ancestor_id << "],[" << column_name_type_discriminator << "],[" << column_name_value_double << "],[" << column_name_value_integer <<
273 "],[" << column_name_value_string << "],[" << column_name_name << "] As Path " <<
274
35/70
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 10 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 10 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 10 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 10 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 10 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 10 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 10 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 10 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 10 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 10 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 10 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 10 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 10 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 10 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 10 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 10 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 10 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 10 times.
✗ Branch 62 not taken.
✓ Branch 64 taken 10 times.
✗ Branch 65 not taken.
✓ Branch 67 taken 10 times.
✗ Branch 68 not taken.
✓ Branch 70 taken 10 times.
✗ Branch 71 not taken.
✓ Branch 73 taken 10 times.
✗ Branch 74 not taken.
✓ Branch 76 taken 10 times.
✗ Branch 77 not taken.
✓ Branch 79 taken 10 times.
✗ Branch 80 not taken.
✓ Branch 82 taken 10 times.
✗ Branch 83 not taken.
✓ Branch 85 taken 10 times.
✗ Branch 86 not taken.
✓ Branch 88 taken 10 times.
✗ Branch 89 not taken.
✓ Branch 91 taken 10 times.
✗ Branch 92 not taken.
✓ Branch 94 taken 10 times.
✗ Branch 95 not taken.
✓ Branch 97 taken 10 times.
✗ Branch 98 not taken.
✓ Branch 100 taken 10 times.
✗ Branch 101 not taken.
✓ Branch 103 taken 10 times.
✗ Branch 104 not taken.
10 "FROM [" << metadata_table_name << "] ";
275
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
10 if (parent_has_value)
276 {
277
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
6 string_stream << "WHERE " << column_name_ancestor_id << "=?1 ";
278 }
279 else
280 {
281
3/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
4 string_stream << "WHERE " << column_name_ancestor_id << " IS NULL ";
282 }
283
284 string_stream << "UNION ALL " <<
285 "SELECT [c].[" << column_name_pk << "],[c].[" << column_name_name << "],[c].[" << column_name_ancestor_id << "],[c].[" << column_name_type_discriminator << "],[c].[" << column_name_value_double << "],[c].[" << column_name_value_integer << "],[c].[" <<
286 column_name_value_string << "],[cte].Path || '" << DocumentMetadataBase::kPathDelimiter_ << "' ||c." << column_name_name << " " <<
287 "FROM [" << metadata_table_name << "] [c] " <<
288 "JOIN [cte] ON [c].[" << column_name_ancestor_id << "] = [cte].[" << column_name_pk << "]) " <<
289 "SELECT [" << column_name_pk << "],[" << column_name_name << "],[" << column_name_type_discriminator << "],[" << column_name_value_double << "],[" << column_name_value_integer << "],[" << column_name_value_string << "],[Path] " <<
290
42/84
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 10 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 10 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 10 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 10 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 10 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 10 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 10 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 10 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 10 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 10 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 10 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 10 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 10 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 10 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 10 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 10 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 10 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 10 times.
✗ Branch 62 not taken.
✓ Branch 64 taken 10 times.
✗ Branch 65 not taken.
✓ Branch 67 taken 10 times.
✗ Branch 68 not taken.
✓ Branch 70 taken 10 times.
✗ Branch 71 not taken.
✓ Branch 73 taken 10 times.
✗ Branch 74 not taken.
✓ Branch 76 taken 10 times.
✗ Branch 77 not taken.
✓ Branch 79 taken 10 times.
✗ Branch 80 not taken.
✓ Branch 82 taken 10 times.
✗ Branch 83 not taken.
✓ Branch 85 taken 10 times.
✗ Branch 86 not taken.
✓ Branch 88 taken 10 times.
✗ Branch 89 not taken.
✓ Branch 91 taken 10 times.
✗ Branch 92 not taken.
✓ Branch 94 taken 10 times.
✗ Branch 95 not taken.
✓ Branch 97 taken 10 times.
✗ Branch 98 not taken.
✓ Branch 100 taken 10 times.
✗ Branch 101 not taken.
✓ Branch 103 taken 10 times.
✗ Branch 104 not taken.
✓ Branch 106 taken 10 times.
✗ Branch 107 not taken.
✓ Branch 109 taken 10 times.
✗ Branch 110 not taken.
✓ Branch 112 taken 10 times.
✗ Branch 113 not taken.
✓ Branch 115 taken 10 times.
✗ Branch 116 not taken.
✓ Branch 118 taken 10 times.
✗ Branch 119 not taken.
✓ Branch 121 taken 10 times.
✗ Branch 122 not taken.
✓ Branch 124 taken 10 times.
✗ Branch 125 not taken.
10 "FROM [cte];";
291 }
292 else
293 {
294 string_stream <<
295 "WITH RECURSIVE cte AS(" <<
296 "SELECT " << column_name_pk << "," << column_name_name << "," << column_name_ancestor_id << "," << column_name_type_discriminator << "," << column_name_value_double << "," << column_name_value_integer << "," << column_name_value_string << " " <<
297
19/38
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 16 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 16 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 16 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 16 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 16 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 16 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 16 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 16 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 16 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 16 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 16 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 16 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 16 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 16 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 16 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 16 times.
✗ Branch 56 not taken.
16 "FROM [" << metadata_table_name << "] ";
298
299
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
16 if (parent_has_value)
300 {
301
3/6
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
12 string_stream << "WHERE " << column_name_ancestor_id << "=?1 ";
302 }
303 else
304 {
305
3/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
4 string_stream << "WHERE " << column_name_ancestor_id << " IS NULL ";
306 }
307
308 string_stream <<
309 "UNION ALL " <<
310 "SELECT c." << column_name_pk << ",c." << column_name_name << ",c." << column_name_ancestor_id << ",c." << column_name_type_discriminator << ",c." << column_name_value_double << ",c." << column_name_value_integer << ",c." << column_name_value_string << " " <<
311 "FROM [" << metadata_table_name << "] c " <<
312 "JOIN cte ON c." << column_name_ancestor_id << "=cte." << column_name_pk << " " <<
313 ") " <<
314
38/76
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 16 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 16 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 16 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 16 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 16 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 16 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 16 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 16 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 16 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 16 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 16 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 16 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 16 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 16 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 16 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 16 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 16 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 16 times.
✗ Branch 62 not taken.
✓ Branch 64 taken 16 times.
✗ Branch 65 not taken.
✓ Branch 67 taken 16 times.
✗ Branch 68 not taken.
✓ Branch 70 taken 16 times.
✗ Branch 71 not taken.
✓ Branch 73 taken 16 times.
✗ Branch 74 not taken.
✓ Branch 76 taken 16 times.
✗ Branch 77 not taken.
✓ Branch 79 taken 16 times.
✗ Branch 80 not taken.
✓ Branch 82 taken 16 times.
✗ Branch 83 not taken.
✓ Branch 85 taken 16 times.
✗ Branch 86 not taken.
✓ Branch 88 taken 16 times.
✗ Branch 89 not taken.
✓ Branch 91 taken 16 times.
✗ Branch 92 not taken.
✓ Branch 94 taken 16 times.
✗ Branch 95 not taken.
✓ Branch 97 taken 16 times.
✗ Branch 98 not taken.
✓ Branch 100 taken 16 times.
✗ Branch 101 not taken.
✓ Branch 103 taken 16 times.
✗ Branch 104 not taken.
✓ Branch 106 taken 16 times.
✗ Branch 107 not taken.
✓ Branch 109 taken 16 times.
✗ Branch 110 not taken.
✓ Branch 112 taken 16 times.
✗ Branch 113 not taken.
16 "SELECT " << column_name_pk << "," << column_name_name << "," << column_name_type_discriminator << "," << column_name_value_double << "," << column_name_value_integer << "," << column_name_value_string << " FROM cte;";
315 }
316 }
317 else
318 {
319
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 28 times.
36 if (include_path)
320 {
321 string_stream << "WITH RECURSIVE [cte](" <<
322 column_name_pk << "," << column_name_name << "," << column_name_ancestor_id << "," << column_name_type_discriminator << "," << column_name_value_double << "," << column_name_value_integer << "," << column_name_value_string << ",Path) AS(" <<
323 "SELECT [" << column_name_pk << "],[" << column_name_name << "],[" << column_name_ancestor_id << "],[" << column_name_type_discriminator << "],[" << column_name_value_double << "],[" << column_name_value_integer << "],[" <<
324 column_name_value_string << "],[" << column_name_name << "] As Path " <<
325
35/70
✓ 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.
✓ Branch 13 taken 8 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 8 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 8 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 8 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 8 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 8 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 8 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 8 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 8 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 8 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 8 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 8 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 8 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 8 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 8 times.
✗ Branch 62 not taken.
✓ Branch 64 taken 8 times.
✗ Branch 65 not taken.
✓ Branch 67 taken 8 times.
✗ Branch 68 not taken.
✓ Branch 70 taken 8 times.
✗ Branch 71 not taken.
✓ Branch 73 taken 8 times.
✗ Branch 74 not taken.
✓ Branch 76 taken 8 times.
✗ Branch 77 not taken.
✓ Branch 79 taken 8 times.
✗ Branch 80 not taken.
✓ Branch 82 taken 8 times.
✗ Branch 83 not taken.
✓ Branch 85 taken 8 times.
✗ Branch 86 not taken.
✓ Branch 88 taken 8 times.
✗ Branch 89 not taken.
✓ Branch 91 taken 8 times.
✗ Branch 92 not taken.
✓ Branch 94 taken 8 times.
✗ Branch 95 not taken.
✓ Branch 97 taken 8 times.
✗ Branch 98 not taken.
✓ Branch 100 taken 8 times.
✗ Branch 101 not taken.
✓ Branch 103 taken 8 times.
✗ Branch 104 not taken.
8 "FROM [" << metadata_table_name << "] ";
326
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if (parent_has_value)
327 {
328
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
6 string_stream << "WHERE " << column_name_ancestor_id << "=?1 ";
329 }
330 else
331 {
332
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 << "WHERE " << column_name_ancestor_id << " IS NULL ";
333 }
334
335 string_stream << "UNION ALL " <<
336 "SELECT [c].[" << column_name_pk << "],[c].[" << column_name_name << "],[c].[" << column_name_ancestor_id << "],[c].[" << column_name_type_discriminator << "],[c].[" << column_name_value_double << "],[c].[" << column_name_value_integer << "],[c].[" <<
337 column_name_value_string << "],[cte].Path || '" << DocumentMetadataBase::kPathDelimiter_ << "' ||c." << column_name_name << " " <<
338 "FROM [" << metadata_table_name << "] [c] " <<
339 "JOIN [cte] ON [c].[" << column_name_ancestor_id << "] = [cte].[" << column_name_pk << "]) " <<
340 "SELECT [" << column_name_pk << "],[" << column_name_name << "],[" << column_name_type_discriminator << "],[" << column_name_value_double << "],[" << column_name_value_integer << "],[" << column_name_value_string << "],[Path] " <<
341
42/84
✓ 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.
✓ Branch 13 taken 8 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 8 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 8 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 8 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 8 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 8 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 8 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 8 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 8 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 8 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 8 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 8 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 8 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 8 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 8 times.
✗ Branch 62 not taken.
✓ Branch 64 taken 8 times.
✗ Branch 65 not taken.
✓ Branch 67 taken 8 times.
✗ Branch 68 not taken.
✓ Branch 70 taken 8 times.
✗ Branch 71 not taken.
✓ Branch 73 taken 8 times.
✗ Branch 74 not taken.
✓ Branch 76 taken 8 times.
✗ Branch 77 not taken.
✓ Branch 79 taken 8 times.
✗ Branch 80 not taken.
✓ Branch 82 taken 8 times.
✗ Branch 83 not taken.
✓ Branch 85 taken 8 times.
✗ Branch 86 not taken.
✓ Branch 88 taken 8 times.
✗ Branch 89 not taken.
✓ Branch 91 taken 8 times.
✗ Branch 92 not taken.
✓ Branch 94 taken 8 times.
✗ Branch 95 not taken.
✓ Branch 97 taken 8 times.
✗ Branch 98 not taken.
✓ Branch 100 taken 8 times.
✗ Branch 101 not taken.
✓ Branch 103 taken 8 times.
✗ Branch 104 not taken.
✓ Branch 106 taken 8 times.
✗ Branch 107 not taken.
✓ Branch 109 taken 8 times.
✗ Branch 110 not taken.
✓ Branch 112 taken 8 times.
✗ Branch 113 not taken.
✓ Branch 115 taken 8 times.
✗ Branch 116 not taken.
✓ Branch 118 taken 8 times.
✗ Branch 119 not taken.
✓ Branch 121 taken 8 times.
✗ Branch 122 not taken.
✓ Branch 124 taken 8 times.
✗ Branch 125 not taken.
8 "FROM [cte] ";
342
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if (parent_has_value)
343 {
344
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
6 string_stream << "WHERE " << column_name_ancestor_id << "=?1;";
345 }
346 else
347 {
348
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 << "WHERE " << column_name_ancestor_id << " IS NULL;";
349 }
350 }
351 else
352 {
353 string_stream <<
354
15/30
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 28 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 28 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 28 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 28 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 28 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 28 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 28 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 28 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 28 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 28 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 28 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 28 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 28 times.
✗ Branch 44 not taken.
28 "SELECT " << column_name_pk << "," << column_name_name << "," << column_name_type_discriminator << "," << column_name_value_double << "," << column_name_value_integer << "," << column_name_value_string << " FROM [" << metadata_table_name << "] ";
355
356
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (parent_has_value)
357 {
358
3/6
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 28 times.
✗ Branch 8 not taken.
28 string_stream << "WHERE " << column_name_ancestor_id << "=?1 ";
359 }
360 else
361 {
362 string_stream << "WHERE " << column_name_ancestor_id << " IS NULL ";
363 }
364 }
365 }
366
367
2/4
✓ Branch 5 taken 62 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 62 times.
✗ Branch 9 not taken.
62 auto statement = this->GetDocument()->GetDatabase_connection()->PrepareStatement(string_stream.str());
368
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 10 times.
62 if (parent_has_value)
369 {
370
2/4
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 52 times.
✗ Branch 6 not taken.
52 statement->BindInt64(1, parent.value());
371 }
372
373 124 return statement;
374 62 }
375
376 210 imgdoc2::DocumentMetadataItem DocumentMetadataReader::RetrieveDocumentMetadataItemFromStatement(const std::shared_ptr<IDbStatement>& statement, imgdoc2::DocumentMetadataItemFlags flags, const string& path_to_prepend)
377 {
378 210 DocumentMetadataItem item;
379 210 item.flags = flags;
380
2/2
✓ Branch 1 taken 186 times.
✓ Branch 2 taken 24 times.
210 if ((flags & DocumentMetadataItemFlags::kPrimaryKeyValid) == DocumentMetadataItemFlags::kPrimaryKeyValid)
381 {
382
1/2
✓ Branch 2 taken 186 times.
✗ Branch 3 not taken.
186 item.primary_key = statement->GetResultInt64(0);
383 }
384
385
2/2
✓ Branch 1 taken 186 times.
✓ Branch 2 taken 24 times.
210 if ((flags & DocumentMetadataItemFlags::kNameValid) == DocumentMetadataItemFlags::kNameValid)
386 {
387
1/2
✓ Branch 2 taken 186 times.
✗ Branch 3 not taken.
186 item.name = statement->GetResultString(1);
388 }
389
390
2/2
✓ Branch 1 taken 186 times.
✓ Branch 2 taken 24 times.
210 if ((flags & DocumentMetadataItemFlags::kDocumentMetadataTypeAndValueValid) == DocumentMetadataItemFlags::kDocumentMetadataTypeAndValueValid)
391 {
392
1/2
✓ Branch 2 taken 186 times.
✗ Branch 3 not taken.
186 const auto database_item_type_value = statement->GetResultInt32(2);
393
4/6
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 46 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
186 switch (static_cast<DatabaseDataTypeValue>(database_item_type_value))
394 {
395 132 case DatabaseDataTypeValue::null:
396 132 item.value = std::monostate();
397 132 item.type = DocumentMetadataType::kNull;
398 132 break;
399 4 case DatabaseDataTypeValue::int32:
400
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 item.value = IDocumentMetadataWrite::metadata_item_variant(statement->GetResultInt32(4));
401 4 item.type = DocumentMetadataType::kInt32;
402 4 break;
403 4 case DatabaseDataTypeValue::doublefloat:
404
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 item.value = IDocumentMetadataWrite::metadata_item_variant(statement->GetResultDouble(3));
405 4 item.type = DocumentMetadataType::kDouble;
406 4 break;
407 46 case DatabaseDataTypeValue::utf8string:
408
1/2
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
46 item.value = IDocumentMetadataWrite::metadata_item_variant(statement->GetResultString(5));
409 46 item.type = DocumentMetadataType::kText;
410 46 break;
411 case DatabaseDataTypeValue::json:
412 item.value = IDocumentMetadataWrite::metadata_item_variant(statement->GetResultString(5));
413 item.type = DocumentMetadataType::kJson;
414 break;
415 default:
416 throw runtime_error("DocumentMetadataReader::GetItem: Unknown data type");
417 }
418 }
419
420
2/2
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 114 times.
210 if ((flags & DocumentMetadataItemFlags::kCompletePath) == DocumentMetadataItemFlags::kCompletePath)
421 {
422
2/4
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 96 times.
✗ Branch 6 not taken.
96 item.complete_path = path_to_prepend + statement->GetResultString(6);
423 }
424
425 210 return item;
426 }
427
428 48 bool DocumentMetadataReader::GetPathForNode(imgdoc2::dbIndex node_id, std::string& path)
429 {
430 /*
431 Here we construct a query that will return the path for a given node. The query is constructed as follows:
432
433 WITH RECURSIVE item_path(Pk, Name, AncestorId, path) AS(
434 -- Base case: select items with no parent (top-level items)
435 SELECT
436 Pk,
437 Name,
438 AncestorId,
439 Name AS path
440 FROM METADATA
441 WHERE AncestorId IS NULL
442
443 UNION ALL
444
445 -- Recursive case: join items with their parent items in the item_path
446 SELECT
447 i.Pk,
448 i.Name,
449 i.AncestorId,
450 ip.path || '/' || i.Name AS path
451 FROM METADATA i
452 JOIN item_path ip ON i.AncestorId = ip.Pk
453 )
454
455 -- Choose the item for which you want to find the path
456 SELECT path
457 FROM item_path
458 WHERE Pk = :the-item-id-here:;
459 */
460
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 ostringstream string_stream;
461
462
2/4
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 48 times.
✗ Branch 7 not taken.
48 const auto metadata_table_name = this->GetDocument()->GetDataBaseConfigurationCommon()->GetTableNameForMetadataTableOrThrow();
463
2/4
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 48 times.
✗ Branch 7 not taken.
48 const auto column_name_pk = this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_Pk);
464
2/4
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 48 times.
✗ Branch 7 not taken.
48 const auto column_name_name = this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_Name);
465
2/4
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 48 times.
✗ Branch 7 not taken.
48 const auto column_name_ancestor_id = this->GetDocument()->GetDataBaseConfigurationCommon()->GetColumnNameOfMetadataTableOrThrow(DatabaseConfigurationCommon::kMetadataTable_Column_AncestorId);
466
467 string_stream << "WITH RECURSIVE item_path (" << column_name_pk << "," << column_name_name << "," << column_name_ancestor_id << ",path) AS( " <<
468 "SELECT " << column_name_pk << "," << column_name_name << "," << column_name_ancestor_id << "," << column_name_name << " AS path " <<
469 "FROM " << metadata_table_name << " WHERE " << column_name_ancestor_id << " IS NULL " <<
470 "UNION ALL " <<
471 "SELECT i." << column_name_pk << ",i." << column_name_name << ",i." << column_name_ancestor_id << ",ip.path || '" << DocumentMetadataBase::kPathDelimiter_ << "' || i." << column_name_name << " AS path " <<
472 "FROM " << metadata_table_name << " i " <<
473 "JOIN item_path ip ON i." << column_name_ancestor_id << " = ip." << column_name_pk << ") " <<
474
44/88
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 48 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 48 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 48 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 48 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 48 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 48 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 48 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 48 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 48 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 48 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 48 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 48 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 48 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 48 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 48 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 48 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 48 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 48 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 48 times.
✗ Branch 62 not taken.
✓ Branch 64 taken 48 times.
✗ Branch 65 not taken.
✓ Branch 67 taken 48 times.
✗ Branch 68 not taken.
✓ Branch 70 taken 48 times.
✗ Branch 71 not taken.
✓ Branch 73 taken 48 times.
✗ Branch 74 not taken.
✓ Branch 76 taken 48 times.
✗ Branch 77 not taken.
✓ Branch 79 taken 48 times.
✗ Branch 80 not taken.
✓ Branch 82 taken 48 times.
✗ Branch 83 not taken.
✓ Branch 85 taken 48 times.
✗ Branch 86 not taken.
✓ Branch 88 taken 48 times.
✗ Branch 89 not taken.
✓ Branch 91 taken 48 times.
✗ Branch 92 not taken.
✓ Branch 94 taken 48 times.
✗ Branch 95 not taken.
✓ Branch 97 taken 48 times.
✗ Branch 98 not taken.
✓ Branch 100 taken 48 times.
✗ Branch 101 not taken.
✓ Branch 103 taken 48 times.
✗ Branch 104 not taken.
✓ Branch 106 taken 48 times.
✗ Branch 107 not taken.
✓ Branch 109 taken 48 times.
✗ Branch 110 not taken.
✓ Branch 112 taken 48 times.
✗ Branch 113 not taken.
✓ Branch 115 taken 48 times.
✗ Branch 116 not taken.
✓ Branch 118 taken 48 times.
✗ Branch 119 not taken.
✓ Branch 121 taken 48 times.
✗ Branch 122 not taken.
✓ Branch 124 taken 48 times.
✗ Branch 125 not taken.
✓ Branch 127 taken 48 times.
✗ Branch 128 not taken.
✓ Branch 130 taken 48 times.
✗ Branch 131 not taken.
48 "SELECT path FROM item_path WHERE " << column_name_pk << "=?1;";
475
476
2/4
✓ Branch 5 taken 48 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 48 times.
✗ Branch 9 not taken.
48 const auto statement = this->GetDocument()->GetDatabase_connection()->PrepareStatement(string_stream.str());
477
1/2
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
48 statement->BindInt64(1, node_id);
478
479
3/4
✓ Branch 6 taken 48 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✓ Branch 9 taken 36 times.
48 if (!this->GetDocument()->GetDatabase_connection()->StepStatement(statement.get()))
480 {
481 12 return false;
482 }
483
484
1/2
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
36 path = statement->GetResultString(0);
485 36 return true;
486 48 }
487