# DumpToSQLITE3.cxx

    /*=========================================================================

      Program: GDCM (Grassroots DICOM). A DICOM library
      Module:  $URL$

      Copyright (c) 2006-2010 Mathieu Malaterre
      All rights reserved.
      See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.

         This software is distributed WITHOUT ANY WARRANTY; without even
         the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
         PURPOSE.  See the above copyright notice for more information.

    =========================================================================*/
    /*
     * Ref:
     * http://massmail.spl.harvard.edu/public-archives/slicer-devel/2010/004408.html
     *
     * Implementation details:
     * http://www.sqlite.org/c3ref/bind_blob.html
     * http://www.adp-gmbh.ch/sqlite/bind_insert.html
     */
    #include "gdcmScanner.h"
    #include "gdcmDirectory.h"
    #include "gdcmTag.h"
    #include "gdcmTrace.h"

    #include "sqlite3.h"

    #include <stdio.h>
    #include <time.h>

    int main(int argc, char *argv[])
    {
      if( argc < 2 )
        {
        return 1;
        }
      time_t time_start = time(0);

      gdcm::Trace::SetDebug( false );
      gdcm::Trace::SetWarning( false );
      const char *inputdirectory = argv[1];

      gdcm::Directory d;
      unsigned int nfiles = d.Load( inputdirectory, true);

      gdcm::Scanner s;
      using gdcm::Tag;
      s.AddTag( Tag(0x20,0xd) ); // Study Instance UID
      s.AddTag( Tag(0x20,0xe) ); // Series Instance UID

      bool b = s.Scan( d.GetFilenames() );
      if( !b ) return 1;
      time_t time_scanner = time(0);

      std::cout << "Finished loading data from : " << nfiles << " files" << std::endl;

    //  MappingType const &mappings = s.GetMappings();

      sqlite3* db;
      sqlite3_open("./dicom.db", &db);

      if(db == 0)
        {
        std::cerr << "Could not open database." << std::endl;
        return 1;
        }

      const char sql_stmt[] = "create table browser (seriesuid, studyuid)";
      int   ret;

      char *errmsg;
      ret = sqlite3_exec(db, sql_stmt, 0, 0, &errmsg);

      if(ret != SQLITE_OK)
        {
        printf("Error in statement: %s [%s].\n", sql_stmt, errmsg);
        return 1;
        }
      using gdcm::Directory;
      using gdcm::Scanner;
      const Directory::FilenamesType& files = d.GetFilenames();
      Directory::FilenamesType::const_iterator file = files.begin();

      sqlite3_stmt *stmt;
      if ( sqlite3_prepare(
          db,
          "insert into browser values (?,?)",  // stmt
          -1, // If than zero, then stmt is read up to the first nul terminator
          &stmt,
          0  // Pointer to unused portion of stmt
      )
        != SQLITE_OK)
        {
        printf("\nCould not prepare statement.");
        return 1;
        }
      //printf("\nThe statement has %d wildcards\n", sqlite3_bind_parameter_count(stmt));
      for(; file != files.end(); ++file)
        {
        const char *filename = file->c_str();
        bool b = s.IsKey(filename);
        if( b )
          {
          const Scanner::TagToValue &mapping = s.GetMapping(filename);
          Scanner::TagToValue::const_iterator it = mapping.begin();

          sqlite3_reset(stmt);

          for( int index = 1; it != mapping.end(); ++it, ++index)
            {
            const Tag & tag = it->first;
            const char *value = it->second;

            if (sqlite3_bind_text (
                stmt,
                index,  // Index of wildcard
                value,
                strlen(value),  // length of text
                SQLITE_STATIC // SQLite assumes that the information is in static
            )
              != SQLITE_OK)
              {
              printf("\nCould not bind int.\n");
              return 1;
              }
            }
          if (sqlite3_step(stmt) != SQLITE_DONE)
            {
            printf("\nCould not step (execute) stmt.\n");
            return 1;
            }
          }
        }

      sqlite3_close(db);

      time_t time_sqlite = time(0);

      std::cout << "Time to scan DICOM files: " << (time_scanner - time_start) << std::endl;
      std::cout << "Time to build SQLITE3: " << (time_sqlite - time_scanner) << std::endl;

      return 0;
    }