comparison Framework/Common/DatabaseManager.cpp @ 70:e6c13ddd26d9 db-changes

all integration tests passing with LookupResources extension
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 03 Jan 2019 14:04:46 +0100
parents 714c5d2bee76
children 569e17419eae
comparison
equal deleted inserted replaced
69:19764fc60ade 70:e6c13ddd26d9
277 } 277 }
278 } 278 }
279 } 279 }
280 280
281 281
282 IResult& DatabaseManager::CachedStatement::GetResult() const
283 {
284 if (result_.get() == NULL)
285 {
286 LOG(ERROR) << "Accessing the results of a statement without having executed it";
287 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
288 }
289
290 return *result_;
291 }
292
293
294 void DatabaseManager::CachedStatement::Setup(const char* sql)
295 {
296 statement_ = manager_.LookupCachedStatement(location_);
297
298 if (statement_ == NULL)
299 {
300 query_.reset(new Query(sql));
301 }
302 else
303 {
304 LOG(TRACE) << "Reusing cached statement from "
305 << location_.GetFile() << ":" << location_.GetLine();
306 }
307 }
308
309
310 DatabaseManager::Transaction::Transaction(DatabaseManager& manager) : 282 DatabaseManager::Transaction::Transaction(DatabaseManager& manager) :
311 lock_(manager.mutex_), 283 lock_(manager.mutex_),
312 manager_(manager), 284 manager_(manager),
313 database_(manager.GetDatabase()), 285 database_(manager.GetDatabase()),
314 committed_(false) 286 committed_(false)
345 manager_.CommitTransaction(); 317 manager_.CommitTransaction();
346 committed_ = true; 318 committed_ = true;
347 } 319 }
348 } 320 }
349 321
322
323 IResult& DatabaseManager::StatementBase::GetResult() const
324 {
325 if (result_.get() == NULL)
326 {
327 LOG(ERROR) << "Accessing the results of a statement without having executed it";
328 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
329 }
330
331 return *result_;
332 }
333
334
335 void DatabaseManager::StatementBase::SetQuery(Query* query)
336 {
337 std::auto_ptr<Query> protection(query);
338
339 if (query_.get() != NULL)
340 {
341 LOG(ERROR) << "Cannot set twice a query";
342 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
343 }
344
345 if (query == NULL)
346 {
347 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
348 }
349
350 query_.reset(protection.release());
351 }
352
353
354 void DatabaseManager::StatementBase::SetResult(IResult* result)
355 {
356 std::auto_ptr<IResult> protection(result);
357
358 if (result_.get() != NULL)
359 {
360 LOG(ERROR) << "Cannot execute twice a statement";
361 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
362 }
363
364 if (result == NULL)
365 {
366 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
367 }
368
369 result_.reset(protection.release());
370 }
371
372
373 DatabaseManager::StatementBase::StatementBase(DatabaseManager& manager) :
374 manager_(manager),
375 lock_(manager_.mutex_),
376 transaction_(manager_.GetTransaction())
377 {
378 }
379
380
381 DatabaseManager::StatementBase::~StatementBase()
382 {
383 manager_.ReleaseImplicitTransaction();
384 }
385
386
387 void DatabaseManager::StatementBase::SetReadOnly(bool readOnly)
388 {
389 if (query_.get() != NULL)
390 {
391 query_->SetReadOnly(readOnly);
392 }
393 }
394
395
396 void DatabaseManager::StatementBase::SetParameterType(const std::string& parameter,
397 ValueType type)
398 {
399 if (query_.get() != NULL)
400 {
401 query_->SetType(parameter, type);
402 }
403 }
404
405 bool DatabaseManager::StatementBase::IsDone() const
406 {
407 try
408 {
409 return GetResult().IsDone();
410 }
411 catch (Orthanc::OrthancException& e)
412 {
413 manager_.CloseIfUnavailable(e.GetErrorCode());
414 throw;
415 }
416 }
417
418
419 void DatabaseManager::StatementBase::Next()
420 {
421 try
422 {
423 GetResult().Next();
424 }
425 catch (Orthanc::OrthancException& e)
426 {
427 manager_.CloseIfUnavailable(e.GetErrorCode());
428 throw;
429 }
430 }
431
432
433 size_t DatabaseManager::StatementBase::GetResultFieldsCount() const
434 {
435 try
436 {
437 return GetResult().GetFieldsCount();
438 }
439 catch (Orthanc::OrthancException& e)
440 {
441 manager_.CloseIfUnavailable(e.GetErrorCode());
442 throw;
443 }
444 }
445
446
447 void DatabaseManager::StatementBase::SetResultFieldType(size_t field,
448 ValueType type)
449 {
450 try
451 {
452 if (!GetResult().IsDone())
453 {
454 GetResult().SetExpectedType(field, type);
455 }
456 }
457 catch (Orthanc::OrthancException& e)
458 {
459 manager_.CloseIfUnavailable(e.GetErrorCode());
460 throw;
461 }
462 }
463
464
465 const IValue& DatabaseManager::StatementBase::GetResultField(size_t index) const
466 {
467 try
468 {
469 return GetResult().GetField(index);
470 }
471 catch (Orthanc::OrthancException& e)
472 {
473 manager_.CloseIfUnavailable(e.GetErrorCode());
474 throw;
475 }
476 }
477
350 478
351 DatabaseManager::CachedStatement::CachedStatement(const StatementLocation& location, 479 DatabaseManager::CachedStatement::CachedStatement(const StatementLocation& location,
352 DatabaseManager& manager, 480 DatabaseManager& manager,
353 const char* sql) : 481 const std::string& sql) :
354 manager_(manager), 482 StatementBase(manager),
355 lock_(manager_.mutex_), 483 location_(location)
356 database_(manager_.GetDatabase()), 484 {
357 location_(location), 485 statement_ = GetManager().LookupCachedStatement(location_);
358 transaction_(manager_.GetTransaction()) 486
359 { 487 if (statement_ == NULL)
360 Setup(sql); 488 {
361 } 489 SetQuery(new Query(sql));
362 490 }
363 491 else
364 DatabaseManager::CachedStatement::CachedStatement(const StatementLocation& location, 492 {
365 Transaction& transaction, 493 LOG(TRACE) << "Reusing cached statement from "
366 const char* sql) : 494 << location_.GetFile() << ":" << location_.GetLine();
367 manager_(transaction.GetManager()), 495 }
368 lock_(manager_.mutex_), 496 }
369 database_(manager_.GetDatabase()), 497
370 location_(location), 498
371 transaction_(manager_.GetTransaction())
372 {
373 Setup(sql);
374 }
375
376
377 DatabaseManager::CachedStatement::~CachedStatement()
378 {
379 manager_.ReleaseImplicitTransaction();
380 }
381
382
383 void DatabaseManager::CachedStatement::SetReadOnly(bool readOnly)
384 {
385 if (query_.get() != NULL)
386 {
387 query_->SetReadOnly(readOnly);
388 }
389 }
390
391
392 void DatabaseManager::CachedStatement::SetParameterType(const std::string& parameter,
393 ValueType type)
394 {
395 if (query_.get() != NULL)
396 {
397 query_->SetType(parameter, type);
398 }
399 }
400
401
402 void DatabaseManager::CachedStatement::Execute()
403 {
404 Dictionary parameters;
405 Execute(parameters);
406 }
407
408
409 void DatabaseManager::CachedStatement::Execute(const Dictionary& parameters) 499 void DatabaseManager::CachedStatement::Execute(const Dictionary& parameters)
410 { 500 {
411 if (result_.get() != NULL) 501 try
412 { 502 {
413 LOG(ERROR) << "Cannot execute twice a statement"; 503 std::auto_ptr<Query> query(ReleaseQuery());
414 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); 504
415 } 505 if (query.get() != NULL)
416
417 try
418 {
419 if (query_.get() != NULL)
420 { 506 {
421 // Register the newly-created statement 507 // Register the newly-created statement
422 assert(statement_ == NULL); 508 assert(statement_ == NULL);
423 statement_ = &manager_.CacheStatement(location_, *query_); 509 statement_ = &GetManager().CacheStatement(location_, *query);
424 query_.reset(NULL);
425 } 510 }
426 511
427 assert(statement_ != NULL); 512 assert(statement_ != NULL);
428 result_.reset(transaction_.Execute(*statement_, parameters)); 513 SetResult(GetTransaction().Execute(*statement_, parameters));
429 } 514 }
430 catch (Orthanc::OrthancException& e) 515 catch (Orthanc::OrthancException& e)
431 { 516 {
432 manager_.CloseIfUnavailable(e.GetErrorCode()); 517 GetManager().CloseIfUnavailable(e.GetErrorCode());
433 throw; 518 throw;
434 } 519 }
435 } 520 }
436 521
437 522
438 bool DatabaseManager::CachedStatement::IsDone() const 523 DatabaseManager::StandaloneStatement::StandaloneStatement(DatabaseManager& manager,
439 { 524 const std::string& sql) :
440 try 525 StatementBase(manager)
441 { 526 {
442 return GetResult().IsDone(); 527 SetQuery(new Query(sql));
443 } 528 }
444 catch (Orthanc::OrthancException& e) 529
445 { 530
446 manager_.CloseIfUnavailable(e.GetErrorCode()); 531 DatabaseManager::StandaloneStatement::~StandaloneStatement()
447 throw; 532 {
448 } 533 // The result must be removed before the statement, cf. (*)
449 } 534 ClearResult();
450 535 statement_.reset();
451 536 }
452 void DatabaseManager::CachedStatement::Next() 537
453 { 538
454 try 539 void DatabaseManager::StandaloneStatement::Execute(const Dictionary& parameters)
455 { 540 {
456 GetResult().Next(); 541 try
457 } 542 {
458 catch (Orthanc::OrthancException& e) 543 std::auto_ptr<Query> query(ReleaseQuery());
459 { 544 assert(query.get() != NULL);
460 manager_.CloseIfUnavailable(e.GetErrorCode()); 545
461 throw; 546 // The "statement_" object must be kept as long as the "IResult"
462 } 547 // is not destroyed, as the "IResult" can make calls to the
463 } 548 // statement (this is the case for SQLite and MySQL) - (*)
464 549 statement_.reset(GetManager().GetDatabase().Compile(*query));
465 550 assert(statement_.get() != NULL);
466 size_t DatabaseManager::CachedStatement::GetResultFieldsCount() const 551
467 { 552 SetResult(GetTransaction().Execute(*statement_, parameters));
468 try 553 }
469 { 554 catch (Orthanc::OrthancException& e)
470 return GetResult().GetFieldsCount(); 555 {
471 } 556 GetManager().CloseIfUnavailable(e.GetErrorCode());
472 catch (Orthanc::OrthancException& e)
473 {
474 manager_.CloseIfUnavailable(e.GetErrorCode());
475 throw;
476 }
477 }
478
479
480 void DatabaseManager::CachedStatement::SetResultFieldType(size_t field,
481 ValueType type)
482 {
483 try
484 {
485 if (!GetResult().IsDone())
486 {
487 GetResult().SetExpectedType(field, type);
488 }
489 }
490 catch (Orthanc::OrthancException& e)
491 {
492 manager_.CloseIfUnavailable(e.GetErrorCode());
493 throw;
494 }
495 }
496
497
498 const IValue& DatabaseManager::CachedStatement::GetResultField(size_t index) const
499 {
500 try
501 {
502 return GetResult().GetField(index);
503 }
504 catch (Orthanc::OrthancException& e)
505 {
506 manager_.CloseIfUnavailable(e.GetErrorCode());
507 throw; 557 throw;
508 } 558 }
509 } 559 }
510 } 560 }