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 }