comparison Framework/Plugins/IndexBackend.cpp @ 581:a80775ee5eea find-refactoring

MySQL: Added support for ExtendedFind
author Alain Mazy <am@orthanc.team>
date Mon, 21 Oct 2024 14:34:57 +0200
parents 35d2df9572b1
children 8296c6a0238e
comparison
equal deleted inserted replaced
580:35d2df9572b1 581:a80775ee5eea
2189 default: 2189 default:
2190 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); 2190 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
2191 } 2191 }
2192 } 2192 }
2193 2193
2194 virtual std::string FormatNull(const char* type)
2195 {
2196 switch (dialect_)
2197 {
2198 case Dialect_PostgreSQL:
2199 return std::string("NULL::") + type;
2200 case Dialect_MSSQL:
2201 case Dialect_SQLite:
2202 case Dialect_MySQL:
2203 return "NULL";
2204
2205 default:
2206 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
2207 }
2208 }
2209
2210
2194 virtual std::string FormatLimits(uint64_t since, uint64_t count) 2211 virtual std::string FormatLimits(uint64_t since, uint64_t count)
2195 { 2212 {
2196 std::string sql; 2213 std::string sql;
2197 2214
2198 switch (dialect_) 2215 switch (dialect_)
2208 sql += " FETCH NEXT " + boost::lexical_cast<std::string>(count) + " ROWS ONLY "; 2225 sql += " FETCH NEXT " + boost::lexical_cast<std::string>(count) + " ROWS ONLY ";
2209 } 2226 }
2210 }; break; 2227 }; break;
2211 case Dialect_SQLite: 2228 case Dialect_SQLite:
2212 case Dialect_PostgreSQL: 2229 case Dialect_PostgreSQL:
2213 case Dialect_MySQL:
2214 { 2230 {
2215 if (count > 0) 2231 if (count > 0)
2216 { 2232 {
2217 sql += " LIMIT " + boost::lexical_cast<std::string>(count); 2233 sql += " LIMIT " + boost::lexical_cast<std::string>(count);
2218 } 2234 }
2219 if (since > 0) 2235 if (since > 0)
2220 { 2236 {
2221 sql += " OFFSET " + boost::lexical_cast<std::string>(since); 2237 sql += " OFFSET " + boost::lexical_cast<std::string>(since);
2238 }
2239 }; break;
2240 case Dialect_MySQL:
2241 {
2242 if (count > 0 && since > 0)
2243 {
2244 sql += " LIMIT " + boost::lexical_cast<std::string>(since) + ", " + boost::lexical_cast<std::string>(count);
2245 }
2246 else if (count > 0)
2247 {
2248 sql += " LIMIT " + boost::lexical_cast<std::string>(count);
2249 }
2250 else if (since > 0)
2251 {
2252 sql += " LIMIT " + boost::lexical_cast<std::string>(since) + ", 18446744073709551615"; // max uint64 value when you don't want any limit
2222 } 2253 }
2223 }; break; 2254 }; break;
2224 default: 2255 default:
2225 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); 2256 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
2226 } 2257 }
3197 std::string lookupSql; 3228 std::string lookupSql;
3198 ISqlLookupFormatter::Apply(lookupSql, formatter, request); 3229 ISqlLookupFormatter::Apply(lookupSql, formatter, request);
3199 3230
3200 sql = "WITH Lookup AS (" + lookupSql + ") SELECT COUNT(*) FROM Lookup"; 3231 sql = "WITH Lookup AS (" + lookupSql + ") SELECT COUNT(*) FROM Lookup";
3201 3232
3202 DatabaseManager::StandaloneStatement statement(manager, sql); // TODO-FIND: cache dynamic statement ? Probably worth it since it can be very complex queries ! 3233 DatabaseManager::CachedStatement statement(STATEMENT_FROM_HERE_DYNAMIC(sql), manager, sql);
3203 formatter.PrepareStatement(statement);
3204 statement.Execute(formatter.GetDictionary()); 3234 statement.Execute(formatter.GetDictionary());
3205 response.mutable_count_resources()->set_count(statement.ReadInteger64(0)); 3235 response.mutable_count_resources()->set_count(statement.ReadInteger64(0));
3206 } 3236 }
3207 3237
3208 void IndexBackend::ExecuteFind(Orthanc::DatabasePluginMessages::TransactionResponse& response, 3238 void IndexBackend::ExecuteFind(Orthanc::DatabasePluginMessages::TransactionResponse& response,
3222 3252
3223 std::string sql; 3253 std::string sql;
3224 3254
3225 // extract the resource id of interest by executing the lookup in a CTE 3255 // extract the resource id of interest by executing the lookup in a CTE
3226 LookupFormatter formatter(manager.GetDialect()); 3256 LookupFormatter formatter(manager.GetDialect());
3227 std::string lookupSql; 3257 std::string lookupSqlCTE;
3228 ISqlLookupFormatter::Apply(lookupSql, formatter, request); 3258 ISqlLookupFormatter::Apply(lookupSqlCTE, formatter, request);
3229 3259
3230 // base query, retrieve the ordered internalId and publicId of the selected resources 3260 // base query, retrieve the ordered internalId and publicId of the selected resources
3231 sql = "WITH Lookup AS (" + lookupSql + ") " 3261 sql = "WITH Lookup AS (" + lookupSqlCTE + ") ";
3232 "SELECT " 3262
3263 std::string oneInstanceSqlCTE;
3264
3265 if (request.level() != Orthanc::DatabasePluginMessages::ResourceType::RESOURCE_INSTANCE &&
3266 request.retrieve_one_instance_metadata_and_attachments())
3267 {
3268 switch (request.level())
3269 {
3270 case Orthanc::DatabasePluginMessages::ResourceType::RESOURCE_SERIES:
3271 {
3272 oneInstanceSqlCTE = "SELECT Lookup.internalId AS parentInternalId, childLevel.publicId AS instancePublicId, childLevel.internalId AS instanceInternalId, ROW_NUMBER() OVER (PARTITION BY Lookup.internalId ORDER BY childLevel.publicId) AS rowNum"
3273 " FROM Resources AS childLevel "
3274 " INNER JOIN Lookup ON childLevel.parentId = Lookup.internalId";
3275 }; break;
3276 case Orthanc::DatabasePluginMessages::ResourceType::RESOURCE_STUDY:
3277 {
3278 oneInstanceSqlCTE = "SELECT Lookup.internalId AS parentInternalId, grandChildLevel.publicId AS instancePublicId, grandChildLevel.internalId AS instanceInternalId, ROW_NUMBER() OVER (PARTITION BY Lookup.internalId ORDER BY grandChildLevel.publicId) AS rowNum"
3279 " FROM Resources AS grandChildLevel "
3280 " INNER JOIN Resources childLevel ON grandChildLevel.parentId = childLevel.internalId "
3281 " INNER JOIN Lookup ON childLevel.parentId = Lookup.internalId";
3282 }; break;
3283 case Orthanc::DatabasePluginMessages::ResourceType::RESOURCE_PATIENT:
3284 {
3285 oneInstanceSqlCTE = "SELECT Lookup.internalId AS parentInternalId, grandGrandChildLevel.publicId AS instancePublicId, grandGrandChildLevel.internalId AS instanceInternalId, ROW_NUMBER() OVER (PARTITION BY Lookup.internalId ORDER BY grandGrandChildLevel.publicId) AS rowNum"
3286 " FROM Resources AS grandGrandChildLevel "
3287 " INNER JOIN Resources grandChildLevel ON grandGrandChildLevel.parentId = grandChildLevel.internalId "
3288 " INNER JOIN Resources childLevel ON grandChildLevel.parentId = childLevel.internalId "
3289 " INNER JOIN Lookup ON childLevel.parentId = Lookup.internalId";
3290 }; break;
3291 default:
3292 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
3293 }
3294 sql += ", _OneInstance AS (" + oneInstanceSqlCTE + ") ";
3295 sql += ", OneInstance AS (SELECT parentInternalId, instancePublicId, instanceInternalId FROM _OneInstance WHERE rowNum = 1) "; // this is a generic way to implement DISTINCT ON
3296 }
3297
3298 // if (!oneInstanceSqlCTE.empty() && (manager.GetDialect() == Dialect_MySQL || manager.GetDialect() == Dialect_SQLite))
3299 // { // all CTEs must be declared first in some dialects
3300 // }
3301
3302 sql += " SELECT "
3233 " " TOSTRING(QUERY_LOOKUP) " AS c0_queryId, " 3303 " " TOSTRING(QUERY_LOOKUP) " AS c0_queryId, "
3234 " Lookup.internalId AS c1_internalId, " 3304 " Lookup.internalId AS c1_internalId, "
3235 " Lookup.rowNumber AS c2_rowNumber, " 3305 " Lookup.rowNumber AS c2_rowNumber, "
3236 " Lookup.publicId AS c3_string1, " 3306 " Lookup.publicId AS c3_string1, "
3237 " NULL::TEXT AS c4_string2, " 3307 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3238 " NULL::TEXT AS c5_string3, " 3308 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3239 " NULL::INT AS c6_int1, " 3309 " " + formatter.FormatNull("INT") + " AS c6_int1, "
3240 " NULL::INT AS c7_int2, " 3310 " " + formatter.FormatNull("INT") + " AS c7_int2, "
3241 " NULL::BIGINT AS c8_big_int1, " 3311 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3242 " NULL::BIGINT AS c9_big_int2 " 3312 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3243 " FROM Lookup "; 3313 " FROM Lookup ";
3244 3314
3245 // need MainDicomTags from resource ? 3315 // need MainDicomTags from resource ?
3246 if (request.retrieve_main_dicom_tags()) 3316 if (request.retrieve_main_dicom_tags())
3247 { 3317 {
3248 sql += "UNION SELECT " 3318 sql += "UNION ALL SELECT "
3249 " " TOSTRING(QUERY_MAIN_DICOM_TAGS) " AS c0_queryId, " 3319 " " TOSTRING(QUERY_MAIN_DICOM_TAGS) " AS c0_queryId, "
3250 " Lookup.internalId AS c1_internalId, " 3320 " Lookup.internalId AS c1_internalId, "
3251 " NULL::BIGINT AS c2_rowNumber, " 3321 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3252 " value AS c3_string1, " 3322 " value AS c3_string1, "
3253 " NULL::TEXT AS c4_string2, " 3323 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3254 " NULL::TEXT AS c5_string3, " 3324 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3255 " tagGroup AS c6_int1, " 3325 " tagGroup AS c6_int1, "
3256 " tagElement AS c7_int2, " 3326 " tagElement AS c7_int2, "
3257 " NULL::BIGINT AS c8_big_int1, " 3327 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3258 " NULL::BIGINT AS c9_big_int2 " 3328 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3259 "FROM Lookup " 3329 "FROM Lookup "
3260 "INNER JOIN MainDicomTags ON MainDicomTags.id = Lookup.internalId "; 3330 "INNER JOIN MainDicomTags ON MainDicomTags.id = Lookup.internalId ";
3261 } 3331 }
3262 3332
3263 // need resource metadata ? 3333 // need resource metadata ?
3264 if (request.retrieve_metadata()) 3334 if (request.retrieve_metadata())
3265 { 3335 {
3266 sql += "UNION SELECT " 3336 sql += "UNION ALL SELECT "
3267 " " TOSTRING(QUERY_METADATA) " AS c0_queryId, " 3337 " " TOSTRING(QUERY_METADATA) " AS c0_queryId, "
3268 " Lookup.internalId AS c1_internalId, " 3338 " Lookup.internalId AS c1_internalId, "
3269 " NULL::BIGINT AS c2_rowNumber, " 3339 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3270 " value AS c3_string1, " 3340 " value AS c3_string1, "
3271 " NULL::TEXT AS c4_string2, " 3341 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3272 " NULL::TEXT AS c5_string3, " 3342 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3273 " type AS c6_int1, " 3343 " type AS c6_int1, "
3274 " NULL::INT AS c7_int2, " 3344 " " + formatter.FormatNull("INT") + " AS c7_int2, "
3275 " NULL::BIGINT AS c8_big_int1, " 3345 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3276 " NULL::BIGINT AS c9_big_int2 " 3346 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3277 "FROM Lookup " 3347 "FROM Lookup "
3278 "INNER JOIN Metadata ON Metadata.id = Lookup.internalId "; 3348 "INNER JOIN Metadata ON Metadata.id = Lookup.internalId ";
3279 } 3349 }
3280 3350
3281 // need resource attachments ? 3351 // need resource attachments ?
3282 if (request.retrieve_attachments()) 3352 if (request.retrieve_attachments())
3283 { 3353 {
3284 sql += "UNION SELECT " 3354 sql += "UNION ALL SELECT "
3285 " " TOSTRING(QUERY_ATTACHMENTS) " AS c0_queryId, " 3355 " " TOSTRING(QUERY_ATTACHMENTS) " AS c0_queryId, "
3286 " Lookup.internalId AS c1_internalId, " 3356 " Lookup.internalId AS c1_internalId, "
3287 " NULL::BIGINT AS c2_rowNumber, " 3357 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3288 " uuid AS c3_string1, " 3358 " uuid AS c3_string1, "
3289 " uncompressedHash AS c4_string2, " 3359 " uncompressedHash AS c4_string2, "
3290 " compressedHash AS c5_string3, " 3360 " compressedHash AS c5_string3, "
3291 " fileType AS c6_int1, " 3361 " fileType AS c6_int1, "
3292 " compressionType AS c7_int2, " 3362 " compressionType AS c7_int2, "
3297 } 3367 }
3298 3368
3299 // need resource labels ? 3369 // need resource labels ?
3300 if (request.retrieve_labels()) 3370 if (request.retrieve_labels())
3301 { 3371 {
3302 sql += "UNION SELECT " 3372 sql += "UNION ALL SELECT "
3303 " " TOSTRING(QUERY_LABELS) " AS c0_queryId, " 3373 " " TOSTRING(QUERY_LABELS) " AS c0_queryId, "
3304 " Lookup.internalId AS c1_internalId, " 3374 " Lookup.internalId AS c1_internalId, "
3305 " NULL::BIGINT AS c2_rowNumber, " 3375 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3306 " label AS c3_string1, " 3376 " label AS c3_string1, "
3307 " NULL::TEXT AS c4_string2, " 3377 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3308 " NULL::TEXT AS c5_string3, " 3378 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3309 " NULL::INT AS c6_int1, " 3379 " " + formatter.FormatNull("INT") + " AS c6_int1, "
3310 " NULL::INT AS c7_int2, " 3380 " " + formatter.FormatNull("INT") + " AS c7_int2, "
3311 " NULL::BIGINT AS c8_big_int1, " 3381 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3312 " NULL::BIGINT AS c9_big_int2 " 3382 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3313 "FROM Lookup " 3383 "FROM Lookup "
3314 "INNER JOIN Labels ON Labels.id = Lookup.internalId "; 3384 "INNER JOIN Labels ON Labels.id = Lookup.internalId ";
3315 } 3385 }
3316 3386
3317 // need MainDicomTags from parent ? 3387 // need MainDicomTags from parent ?
3334 break; 3404 break;
3335 } 3405 }
3336 3406
3337 if (parentSpec->retrieve_main_dicom_tags()) 3407 if (parentSpec->retrieve_main_dicom_tags())
3338 { 3408 {
3339 sql += "UNION SELECT " 3409 sql += "UNION ALL SELECT "
3340 " " TOSTRING(QUERY_PARENT_MAIN_DICOM_TAGS) " AS c0_queryId, " 3410 " " TOSTRING(QUERY_PARENT_MAIN_DICOM_TAGS) " AS c0_queryId, "
3341 " Lookup.internalId AS c1_internalId, " 3411 " Lookup.internalId AS c1_internalId, "
3342 " NULL::BIGINT AS c2_rowNumber, " 3412 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3343 " value AS c3_string1, " 3413 " value AS c3_string1, "
3344 " NULL::TEXT AS c4_string2, " 3414 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3345 " NULL::TEXT AS c5_string3, " 3415 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3346 " tagGroup AS c6_int1, " 3416 " tagGroup AS c6_int1, "
3347 " tagElement AS c7_int2, " 3417 " tagElement AS c7_int2, "
3348 " NULL::BIGINT AS c8_big_int1, " 3418 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3349 " NULL::BIGINT AS c9_big_int2 " 3419 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3350 "FROM Lookup " 3420 "FROM Lookup "
3351 "INNER JOIN Resources currentLevel ON Lookup.internalId = currentLevel.internalId " 3421 "INNER JOIN Resources currentLevel ON Lookup.internalId = currentLevel.internalId "
3352 "INNER JOIN MainDicomTags ON MainDicomTags.id = currentLevel.parentId "; 3422 "INNER JOIN MainDicomTags ON MainDicomTags.id = currentLevel.parentId ";
3353 } 3423 }
3354 3424
3355 if (parentSpec->retrieve_metadata()) 3425 if (parentSpec->retrieve_metadata())
3356 { 3426 {
3357 sql += "UNION SELECT " 3427 sql += "UNION ALL SELECT "
3358 " " TOSTRING(QUERY_PARENT_METADATA) " AS c0_queryId, " 3428 " " TOSTRING(QUERY_PARENT_METADATA) " AS c0_queryId, "
3359 " Lookup.internalId AS c1_internalId, " 3429 " Lookup.internalId AS c1_internalId, "
3360 " NULL::BIGINT AS c2_rowNumber, " 3430 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3361 " value AS c3_string1, " 3431 " value AS c3_string1, "
3362 " NULL::TEXT AS c4_string2, " 3432 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3363 " NULL::TEXT AS c5_string3, " 3433 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3364 " type AS c6_int1, " 3434 " type AS c6_int1, "
3365 " NULL::INT AS c7_int2, " 3435 " " + formatter.FormatNull("INT") + " AS c7_int2, "
3366 " NULL::BIGINT AS c8_big_int1, " 3436 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3367 " NULL::BIGINT AS c9_big_int2 " 3437 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3368 "FROM Lookup " 3438 "FROM Lookup "
3369 "INNER JOIN Resources currentLevel ON Lookup.internalId = currentLevel.internalId " 3439 "INNER JOIN Resources currentLevel ON Lookup.internalId = currentLevel.internalId "
3370 "INNER JOIN Metadata ON Metadata.id = currentLevel.parentId "; 3440 "INNER JOIN Metadata ON Metadata.id = currentLevel.parentId ";
3371 } 3441 }
3372 3442
3387 break; 3457 break;
3388 } 3458 }
3389 3459
3390 if (grandparentSpec->retrieve_main_dicom_tags()) 3460 if (grandparentSpec->retrieve_main_dicom_tags())
3391 { 3461 {
3392 sql += "UNION SELECT " 3462 sql += "UNION ALL SELECT "
3393 " " TOSTRING(QUERY_GRAND_PARENT_MAIN_DICOM_TAGS) " AS c0_queryId, " 3463 " " TOSTRING(QUERY_GRAND_PARENT_MAIN_DICOM_TAGS) " AS c0_queryId, "
3394 " Lookup.internalId AS c1_internalId, " 3464 " Lookup.internalId AS c1_internalId, "
3395 " NULL::BIGINT AS c2_rowNumber, " 3465 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3396 " value AS c3_string1, " 3466 " value AS c3_string1, "
3397 " NULL::TEXT AS c4_string2, " 3467 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3398 " NULL::TEXT AS c5_string3, " 3468 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3399 " tagGroup AS c6_int1, " 3469 " tagGroup AS c6_int1, "
3400 " tagElement AS c7_int2, " 3470 " tagElement AS c7_int2, "
3401 " NULL::BIGINT AS c8_big_int1, " 3471 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3402 " NULL::BIGINT AS c9_big_int2 " 3472 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3403 "FROM Lookup " 3473 "FROM Lookup "
3404 "INNER JOIN Resources currentLevel ON Lookup.internalId = currentLevel.internalId " 3474 "INNER JOIN Resources currentLevel ON Lookup.internalId = currentLevel.internalId "
3405 "INNER JOIN Resources parentLevel ON currentLevel.parentId = parentLevel.internalId " 3475 "INNER JOIN Resources parentLevel ON currentLevel.parentId = parentLevel.internalId "
3406 "INNER JOIN MainDicomTags ON MainDicomTags.id = parentLevel.parentId "; 3476 "INNER JOIN MainDicomTags ON MainDicomTags.id = parentLevel.parentId ";
3407 } 3477 }
3408 3478
3409 if (grandparentSpec->retrieve_metadata()) 3479 if (grandparentSpec->retrieve_metadata())
3410 { 3480 {
3411 sql += "UNION SELECT " 3481 sql += "UNION ALL SELECT "
3412 " " TOSTRING(QUERY_GRAND_PARENT_METADATA) " AS c0_queryId, " 3482 " " TOSTRING(QUERY_GRAND_PARENT_METADATA) " AS c0_queryId, "
3413 " Lookup.internalId AS c1_internalId, " 3483 " Lookup.internalId AS c1_internalId, "
3414 " NULL::BIGINT AS c2_rowNumber, " 3484 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3415 " value AS c3_string1, " 3485 " value AS c3_string1, "
3416 " NULL::TEXT AS c4_string2, " 3486 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3417 " NULL::TEXT AS c5_string3, " 3487 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3418 " type AS c6_int1, " 3488 " type AS c6_int1, "
3419 " NULL::INT AS c7_int2, " 3489 " " + formatter.FormatNull("INT") + " AS c7_int2, "
3420 " NULL::BIGINT AS c8_big_int1, " 3490 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3421 " NULL::BIGINT AS c9_big_int2 " 3491 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3422 "FROM Lookup " 3492 "FROM Lookup "
3423 "INNER JOIN Resources currentLevel ON Lookup.internalId = currentLevel.internalId " 3493 "INNER JOIN Resources currentLevel ON Lookup.internalId = currentLevel.internalId "
3424 "INNER JOIN Resources parentLevel ON currentLevel.parentId = parentLevel.internalId " 3494 "INNER JOIN Resources parentLevel ON currentLevel.parentId = parentLevel.internalId "
3425 "INNER JOIN Metadata ON Metadata.id = parentLevel.parentId "; 3495 "INNER JOIN Metadata ON Metadata.id = parentLevel.parentId ";
3426 } 3496 }
3447 break; 3517 break;
3448 } 3518 }
3449 3519
3450 if (childrenSpec->retrieve_main_dicom_tags_size() > 0) 3520 if (childrenSpec->retrieve_main_dicom_tags_size() > 0)
3451 { 3521 {
3452 sql += "UNION SELECT " 3522 sql += "UNION ALL SELECT "
3453 " " TOSTRING(QUERY_CHILDREN_MAIN_DICOM_TAGS) " AS c0_queryId, " 3523 " " TOSTRING(QUERY_CHILDREN_MAIN_DICOM_TAGS) " AS c0_queryId, "
3454 " Lookup.internalId AS c1_internalId, " 3524 " Lookup.internalId AS c1_internalId, "
3455 " NULL::BIGINT AS c2_rowNumber, " 3525 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3456 " value AS c3_string1, " 3526 " value AS c3_string1, "
3457 " NULL::TEXT AS c4_string2, " 3527 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3458 " NULL::TEXT AS c5_string3, " 3528 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3459 " tagGroup AS c6_int1, " 3529 " tagGroup AS c6_int1, "
3460 " tagElement AS c7_int2, " 3530 " tagElement AS c7_int2, "
3461 " NULL::BIGINT AS c8_big_int1, " 3531 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3462 " NULL::BIGINT AS c9_big_int2 " 3532 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3463 "FROM Lookup " 3533 "FROM Lookup "
3464 " INNER JOIN Resources childLevel ON childLevel.parentId = Lookup.internalId " 3534 " INNER JOIN Resources childLevel ON childLevel.parentId = Lookup.internalId "
3465 " INNER JOIN MainDicomTags ON MainDicomTags.id = childLevel.internalId AND (tagGroup, tagElement) IN (" + JoinRequestedTags(childrenSpec) + ")"; 3535 " INNER JOIN MainDicomTags ON MainDicomTags.id = childLevel.internalId AND (tagGroup, tagElement) IN (" + JoinRequestedTags(childrenSpec) + ")";
3466 } 3536 }
3467 3537
3468 // need children identifiers ? 3538 // need children identifiers ?
3469 if (childrenSpec->retrieve_identifiers()) 3539 if (childrenSpec->retrieve_identifiers())
3470 { 3540 {
3471 sql += "UNION SELECT " 3541 sql += "UNION ALL SELECT "
3472 " " TOSTRING(QUERY_CHILDREN_IDENTIFIERS) " AS c0_queryId, " 3542 " " TOSTRING(QUERY_CHILDREN_IDENTIFIERS) " AS c0_queryId, "
3473 " Lookup.internalId AS c1_internalId, " 3543 " Lookup.internalId AS c1_internalId, "
3474 " NULL::BIGINT AS c2_rowNumber, " 3544 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3475 " childLevel.publicId AS c3_string1, " 3545 " childLevel.publicId AS c3_string1, "
3476 " NULL::TEXT AS c4_string2, " 3546 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3477 " NULL::TEXT AS c5_string3, " 3547 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3478 " NULL::INT AS c6_int1, " 3548 " " + formatter.FormatNull("INT") + " AS c6_int1, "
3479 " NULL::INT AS c7_int2, " 3549 " " + formatter.FormatNull("INT") + " AS c7_int2, "
3480 " NULL::BIGINT AS c8_big_int1, " 3550 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3481 " NULL::BIGINT AS c9_big_int2 " 3551 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3482 "FROM Lookup " 3552 "FROM Lookup "
3483 " INNER JOIN Resources childLevel ON Lookup.internalId = childLevel.parentId "; 3553 " INNER JOIN Resources childLevel ON Lookup.internalId = childLevel.parentId ";
3484 } 3554 }
3485 3555
3486 if (childrenSpec->retrieve_metadata_size() > 0) 3556 if (childrenSpec->retrieve_metadata_size() > 0)
3487 { 3557 {
3488 sql += "UNION SELECT " 3558 sql += "UNION ALL SELECT "
3489 " " TOSTRING(QUERY_CHILDREN_METADATA) " AS c0_queryId, " 3559 " " TOSTRING(QUERY_CHILDREN_METADATA) " AS c0_queryId, "
3490 " Lookup.internalId AS c1_internalId, " 3560 " Lookup.internalId AS c1_internalId, "
3491 " NULL::BIGINT AS c2_rowNumber, " 3561 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3492 " value AS c3_string1, " 3562 " value AS c3_string1, "
3493 " NULL::TEXT AS c4_string2, " 3563 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3494 " NULL::TEXT AS c5_string3, " 3564 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3495 " type AS c6_int1, " 3565 " type AS c6_int1, "
3496 " NULL::INT AS c7_int2, " 3566 " " + formatter.FormatNull("INT") + " AS c7_int2, "
3497 " NULL::BIGINT AS c8_big_int1, " 3567 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3498 " NULL::BIGINT AS c9_big_int2 " 3568 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3499 "FROM Lookup " 3569 "FROM Lookup "
3500 " INNER JOIN Resources childLevel ON childLevel.parentId = Lookup.internalId " 3570 " INNER JOIN Resources childLevel ON childLevel.parentId = Lookup.internalId "
3501 " INNER JOIN Metadata ON Metadata.id = childLevel.internalId AND Metadata.type IN (" + JoinRequestedMetadata(childrenSpec) + ") "; 3571 " INNER JOIN Metadata ON Metadata.id = childLevel.internalId AND Metadata.type IN (" + JoinRequestedMetadata(childrenSpec) + ") ";
3502 } 3572 }
3503 3573
3518 } 3588 }
3519 3589
3520 // need grand children identifiers ? 3590 // need grand children identifiers ?
3521 if (grandchildrenSpec->retrieve_identifiers()) 3591 if (grandchildrenSpec->retrieve_identifiers())
3522 { 3592 {
3523 sql += "UNION SELECT " 3593 sql += "UNION ALL SELECT "
3524 " " TOSTRING(QUERY_GRAND_CHILDREN_IDENTIFIERS) " AS c0_queryId, " 3594 " " TOSTRING(QUERY_GRAND_CHILDREN_IDENTIFIERS) " AS c0_queryId, "
3525 " Lookup.internalId AS c1_internalId, " 3595 " Lookup.internalId AS c1_internalId, "
3526 " NULL::BIGINT AS c2_rowNumber, " 3596 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3527 " grandChildLevel.publicId AS c3_string1, " 3597 " grandChildLevel.publicId AS c3_string1, "
3528 " NULL::TEXT AS c4_string2, " 3598 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3529 " NULL::TEXT AS c5_string3, " 3599 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3530 " NULL::INT AS c6_int1, " 3600 " " + formatter.FormatNull("INT") + " AS c6_int1, "
3531 " NULL::INT AS c7_int2, " 3601 " " + formatter.FormatNull("INT") + " AS c7_int2, "
3532 " NULL::BIGINT AS c8_big_int1, " 3602 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3533 " NULL::BIGINT AS c9_big_int2 " 3603 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3534 "FROM Lookup " 3604 "FROM Lookup "
3535 "INNER JOIN Resources childLevel ON Lookup.internalId = childLevel.parentId " 3605 "INNER JOIN Resources childLevel ON Lookup.internalId = childLevel.parentId "
3536 "INNER JOIN Resources grandChildLevel ON childLevel.internalId = grandChildLevel.parentId "; 3606 "INNER JOIN Resources grandChildLevel ON childLevel.internalId = grandChildLevel.parentId ";
3537 } 3607 }
3538 3608
3539 if (grandchildrenSpec->retrieve_main_dicom_tags_size() > 0) 3609 if (grandchildrenSpec->retrieve_main_dicom_tags_size() > 0)
3540 { 3610 {
3541 sql += "UNION SELECT " 3611 sql += "UNION ALL SELECT "
3542 " " TOSTRING(QUERY_GRAND_CHILDREN_MAIN_DICOM_TAGS) " AS c0_queryId, " 3612 " " TOSTRING(QUERY_GRAND_CHILDREN_MAIN_DICOM_TAGS) " AS c0_queryId, "
3543 " Lookup.internalId AS c1_internalId, " 3613 " Lookup.internalId AS c1_internalId, "
3544 " NULL::BIGINT AS c2_rowNumber, " 3614 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3545 " value AS c3_string1, " 3615 " value AS c3_string1, "
3546 " NULL::TEXT AS c4_string2, " 3616 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3547 " NULL::TEXT AS c5_string3, " 3617 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3548 " tagGroup AS c6_int1, " 3618 " tagGroup AS c6_int1, "
3549 " tagElement AS c7_int2, " 3619 " tagElement AS c7_int2, "
3550 " NULL::BIGINT AS c8_big_int1, " 3620 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3551 " NULL::BIGINT AS c9_big_int2 " 3621 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3552 "FROM Lookup " 3622 "FROM Lookup "
3553 " INNER JOIN Resources childLevel ON childLevel.parentId = Lookup.internalId " 3623 " INNER JOIN Resources childLevel ON childLevel.parentId = Lookup.internalId "
3554 " INNER JOIN Resources grandChildLevel ON grandChildLevel.parentId = childLevel.internalId " 3624 " INNER JOIN Resources grandChildLevel ON grandChildLevel.parentId = childLevel.internalId "
3555 " INNER JOIN MainDicomTags ON MainDicomTags.id = grandChildLevel.internalId AND (tagGroup, tagElement) IN (" + JoinRequestedTags(grandchildrenSpec) + ")"; 3625 " INNER JOIN MainDicomTags ON MainDicomTags.id = grandChildLevel.internalId AND (tagGroup, tagElement) IN (" + JoinRequestedTags(grandchildrenSpec) + ")";
3556 } 3626 }
3557 3627
3558 if (grandchildrenSpec->retrieve_metadata_size() > 0) 3628 if (grandchildrenSpec->retrieve_metadata_size() > 0)
3559 { 3629 {
3560 sql += "UNION SELECT " 3630 sql += "UNION ALL SELECT "
3561 " " TOSTRING(QUERY_GRAND_CHILDREN_METADATA) " AS c0_queryId, " 3631 " " TOSTRING(QUERY_GRAND_CHILDREN_METADATA) " AS c0_queryId, "
3562 " Lookup.internalId AS c1_internalId, " 3632 " Lookup.internalId AS c1_internalId, "
3563 " NULL::BIGINT AS c2_rowNumber, " 3633 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3564 " value AS c3_string1, " 3634 " value AS c3_string1, "
3565 " NULL::TEXT AS c4_string2, " 3635 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3566 " NULL::TEXT AS c5_string3, " 3636 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3567 " type AS c6_int1, " 3637 " type AS c6_int1, "
3568 " NULL::INT AS c7_int2, " 3638 " " + formatter.FormatNull("INT") + " AS c7_int2, "
3569 " NULL::BIGINT AS c8_big_int1, " 3639 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3570 " NULL::BIGINT AS c9_big_int2 " 3640 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3571 "FROM Lookup " 3641 "FROM Lookup "
3572 " INNER JOIN Resources childLevel ON childLevel.parentId = Lookup.internalId " 3642 " INNER JOIN Resources childLevel ON childLevel.parentId = Lookup.internalId "
3573 " INNER JOIN Resources grandChildLevel ON grandChildLevel.parentId = childLevel.internalId " 3643 " INNER JOIN Resources grandChildLevel ON grandChildLevel.parentId = childLevel.internalId "
3574 " INNER JOIN Metadata ON Metadata.id = grandChildLevel.internalId AND Metadata.type IN (" + JoinRequestedMetadata(grandchildrenSpec) + ") "; 3644 " INNER JOIN Metadata ON Metadata.id = grandChildLevel.internalId AND Metadata.type IN (" + JoinRequestedMetadata(grandchildrenSpec) + ") ";
3575 } 3645 }
3579 const Orthanc::DatabasePluginMessages::Find_Request_ChildrenSpecification* grandgrandchildrenSpec = &(request.children_instances()); 3649 const Orthanc::DatabasePluginMessages::Find_Request_ChildrenSpecification* grandgrandchildrenSpec = &(request.children_instances());
3580 3650
3581 // need grand children identifiers ? 3651 // need grand children identifiers ?
3582 if (grandgrandchildrenSpec->retrieve_identifiers()) 3652 if (grandgrandchildrenSpec->retrieve_identifiers())
3583 { 3653 {
3584 sql += "UNION SELECT " 3654 sql += "UNION ALL SELECT "
3585 " " TOSTRING(QUERY_GRAND_GRAND_CHILDREN_IDENTIFIERS) " AS c0_queryId, " 3655 " " TOSTRING(QUERY_GRAND_GRAND_CHILDREN_IDENTIFIERS) " AS c0_queryId, "
3586 " Lookup.internalId AS c1_internalId, " 3656 " Lookup.internalId AS c1_internalId, "
3587 " NULL::BIGINT AS c2_rowNumber, " 3657 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3588 " grandGrandChildLevel.publicId AS c3_string1, " 3658 " grandGrandChildLevel.publicId AS c3_string1, "
3589 " NULL::TEXT AS c4_string2, " 3659 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3590 " NULL::TEXT AS c5_string3, " 3660 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3591 " NULL::INT AS c6_int1, " 3661 " " + formatter.FormatNull("INT") + " AS c6_int1, "
3592 " NULL::INT AS c7_int2, " 3662 " " + formatter.FormatNull("INT") + " AS c7_int2, "
3593 " NULL::BIGINT AS c8_big_int1, " 3663 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3594 " NULL::BIGINT AS c9_big_int2 " 3664 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3595 "FROM Lookup " 3665 "FROM Lookup "
3596 "INNER JOIN Resources childLevel ON Lookup.internalId = childLevel.parentId " 3666 "INNER JOIN Resources childLevel ON Lookup.internalId = childLevel.parentId "
3597 "INNER JOIN Resources grandChildLevel ON childLevel.internalId = grandChildLevel.parentId " 3667 "INNER JOIN Resources grandChildLevel ON childLevel.internalId = grandChildLevel.parentId "
3598 "INNER JOIN Resources grandGrandChildLevel ON grandChildLevel.internalId = grandGrandChildLevel.parentId "; 3668 "INNER JOIN Resources grandGrandChildLevel ON grandChildLevel.internalId = grandGrandChildLevel.parentId ";
3599 } 3669 }
3602 } 3672 }
3603 3673
3604 // need parent identifier ? 3674 // need parent identifier ?
3605 if (request.retrieve_parent_identifier()) 3675 if (request.retrieve_parent_identifier())
3606 { 3676 {
3607 sql += "UNION SELECT " 3677 sql += "UNION ALL SELECT "
3608 " " TOSTRING(QUERY_PARENT_IDENTIFIER) " AS c0_queryId, " 3678 " " TOSTRING(QUERY_PARENT_IDENTIFIER) " AS c0_queryId, "
3609 " Lookup.internalId AS c1_internalId, " 3679 " Lookup.internalId AS c1_internalId, "
3610 " NULL::BIGINT AS c2_rowNumber, " 3680 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3611 " parentLevel.publicId AS c3_string1, " 3681 " parentLevel.publicId AS c3_string1, "
3612 " NULL::TEXT AS c4_string2, " 3682 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3613 " NULL::TEXT AS c5_string3, " 3683 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3614 " NULL::INT AS c6_int1, " 3684 " " + formatter.FormatNull("INT") + " AS c6_int1, "
3615 " NULL::INT AS c7_int2, " 3685 " " + formatter.FormatNull("INT") + " AS c7_int2, "
3616 " NULL::BIGINT AS c8_big_int1, " 3686 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3617 " NULL::BIGINT AS c9_big_int2 " 3687 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3618 "FROM Lookup " 3688 "FROM Lookup "
3619 " INNER JOIN Resources currentLevel ON currentLevel.internalId = Lookup.internalId " 3689 " INNER JOIN Resources currentLevel ON currentLevel.internalId = Lookup.internalId "
3620 " INNER JOIN Resources parentLevel ON currentLevel.parentId = parentLevel.internalId "; 3690 " INNER JOIN Resources parentLevel ON currentLevel.parentId = parentLevel.internalId ";
3621 } 3691 }
3622 3692
3623 // need one instance info ? 3693 // need one instance info ?
3624 if (request.level() != Orthanc::DatabasePluginMessages::ResourceType::RESOURCE_INSTANCE && 3694 if (request.level() != Orthanc::DatabasePluginMessages::ResourceType::RESOURCE_INSTANCE &&
3625 request.retrieve_one_instance_metadata_and_attachments()) 3695 request.retrieve_one_instance_metadata_and_attachments())
3626 { 3696 {
3627 // Here, we create a nested CTE 'OneInstance' with one instance ID to join with metadata and main 3697 sql += " UNION ALL SELECT"
3628 sql += "UNION"
3629 " (WITH OneInstance AS";
3630
3631 switch (request.level())
3632 {
3633 case Orthanc::DatabasePluginMessages::ResourceType::RESOURCE_SERIES:
3634 {
3635 sql+= " (SELECT DISTINCT ON (Lookup.internalId) Lookup.internalId AS parentInternalId, childLevel.publicId AS instancePublicId, childLevel.internalId AS instanceInternalId"
3636 " FROM Resources AS childLevel "
3637 " INNER JOIN Lookup ON childLevel.parentId = Lookup.internalId) ";
3638 }; break;
3639 case Orthanc::DatabasePluginMessages::ResourceType::RESOURCE_STUDY:
3640 {
3641 sql+= " (SELECT DISTINCT ON (Lookup.internalId) Lookup.internalId AS parentInternalId, grandChildLevel.publicId AS instancePublicId, grandChildLevel.internalId AS instanceInternalId"
3642 " FROM Resources AS grandChildLevel "
3643 " INNER JOIN Resources childLevel ON grandChildLevel.parentId = childLevel.internalId "
3644 " INNER JOIN Lookup ON childLevel.parentId = Lookup.internalId) ";
3645 }; break;
3646 case Orthanc::DatabasePluginMessages::ResourceType::RESOURCE_PATIENT:
3647 {
3648 sql+= " (SELECT DISTINCT ON (Lookup.internalId) Lookup.internalId AS parentInternalId, grandGrandChildLevel.publicId AS instancePublicId, grandGrandChildLevel.internalId AS instanceInternalId"
3649 " FROM Resources AS grandGrandChildLevel "
3650 " INNER JOIN Resources grandChildLevel ON grandGrandChildLevel.parentId = grandChildLevel.internalId "
3651 " INNER JOIN Resources childLevel ON grandChildLevel.parentId = childLevel.internalId "
3652 " INNER JOIN Lookup ON childLevel.parentId = Lookup.internalId) ";
3653 }; break;
3654 default:
3655 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
3656 }
3657
3658 sql += " SELECT"
3659 " " TOSTRING(QUERY_ONE_INSTANCE_IDENTIFIER) " AS c0_queryId, " 3698 " " TOSTRING(QUERY_ONE_INSTANCE_IDENTIFIER) " AS c0_queryId, "
3660 " parentInternalId AS c1_internalId, " 3699 " parentInternalId AS c1_internalId, "
3661 " NULL::BIGINT AS c2_rowNumber, " 3700 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3662 " instancePublicId AS c3_string1, " 3701 " instancePublicId AS c3_string1, "
3663 " NULL::TEXT AS c4_string2, " 3702 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3664 " NULL::TEXT AS c5_string3, " 3703 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3665 " NULL::INT AS c6_int1, " 3704 " " + formatter.FormatNull("INT") + " AS c6_int1, "
3666 " NULL::INT AS c7_int2, " 3705 " " + formatter.FormatNull("INT") + " AS c7_int2, "
3667 " instanceInternalId AS c8_big_int1, " 3706 " instanceInternalId AS c8_big_int1, "
3668 " NULL::BIGINT AS c9_big_int2 " 3707 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3669 " FROM OneInstance "; 3708 " FROM OneInstance ";
3670 3709
3671 sql += " UNION SELECT" 3710 sql += " UNION ALL SELECT"
3672 " " TOSTRING(QUERY_ONE_INSTANCE_METADATA) " AS c0_queryId, " 3711 " " TOSTRING(QUERY_ONE_INSTANCE_METADATA) " AS c0_queryId, "
3673 " parentInternalId AS c1_internalId, " 3712 " parentInternalId AS c1_internalId, "
3674 " NULL::BIGINT AS c2_rowNumber, " 3713 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3675 " Metadata.value AS c3_string1, " 3714 " Metadata.value AS c3_string1, "
3676 " NULL::TEXT AS c4_string2, " 3715 " " + formatter.FormatNull("TEXT") + " AS c4_string2, "
3677 " NULL::TEXT AS c5_string3, " 3716 " " + formatter.FormatNull("TEXT") + " AS c5_string3, "
3678 " Metadata.type AS c6_int1, " 3717 " Metadata.type AS c6_int1, "
3679 " NULL::INT AS c7_int2, " 3718 " " + formatter.FormatNull("INT") + " AS c7_int2, "
3680 " NULL::BIGINT AS c8_big_int1, " 3719 " " + formatter.FormatNull("BIGINT") + " AS c8_big_int1, "
3681 " NULL::BIGINT AS c9_big_int2 " 3720 " " + formatter.FormatNull("BIGINT") + " AS c9_big_int2 "
3682 " FROM Metadata " 3721 " FROM Metadata "
3683 " INNER JOIN OneInstance ON Metadata.id = OneInstance.instanceInternalId"; 3722 " INNER JOIN OneInstance ON Metadata.id = OneInstance.instanceInternalId";
3684 3723
3685 sql += " UNION SELECT" 3724 sql += " UNION ALL SELECT"
3686 " " TOSTRING(QUERY_ONE_INSTANCE_ATTACHMENTS) " AS c0_queryId, " 3725 " " TOSTRING(QUERY_ONE_INSTANCE_ATTACHMENTS) " AS c0_queryId, "
3687 " parentInternalId AS c1_internalId, " 3726 " parentInternalId AS c1_internalId, "
3688 " NULL::BIGINT AS c2_rowNumber, " 3727 " " + formatter.FormatNull("BIGINT") + " AS c2_rowNumber, "
3689 " uuid AS c3_string1, " 3728 " uuid AS c3_string1, "
3690 " uncompressedHash AS c4_string2, " 3729 " uncompressedHash AS c4_string2, "
3691 " compressedHash AS c5_string3, " 3730 " compressedHash AS c5_string3, "
3692 " fileType AS c6_int1, " 3731 " fileType AS c6_int1, "
3693 " compressionType AS c7_int2, " 3732 " compressionType AS c7_int2, "
3694 " compressedSize AS c8_big_int1, " 3733 " compressedSize AS c8_big_int1, "
3695 " uncompressedSize AS c9_big_int2 " 3734 " uncompressedSize AS c9_big_int2 "
3696 " FROM AttachedFiles " 3735 " FROM AttachedFiles "
3697 " INNER JOIN OneInstance ON AttachedFiles.id = OneInstance.instanceInternalId"; 3736 " INNER JOIN OneInstance ON AttachedFiles.id = OneInstance.instanceInternalId";
3698 3737
3699 sql += " ) "; 3738 // sql += " ) ";
3700 3739
3701 } 3740 }
3702 3741
3703 sql += " ORDER BY c0_queryId, c2_rowNumber"; // this is really important to make sure that the Lookup query is the first one to provide results since we use it to create the responses element ! 3742 sql += " ORDER BY c0_queryId, c2_rowNumber"; // this is really important to make sure that the Lookup query is the first one to provide results since we use it to create the responses element !
3704 3743
3705 DatabaseManager::StandaloneStatement statement(manager, sql); // TODO-FIND: cache dynamic statement ? Probably worth it since it can be very complex queries ! 3744 std::unique_ptr<DatabaseManager::StatementBase> statement;
3706 formatter.PrepareStatement(statement); 3745 if (manager.GetDialect() == Dialect_MySQL)
3707 statement.Execute(formatter.GetDictionary()); 3746 { // TODO: investigate why "complex" cached statement do not seem to work properly in MySQL
3708 3747 statement.reset(new DatabaseManager::StandaloneStatement(manager, sql));
3748 }
3749 else
3750 {
3751 statement.reset(new DatabaseManager::CachedStatement(STATEMENT_FROM_HERE_DYNAMIC(sql), manager, sql));
3752 }
3753
3754 statement->Execute(formatter.GetDictionary());
3755
3756 // LOG(INFO) << sql;
3709 3757
3710 std::map<int64_t, Orthanc::DatabasePluginMessages::Find_Response*> responses; 3758 std::map<int64_t, Orthanc::DatabasePluginMessages::Find_Response*> responses;
3711 3759
3712 while (!statement.IsDone()) 3760 while (!statement->IsDone())
3713 { 3761 {
3714 int32_t queryId = statement.ReadInteger32(C0_QUERY_ID); 3762 int32_t queryId = statement->ReadInteger32(C0_QUERY_ID);
3715 int64_t internalId = statement.ReadInteger64(C1_INTERNAL_ID); 3763 int64_t internalId = statement->ReadInteger64(C1_INTERNAL_ID);
3716 3764
3717 assert(queryId == QUERY_LOOKUP || responses.find(internalId) != responses.end()); // the QUERY_LOOKUP must be read first and must create the response before any other query tries to populate the fields 3765 assert(queryId == QUERY_LOOKUP || responses.find(internalId) != responses.end()); // the QUERY_LOOKUP must be read first and must create the response before any other query tries to populate the fields
3766
3767 // LOG(INFO) << queryId << " " << statement->ReadString(C3_STRING_1);
3718 3768
3719 switch (queryId) 3769 switch (queryId)
3720 { 3770 {
3721 case QUERY_LOOKUP: 3771 case QUERY_LOOKUP:
3722 responses[internalId] = response.add_find(); 3772 responses[internalId] = response.add_find();
3723 responses[internalId]->set_public_id(statement.ReadString(C3_STRING_1)); 3773 responses[internalId]->set_public_id(statement->ReadString(C3_STRING_1));
3724 responses[internalId]->set_internal_id(internalId); 3774 responses[internalId]->set_internal_id(internalId);
3725 break; 3775 break;
3726 3776
3727 case QUERY_LABELS: 3777 case QUERY_LABELS:
3728 responses[internalId]->add_labels(statement.ReadString(C3_STRING_1)); 3778 responses[internalId]->add_labels(statement->ReadString(C3_STRING_1));
3729 break; 3779 break;
3730 3780
3731 case QUERY_MAIN_DICOM_TAGS: 3781 case QUERY_MAIN_DICOM_TAGS:
3732 { 3782 {
3733 Orthanc::DatabasePluginMessages::Find_Response_ResourceContent* content = GetResourceContent(responses[internalId], request.level()); 3783 Orthanc::DatabasePluginMessages::Find_Response_ResourceContent* content = GetResourceContent(responses[internalId], request.level());
3734 Orthanc::DatabasePluginMessages::Find_Response_Tag* tag = content->add_main_dicom_tags(); 3784 Orthanc::DatabasePluginMessages::Find_Response_Tag* tag = content->add_main_dicom_tags();
3735 3785
3736 tag->set_value(statement.ReadString(C3_STRING_1)); 3786 tag->set_value(statement->ReadString(C3_STRING_1));
3737 tag->set_group(statement.ReadInteger32(C6_INT_1)); 3787 tag->set_group(statement->ReadInteger32(C6_INT_1));
3738 tag->set_element(statement.ReadInteger32(C7_INT_2)); 3788 tag->set_element(statement->ReadInteger32(C7_INT_2));
3739 }; break; 3789 }; break;
3740 3790
3741 case QUERY_PARENT_MAIN_DICOM_TAGS: 3791 case QUERY_PARENT_MAIN_DICOM_TAGS:
3742 { 3792 {
3743 Orthanc::DatabasePluginMessages::Find_Response_ResourceContent* content = GetResourceContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() - 1)); 3793 Orthanc::DatabasePluginMessages::Find_Response_ResourceContent* content = GetResourceContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() - 1));
3744 Orthanc::DatabasePluginMessages::Find_Response_Tag* tag = content->add_main_dicom_tags(); 3794 Orthanc::DatabasePluginMessages::Find_Response_Tag* tag = content->add_main_dicom_tags();
3745 3795
3746 tag->set_value(statement.ReadString(C3_STRING_1)); 3796 tag->set_value(statement->ReadString(C3_STRING_1));
3747 tag->set_group(statement.ReadInteger32(C6_INT_1)); 3797 tag->set_group(statement->ReadInteger32(C6_INT_1));
3748 tag->set_element(statement.ReadInteger32(C7_INT_2)); 3798 tag->set_element(statement->ReadInteger32(C7_INT_2));
3749 }; break; 3799 }; break;
3750 3800
3751 case QUERY_GRAND_PARENT_MAIN_DICOM_TAGS: 3801 case QUERY_GRAND_PARENT_MAIN_DICOM_TAGS:
3752 { 3802 {
3753 Orthanc::DatabasePluginMessages::Find_Response_ResourceContent* content = GetResourceContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() - 2)); 3803 Orthanc::DatabasePluginMessages::Find_Response_ResourceContent* content = GetResourceContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() - 2));
3754 Orthanc::DatabasePluginMessages::Find_Response_Tag* tag = content->add_main_dicom_tags(); 3804 Orthanc::DatabasePluginMessages::Find_Response_Tag* tag = content->add_main_dicom_tags();
3755 3805
3756 tag->set_value(statement.ReadString(C3_STRING_1)); 3806 tag->set_value(statement->ReadString(C3_STRING_1));
3757 tag->set_group(statement.ReadInteger32(C6_INT_1)); 3807 tag->set_group(statement->ReadInteger32(C6_INT_1));
3758 tag->set_element(statement.ReadInteger32(C7_INT_2)); 3808 tag->set_element(statement->ReadInteger32(C7_INT_2));
3759 }; break; 3809 }; break;
3760 3810
3761 case QUERY_CHILDREN_IDENTIFIERS: 3811 case QUERY_CHILDREN_IDENTIFIERS:
3762 { 3812 {
3763 Orthanc::DatabasePluginMessages::Find_Response_ChildrenContent* content = GetChildrenContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() + 1)); 3813 Orthanc::DatabasePluginMessages::Find_Response_ChildrenContent* content = GetChildrenContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() + 1));
3764 content->add_identifiers(statement.ReadString(C3_STRING_1)); 3814 content->add_identifiers(statement->ReadString(C3_STRING_1));
3765 }; break; 3815 }; break;
3766 3816
3767 case QUERY_CHILDREN_MAIN_DICOM_TAGS: 3817 case QUERY_CHILDREN_MAIN_DICOM_TAGS:
3768 { 3818 {
3769 Orthanc::DatabasePluginMessages::Find_Response_ChildrenContent* content = GetChildrenContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() + 1)); 3819 Orthanc::DatabasePluginMessages::Find_Response_ChildrenContent* content = GetChildrenContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() + 1));
3770 Orthanc::DatabasePluginMessages::Find_Response_MultipleTags* tag = content->add_main_dicom_tags(); 3820 Orthanc::DatabasePluginMessages::Find_Response_MultipleTags* tag = content->add_main_dicom_tags();
3771 tag->add_values(statement.ReadString(C3_STRING_1)); // TODO: handle sequences ?? 3821 tag->add_values(statement->ReadString(C3_STRING_1)); // TODO: handle sequences ??
3772 tag->set_group(statement.ReadInteger32(C6_INT_1)); 3822 tag->set_group(statement->ReadInteger32(C6_INT_1));
3773 tag->set_element(statement.ReadInteger32(C7_INT_2)); 3823 tag->set_element(statement->ReadInteger32(C7_INT_2));
3774 }; break; 3824 }; break;
3775 3825
3776 case QUERY_CHILDREN_METADATA: 3826 case QUERY_CHILDREN_METADATA:
3777 { 3827 {
3778 Orthanc::DatabasePluginMessages::Find_Response_ChildrenContent* content = GetChildrenContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() + 1)); 3828 Orthanc::DatabasePluginMessages::Find_Response_ChildrenContent* content = GetChildrenContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() + 1));
3779 Orthanc::DatabasePluginMessages::Find_Response_MultipleMetadata* metadata = content->add_metadata(); 3829 Orthanc::DatabasePluginMessages::Find_Response_MultipleMetadata* metadata = content->add_metadata();
3780 3830
3781 metadata->add_values(statement.ReadString(C3_STRING_1)); 3831 metadata->add_values(statement->ReadString(C3_STRING_1));
3782 metadata->set_key(statement.ReadInteger32(C6_INT_1)); 3832 metadata->set_key(statement->ReadInteger32(C6_INT_1));
3783 }; break; 3833 }; break;
3784 3834
3785 case QUERY_GRAND_CHILDREN_IDENTIFIERS: 3835 case QUERY_GRAND_CHILDREN_IDENTIFIERS:
3786 { 3836 {
3787 Orthanc::DatabasePluginMessages::Find_Response_ChildrenContent* content = GetChildrenContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() + 2)); 3837 Orthanc::DatabasePluginMessages::Find_Response_ChildrenContent* content = GetChildrenContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() + 2));
3788 content->add_identifiers(statement.ReadString(C3_STRING_1)); 3838 content->add_identifiers(statement->ReadString(C3_STRING_1));
3789 }; break; 3839 }; break;
3790 3840
3791 case QUERY_GRAND_CHILDREN_MAIN_DICOM_TAGS: 3841 case QUERY_GRAND_CHILDREN_MAIN_DICOM_TAGS:
3792 { 3842 {
3793 Orthanc::DatabasePluginMessages::Find_Response_ChildrenContent* content = GetChildrenContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() + 2)); 3843 Orthanc::DatabasePluginMessages::Find_Response_ChildrenContent* content = GetChildrenContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() + 2));
3794 Orthanc::DatabasePluginMessages::Find_Response_MultipleTags* tag = content->add_main_dicom_tags(); 3844 Orthanc::DatabasePluginMessages::Find_Response_MultipleTags* tag = content->add_main_dicom_tags();
3795 3845
3796 tag->add_values(statement.ReadString(C3_STRING_1)); // TODO: handle sequences ?? 3846 tag->add_values(statement->ReadString(C3_STRING_1)); // TODO: handle sequences ??
3797 tag->set_group(statement.ReadInteger32(C6_INT_1)); 3847 tag->set_group(statement->ReadInteger32(C6_INT_1));
3798 tag->set_element(statement.ReadInteger32(C7_INT_2)); 3848 tag->set_element(statement->ReadInteger32(C7_INT_2));
3799 }; break; 3849 }; break;
3800 3850
3801 case QUERY_GRAND_CHILDREN_METADATA: 3851 case QUERY_GRAND_CHILDREN_METADATA:
3802 { 3852 {
3803 Orthanc::DatabasePluginMessages::Find_Response_ChildrenContent* content = GetChildrenContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() + 2)); 3853 Orthanc::DatabasePluginMessages::Find_Response_ChildrenContent* content = GetChildrenContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() + 2));
3804 Orthanc::DatabasePluginMessages::Find_Response_MultipleMetadata* metadata = content->add_metadata(); 3854 Orthanc::DatabasePluginMessages::Find_Response_MultipleMetadata* metadata = content->add_metadata();
3805 3855
3806 metadata->add_values(statement.ReadString(C3_STRING_1)); 3856 metadata->add_values(statement->ReadString(C3_STRING_1));
3807 metadata->set_key(statement.ReadInteger32(C6_INT_1)); 3857 metadata->set_key(statement->ReadInteger32(C6_INT_1));
3808 }; break; 3858 }; break;
3809 3859
3810 case QUERY_GRAND_GRAND_CHILDREN_IDENTIFIERS: 3860 case QUERY_GRAND_GRAND_CHILDREN_IDENTIFIERS:
3811 { 3861 {
3812 Orthanc::DatabasePluginMessages::Find_Response_ChildrenContent* content = GetChildrenContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() + 3)); 3862 Orthanc::DatabasePluginMessages::Find_Response_ChildrenContent* content = GetChildrenContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() + 3));
3813 content->add_identifiers(statement.ReadString(C3_STRING_1)); 3863 content->add_identifiers(statement->ReadString(C3_STRING_1));
3814 }; break; 3864 }; break;
3815 3865
3816 case QUERY_ATTACHMENTS: 3866 case QUERY_ATTACHMENTS:
3817 { 3867 {
3818 Orthanc::DatabasePluginMessages::FileInfo* attachment = responses[internalId]->add_attachments(); 3868 Orthanc::DatabasePluginMessages::FileInfo* attachment = responses[internalId]->add_attachments();
3819 3869
3820 attachment->set_uuid(statement.ReadString(C3_STRING_1)); 3870 attachment->set_uuid(statement->ReadString(C3_STRING_1));
3821 attachment->set_uncompressed_hash(statement.ReadString(C4_STRING_2)); 3871 attachment->set_uncompressed_hash(statement->ReadString(C4_STRING_2));
3822 attachment->set_compressed_hash(statement.ReadString(C5_STRING_3)); 3872 attachment->set_compressed_hash(statement->ReadString(C5_STRING_3));
3823 attachment->set_content_type(statement.ReadInteger32(C6_INT_1)); 3873 attachment->set_content_type(statement->ReadInteger32(C6_INT_1));
3824 attachment->set_compression_type(statement.ReadInteger32(C7_INT_2)); 3874 attachment->set_compression_type(statement->ReadInteger32(C7_INT_2));
3825 attachment->set_compressed_size(statement.ReadInteger64(C8_BIG_INT_1)); 3875 attachment->set_compressed_size(statement->ReadInteger64(C8_BIG_INT_1));
3826 attachment->set_uncompressed_size(statement.ReadInteger64(C9_BIG_INT_2)); 3876 attachment->set_uncompressed_size(statement->ReadInteger64(C9_BIG_INT_2));
3827 }; break; 3877 }; break;
3828 3878
3829 case QUERY_METADATA: 3879 case QUERY_METADATA:
3830 { 3880 {
3831 Orthanc::DatabasePluginMessages::Find_Response_ResourceContent* content = GetResourceContent(responses[internalId], request.level()); 3881 Orthanc::DatabasePluginMessages::Find_Response_ResourceContent* content = GetResourceContent(responses[internalId], request.level());
3832 Orthanc::DatabasePluginMessages::Find_Response_Metadata* metadata = content->add_metadata(); 3882 Orthanc::DatabasePluginMessages::Find_Response_Metadata* metadata = content->add_metadata();
3833 3883
3834 metadata->set_value(statement.ReadString(C3_STRING_1)); 3884 metadata->set_value(statement->ReadString(C3_STRING_1));
3835 metadata->set_key(statement.ReadInteger32(C6_INT_1)); 3885 metadata->set_key(statement->ReadInteger32(C6_INT_1));
3836 }; break; 3886 }; break;
3837 3887
3838 case QUERY_PARENT_METADATA: 3888 case QUERY_PARENT_METADATA:
3839 { 3889 {
3840 Orthanc::DatabasePluginMessages::Find_Response_ResourceContent* content = GetResourceContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() - 1)); 3890 Orthanc::DatabasePluginMessages::Find_Response_ResourceContent* content = GetResourceContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() - 1));
3841 Orthanc::DatabasePluginMessages::Find_Response_Metadata* metadata = content->add_metadata(); 3891 Orthanc::DatabasePluginMessages::Find_Response_Metadata* metadata = content->add_metadata();
3842 3892
3843 metadata->set_value(statement.ReadString(C3_STRING_1)); 3893 metadata->set_value(statement->ReadString(C3_STRING_1));
3844 metadata->set_key(statement.ReadInteger32(C6_INT_1)); 3894 metadata->set_key(statement->ReadInteger32(C6_INT_1));
3845 }; break; 3895 }; break;
3846 3896
3847 case QUERY_GRAND_PARENT_METADATA: 3897 case QUERY_GRAND_PARENT_METADATA:
3848 { 3898 {
3849 Orthanc::DatabasePluginMessages::Find_Response_ResourceContent* content = GetResourceContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() - 2)); 3899 Orthanc::DatabasePluginMessages::Find_Response_ResourceContent* content = GetResourceContent(responses[internalId], static_cast<Orthanc::DatabasePluginMessages::ResourceType>(request.level() - 2));
3850 Orthanc::DatabasePluginMessages::Find_Response_Metadata* metadata = content->add_metadata(); 3900 Orthanc::DatabasePluginMessages::Find_Response_Metadata* metadata = content->add_metadata();
3851 3901
3852 metadata->set_value(statement.ReadString(C3_STRING_1)); 3902 metadata->set_value(statement->ReadString(C3_STRING_1));
3853 metadata->set_key(statement.ReadInteger32(C6_INT_1)); 3903 metadata->set_key(statement->ReadInteger32(C6_INT_1));
3854 }; break; 3904 }; break;
3855 3905
3856 case QUERY_PARENT_IDENTIFIER: 3906 case QUERY_PARENT_IDENTIFIER:
3857 { 3907 {
3858 responses[internalId]->set_parent_public_id(statement.ReadString(C3_STRING_1)); 3908 responses[internalId]->set_parent_public_id(statement->ReadString(C3_STRING_1));
3859 }; break; 3909 }; break;
3860 3910
3861 case QUERY_ONE_INSTANCE_IDENTIFIER: 3911 case QUERY_ONE_INSTANCE_IDENTIFIER:
3862 { 3912 {
3863 responses[internalId]->set_one_instance_public_id(statement.ReadString(C3_STRING_1)); 3913 responses[internalId]->set_one_instance_public_id(statement->ReadString(C3_STRING_1));
3864 }; break; 3914 }; break;
3865 case QUERY_ONE_INSTANCE_METADATA: 3915 case QUERY_ONE_INSTANCE_METADATA:
3866 { 3916 {
3867 Orthanc::DatabasePluginMessages::Find_Response_Metadata* metadata = responses[internalId]->add_one_instance_metadata(); 3917 Orthanc::DatabasePluginMessages::Find_Response_Metadata* metadata = responses[internalId]->add_one_instance_metadata();
3868 3918
3869 metadata->set_value(statement.ReadString(C3_STRING_1)); 3919 metadata->set_value(statement->ReadString(C3_STRING_1));
3870 metadata->set_key(statement.ReadInteger32(C6_INT_1)); 3920 metadata->set_key(statement->ReadInteger32(C6_INT_1));
3871 }; break; 3921 }; break;
3872 case QUERY_ONE_INSTANCE_ATTACHMENTS: 3922 case QUERY_ONE_INSTANCE_ATTACHMENTS:
3873 { 3923 {
3874 Orthanc::DatabasePluginMessages::FileInfo* attachment = responses[internalId]->add_one_instance_attachments(); 3924 Orthanc::DatabasePluginMessages::FileInfo* attachment = responses[internalId]->add_one_instance_attachments();
3875 3925
3876 attachment->set_uuid(statement.ReadString(C3_STRING_1)); 3926 attachment->set_uuid(statement->ReadString(C3_STRING_1));
3877 attachment->set_uncompressed_hash(statement.ReadString(C4_STRING_2)); 3927 attachment->set_uncompressed_hash(statement->ReadString(C4_STRING_2));
3878 attachment->set_compressed_hash(statement.ReadString(C5_STRING_3)); 3928 attachment->set_compressed_hash(statement->ReadString(C5_STRING_3));
3879 attachment->set_content_type(statement.ReadInteger32(C6_INT_1)); 3929 attachment->set_content_type(statement->ReadInteger32(C6_INT_1));
3880 attachment->set_compression_type(statement.ReadInteger32(C7_INT_2)); 3930 attachment->set_compression_type(statement->ReadInteger32(C7_INT_2));
3881 attachment->set_compressed_size(statement.ReadInteger64(C8_BIG_INT_1)); 3931 attachment->set_compressed_size(statement->ReadInteger64(C8_BIG_INT_1));
3882 attachment->set_uncompressed_size(statement.ReadInteger64(C9_BIG_INT_2)); 3932 attachment->set_uncompressed_size(statement->ReadInteger64(C9_BIG_INT_2));
3883 }; break; 3933 }; break;
3884 3934
3885 default: 3935 default:
3886 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); 3936 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
3887 } 3937 }
3888 statement.Next(); 3938 statement->Next();
3889 } 3939 }
3890 } 3940 }
3891 #endif 3941 #endif
3892 3942
3893 } 3943 }