浏览代码

Add loggedExec for sql queries and fix Study insert

Queries were failing silently due to unchecked characters
in data strings (for example 'Brigham and Women's Hospital')

This commit adds new logging function for debugging.

Also changes the Study level insert to use the bindValue methods
to avoid the 'quotin' hell' issue.
Steve Pieper 13 年之前
父节点
当前提交
a595dc12d9
共有 2 个文件被更改,包括 79 次插入24 次删除
  1. 71 24
      Libs/DICOM/Core/ctkDICOMIndexer.cpp
  2. 8 0
      Libs/DICOM/Core/ctkDICOMIndexer.h

+ 71 - 24
Libs/DICOM/Core/ctkDICOMIndexer.cpp

@@ -21,6 +21,7 @@
 // Qt includes
 // Qt includes
 #include <QSqlQuery>
 #include <QSqlQuery>
 #include <QSqlRecord>
 #include <QSqlRecord>
+#include <QSqlError>
 #include <QVariant>
 #include <QVariant>
 #include <QDate>
 #include <QDate>
 #include <QStringList>
 #include <QStringList>
@@ -111,6 +112,37 @@ ctkDICOMIndexer::~ctkDICOMIndexer()
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
+bool ctkDICOMIndexer::loggedExec(QSqlQuery& query)
+{
+  return (this->loggedExec(query, QString("")));
+}
+
+//------------------------------------------------------------------------------
+bool ctkDICOMIndexer::loggedExec(QSqlQuery& query, const QString& queryString)
+{
+  bool success;
+  if (queryString.compare(""))
+    {
+    success = query.exec(queryString);
+    }
+  else
+    {
+    success = query.exec();
+    }
+  if (!success)
+    {
+    QSqlError sqlError = query.lastError();
+    logger.debug( "SQL failed\n Bad SQL: " + query.lastQuery());
+    logger.debug( "Error text: " + sqlError.text());
+    }
+  else
+    {
+  logger.debug( "SQL worked!\n SQL: " + query.lastQuery());
+    }
+  return (success);
+}
+
+//------------------------------------------------------------------------------
 void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase, 
 void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase, 
                                    const QString& filePath,
                                    const QString& filePath,
                                    const QString& destinationDirectoryName,
                                    const QString& destinationDirectoryName,
@@ -133,7 +165,7 @@ void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase,
   QSqlQuery check_filename_query(ctkDICOMDatabase.database());
   QSqlQuery check_filename_query(ctkDICOMDatabase.database());
   check_filename_query.prepare("SELECT InsertTimestamp FROM Images WHERE Filename == ?");
   check_filename_query.prepare("SELECT InsertTimestamp FROM Images WHERE Filename == ?");
   check_filename_query.bindValue(0,filePath);
   check_filename_query.bindValue(0,filePath);
-  check_filename_query.exec();
+  this->loggedExec(check_filename_query);
   if (
   if (
     check_filename_query.next() &&
     check_filename_query.next() &&
     QFileInfo(filePath).lastModified() < QDateTime::fromString(check_filename_query.value(0).toString(),Qt::ISODate)
     QFileInfo(filePath).lastModified() < QDateTime::fromString(check_filename_query.value(0).toString(),Qt::ISODate)
@@ -250,7 +282,7 @@ void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase,
     QSqlQuery check_exists_query(ctkDICOMDatabase.database());
     QSqlQuery check_exists_query(ctkDICOMDatabase.database());
     std::stringstream check_exists_query_string;
     std::stringstream check_exists_query_string;
     check_exists_query_string << "SELECT * FROM Patients WHERE PatientID = '" << patientID << "'";
     check_exists_query_string << "SELECT * FROM Patients WHERE PatientID = '" << patientID << "'";
-    check_exists_query.exec(check_exists_query_string.str().c_str());
+    this->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
 
 
     /// we check only patients with the same PatientID
     /// we check only patients with the same PatientID
     /// PatientID is not unique in DICOM, so we also compare Name and BirthDate
     /// PatientID is not unique in DICOM, so we also compare Name and BirthDate
@@ -286,7 +318,7 @@ void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase,
       << patientsAge << "','"
       << patientsAge << "','"
       << patientComments << "')";
       << patientComments << "')";
 
 
-      insert_patient_query.exec(query_string.str().c_str());
+      this->loggedExec(insert_patient_query, query_string.str().c_str());
 
 
       patientUID = insert_patient_query.lastInsertId().toInt();
       patientUID = insert_patient_query.lastInsertId().toInt();
       insert_patient_query.finish();
       insert_patient_query.finish();
@@ -315,7 +347,9 @@ void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase,
     QSqlQuery check_exists_query(ctkDICOMDatabase.database());
     QSqlQuery check_exists_query(ctkDICOMDatabase.database());
     std::stringstream check_exists_query_string;
     std::stringstream check_exists_query_string;
     check_exists_query_string << "SELECT * FROM Studies WHERE StudyInstanceUID = '" << studyInstanceUID << "'";
     check_exists_query_string << "SELECT * FROM Studies WHERE StudyInstanceUID = '" << studyInstanceUID << "'";
-    check_exists_query.exec(check_exists_query_string.str().c_str());
+    this->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
+
+    logger.debug( "Checking for study: " + QString(studyInstanceUID.c_str()) );
 
 
     if(!check_exists_query.next())
     if(!check_exists_query.next())
     {
     {
@@ -323,20 +357,24 @@ void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase,
       QSqlQuery insert_query(ctkDICOMDatabase.database());
       QSqlQuery insert_query(ctkDICOMDatabase.database());
       std::stringstream query_string;
       std::stringstream query_string;
 
 
-      query_string << "INSERT INTO Studies VALUES('"
-        << studyInstanceUID << "','"
-        << patientUID << "','"
-        << studyID << "','"
-        << QDate::fromString(studyDate.c_str(), "yyyyMMdd").toString("yyyy-MM-dd").toStdString() << "','"
-        << studyTime << "','"
-        << accessionNumber << "','"
-        << modalitiesInStudy << "','"
-        << institutionName << "','"
-        << referringPhysician << "','"
-        << performingPhysiciansName << "','"
-        << studyDescription << "')";
-
-      insert_query.exec(query_string.str().c_str());
+      // TODO: all INSERTS should be changed to use the prepare/bindValue methods
+      // to avoid quoting issues
+      insert_query.prepare("INSERT INTO Studies (StudyInstanceUID, PatientsUID, StudyID, StudyDate, StudyTime, AccessionNumber, ModalitiesInStudy, InstitutionName, ReferringPhysician, PerformingPhysiciansName, StudyDescription) VALUES (:StudyInstanceUID, :PatientsUID, :StudyID, :StudyDate, :StudyTime, :AccessionNumber, :ModalitiesInStudy, :InstitutionName, :ReferringPhysician, :PerformingPhysiciansName, :StudyDescription)");
+
+      insert_query.bindValue(":StudyInstanceUID", QString(studyInstanceUID.c_str()));
+      insert_query.bindValue(":PatientsUID", patientUID);
+      insert_query.bindValue(":StudyID", QString(studyID.c_str()));
+      insert_query.bindValue(":StudyDate", QDate::fromString(studyDate.c_str(), "yyyyMMdd").toString("yyyy-MM-dd"));
+      insert_query.bindValue(":StudyTime", QString(studyTime.c_str()));
+      insert_query.bindValue(":AccessionNumber", QString(accessionNumber.c_str()));
+      insert_query.bindValue(":ModalitiesInStudy", QString(modalitiesInStudy.c_str()));
+      insert_query.bindValue(":InstitutionName", QString(institutionName.c_str()));
+      insert_query.bindValue(":ReferringPhysician", QString(referringPhysician.c_str()));
+      insert_query.bindValue(":PerformingPhysiciansName", QString(performingPhysiciansName.c_str()));
+      insert_query.bindValue(":StudyDescription", QString(studyDescription.c_str()));
+
+      this->loggedExec(insert_query);
+      logger.debug( "Inserted study: " + QString(studyInstanceUID.c_str()) );
     }
     }
   }
   }
 
 
@@ -352,7 +390,9 @@ void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase,
     QSqlQuery check_exists_query(ctkDICOMDatabase.database());
     QSqlQuery check_exists_query(ctkDICOMDatabase.database());
     std::stringstream check_exists_query_string;
     std::stringstream check_exists_query_string;
     check_exists_query_string << "SELECT * FROM Series WHERE SeriesInstanceUID = '" << seriesInstanceUID << "'";
     check_exists_query_string << "SELECT * FROM Series WHERE SeriesInstanceUID = '" << seriesInstanceUID << "'";
-    check_exists_query.exec(check_exists_query_string.str().c_str());
+    this->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
+
+    logger.debug( "Checking series: " + QString(seriesInstanceUID.c_str()) );
 
 
     if(!check_exists_query.next())
     if(!check_exists_query.next())
     {
     {
@@ -375,7 +415,8 @@ void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase,
         << static_cast<int>(echoNumber) << "','"
         << static_cast<int>(echoNumber) << "','"
         << static_cast<int>(temporalPosition) << "')";
         << static_cast<int>(temporalPosition) << "')";
 
 
-      insert_query.exec(query_string.str().c_str());
+      this->loggedExec(insert_query, query_string.str().c_str());
+      logger.debug( "Inserted series: " + QString(seriesInstanceUID.c_str()) );
     }
     }
   }
   }
 
 
@@ -392,14 +433,17 @@ void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase,
   {
   {
     QFile currentFile( filePath );
     QFile currentFile( filePath );
     QDir destinationDir(destinationDirectoryName + "/dicom");
     QDir destinationDir(destinationDirectoryName + "/dicom");
-    QString finalFilePath = sopInstanceUID.c_str();
+    finalFilePath = sopInstanceUID.c_str();
     if (createHierarchy)
     if (createHierarchy)
     {
     {
       destinationDir.mkpath(studySeriesDirectory);
       destinationDir.mkpath(studySeriesDirectory);
       finalFilePath.prepend( destinationDir.absolutePath() + "/"  + studySeriesDirectory + "/" );
       finalFilePath.prepend( destinationDir.absolutePath() + "/"  + studySeriesDirectory + "/" );
     }
     }
     currentFile.copy(finalFilePath);
     currentFile.copy(finalFilePath);
+    logger.debug( "Copy file from: " + filePath );
+    logger.debug( "Copy file to  : " + finalFilePath );
   }
   }
+  logger.debug(QString("finalFilePath: ") + finalFilePath);
 
 
   if (createThumbnails)
   if (createThumbnails)
   {
   {
@@ -424,11 +468,13 @@ void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase,
 //    std::stringstream relativeFilePath;
 //    std::stringstream relativeFilePath;
 //    relativeFilePath << seriesInstanceUID.c_str() << "/" << currentFilePath.getFileName();
 //    relativeFilePath << seriesInstanceUID.c_str() << "/" << currentFilePath.getFileName();
 
 
+  logger.debug(QString("Adding file path to dabase: ") + finalFilePath);
+
   QSqlQuery check_exists_query(ctkDICOMDatabase.database());
   QSqlQuery check_exists_query(ctkDICOMDatabase.database());
   std::stringstream check_exists_query_string;
   std::stringstream check_exists_query_string;
 //    check_exists_query_string << "SELECT * FROM Images WHERE Filename = '" << relativeFilePath.str() << "'";
 //    check_exists_query_string << "SELECT * FROM Images WHERE Filename = '" << relativeFilePath.str() << "'";
   check_exists_query_string << "SELECT * FROM Images WHERE SOPInstanceUID = '" << sopInstanceUID << "'";
   check_exists_query_string << "SELECT * FROM Images WHERE SOPInstanceUID = '" << sopInstanceUID << "'";
-  check_exists_query.exec(check_exists_query_string.str().c_str());
+  this->loggedExec(check_exists_query, check_exists_query_string.str().c_str());
 
 
   if(!check_exists_query.next())
   if(!check_exists_query.next())
   {
   {
@@ -439,7 +485,8 @@ void ctkDICOMIndexer::addFile(ctkDICOMDatabase& ctkDICOMDatabase,
     query_string << "INSERT INTO Images VALUES('"
     query_string << "INSERT INTO Images VALUES('"
       << sopInstanceUID << "','" << finalFilePath.toStdString() << "','" << seriesInstanceUID << "','" << QDateTime::currentDateTime().toString(Qt::ISODate).toStdString() << "')";
       << sopInstanceUID << "','" << finalFilePath.toStdString() << "','" << seriesInstanceUID << "','" << QDateTime::currentDateTime().toString(Qt::ISODate).toStdString() << "')";
 
 
-    insert_query.exec(query_string.str().c_str());
+    this->loggedExec(insert_query, query_string.str().c_str());
+    logger.debug(QString("added file path to dabase: ") + query_string.str().c_str());
   }
   }
 
 
 }
 }
@@ -488,7 +535,7 @@ void ctkDICOMIndexer::refreshDatabase(ctkDICOMDatabase& ctkDICOMDatabase, const
   QSqlQuery allFilesQuery(ctkDICOMDatabase.database());
   QSqlQuery allFilesQuery(ctkDICOMDatabase.database());
   QStringList databaseFileNames;
   QStringList databaseFileNames;
   QStringList filesToRemove;
   QStringList filesToRemove;
-  allFilesQuery.exec("SELECT Filename from Images;");
+  this->loggedExec(allFilesQuery, "SELECT Filename from Images;");
 
 
   while (allFilesQuery.next())
   while (allFilesQuery.next())
     {
     {

+ 8 - 0
Libs/DICOM/Core/ctkDICOMIndexer.h

@@ -65,6 +65,14 @@ public:
 
 
   Q_INVOKABLE void refreshDatabase(ctkDICOMDatabase& database, const QString& directoryName);
   Q_INVOKABLE void refreshDatabase(ctkDICOMDatabase& database, const QString& directoryName);
 
 
+  /**
+      \brief runs a query and prints debug output of status
+ 
+  */
+  bool loggedExec(QSqlQuery& query);
+  bool loggedExec(QSqlQuery& query, const QString& queryString);
+
+
   ///
   ///
   /// set thumbnail generator object
   /// set thumbnail generator object
   void setThumbnailGenerator(ctkDICOMAbstractThumbnailGenerator* generator);
   void setThumbnailGenerator(ctkDICOMAbstractThumbnailGenerator* generator);