-
Notifications
You must be signed in to change notification settings - Fork 0
Simplified API.
In the following code, we omit the namespace, use:
using namespace syd;
Get instance:
DatabaseManager * m = DatabaseManager::GetInstance();
auto & list = m->GetDatabaseSchemas();
Create a database:
Database * db = m->Create("StandardDatabase", dbname, folder);
Read a database:
Database * db = m->Read(dbname);
StandardDatabase * db = m->Read<StandardDatabase>(dbname);
Basics operations are 'CRUD': Create, Read, Update and Delete.
// Get the name of the sql schema, i.e. "StandardDatabase"
std::string s = db->GetDatabaseSchema();
// Get the filename i.e. test.db
std::string s = db->GetFilename();
// Get the image folder of the db, relative to the test.db folder
std::string s = db->GetDBFolder();
// Get the image folder (absolute path)
std::string s = db->GetAbsoluteDBFolder();
Insert an element (with table Patient as example but could be other tables):
db->Insert<Patient>(patient);
db->Insert<Patient>(vector_of_patients); // vector of elements
TableElement * e = db->InsertFromArg("Patient", string_vector); //FIXME
// Get all patients
db->Query<Patient>(vector_of_patients);
// Get all patients matching a query
typedef odb::query<Patient> QueryType;
QueryType q = (QueryType::name == "toto" and QueryType::age < 20)
db->Query<Patient>(q, vector_of_patients);
// Get only one patient matching the query
patient = db->QueryOne(q);
// Get only one patient with its id
patient = db->QueryOne(id);
// Others functions
int n = db->Count(q);
if (db->IfExist<Patient>(id)) { ... }
Update a record in the database.
db->Update<Patient>(patient);
db->Update<Patient>(vector_of_patients);
// Delete by knowing the type of the table
db->Delete<Patient>(patient);
db->Delete<Patient>(vector_of_patients);
// Delete with the name of the table and id
db->Delete("Patient", id);
db->Delete("Patient", vector_of_ids);
Deleting a record can be complicated due to foreign keys (FK) in some tables. Two mecanisms are provided:
- On cascade delete. When a table has a FK, it is possible to choose to delete the record if the record corresponding to the FK is deleted. This is done with the following pragma :
#pragma db on_delete(cascade)
. See table Injection in standard database for example. - In other circumstance, additional tasks must be performed when a record is deleted (for example removing the file on disk when an image is deleted). This is done with the following virtual function:
virtual void OnDelete(const std::string & table_name, TableElementBase * e);
This callback is called every time a record (e) from the table table_name is deleted. See StandardDatabase for example.
Every access to a database can fail for one reason, you can test the result with a try/catch. See here:
try {
// Here, access to the database (insert, query etc)
}
catch (const Exception & e) {
std::cout << e->what(); // Go here if something wrong
}
For debug, you can access to the last SQL query with:
std::string s = db->GetLastSQLQuery();
List of tables: TODO
Direct access to retrieve a patient, an injection:
patient = db->FindPatientByNameOrStudyId("toto");
injection = db->FindInjectionByNameOrId(patient, "Indium111");
db->FindDicom(patient, patterns, series);
When records are delete, a mecanism takes care about dependencies.
Policy:
- Image: also delete Files.
- Files: also delete the files on disk, the Image and the DicomFile
- DicomFile: also delete the File, the DicomSerie
- DicomSerie: also delete the DicomFiles
- Injection: also delete DicomSeries and Timepoint
- Radionuclide: also delete the Injection
- Patient: also delete the Injection
- Tag : TODO
- Timepoint: TODO
Create an object DicomSerieBuilder and set the basics informations:
DicomSerieBuilder b(db);
b.SetInjection(injection);
b.SetForcePatientFlag(true);
b.SearchForFilesInFolder(folder, files);
Main function to create a DicomSerie from a file. Checks if the file is not already in the db, guess if the file should be added to an existing DicomSerie or if a new DicomSerie. The DicomSerie is not yet inserted into the db. See next function.
for(auto f:files) b.CreateDicomSerieFromFile(f.c_str());
Once the files have been created (previous function), insert all created series in the db.
b.InsertDicomSeries();
Create an object TimepointBuilder and set the basics informations:
TimepointBuilder b(db);
b.SetTag(tag);
b.SetIntraTimepointMaxHourDiff(1); // 1 hour max difference between
Consider some DicomSerie and create the corresponding Timepoints. Guess that two dicoms with more than 1 hour acquisition time difference are not in the same Timepoint.
for(auto d:dicom_series) b.InsertDicomSerie(d);
Other functions:
GuessState s = b.GuessTimepointForThisDicomSerie(dicom_serie, vector_of_timepoints);
GuessState s = b.GuessIfDicomCanBeInThisTimepoint(dicom_serie, timepoint);
timepoint = b.CreateTimepoint(dicom_serie);
b.AddDicom(timepoint, dicom_serie);
Create object Image and the associated mhd/raw image (with itk):
ImageBuilder b(db);
b.SetImageTag(tag);
syd::Image image = b.InsertImageFromDicomSerie(dicom_serie);