Mercurial > hg > orthanc-databases
comparison Framework/Plugins/IndexBackend.cpp @ 366:cd9521e04249 attach-custom-data
DatabaseBackendAdapterV4: added support for customData + revision when not already done
author | Alain Mazy <am@osimis.io> |
---|---|
date | Thu, 15 Sep 2022 18:12:34 +0200 |
parents | 2a3bbb4104fa |
children | f18e46d7dbf8 |
comparison
equal
deleted
inserted
replaced
365:7671fa7f099e | 366:cd9521e04249 |
---|---|
25 #include "../Common/BinaryStringValue.h" | 25 #include "../Common/BinaryStringValue.h" |
26 #include "../Common/Integer64Value.h" | 26 #include "../Common/Integer64Value.h" |
27 #include "../Common/Utf8StringValue.h" | 27 #include "../Common/Utf8StringValue.h" |
28 #include "DatabaseBackendAdapterV2.h" | 28 #include "DatabaseBackendAdapterV2.h" |
29 #include "DatabaseBackendAdapterV3.h" | 29 #include "DatabaseBackendAdapterV3.h" |
30 #include "DatabaseBackendAdapterV4.h" | |
30 #include "GlobalProperties.h" | 31 #include "GlobalProperties.h" |
31 | 32 |
32 #include <Compatibility.h> // For std::unique_ptr<> | 33 #include <Compatibility.h> // For std::unique_ptr<> |
33 #include <Logging.h> | 34 #include <Logging.h> |
34 #include <OrthancException.h> | 35 #include <OrthancException.h> |
200 DatabaseManager& manager) | 201 DatabaseManager& manager) |
201 { | 202 { |
202 DatabaseManager::CachedStatement statement( | 203 DatabaseManager::CachedStatement statement( |
203 STATEMENT_FROM_HERE, manager, | 204 STATEMENT_FROM_HERE, manager, |
204 "SELECT uuid, fileType, uncompressedSize, uncompressedHash, compressionType, " | 205 "SELECT uuid, fileType, uncompressedSize, uncompressedHash, compressionType, " |
205 "compressedSize, compressedHash FROM DeletedFiles"); | 206 "compressedSize, compressedHash, revision, customData FROM DeletedFiles"); |
206 | 207 |
207 statement.SetReadOnly(true); | 208 statement.SetReadOnly(true); |
208 statement.Execute(); | 209 statement.Execute(); |
209 | 210 |
210 while (!statement.IsDone()) | 211 while (!statement.IsDone()) |
213 statement.ReadInteger32(1), | 214 statement.ReadInteger32(1), |
214 statement.ReadInteger64(2), | 215 statement.ReadInteger64(2), |
215 statement.ReadString(3), | 216 statement.ReadString(3), |
216 statement.ReadInteger32(4), | 217 statement.ReadInteger32(4), |
217 statement.ReadInteger64(5), | 218 statement.ReadInteger64(5), |
218 statement.ReadString(6)); | 219 statement.ReadString(6), |
220 statement.ReadString(8)); | |
219 | 221 |
220 statement.Next(); | 222 statement.Next(); |
221 } | 223 } |
222 } | 224 } |
223 | 225 |
280 { | 282 { |
281 return outputFactory_->CreateOutput(); | 283 return outputFactory_->CreateOutput(); |
282 } | 284 } |
283 } | 285 } |
284 | 286 |
285 | 287 static void ExecuteAddAttachment(DatabaseManager& manager, |
286 static void ExecuteAddAttachment(DatabaseManager::CachedStatement& statement, | |
287 Dictionary& args, | |
288 int64_t id, | 288 int64_t id, |
289 const OrthancPluginAttachment& attachment) | 289 const char* uuid, |
290 { | 290 int32_t contentType, |
291 uint64_t uncompressedSize, | |
292 const char* uncompressedHash, | |
293 int32_t compressionType, | |
294 uint64_t compressedSize, | |
295 const char* compressedHash, | |
296 const char* customData, | |
297 int64_t revision) | |
298 { | |
299 DatabaseManager::CachedStatement statement( | |
300 STATEMENT_FROM_HERE, manager, | |
301 "INSERT INTO AttachedFiles VALUES(${id}, ${type}, ${uuid}, ${compressed}, " | |
302 "${uncompressed}, ${compression}, ${hash}, ${hash-compressed}, ${revision}, ${custom-data})"); | |
303 | |
304 Dictionary args; | |
305 | |
291 statement.SetParameterType("id", ValueType_Integer64); | 306 statement.SetParameterType("id", ValueType_Integer64); |
292 statement.SetParameterType("type", ValueType_Integer64); | 307 statement.SetParameterType("type", ValueType_Integer64); |
293 statement.SetParameterType("uuid", ValueType_Utf8String); | 308 statement.SetParameterType("uuid", ValueType_Utf8String); |
294 statement.SetParameterType("compressed", ValueType_Integer64); | 309 statement.SetParameterType("compressed", ValueType_Integer64); |
295 statement.SetParameterType("uncompressed", ValueType_Integer64); | 310 statement.SetParameterType("uncompressed", ValueType_Integer64); |
296 statement.SetParameterType("compression", ValueType_Integer64); | 311 statement.SetParameterType("compression", ValueType_Integer64); |
297 statement.SetParameterType("hash", ValueType_Utf8String); | 312 statement.SetParameterType("hash", ValueType_Utf8String); |
298 statement.SetParameterType("hash-compressed", ValueType_Utf8String); | 313 statement.SetParameterType("hash-compressed", ValueType_Utf8String); |
314 statement.SetParameterType("revision", ValueType_Integer64); | |
315 statement.SetParameterType("custom-data", ValueType_Utf8String); | |
299 | 316 |
300 args.SetIntegerValue("id", id); | 317 args.SetIntegerValue("id", id); |
301 args.SetIntegerValue("type", attachment.contentType); | 318 args.SetIntegerValue("type", contentType); |
302 args.SetUtf8Value("uuid", attachment.uuid); | 319 args.SetUtf8Value("uuid", uuid); |
303 args.SetIntegerValue("compressed", attachment.compressedSize); | 320 args.SetIntegerValue("compressed", compressedSize); |
304 args.SetIntegerValue("uncompressed", attachment.uncompressedSize); | 321 args.SetIntegerValue("uncompressed", uncompressedSize); |
305 args.SetIntegerValue("compression", attachment.compressionType); | 322 args.SetIntegerValue("compression", compressionType); |
306 args.SetUtf8Value("hash", attachment.uncompressedHash); | 323 args.SetUtf8Value("hash", uncompressedHash); |
307 args.SetUtf8Value("hash-compressed", attachment.compressedHash); | 324 args.SetUtf8Value("hash-compressed", compressedHash); |
325 args.SetIntegerValue("revision", revision); | |
326 args.SetUtf8Value("custom-data", customData); | |
308 | 327 |
309 statement.Execute(args); | 328 statement.Execute(args); |
310 } | 329 } |
311 | 330 |
312 | 331 |
313 void IndexBackend::AddAttachment(DatabaseManager& manager, | 332 void IndexBackend::AddAttachment(DatabaseManager& manager, |
314 int64_t id, | 333 int64_t id, |
315 const OrthancPluginAttachment& attachment, | 334 const OrthancPluginAttachment& attachment, |
316 int64_t revision) | 335 int64_t revision) |
317 { | 336 { |
318 if (HasRevisionsSupport()) | 337 assert(HasRevisionsSupport() && HasAttachmentCustomDataSupport()); // all plugins supports these features now |
319 { | 338 ExecuteAddAttachment(manager, id, attachment.uuid, attachment.contentType, attachment.uncompressedSize, attachment.uncompressedHash, |
320 DatabaseManager::CachedStatement statement( | 339 attachment.compressionType, attachment.compressedSize, attachment.compressedHash, "", revision); |
321 STATEMENT_FROM_HERE, manager, | 340 } |
322 "INSERT INTO AttachedFiles VALUES(${id}, ${type}, ${uuid}, ${compressed}, " | 341 |
323 "${uncompressed}, ${compression}, ${hash}, ${hash-compressed}, ${revision})"); | 342 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 0) |
324 | 343 void IndexBackend::AddAttachment2(DatabaseManager& manager, |
325 Dictionary args; | 344 int64_t id, |
326 | 345 const OrthancPluginAttachment2& attachment, |
327 statement.SetParameterType("revision", ValueType_Integer64); | 346 int64_t revision) |
328 args.SetIntegerValue("revision", revision); | 347 { |
329 | 348 assert(HasRevisionsSupport() && HasAttachmentCustomDataSupport()); // all plugins supports these features now |
330 ExecuteAddAttachment(statement, args, id, attachment); | 349 ExecuteAddAttachment(manager, id, attachment.uuid, attachment.contentType, attachment.uncompressedSize, attachment.uncompressedHash, |
331 } | 350 attachment.compressionType, attachment.compressedSize, attachment.compressedHash, attachment.customData, revision); |
332 else | 351 } |
333 { | 352 #endif |
334 DatabaseManager::CachedStatement statement( | |
335 STATEMENT_FROM_HERE, manager, | |
336 "INSERT INTO AttachedFiles VALUES(${id}, ${type}, ${uuid}, ${compressed}, " | |
337 "${uncompressed}, ${compression}, ${hash}, ${hash-compressed})"); | |
338 | |
339 Dictionary args; | |
340 ExecuteAddAttachment(statement, args, id, attachment); | |
341 } | |
342 } | |
343 | |
344 | 353 |
345 void IndexBackend::AttachChild(DatabaseManager& manager, | 354 void IndexBackend::AttachChild(DatabaseManager& manager, |
346 int64_t parent, | 355 int64_t parent, |
347 int64_t child) | 356 int64_t child) |
348 { | 357 { |
1035 args.SetUtf8Value("date", resource.date); | 1044 args.SetUtf8Value("date", resource.date); |
1036 | 1045 |
1037 statement.Execute(args); | 1046 statement.Execute(args); |
1038 } | 1047 } |
1039 | 1048 |
1040 | 1049 |
1041 static bool ExecuteLookupAttachment(DatabaseManager::CachedStatement& statement, | 1050 /* Use GetOutput().AnswerAttachment() */ |
1042 IDatabaseBackendOutput& output, | 1051 bool IndexBackend::LookupAttachment(IDatabaseBackendOutput& output, |
1052 int64_t& revision /*out*/, | |
1053 DatabaseManager& manager, | |
1043 int64_t id, | 1054 int64_t id, |
1044 int32_t contentType) | 1055 int32_t contentType) |
1045 { | 1056 { |
1057 assert(HasRevisionsSupport() && HasAttachmentCustomDataSupport()); // we force v4 plugins to support both ! | |
1058 DatabaseManager::CachedStatement statement( | |
1059 STATEMENT_FROM_HERE, manager, | |
1060 "SELECT uuid, uncompressedSize, compressionType, compressedSize, uncompressedHash, " | |
1061 "compressedHash, revision, customData FROM AttachedFiles WHERE id=${id} AND fileType=${type}"); | |
1062 | |
1063 | |
1046 statement.SetReadOnly(true); | 1064 statement.SetReadOnly(true); |
1047 statement.SetParameterType("id", ValueType_Integer64); | 1065 statement.SetParameterType("id", ValueType_Integer64); |
1048 statement.SetParameterType("type", ValueType_Integer64); | 1066 statement.SetParameterType("type", ValueType_Integer64); |
1049 | 1067 |
1050 Dictionary args; | 1068 Dictionary args; |
1057 { | 1075 { |
1058 return false; | 1076 return false; |
1059 } | 1077 } |
1060 else | 1078 else |
1061 { | 1079 { |
1080 if (statement.GetResultField(6).GetType() == ValueType_Null) | |
1081 { | |
1082 // "NULL" can happen with a database created by PostgreSQL | |
1083 // plugin <= 3.3 (because of "ALTER TABLE AttachedFiles") | |
1084 revision = 0; | |
1085 } | |
1086 else | |
1087 { | |
1088 revision = statement.ReadInteger64(6); | |
1089 } | |
1090 | |
1091 std::string customData; | |
1092 if (statement.GetResultField(7).GetType() == ValueType_Utf8String) // column has been added in 1.12.0 | |
1093 { | |
1094 customData = statement.ReadString(7); | |
1095 } | |
1096 | |
1097 | |
1062 output.AnswerAttachment(statement.ReadString(0), | 1098 output.AnswerAttachment(statement.ReadString(0), |
1063 contentType, | 1099 contentType, |
1064 statement.ReadInteger64(1), | 1100 statement.ReadInteger64(1), |
1065 statement.ReadString(4), | 1101 statement.ReadString(4), |
1066 statement.ReadInteger32(2), | 1102 statement.ReadInteger32(2), |
1067 statement.ReadInteger64(3), | 1103 statement.ReadInteger64(3), |
1068 statement.ReadString(5)); | 1104 statement.ReadString(5), |
1105 customData); | |
1069 return true; | 1106 return true; |
1070 } | 1107 } |
1071 } | 1108 |
1072 | |
1073 | |
1074 | |
1075 /* Use GetOutput().AnswerAttachment() */ | |
1076 bool IndexBackend::LookupAttachment(IDatabaseBackendOutput& output, | |
1077 int64_t& revision /*out*/, | |
1078 DatabaseManager& manager, | |
1079 int64_t id, | |
1080 int32_t contentType) | |
1081 { | |
1082 if (HasRevisionsSupport()) | |
1083 { | |
1084 DatabaseManager::CachedStatement statement( | |
1085 STATEMENT_FROM_HERE, manager, | |
1086 "SELECT uuid, uncompressedSize, compressionType, compressedSize, uncompressedHash, " | |
1087 "compressedHash, revision FROM AttachedFiles WHERE id=${id} AND fileType=${type}"); | |
1088 | |
1089 if (ExecuteLookupAttachment(statement, output, id, contentType)) | |
1090 { | |
1091 if (statement.GetResultField(6).GetType() == ValueType_Null) | |
1092 { | |
1093 // "NULL" can happen with a database created by PostgreSQL | |
1094 // plugin <= 3.3 (because of "ALTER TABLE AttachedFiles") | |
1095 revision = 0; | |
1096 } | |
1097 else | |
1098 { | |
1099 revision = statement.ReadInteger64(6); | |
1100 } | |
1101 | |
1102 return true; | |
1103 } | |
1104 else | |
1105 { | |
1106 return false; | |
1107 } | |
1108 } | |
1109 else | |
1110 { | |
1111 DatabaseManager::CachedStatement statement( | |
1112 STATEMENT_FROM_HERE, manager, | |
1113 "SELECT uuid, uncompressedSize, compressionType, compressedSize, uncompressedHash, " | |
1114 "compressedHash FROM AttachedFiles WHERE id=${id} AND fileType=${type}"); | |
1115 | |
1116 revision = 0; | |
1117 | |
1118 return ExecuteLookupAttachment(statement, output, id, contentType); | |
1119 } | |
1120 } | 1109 } |
1121 | 1110 |
1122 | 1111 |
1123 static bool ReadGlobalProperty(std::string& target, | 1112 static bool ReadGlobalProperty(std::string& target, |
1124 DatabaseManager::CachedStatement& statement, | 1113 DatabaseManager::CachedStatement& statement, |
2607 if (backend == NULL) | 2596 if (backend == NULL) |
2608 { | 2597 { |
2609 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | 2598 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); |
2610 } | 2599 } |
2611 | 2600 |
2612 bool hasLoadedV3 = false; | 2601 bool hasLoadedV3OrAbove = false; |
2613 | 2602 |
2614 #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1 | 2603 #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1 |
2615 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2) | 2604 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 0) |
2616 if (OrthancPluginCheckVersionAdvanced(backend->GetContext(), 1, 9, 2) == 1) | 2605 if (OrthancPluginCheckVersionAdvanced(backend->GetContext(), 1, 12, 0) == 1) |
2617 { | 2606 { |
2618 LOG(WARNING) << "The index plugin will use " << countConnections << " connection(s) to the database, " | 2607 LOG(WARNING) << "The index plugin will use " << countConnections << " connection(s) to the database, " |
2619 << "and will retry up to " << maxDatabaseRetries << " time(s) in the case of a collision"; | 2608 << "and will retry up to " << maxDatabaseRetries << " time(s) in the case of a collision"; |
2620 | 2609 |
2610 OrthancDatabases::DatabaseBackendAdapterV4::Register(backend, countConnections, maxDatabaseRetries); | |
2611 hasLoadedV3OrAbove = true; | |
2612 } | |
2613 # elif ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2) | |
2614 if (OrthancPluginCheckVersionAdvanced(backend->GetContext(), 1, 9, 2) == 1) | |
2615 { | |
2616 LOG(WARNING) << "The index plugin will use " << countConnections << " connection(s) to the database, " | |
2617 << "and will retry up to " << maxDatabaseRetries << " time(s) in the case of a collision"; | |
2618 | |
2621 OrthancDatabases::DatabaseBackendAdapterV3::Register(backend, countConnections, maxDatabaseRetries); | 2619 OrthancDatabases::DatabaseBackendAdapterV3::Register(backend, countConnections, maxDatabaseRetries); |
2622 hasLoadedV3 = true; | 2620 hasLoadedV3OrAbove = true; |
2623 } | 2621 } |
2624 # endif | 2622 # endif |
2625 #endif | 2623 #endif |
2626 | 2624 |
2627 if (!hasLoadedV3) | 2625 if (!hasLoadedV3OrAbove) |
2628 { | 2626 { |
2629 LOG(WARNING) << "Performance warning: Your version of the Orthanc core or SDK doesn't support multiple readers/writers"; | 2627 LOG(WARNING) << "Performance warning: Your version of the Orthanc core or SDK doesn't support multiple readers/writers"; |
2630 OrthancDatabases::DatabaseBackendAdapterV2::Register(backend); | 2628 OrthancDatabases::DatabaseBackendAdapterV2::Register(backend); |
2631 } | 2629 } |
2632 } | 2630 } |