diff --git a/GeoModelExamples/HelloToyXML/Hello-Data.xml b/GeoModelExamples/HelloToyXML/Hello-Data.xml index 94b654bc15121ed35baef43c085bb99663c5bd04..a75372ca77065c17e039f7d93e4ab4b8feb9e2e0 100644 --- a/GeoModelExamples/HelloToyXML/Hello-Data.xml +++ b/GeoModelExamples/HelloToyXML/Hello-Data.xml @@ -1,15 +1,15 @@ <?xml version="1.0" encoding="UTF-8" standalone="no" ?> <GeoInpTables> -<Table name="HelloCables"> - <Row BARRELACCORDIONCABLES_DATA_ID="0" DLAR="1.396" DKAP="1.46" DCU="8.96" PERKAP="38" PERCU="62" PERAIR="14" HEIGHT="7" THICKIN=".1" THICKFAC=".517" ACCORCAB="64" CLEARANCE=".6"/> +<Table name="HELLOCABLES"> + <Row HELLOCABLES_DATA_ID="0" DLAR="1.396" DKAP="1.46" DCU="8.96" PERKAP="38" PERCU="62" PERAIR="14" HEIGHT="7" THICKIN=".1" THICKFAC=".517" ACCORCAB="64" CLEARANCE=".6"/> </Table> -<Table name="HelloBoxes"> - <Row BARRELDMBOXES_DATA_ID="1" BOXNAME="Ped1" HLEN="67" HWDT="380.18" HHGT="245.65"/> - <Row BARRELDMBOXES_DATA_ID="3" BOXNAME="Crate2" HLEN="250" HWDT="396.87" HHGT="245.55"/> - <Row BARRELDMBOXES_DATA_ID="4" BOXNAME="Crate3" HLEN="186.5" HWDT="3.175" HHGT="245.55" XTR="6.7"/> +<Table name="HELLOBOXES"> + <Row HELLOBOXES_DATA_ID="1" BOXNAME="Ped1" HLEN="67" HWDT="380.18" HHGT="245.65"/> + <Row HELLOBOXES_DATA_ID="3" BOXNAME="Crate2" HLEN="250" HWDT="396.87" HHGT="245.55"/> + <Row HELLOBOXES_DATA_ID="4" BOXNAME="Crate3" HLEN="186.5" HWDT="3.175" HHGT="245.55" XTR="6.7"/> </Table> </GeoInpTables> diff --git a/GeoModelExamples/HelloToyXML/Hello-Defs.xml b/GeoModelExamples/HelloToyXML/Hello-Defs.xml index 0ab08456a5529dae4556cd5fb52868bf8c65431e..377abf3d18da79f620e0b64687df221e0760cf34 100644 --- a/GeoModelExamples/HelloToyXML/Hello-Defs.xml +++ b/GeoModelExamples/HelloToyXML/Hello-Defs.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="UTF-8" standalone="no" ?> <GeoInpDefs> -<TableDef name="HelloCables"> - <ColDef name="BARRELACCORDIONCABLES_DATA_ID" type="LONG"/> +<TableDef name="HELLOCABLES"> + <ColDef name="HELLOCABLES_DATA_ID" type="LONG"/> <ColDef name="DLAR" type="DOUBLE"/> <ColDef name="DKAP" type="DOUBLE"/> <ColDef name="DCU" type="DOUBLE"/> @@ -17,8 +17,8 @@ </TableDef> -<TableDef name="HelloBoxes"> - <ColDef name="BARRELDMBOXES_DATA_ID" type="LONG"/> +<TableDef name="HELLOBOXES"> + <ColDef name="HELLOBOXES_DATA_ID" type="LONG"/> <ColDef name="BOXNAME" type="STRING"/> <ColDef name="HLEN" type="DOUBLE"/> <ColDef name="HWDT" type="DOUBLE"/> diff --git a/GeoModelExamples/HelloToyXML/step1_create_store_geo_and_publish_nodes.cpp b/GeoModelExamples/HelloToyXML/step1_create_store_geo_and_publish_nodes.cpp index 6b13d42572fc8ce39688a809bb08f677b13eef18..2cc74c47bd4be1414b641cb650deb0dbcc9cb213 100644 --- a/GeoModelExamples/HelloToyXML/step1_create_store_geo_and_publish_nodes.cpp +++ b/GeoModelExamples/HelloToyXML/step1_create_store_geo_and_publish_nodes.cpp @@ -1,331 +1,381 @@ /* - Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration */ /* -* author: Riccardo Maria Bianchi <riccardo.maria.bianchi@cern.ch> - Dec 2020 -* -* The example shows how to write a more complex Toy detector geometry, -* through the use of GeoSerialTransformers. -* -* It also shows how to publish the list of FullPhysVol and AlignableTransform nodes, -* to be retrieved later (for example, when setting the readout geometry up). -* -* It also shows how to store custom data tables in the output SQLite file, both taken from an external XML data file or defined in the C++ code itself. -* -*/ + * author: Riccardo Maria Bianchi <riccardo.maria.bianchi@cern.ch> - Dec 2020 + * + * The example shows how to write a more complex Toy detector geometry, + * through the use of GeoSerialTransformers. + * + * It also shows how to publish the list of FullPhysVol and AlignableTransform + * nodes, to be retrieved later (for example, when setting the readout geometry + * up). + * + * It also shows how to store custom data tables in the output SQLite file, both + * taken from an external XML data file or defined in the C++ code itself. + * + * Updates: + * - 2023, Jan -- Riccardo Maria BIANCHI -- Fixed write of custom tables. Fixed + * XML Defs. + */ -#include "GeoModelKernel/GeoDefinitions.h" -#include "GeoModelKernel/GeoMaterial.h" +#include "GeoGenericFunctions/AbsFunction.h" +#include "GeoGenericFunctions/Cos.h" +#include "GeoGenericFunctions/Sin.h" +#include "GeoGenericFunctions/Variable.h" +#include "GeoModelDBManager/GMDBManager.h" +#include "GeoModelKernel/GeoAlignableTransform.h" #include "GeoModelKernel/GeoBox.h" -#include "GeoModelKernel/GeoTube.h" +#include "GeoModelKernel/GeoDefinitions.h" +#include "GeoModelKernel/GeoFullPhysVol.h" #include "GeoModelKernel/GeoLogVol.h" +#include "GeoModelKernel/GeoMaterial.h" #include "GeoModelKernel/GeoNameTag.h" #include "GeoModelKernel/GeoPhysVol.h" -#include "GeoModelKernel/GeoFullPhysVol.h" -#include "GeoModelKernel/GeoTransform.h" +#include "GeoModelKernel/GeoPublisher.h" #include "GeoModelKernel/GeoSerialDenominator.h" -#include "GeoModelKernel/GeoAlignableTransform.h" #include "GeoModelKernel/GeoSerialTransformer.h" -#include "GeoModelKernel/GeoPublisher.h" +#include "GeoModelKernel/GeoTransform.h" +#include "GeoModelKernel/GeoTube.h" #include "GeoModelKernel/GeoUtilFunctions.h" - -#include "GeoGenericFunctions/AbsFunction.h" -#include "GeoGenericFunctions/Variable.h" -#include "GeoGenericFunctions/Sin.h" -#include "GeoGenericFunctions/Cos.h" - -#include "GeoModelDBManager/GMDBManager.h" - #include "GeoModelWrite/WriteGeoModel.h" - -#include "GeoXmlMatManager/GeoXmlMatManager.h" -#include "GeoXmlInpManager/GeoXmlInpManager.h" #include "GeoXmlInpManager/GeoInpRecordset.h" - +#include "GeoXmlInpManager/GeoXmlInpManager.h" +#include "GeoXmlMatManager/GeoXmlMatManager.h" // Units #include "GeoModelKernel/Units.h" -#define SYSTEM_OF_UNITS GeoModelKernelUnits // so we will get, e.g., 'SYSTEM_OF_UNITS::cm' +#define SYSTEM_OF_UNITS \ + GeoModelKernelUnits // so we will get, e.g., 'SYSTEM_OF_UNITS::cm' // C++ includes -#include <iostream> +#include <cstdlib> // EXIT_FAILURE #include <fstream> -#include <cstdlib> // EXIT_FAILURE +#include <iostream> using namespace GeoGenfun; using namespace GeoXF; -int main(int argc, char *argv[]) -{ - //-----------------------------------------------------------------------------------// - // Define the materials that we shall use. // - // ----------------------------------------------------------------------------------// - - // Define the units - #define gr SYSTEM_OF_UNITS::gram - #define mole SYSTEM_OF_UNITS::mole - #define cm3 SYSTEM_OF_UNITS::cm3 - - // Define the chemical elements - GeoElement* Nitrogen = new GeoElement ("Nitrogen" ,"N" , 7.0 , 14.0067 *gr/mole); - GeoElement* Oxygen = new GeoElement ("Oxygen" ,"O" , 8.0 , 15.9995 *gr/mole); - GeoElement* Argon = new GeoElement ("Argon" ,"Ar" , 18.0 , 39.948 *gr/mole); - GeoElement* Hydrogen = new GeoElement ("Hydrogen" ,"H" , 1.0 , 1.00797 *gr/mole); - GeoElement* Iron = new GeoElement ("Iron" ,"Fe" , 26.0 , 55.847 *gr/mole); - GeoElement* Carbon = new GeoElement ("Carbon" ,"C" , 6.0 , 12.0107 *gr/mole); - GeoElement* Sillicon = new GeoElement ("Silicon" ,"Si" , 14.0 , 28.085 *gr/mole); - - // Define the materials - - // Air: Nitrogen + Oxygen + Argon + Hydrogen - double densityOfAir=0.001214 *gr/cm3; - GeoMaterial *air = new GeoMaterial("Air", densityOfAir); - air->add(Nitrogen , 0.7494); - air->add(Oxygen, 0.2369); - air->add(Argon, 0.0129); - air->add(Hydrogen, 0.0008); - air->lock(); - - // Steel: Iron + Carbon - GeoMaterial* steel = new GeoMaterial("Steel", 7.9 *gr/cm3); - steel->add(Iron , 0.98); - steel->add(Carbon, 0.02); - steel->lock(); - - // Silicon 100% (Detector) - GeoMaterial* silicon = new GeoMaterial("Silicon", 2.329 *gr/cm3); - silicon->add(const_cast<GeoElement*> (Sillicon), 1.0); - silicon->lock(); - - // Carbon - GeoMaterial* carbon = new GeoMaterial("Carbon", 2.329 *gr/cm3); - carbon->add(const_cast<GeoElement*> (Carbon), 1.0); - carbon->lock(); - - - //--------------------------------------// - // Next make the box that describes - // the shape of the toy volume: - //--------------------------------------// - double x_toyBox, y_toyBox, z_toyBox; - const GeoBox *toyBox = new GeoBox(1200*SYSTEM_OF_UNITS::cm,1200*SYSTEM_OF_UNITS::cm, 1200*SYSTEM_OF_UNITS::cm); - - //--------------------------------------// - // Bundle this with a material - // into a logical volume: - //--------------------------------------// - const GeoLogVol *toyLog = new GeoLogVol("ToyLog", toyBox, air); // - - //--------------------------------------// - // ..And create a physical volume: - //--------------------------------------// - GeoPhysVol *toyPhys = new GeoPhysVol(toyLog); - - //--------------------------------------// - // Daughters - //--------------------------------------// - double x_ringTube, y_ringTube, z_ringTube; - const GeoTube *ringTube = new GeoTube(500*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm, 5.0*SYSTEM_OF_UNITS::cm); - - // Bundle this with a material // - // into a logical volume: // - const GeoLogVol *ringLog = new GeoLogVol("RingLog", ringTube, carbon); - - // Make 100 of these // - // within the volume of the toy: // - GeoSerialDenominator *ringName = new GeoSerialDenominator("RING"); - toyPhys->add(ringName); - - // Instanciate a GeoPublisher, to publish the list of FullPhysVol and AlignableTransforms nodes - GeoPublisher* publisher = new GeoPublisher; - // Optional - We set a name for the publisher: it will be appended to the name of the DB tables that host our published AXF and FPV nodes. - // Note : This is not compulsory: if not set, the default table name will be used; - // however, it helps to keep the output data well organized. - publisher->setName("HelloToyXML"); - - for (int i=0;i<100;i++) { - GeoFullPhysVol *ringPhys = new GeoFullPhysVol(ringLog); - GeoAlignableTransform *xform = new GeoAlignableTransform(GeoTrf::TranslateZ3D((i-50)*20*SYSTEM_OF_UNITS::cm)); - toyPhys->add(xform); - toyPhys->add(ringPhys); - - - // *** publish the list of FPV and AXF nodes *** - // in this example, we use integer-based keys for FullPhysVols... - unsigned int keyInt = i+1; - publisher->publishNode<GeoVFullPhysVol*,unsigned>(ringPhys, keyInt); - // ...and string-based keys for AlignableTransforms - std::string keyStr = "HelloToy-AXF-" + std::to_string(i+1); - publisher->publishNode<GeoAlignableTransform*,std::string>(xform, keyStr); - - //std::cout << "step1 - FPV, key: " << keyInt - // << " - xf: "; - //GeoUtilFunctions::printTrf(ringPhys->getAbsoluteTransform()); - - } - - - //--------------------------------------// - // Now, in addition to active daughters, - // add some passive material. - // This is done here using - // the "SerialTransformer", - // our way of parameterizing volumes. - // It does not need to be done this way, - // but we want to provide an example of - // parametrizations in the Toy - //--------------------------------------// - - GeoBox *sPass = new GeoBox(5.0*SYSTEM_OF_UNITS::cm, 30*SYSTEM_OF_UNITS::cm, 30*SYSTEM_OF_UNITS::cm); - GeoLogVol *lPass = new GeoLogVol("Passive", sPass, steel); - GeoPhysVol *pPass = new GeoPhysVol(lPass); - - GeoBox *sIPass = new GeoBox(4*SYSTEM_OF_UNITS::cm, 25*SYSTEM_OF_UNITS::cm, 25*SYSTEM_OF_UNITS::cm); - GeoLogVol *lIPass = new GeoLogVol("InnerPassive", sIPass, silicon); - GeoPhysVol *pIPass = new GeoPhysVol(lIPass); - - pPass->add(pIPass); - - const unsigned int NPLATES=100; - Variable i; - Sin sin; - GENFUNCTION f = 360*SYSTEM_OF_UNITS::deg/NPLATES*i; - GENFUNCTION g = sin(4*f); - GENFUNCTION h = -g; - TRANSFUNCTION t1 = Pow(GeoTrf::RotateZ3D(1.0),f)*GeoTrf::TranslateX3D(1100*SYSTEM_OF_UNITS::cm)*Pow(GeoTrf::TranslateZ3D(800*SYSTEM_OF_UNITS::cm),g); - TRANSFUNCTION t2 = Pow(GeoTrf::RotateZ3D(1.0),f)*GeoTrf::TranslateX3D(1100*SYSTEM_OF_UNITS::cm)*Pow(GeoTrf::TranslateZ3D(800*SYSTEM_OF_UNITS::cm),h); - - //--------------------------------------// - // Inside, by the way, the serial transformer - // will evaluate the functions: - // HepTransform3D xf = t1(i), for i=1,NPLATES.... - //--------------------------------------// - - GeoSerialDenominator *pass1Name = new GeoSerialDenominator("PASSIVE-1-"); - GeoSerialTransformer *s1 = new GeoSerialTransformer(pPass,&t1, NPLATES); - toyPhys->add(pass1Name); - toyPhys->add(s1); - - GeoSerialDenominator *pass2Name = new GeoSerialDenominator("PASSIVE-2-"); - GeoSerialTransformer *s2 = new GeoSerialTransformer(pPass,&t2, NPLATES); - toyPhys->add(pass2Name); - toyPhys->add(s2); - - - - //------------------------------------------------------------------------------------// - // Writing the geometry to file - //------------------------------------------------------------------------------------// - std::string path = "geometry.db"; - - // check if DB file exists. If yes, delete it. - std::ifstream infile(path.c_str()); - if ( infile.good() ) { - if( remove( path.c_str() ) != 0 ) - perror( "Error deleting file" ); - else { - std::string msg = "Previously existing " + path + " successfully deleted"; - puts( msg.c_str() ); - } - } - infile.close(); - - // open the DB connection - GMDBManager db(path); - - // check the DB connection - if (db.checkIsDBOpen()) { - std::cout << "OK! Database is open!" << std::endl; - } else { - std::cout << "Database ERROR!! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } - - // Dump the GeoModel tree - std::cout << "Dumping the GeoModel geometry tree..." << std::endl; - GeoModelIO::WriteGeoModel dumpGeoModelGraph(db); // init the GeoModel node action - toyPhys->exec(&dumpGeoModelGraph); // visit all GeoModel nodes - - - //===================== - // Auxiliary Data - //===================== - - // Now, we save auxiliary data to the output DB file - // in additional custom DB tables - // Those data are meant to be used by detector code later in the workflow - // so, it must be stored in the DB besides the actual GeoModel data themselves. - // - - // In these first two examples, we load auxiliary data from custom XML files - // through the use of the GeoModelATLAS/GeoModelDataManagers - // Then, we store the auxiliary data directly to the DB files. - // - // At first, we need to get the GeoModelDataManagers' XML Input Manager - // As per GeoModelDataManagers' architecture, we need to load both the file - // containing the tables' defiintions and the one containing the actual tables' data - GeoXmlInpManager* inpman = GeoXmlInpManager::getManager(); - inpman->parse("Hello-Defs.xml"); - inpman->parse("Hello-Data.xml"); - // Then, we set the name of the first of the tables that we want to store in the DB... - std::string tableName = "HelloCables"; - // ...we get the corresponding "Recordset"'s data (i.e., the table's columns definitions and data rows - std::pair<std::map<std::string, std::vector<std::string>>, std::vector<std::vector<GeoInp>>> helloCablesData = inpman->getRecordsetData(tableName); - // ...and we store that table to the output DB - dumpGeoModelGraph.storeDataTable( tableName, (helloCablesData.first)["colNames"], (helloCablesData.first)["colTypes"], helloCablesData.second ); - - // Here an example for a second table of auxiliary data, which we want to store in the DB for later use - tableName = "HelloBoxes"; - std::pair<std::map<std::string, std::vector<std::string>>, std::vector<std::vector<GeoInp>>> helloBoxesData = inpman->getRecordsetData(tableName); - dumpGeoModelGraph.storeDataTable( tableName, (helloBoxesData.first)["colNames"], (helloBoxesData.first)["colTypes"], helloBoxesData.second ); - - // Not all auxiliary data need to come from XML files. - // Here, we create a custom table made of strings, directly in the code. - // We define a table's name - // Then, we define the names and types of the columns, storing them as vectors of strings - // Then, we populate vectors of strings with the table's data. One vector for each table's row. - // Then, we store the data into the DB. - tableName = "HelloTest"; - std::vector<std::string> tableColNames = {"MY_DATA_ID", "WEIGTH", "NAME"}; - std::vector<std::string> tableColTypes = {"long", "double", "string"}; - std::vector<std::variant<int,long,float,double,std::string>> vec1 = {1, 15, "Ped1"}; - std::vector<std::variant<int,long,float,double,std::string>> vec2 = {3, "NULL", "Crate2"}; - std::vector<std::vector<std::variant<int,long,float,double,std::string>>> tableData = { vec1, vec2 }; - dumpGeoModelGraph.storeDataTable( tableName, tableColNames, tableColTypes, tableData ); - - - //===================== - // Save to the DB - //===================== - // Save the GeoModel tree to the SQlite DB file. - // We pass a pointer to the GeoPublisher as well, so the list of published - // FullPhysVol and AlignableTransform nodes will be stored into the DB too. - dumpGeoModelGraph.saveToDB( publisher ); - - std::cout << "\n-----\nDONE. Geometry saved.\n-----\n" <<std::endl; - - - //------------------------------------------------------------------------------------// - // Testing the persitified geometry - //------------------------------------------------------------------------------------// -/* - std::cout << "\nTest - list of all the GeoFullPhysVol nodes in the persistified geometry:" << std::endl; - db.printAllFullPhysVols(); - std::cout << "\nTest - list of all the GeoAlignableTransform nodes in the persistified geometry:" << std::endl; - db.printAllAlignableTransforms(); - - std::cout << "\nTest - list of all the 'published' GeoFullPhysVol nodes in the persistified geometry:" << std::endl; - db.printAllPublishedFullPhysVols( publisher->getName() ); - std::cout << "\nTest - list of all the 'published' GeoAlignableTransform nodes in the persistified geometry:" << std::endl; - db.printAllPublishedAlignableTransforms( publisher->getName() ); -*/ - // cleaning - delete publisher; - publisher = nullptr; - - - return 0; - +int main(int argc, char *argv[]) { + //-----------------------------------------------------------------------------------// + // Define the materials that we shall use. // + // ----------------------------------------------------------------------------------// + +// Define the units +#define gr SYSTEM_OF_UNITS::gram +#define mole SYSTEM_OF_UNITS::mole +#define cm3 SYSTEM_OF_UNITS::cm3 + + // Define the chemical elements + GeoElement *Nitrogen = + new GeoElement("Nitrogen", "N", 7.0, 14.0067 * gr / mole); + GeoElement *Oxygen = + new GeoElement("Oxygen", "O", 8.0, 15.9995 * gr / mole); + GeoElement *Argon = new GeoElement("Argon", "Ar", 18.0, 39.948 * gr / mole); + GeoElement *Hydrogen = + new GeoElement("Hydrogen", "H", 1.0, 1.00797 * gr / mole); + GeoElement *Iron = new GeoElement("Iron", "Fe", 26.0, 55.847 * gr / mole); + GeoElement *Carbon = + new GeoElement("Carbon", "C", 6.0, 12.0107 * gr / mole); + GeoElement *Sillicon = + new GeoElement("Silicon", "Si", 14.0, 28.085 * gr / mole); + + // Define the materials + + // Air: Nitrogen + Oxygen + Argon + Hydrogen + double densityOfAir = 0.001214 * gr / cm3; + GeoMaterial *air = new GeoMaterial("Air", densityOfAir); + air->add(Nitrogen, 0.7494); + air->add(Oxygen, 0.2369); + air->add(Argon, 0.0129); + air->add(Hydrogen, 0.0008); + air->lock(); + + // Steel: Iron + Carbon + GeoMaterial *steel = new GeoMaterial("Steel", 7.9 * gr / cm3); + steel->add(Iron, 0.98); + steel->add(Carbon, 0.02); + steel->lock(); + + // Silicon 100% (Detector) + GeoMaterial *silicon = new GeoMaterial("Silicon", 2.329 * gr / cm3); + silicon->add(const_cast<GeoElement *>(Sillicon), 1.0); + silicon->lock(); + + // Carbon + GeoMaterial *carbon = new GeoMaterial("Carbon", 2.329 * gr / cm3); + carbon->add(const_cast<GeoElement *>(Carbon), 1.0); + carbon->lock(); + + //--------------------------------------// + // Next make the box that describes + // the shape of the toy volume: + //--------------------------------------// + double x_toyBox, y_toyBox, z_toyBox; + const GeoBox *toyBox = + new GeoBox(1200 * SYSTEM_OF_UNITS::cm, 1200 * SYSTEM_OF_UNITS::cm, + 1200 * SYSTEM_OF_UNITS::cm); + + //--------------------------------------// + // Bundle this with a material + // into a logical volume: + //--------------------------------------// + const GeoLogVol *toyLog = new GeoLogVol("ToyLog", toyBox, air); // + + //--------------------------------------// + // ..And create a physical volume: + //--------------------------------------// + GeoPhysVol *toyPhys = new GeoPhysVol(toyLog); + + //--------------------------------------// + // Daughters + //--------------------------------------// + double x_ringTube, y_ringTube, z_ringTube; + const GeoTube *ringTube = + new GeoTube(500 * SYSTEM_OF_UNITS::cm, 1000 * SYSTEM_OF_UNITS::cm, + 5.0 * SYSTEM_OF_UNITS::cm); + + // Bundle this with a material // + // into a logical volume: // + const GeoLogVol *ringLog = new GeoLogVol("RingLog", ringTube, carbon); + + // Make 100 of these // + // within the volume of the toy: // + GeoSerialDenominator *ringName = new GeoSerialDenominator("RING"); + toyPhys->add(ringName); + + // Instanciate a GeoPublisher, to publish the list of FullPhysVol and + // AlignableTransforms nodes + GeoPublisher *publisher = new GeoPublisher; + // Optional - We set a name for the publisher: it will be appended to the + // name of the DB tables that host our published AXF and FPV nodes. Note : + // This is not compulsory: if not set, the default table name will be used; + // however, it helps to keep the output data well organized. + publisher->setName("HelloToyXML"); + + for (int i = 0; i < 100; i++) { + GeoFullPhysVol *ringPhys = new GeoFullPhysVol(ringLog); + GeoAlignableTransform *xform = new GeoAlignableTransform( + GeoTrf::TranslateZ3D((i - 50) * 20 * SYSTEM_OF_UNITS::cm)); + toyPhys->add(xform); + toyPhys->add(ringPhys); + + // *** publish the list of FPV and AXF nodes *** + // in this example, we use integer-based keys for FullPhysVols... + unsigned int keyInt = i + 1; + publisher->publishNode<GeoVFullPhysVol *, unsigned>(ringPhys, keyInt); + // ...and string-based keys for AlignableTransforms + std::string keyStr = "HelloToy-AXF-" + std::to_string(i + 1); + publisher->publishNode<GeoAlignableTransform *, std::string>(xform, + keyStr); + + // std::cout << "step1 - FPV, key: " << keyInt + // << " - xf: "; + // GeoUtilFunctions::printTrf(ringPhys->getAbsoluteTransform()); + } + + //--------------------------------------// + // Now, in addition to active daughters, + // add some passive material. + // This is done here using + // the "SerialTransformer", + // our way of parameterizing volumes. + // It does not need to be done this way, + // but we want to provide an example of + // parametrizations in the Toy + //--------------------------------------// + + GeoBox *sPass = + new GeoBox(5.0 * SYSTEM_OF_UNITS::cm, 30 * SYSTEM_OF_UNITS::cm, + 30 * SYSTEM_OF_UNITS::cm); + GeoLogVol *lPass = new GeoLogVol("Passive", sPass, steel); + GeoPhysVol *pPass = new GeoPhysVol(lPass); + + GeoBox *sIPass = + new GeoBox(4 * SYSTEM_OF_UNITS::cm, 25 * SYSTEM_OF_UNITS::cm, + 25 * SYSTEM_OF_UNITS::cm); + GeoLogVol *lIPass = new GeoLogVol("InnerPassive", sIPass, silicon); + GeoPhysVol *pIPass = new GeoPhysVol(lIPass); + + pPass->add(pIPass); + + const unsigned int NPLATES = 100; + Variable i; + Sin sin; + GENFUNCTION f = 360 * SYSTEM_OF_UNITS::deg / NPLATES * i; + GENFUNCTION g = sin(4 * f); + GENFUNCTION h = -g; + TRANSFUNCTION t1 = Pow(GeoTrf::RotateZ3D(1.0), f) * + GeoTrf::TranslateX3D(1100 * SYSTEM_OF_UNITS::cm) * + Pow(GeoTrf::TranslateZ3D(800 * SYSTEM_OF_UNITS::cm), g); + TRANSFUNCTION t2 = Pow(GeoTrf::RotateZ3D(1.0), f) * + GeoTrf::TranslateX3D(1100 * SYSTEM_OF_UNITS::cm) * + Pow(GeoTrf::TranslateZ3D(800 * SYSTEM_OF_UNITS::cm), h); + + //--------------------------------------// + // Inside, by the way, the serial transformer + // will evaluate the functions: + // HepTransform3D xf = t1(i), for i=1,NPLATES.... + //--------------------------------------// + + GeoSerialDenominator *pass1Name = new GeoSerialDenominator("PASSIVE-1-"); + GeoSerialTransformer *s1 = new GeoSerialTransformer(pPass, &t1, NPLATES); + toyPhys->add(pass1Name); + toyPhys->add(s1); + + GeoSerialDenominator *pass2Name = new GeoSerialDenominator("PASSIVE-2-"); + GeoSerialTransformer *s2 = new GeoSerialTransformer(pPass, &t2, NPLATES); + toyPhys->add(pass2Name); + toyPhys->add(s2); + + //------------------------------------------------------------------------------------// + // Writing the geometry to file + //------------------------------------------------------------------------------------// + std::string path = "geometry.db"; + + // check if DB file exists. If yes, delete it. + std::ifstream infile(path.c_str()); + if (infile.good()) { + if (remove(path.c_str()) != 0) + perror("Error deleting file"); + else { + std::string msg = + "Previously existing " + path + " successfully deleted"; + puts(msg.c_str()); + } + } + infile.close(); + + // open the DB connection + GMDBManager db(path); + + // check the DB connection + if (db.checkIsDBOpen()) { + std::cout << "OK! Database is open!" << std::endl; + } else { + std::cout << "Database ERROR!! Exiting..." << std::endl; + exit(EXIT_FAILURE); + } + + // Dump the GeoModel tree + std::cout << "Dumping the GeoModel geometry tree..." << std::endl; + GeoModelIO::WriteGeoModel dumpGeoModelGraph( + db); // init the GeoModel node action + toyPhys->exec(&dumpGeoModelGraph); // visit all GeoModel nodes + + //===================== + // Auxiliary Data + //===================== + + // Now, we save auxiliary data to the output DB file + // in additional custom DB tables + // Those data are meant to be used by detector code later in the workflow + // so, it must be stored in the DB besides the actual GeoModel data + // themselves. + // + + // In these first two examples, we load auxiliary data from custom XML files + // through the use of the GeoModelATLAS/GeoModelDataManagers + // Then, we store the auxiliary data directly to the DB files. + // + // At first, we need to get the GeoModelDataManagers' XML Input Manager + // As per GeoModelDataManagers' architecture, we need to load both the file + // containing the tables' defiintions and the one containing the actual + // tables' data + GeoXmlInpManager *inpman = GeoXmlInpManager::getManager(); + inpman->parse("Hello-Defs.xml"); + inpman->parse("Hello-Data.xml"); + // Then, we set the name of the first of the tables that we want to store in + // the DB... + // Note: table names must be in CAPITAL letters + std::string tableName = "HELLOCABLES"; + // ...we get the corresponding "Recordset"'s data (i.e., the table's columns + // definitions and data rows + std::pair<std::map<std::string, std::vector<std::string>>, + std::vector<std::vector<GeoInp>>> + helloCablesData = inpman->getRecordsetData(tableName); + // ...and we store that table to the output DB + dumpGeoModelGraph.storeDataTable( + tableName, (helloCablesData.first)["colNames"], + (helloCablesData.first)["colTypes"], helloCablesData.second); + + // Here an example for a second table of auxiliary data, which we want to + // store in the DB for later use + // Note: table names must be in CAPITAL letters + tableName = "HELLOBOXES"; + std::pair<std::map<std::string, std::vector<std::string>>, + std::vector<std::vector<GeoInp>>> + helloBoxesData = inpman->getRecordsetData(tableName); + dumpGeoModelGraph.storeDataTable( + tableName, (helloBoxesData.first)["colNames"], + (helloBoxesData.first)["colTypes"], helloBoxesData.second); + + // Not all auxiliary data need to come from XML files. + // Here, we create a custom table made of strings, directly in the code. + // We define a table's name + // Then, we define the names and types of the columns, storing them as + // vectors of strings. Then, we populate vectors of strings with the table's + // data. One vector for each table's row. Then, we store the data into the + // DB. + tableName = "HelloTest"; + std::vector<std::string> tableColNames = {"MY_DATA_ID", "WEIGTH", "NAME"}; + std::vector<std::string> tableColTypes = { + "LONG", "DOUBLE", + "STRING"}; // NOTE: types must be defined in CAPITAL letters + std::vector<std::variant<int, long, float, double, std::string>> vec1 = { + 1, 15, "Ped1"}; + std::vector<std::variant<int, long, float, double, std::string>> vec2 = { + 3, "NULL", "Crate2"}; // we have a NULL just as an example + std::vector< + std::vector<std::variant<int, long, float, double, std::string>>> + tableData = {vec1, vec2}; + dumpGeoModelGraph.storeDataTable(tableName, tableColNames, tableColTypes, + tableData); + + //===================== + // Save to the DB + //===================== + // Save the GeoModel tree to the SQlite DB + // file. We pass a pointer to the + // GeoPublisher as well, so the list of + // published FullPhysVol and + // AlignableTransform nodes will be stored + // into the DB too. + dumpGeoModelGraph.saveToDB(publisher); + + std::cout << "\n-----\nDONE. Geometry " + "saved.\n-----\n" + << std::endl; + + //------------------------------------------------------------------------------------// + // Testing the persitified geometry + //------------------------------------------------------------------------------------// + /* + std::cout << "\nTest - list of all the + GeoFullPhysVol nodes in the persistified + geometry:" << std::endl; + db.printAllFullPhysVols(); std::cout + << "\nTest - list of all the + GeoAlignableTransform nodes in the + persistified geometry:" << std::endl; + db.printAllAlignableTransforms(); + + std::cout << "\nTest - list of all the + 'published' GeoFullPhysVol nodes in the + persistified geometry:" << std::endl; + db.printAllPublishedFullPhysVols( + publisher->getName() ); std::cout << + "\nTest - list of all the 'published' + GeoAlignableTransform nodes in the + persistified geometry:" << std::endl; + db.printAllPublishedAlignableTransforms( + publisher->getName() ); + */ + // cleaning + delete publisher; + publisher = nullptr; + + return 0; } diff --git a/GeoModelExamples/HelloToyXML/step2_read_geo_and_published_nodes.cpp b/GeoModelExamples/HelloToyXML/step2_read_geo_and_published_nodes.cpp index 72454350aad6069ba986cd289733373126718910..aa9597213074f2f7bd74a5ff0cd4b09cba463ce2 100644 --- a/GeoModelExamples/HelloToyXML/step2_read_geo_and_published_nodes.cpp +++ b/GeoModelExamples/HelloToyXML/step2_read_geo_and_published_nodes.cpp @@ -1,191 +1,222 @@ -// Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration /* * HelloToyXML.cpp * * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch> * Created on: Dec, 2020 + * Updates: + * - Jan, 2023 -- Added read of custom tables. * */ // GeoModel includes #include "GeoModelDBManager/GMDBManager.h" -#include "GeoModelRead/ReadGeoModel.h" +#include "GeoModelKernel/GeoAlignableTransform.h" #include "GeoModelKernel/GeoBox.h" -#include "GeoModelKernel/GeoPhysVol.h" #include "GeoModelKernel/GeoFullPhysVol.h" -#include "GeoModelKernel/GeoAlignableTransform.h" #include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelKernel/GeoPhysVol.h" #include "GeoModelKernel/GeoUtilFunctions.h" +#include "GeoModelRead/ReadGeoModel.h" // C++ includes +#include <cstdlib> // EXIT_FAILURE +#include <fstream> #include <iostream> #include <map> -#include <fstream> -#include <cstdlib> // EXIT_FAILURE - // Units #include "GeoModelKernel/Units.h" -#define SYSTEM_OF_UNITS GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' - - -GeoPhysVol* createTheWorld(GeoPhysVol* world) -{ - if (world == nullptr) - { - //-----------------------------------------------------------------------------------// - // Define the materials that we shall use. // - // ----------------------------------------------------------------------------------// - - // Define the units - #define gr SYSTEM_OF_UNITS::gram - #define mole SYSTEM_OF_UNITS::mole - #define cm3 SYSTEM_OF_UNITS::cm3 - - // Define the chemical elements - GeoElement* Nitrogen = new GeoElement ("Nitrogen" ,"N" , 7.0 , 14.0067 *gr/mole); - GeoElement* Oxygen = new GeoElement ("Oxygen" ,"O" , 8.0 , 15.9995 *gr/mole); - GeoElement* Argon = new GeoElement ("Argon" ,"Ar" , 18.0 , 39.948 *gr/mole); - GeoElement* Hydrogen = new GeoElement ("Hydrogen" ,"H" , 1.0 , 1.00797 *gr/mole); - - // Define the materials - double densityOfAir=0.001214 *gr/cm3; - GeoMaterial *air = new GeoMaterial("Air", densityOfAir); - air->add(Nitrogen , 0.7494); - air->add(Oxygen, 0.2369); - air->add(Argon, 0.0129); - air->add(Hydrogen, 0.0008); - air->lock(); - - const GeoBox* worldBox = new GeoBox(1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm); - const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air); - world = new GeoPhysVol(worldLog); - } - return world; +#define SYSTEM_OF_UNITS \ + GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' + +GeoPhysVol* createTheWorld(GeoPhysVol* world) { + if (world == nullptr) { + //-----------------------------------------------------------------------------------// +// Define the materials that we shall use. // +// ----------------------------------------------------------------------------------// + +// Define the units +#define gr SYSTEM_OF_UNITS::gram +#define mole SYSTEM_OF_UNITS::mole +#define cm3 SYSTEM_OF_UNITS::cm3 + + // Define the chemical elements + GeoElement* Nitrogen = + new GeoElement("Nitrogen", "N", 7.0, 14.0067 * gr / mole); + GeoElement* Oxygen = + new GeoElement("Oxygen", "O", 8.0, 15.9995 * gr / mole); + GeoElement* Argon = + new GeoElement("Argon", "Ar", 18.0, 39.948 * gr / mole); + GeoElement* Hydrogen = + new GeoElement("Hydrogen", "H", 1.0, 1.00797 * gr / mole); + + // Define the materials + double densityOfAir = 0.001214 * gr / cm3; + GeoMaterial* air = new GeoMaterial("Air", densityOfAir); + air->add(Nitrogen, 0.7494); + air->add(Oxygen, 0.2369); + air->add(Argon, 0.0129); + air->add(Hydrogen, 0.0008); + air->lock(); + + const GeoBox* worldBox = + new GeoBox(1000 * SYSTEM_OF_UNITS::cm, 1000 * SYSTEM_OF_UNITS::cm, + 1000 * SYSTEM_OF_UNITS::cm); + const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air); + world = new GeoPhysVol(worldLog); + } + return world; } - - -int main(int argc, char *argv[]) -{ - // QCoreApplication app(argc, argv); - - // GET GEOMETRY FROM LOCAL DB - // Set valid db path before first run - const std::string path = "./geometry.db"; - std::cout << "Using this DB file:" << path << std::endl; - - // check if DB file exists. If not, return. - // FIXME: TODO: this check should go in the 'GMDBManager' constructor. - std::ifstream infile(path.c_str()); - if ( ! infile.good() ) { - std::cout << "\n\tERROR!! The '" << path << "' file does not exists already!! Please, check.\n"; - exit(EXIT_FAILURE); - } - infile.close(); - - - // open the DB - GMDBManager* db = new GMDBManager(path); - /* Open database */ - if (db->checkIsDBOpen()) { - std::cout << "OK! Database is open!\n"; - } - else { - std::cout << "Database is not open!\n"; - // return; - throw; - } - - - /* setup the GeoModel reader */ - GeoModelIO::ReadGeoModel readInGeo = GeoModelIO::ReadGeoModel(db); - std::cout << "OK! ReadGeoModel is set." << std::endl; - - - /* build the GeoModel tree */ - GeoPhysVol* world = readInGeo.buildGeoModel(); // builds the whole GeoModel tree in memory - std::cout << "ReadGeoModel::buildGeoModel() done." << std::endl; - - - // --- testing the imported Geometry - - // get number of children volumes - unsigned int nChil = world->getNChildVols(); - std:: cout << "world's number of children: " << nChil << std::endl; - - // loop over all children nodes - std::cout << "Looping over all 'volume' children (i.e., GeoPhysVol and GeoFullPhysVol)..." << std::endl; - for (unsigned int idx=0; idx<nChil; ++idx) { - PVConstLink nodeLink = world->getChildVol(idx); - - if ( dynamic_cast<const GeoVPhysVol*>( &(*( nodeLink ))) ) { - - std::cout << "\t" << "the child n. " << idx << " "; - const GeoVPhysVol *childVolV = &(*( nodeLink )); - - if ( dynamic_cast<const GeoPhysVol*>(childVolV) ) { - const GeoPhysVol* childVol = dynamic_cast<const GeoPhysVol*>(childVolV); - std::cout << "is a GeoPhysVol, whose GeoLogVol's name is: " << childVol->getLogVol()->getName(); - std::cout << " and it has "<<childVol->getNChildVols()<<" child volumes" << std::endl; - } - else if ( dynamic_cast<const GeoFullPhysVol*>(childVolV) ) { - const GeoFullPhysVol* childVol = dynamic_cast<const GeoFullPhysVol*>(childVolV); - std::cout << "is a GeoFullPhysVol, whose GeoLogVol's name is: " << childVol->getLogVol()->getName(); - std::cout << " and it has "<<childVol->getNChildVols()<<" child volumes" << std::endl; - std::cout << "\txf:"; GeoUtilFunctions::printTrf(childVol->getAbsoluteTransform()); - } - } - } - - std::cout << "We now read back from the DB the lists of published FullPhysVol and AlignableTransform nodes...\n"; - - // Note: In the Step1 of this example, - // we have published FullPhysVols and AlignableTransforms - // into the DB as: - // - <integer-based key, GeoFullPhysVol*> - // - <string-based key, GeoAlignableTransform*> - // Thus, we now get them back from the DB with the same key types we originally used: - std::map<unsigned int, GeoFullPhysVol*> mapFPV = readInGeo.getPublishedNodes<unsigned int, GeoFullPhysVol*>("HelloToyXML"); - std::map<std::string, GeoAlignableTransform*> mapAXF = readInGeo.getPublishedNodes<std::string, GeoAlignableTransform*>("HelloToyXML"); - - unsigned int ii=0; - std::cout << "\n\nPublished AlignableTransforms from the DB...\n"; - std::cout << "['xf' is the output of 'getTransform()']\n"; - for ( auto const& [key, xf] : mapAXF ) - { - if(0==ii) std::cout << "[key type (compiler's code): '" << typeid(key).name() << "']\n"; - std::cout << "\n\t--> key: " << key - << " - AlignableTransform*: " << xf - << std::endl; - std::cout << "\txf:: "; GeoUtilFunctions::printTrf( xf->getTransform() ); - ++ii; - } - - ii=0; // reset the counter - std::cout << "\n\nPublished FullPhysVols from the DB...\n"; - std::cout << "['xf' is the output of 'getAbsoluteTransform()']\n"; - for ( auto const& [key, vol] : mapFPV ) - { - GeoTrf::Transform3D xf = vol->getAbsoluteTransform(); - - if(0==ii) std::cout << "[key type (compiler's code): '" << typeid(key).name() << "']\n"; - std::cout << "\n\t--> key: " << key - << " - GeoFullPhysVol*: " << vol - << std::endl; - std::cout << "\txf:"; GeoUtilFunctions::printTrf(vol->getAbsoluteTransform()); - ++ii; - } - - - std::cout << "\n\nWe now read back the tables containing auxiliary data, which have been stored in the data file as additional custom tables\n\n"; -readInGeo.printAllDBTables(); -readInGeo.printDBTable("dbversion"); -readInGeo.printDBTable("HelloBoxes"); - - - std::cout << "Everything done." << std::endl; - - return 0; +int main(int argc, char* argv[]) { + // QCoreApplication app(argc, argv); + + // GET GEOMETRY FROM LOCAL DB + // Set valid db path before first run + const std::string path = "./geometry.db"; + std::cout << "Using this DB file:" << path << std::endl; + + // check if DB file exists. If not, return. + // FIXME: TODO: this check should go in the 'GMDBManager' constructor. + std::ifstream infile(path.c_str()); + if (!infile.good()) { + std::cout << "\n\tERROR!! The '" << path + << "' file does not exists already!! Please, check.\n"; + exit(EXIT_FAILURE); + } + infile.close(); + + // open the DB + GMDBManager* db = new GMDBManager(path); + /* Open database */ + if (db->checkIsDBOpen()) { + std::cout << "OK! Database is open!\n"; + } else { + std::cout << "Database is not open!\n"; + // return; + throw; + } + + /* setup the GeoModel reader */ + GeoModelIO::ReadGeoModel readInGeo = GeoModelIO::ReadGeoModel(db); + std::cout << "OK! ReadGeoModel is set." << std::endl; + + /* build the GeoModel tree */ + GeoPhysVol* world = + readInGeo.buildGeoModel(); // builds the whole GeoModel tree in memory + std::cout << "ReadGeoModel::buildGeoModel() done." << std::endl; + + // --- testing the imported Geometry + + // get number of children volumes + unsigned int nChil = world->getNChildVols(); + std::cout << "world's number of children: " << nChil << std::endl; + + // loop over all children nodes + std::cout << "Looping over all 'volume' children (i.e., GeoPhysVol and " + "GeoFullPhysVol)..." + << std::endl; + for (unsigned int idx = 0; idx < nChil; ++idx) { + PVConstLink nodeLink = world->getChildVol(idx); + + if (dynamic_cast<const GeoVPhysVol*>(&(*(nodeLink)))) { + std::cout << "\t" + << "the child n. " << idx << " "; + const GeoVPhysVol* childVolV = &(*(nodeLink)); + + if (dynamic_cast<const GeoPhysVol*>(childVolV)) { + const GeoPhysVol* childVol = + dynamic_cast<const GeoPhysVol*>(childVolV); + std::cout << "is a GeoPhysVol, whose GeoLogVol's name is: " + << childVol->getLogVol()->getName(); + std::cout << " and it has " << childVol->getNChildVols() + << " child volumes" << std::endl; + } else if (dynamic_cast<const GeoFullPhysVol*>(childVolV)) { + const GeoFullPhysVol* childVol = + dynamic_cast<const GeoFullPhysVol*>(childVolV); + std::cout << "is a GeoFullPhysVol, whose GeoLogVol's name is: " + << childVol->getLogVol()->getName(); + std::cout << " and it has " << childVol->getNChildVols() + << " child volumes" << std::endl; + std::cout << "\txf:"; + GeoUtilFunctions::printTrf(childVol->getAbsoluteTransform()); + } + } + } + + std::cout << "We now read back from the DB the lists of published " + "FullPhysVol and AlignableTransform nodes...\n"; + + // Note: In the Step1 of this example, + // we have published FullPhysVols and AlignableTransforms + // into the DB as: + // - <integer-based key, GeoFullPhysVol*> + // - <string-based key, GeoAlignableTransform*> + // Thus, we now get them back from the DB with the same key types we + // originally used: + std::map<unsigned int, GeoFullPhysVol*> mapFPV = + readInGeo.getPublishedNodes<unsigned int, GeoFullPhysVol*>( + "HelloToyXML"); + std::map<std::string, GeoAlignableTransform*> mapAXF = + readInGeo.getPublishedNodes<std::string, GeoAlignableTransform*>( + "HelloToyXML"); + + unsigned int ii = 0; + std::cout << "\n\nPublished AlignableTransforms from the DB...\n"; + std::cout << "['xf' is the output of 'getTransform()']\n"; + for (auto const& [key, xf] : mapAXF) { + if (0 == ii) + std::cout << "[key type (compiler's code): '" << typeid(key).name() + << "']\n"; + std::cout << "\n\t--> key: " << key << " - AlignableTransform*: " << xf + << std::endl; + std::cout << "\txf:: "; + GeoUtilFunctions::printTrf(xf->getTransform()); + ++ii; + } + + ii = 0; // reset the counter + std::cout << "\n\nPublished FullPhysVols from the DB...\n"; + std::cout << "['xf' is the output of 'getAbsoluteTransform()']\n"; + for (auto const& [key, vol] : mapFPV) { + GeoTrf::Transform3D xf = vol->getAbsoluteTransform(); + + if (0 == ii) + std::cout << "[key type (compiler's code): '" << typeid(key).name() + << "']\n"; + std::cout << "\n\t--> key: " << key << " - GeoFullPhysVol*: " << vol + << std::endl; + std::cout << "\txf:"; + GeoUtilFunctions::printTrf(vol->getAbsoluteTransform()); + ++ii; + } + + std::cout << "\n\nWe now list all available tables.\n\n"; + readInGeo.printAllDBTables(); + readInGeo.printDBTable("dbversion"); + + std::cout + << "\n\nWe now print the content of the tables containing auxiliary " + "data, which have been stored in the data file as additional custom " + "tables\n\n"; + readInGeo.printDBTable("HELLOBOXES"); + readInGeo.printDBTable("HELLOCABLES"); + readInGeo.printDBTable("HelloTest"); + + std::cout + << "\n\nWe now read back the tables containing auxiliary data, which " + "have been stored in the data file as additional custom tables\n\n"; + std::vector<std::vector<std::string>> hellotable = + readInGeo.getTableFromTableName("HelloTest"); + for (auto& row : hellotable) { + for (auto& rec : row) { + std::cout << " record: " << rec; + } + std::cout << std::endl; + } + std::cout << "Everything done." << std::endl; + + return 0; } diff --git a/GeoModelIO/GeoModelDBManager/GeoModelDBManager/GMDBManager.h b/GeoModelIO/GeoModelDBManager/GeoModelDBManager/GMDBManager.h index da81529ab1d599e7df16000d051e2f23185e583c..ce4ff886127aadd7584a48887b4419c3a72512ef 100644 --- a/GeoModelIO/GeoModelDBManager/GeoModelDBManager/GMDBManager.h +++ b/GeoModelIO/GeoModelDBManager/GeoModelDBManager/GMDBManager.h @@ -3,25 +3,25 @@ */ /* -* author: 2017, Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch> -* major updates: -* - Aug 2020, R.M.Bianchi, -* Added support to publish lists of FullPhysVol and AlignableTransform nodes -* - Jun 2022 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>, -* Added support for "Verbose" output -*/ + * author: 2017, Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch> + * major updates: + * - Aug 2020, R.M.Bianchi, + * Added support to publish lists of FullPhysVol and + * AlignableTransform nodes + * - Jun 2022 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>, + * Added support for "Verbose" output + */ #ifndef GMDBManager_H #define GMDBManager_H // include C++ #include <iostream> -#include <unordered_map> -#include <vector> #include <string> +#include <typeindex> // std::type_index, needs C++11 +#include <unordered_map> #include <variant> -#include <typeindex> // std::type_index, needs C++11 - +#include <vector> /** * \class GMDBManager @@ -32,280 +32,330 @@ * and performs some basics queries. */ -class GMDBManager -{ -public: - /** - * @brief Constructor - * - * Constructor sets up connection with db and opens it - * @param path - absolute path to db file - */ - GMDBManager(const std::string &path); -// GMDBManagerStd(const std::string &path); - - /** - * @brief Destructor - * - * Close the db connection - */ - ~GMDBManager(); - void DestructorGMDBManagerStd(); - - bool initDB(); - - int loadGeoNodeTypesAndBuildCache(); - - - /** - * @brief Returns true if the DB is correctly open - */ -// bool isOpen() const; - bool checkIsDBOpen() const; - - /** - * @brief Print names of all GeoPhysVol objects in db - */ - void printAllPhysVols() const; - - /** - * @brief Print names of all GeoFullPhysVol objects in db - */ - void printAllFullPhysVols() const; - - /** - * @brief Print names of all GeoLogVol objects in db - */ - void printAllLogVols() const; - - /** - * @brief Print names of all GeoMaterial objects in db - */ - void printAllMaterials() const; - - /** - * @brief Print names of all GeoElement objects in db - */ - void printAllElements() const; - - /** - * @brief Print names of all GeoShape objects in db - */ - void printAllShapes() const; - - /** - * @brief Print names of all GeoSerialDenominator objects in db - */ - void printAllSerialDenominators() const; - - /** - * @brief Print names of all GeoSeriaIdentifier objects in db - */ - void printAllSerialIdentifiers() const; - - /** - * @brief Print names of all GeoIdentifierTag objects in db - */ - void printAllIdentifierTags() const; - - /** - * @brief Print names of all GeoSerialDenominators objects in db - */ - void printAllSerialTransformers() const; - - /** - * @brief Print names of all Function objects in db - */ - void printAllFunctions() const; - - /** - * @brief Print names of all GeoTransform objects in db - */ - void printAllTransforms() const; - - /** - * @brief Print names of all GeoAlignableTransform objects in db - */ - void printAllAlignableTransforms() const; - - /** - * @brief Print names of all GeoNameTag objects in db - */ - void printAllNameTags() const; - - /** - * @brief Print the db table storing all the children positions per parent - */ - void printAllChildrenPositions() const; - - /** - * @brief Print the db table storing all the 'published' GeoVFullPhysVol nodes. - * @details By default, the method prints out the table 'PublishedGeoFullPhysVols'. - * @param suffix If 'suffix' is provided, then the table 'PublishedGeoFullPhysVols-suffix' will be printed. - * @param suffix Optional parameter. If 'suffix' is provided, then the table 'PublishedGeoFullPhysVols-suffix' will be printed. Of course, developers must be first checked the related DB table has been created (e.g., through the tools offered by GeoModelKernel::GeoVStore and its implementation). - * @note The 'suffix' parameter is optional. If not provided, the default table will be printed. - */ - void printAllPublishedFullPhysVols(const std::string suffix = "") const; - - /** - * @brief Print the db table storing all the 'published' GeoAlignableTransform nodes - * @details By default, the method prints out the table 'GeoAlignableTransforms'. - * @param suffix Optional parameter. If 'suffix' is provided, then the table 'GeoAlignableTransforms-suffix' will be printed. Of course, developers must be first checked the related DB table has been created (e.g., through the tools offered by GeoModelKernel::GeoVStore and its implementation). - * @note The 'suffix' parameter is optional. If not provided, the default table will be printed. - */ - void printAllPublishedAlignableTransforms(const std::string suffix = "") const; - +class GMDBManager { + public: /** - * @brief Print the db table storing all the children positions per parent - */ - void printAllNodeTypes() const; + * @brief Constructor + * + * Constructor sets up connection with db and opens it + * @param path - absolute path to db file + */ + GMDBManager(const std::string &path); + // GMDBManagerStd(const std::string &path); - /** - * @brief Print the DB table storing the ID of the PhysVol that is the Root volume - */ - void printRootVolumeId() const; + /** + * @brief Destructor + * + * Close the db connection + */ + ~GMDBManager(); + void DestructorGMDBManagerStd(); - /** - * @brief Print the current version number of the DB schema - */ - void printDBVersion() const; + bool initDB(); - void printAllRecords(const std::string &tableName) const; + int loadGeoNodeTypesAndBuildCache(); - void printAllDBTables(); + /** + * @brief Returns true if the DB is correctly open + */ + // bool isOpen() const; + bool checkIsDBOpen() const; - void createTableDataCaches(); - void getAllDBTables(); - void getAllDBTableColumns(); + /** + * @brief Print names of all GeoPhysVol objects in db + */ + void printAllPhysVols() const; - int execQuery(std::string queryStr); + /** + * @brief Print names of all GeoFullPhysVol objects in db + */ + void printAllFullPhysVols() const; + /** + * @brief Print names of all GeoLogVol objects in db + */ + void printAllLogVols() const; - bool addListOfRecords(const std::string geoType, const std::vector<std::vector<std::string>> records); + /** + * @brief Print names of all GeoMaterial objects in db + */ + void printAllMaterials() const; + /** + * @brief Print names of all GeoElement objects in db + */ + void printAllElements() const; - bool addListOfChildrenPositions(const std::vector<std::vector<std::string>> &records); - - /** - * @brief Save the list of 'published' GeoAlignableTransform nodes to the DB. - * @details The method gets a list of records and stores them in the default table 'PublishedAlignableTransforms". - * @parameter suffix Optional parameter. If provided, the list of records will be saved in a new table named 'PublishedAlignableTransforms-suffix'. - * @note The 'suffix' parameter is optional. If not provided, the records will be saved in the default table. - */ - bool addListOfPublishedAlignableTransforms(const std::vector<std::vector<std::string>> &records, std::string suffix = ""); - - /** - * @brief Save the list of 'published' GeoVFullPhysVol nodes to the DB. - * @details The method gets a list of records and stores them in the default table 'PublishedFullPhysVols". - * @parameter suffix Optional parameter. If provided, the list of records will be saved in a new table named 'PublishedFullPhysVols-suffix'. - * @note The 'suffix' parameter is optional. If not provided, the records will be saved in the default table. - */ - bool addListOfPublishedFullPhysVols(const std::vector<std::vector<std::string>> &records, std::string suffix = ""); + /** + * @brief Print names of all GeoShape objects in db + */ + void printAllShapes() const; - bool addRootVolume(const std::vector<std::string> &values); + /** + * @brief Print names of all GeoSerialDenominator objects in db + */ + void printAllSerialDenominators() const; - // GET methods + /** + * @brief Print names of all GeoSeriaIdentifier objects in db + */ + void printAllSerialIdentifiers() const; - std::string getDBFilePath(); + /** + * @brief Print names of all GeoIdentifierTag objects in db + */ + void printAllIdentifierTags() const; - std::vector<std::string> getRootPhysVol(); + /** + * @brief Print names of all GeoSerialDenominators objects in db + */ + void printAllSerialTransformers() const; + /** + * @brief Print names of all Function objects in db + */ + void printAllFunctions() const; - std::vector<std::string> getItemFromTableName(std::string tableName, unsigned int id); + /** + * @brief Print names of all GeoTransform objects in db + */ + void printAllTransforms() const; - std::vector<std::string> getItemAndType(unsigned int tableId, unsigned int id); + /** + * @brief Print names of all GeoAlignableTransform objects in db + */ + void printAllAlignableTransforms() const; - std::string getNodeTypeFromTableId(unsigned int id); + /** + * @brief Print names of all GeoNameTag objects in db + */ + void printAllNameTags() const; + /** + * @brief Print the db table storing all the children positions per parent + */ + void printAllChildrenPositions() const; - /// methods to dump the DB - std::vector<std::vector<std::string>> getChildrenTable(); - - std::vector<std::vector<std::string>> getPublishedFPVTable( std::string suffix = "" ); - std::vector<std::vector<std::string>> getPublishedAXFTable( std::string suffix = "" ); + /** + * @brief Print the db table storing all the 'published' GeoVFullPhysVol + * nodes. + * @details By default, the method prints out the table + * 'PublishedGeoFullPhysVols'. + * @param suffix If 'suffix' is provided, then the table + * 'PublishedGeoFullPhysVols-suffix' will be printed. + * @param suffix Optional parameter. If 'suffix' is provided, then the table + * 'PublishedGeoFullPhysVols-suffix' will be printed. Of course, developers + * must be first checked the related DB table has been created (e.g., + * through the tools offered by GeoModelKernel::GeoVStore and its + * implementation). + * @note The 'suffix' parameter is optional. If not provided, the default + * table will be printed. + */ + void printAllPublishedFullPhysVols(const std::string suffix = "") const; - std::vector<std::vector<std::string>> getTableFromNodeType(std::string nodeType); + /** + * @brief Print the db table storing all the 'published' + * GeoAlignableTransform nodes + * @details By default, the method prints out the table + * 'GeoAlignableTransforms'. + * @param suffix Optional parameter. If 'suffix' is provided, then the table + * 'GeoAlignableTransforms-suffix' will be printed. Of course, developers + * must be first checked the related DB table has been created (e.g., + * through the tools offered by GeoModelKernel::GeoVStore and its + * implementation). + * @note The 'suffix' parameter is optional. If not provided, the default + * table will be printed. + */ + void printAllPublishedAlignableTransforms( + const std::string suffix = "") const; + + /** + * @brief Print the db table storing all the children positions per parent + */ + void printAllNodeTypes() const; - std::unordered_map<unsigned int, std::string> getAll_TableIDsNodeTypes(); - std::unordered_map<std::string, unsigned int> getAll_NodeTypesTableIDs(); + /** + * @brief Print the DB table storing the ID of the PhysVol that is the Root + * volume + */ + void printRootVolumeId() const; + + /** + * @brief Print the current version number of the DB schema + */ + void printDBVersion() const; - std::vector<std::vector<std::string>> getTableRecords(std::string tableName) const; // TODO: should be private? + void printAllRecords(const std::string &tableName) const; - /** - * @brief Create a custom DB table to store auxiliary data. - * @param tableName The name of the custom table - * @param tableColNames A vector of strings defining the names of the table's columns - * @param tableColTypes A vector of strings defining the types of the table's columns - * @param records A vector of std:variant<int,long,float,double,std::string> storing the table's rows' data - */ - bool createCustomTable(const std::string tableName, const std::vector<std::string> tableColNames, const std::vector<std::string> tableColTypes, const std::vector<std::vector<std::variant<int,long,float,double,std::string>>> &records ); - //bool createCustomTable(const std::string tableName, const std::vector<std::string> tableColNames, const std::vector<std::string> tableColTypes, const std::vector<std::vector<std::string>> &records ); // not used anymore!! + void printAllDBTables(); + void createTableDataCaches(); + void getAllDBTables(); + void getAllDBTableColumns(); + int execQuery(std::string queryStr); -private: + bool addListOfRecords(const std::string geoType, + const std::vector<std::vector<std::string>> records); - /** - * @brief Create all the default DB tables. - */ - bool createTables(); + bool addListOfChildrenPositions( + const std::vector<std::vector<std::string>> &records); - /** - * @brief Create a custom DB table to store a list of published nodes. - * @param tableName The table's name. - * @param keyType The type of the 'key' that identifies the linked node. - */ - bool createTableCustomPublishedNodes(const std::string tableName, const std::string nodeType, const std::type_info* keyType); - - bool addListOfRecordsToTable(const std::string tableName, const std::vector<std::vector<std::string>> records); - bool addListOfRecordsToTable(const std::string tableName, const std::vector<std::vector<std::variant<int,long,float,double,std::string>>> records); -// bool addListOfRecordsToTableOld(const QString tableName, const std::vector<QStringList> records); // for the old SQlite only + /** + * @brief Save the list of 'published' GeoAlignableTransform nodes to the + * DB. + * @details The method gets a list of records and stores them in the default + * table 'PublishedAlignableTransforms". + * @parameter suffix Optional parameter. If provided, the list of records + * will be saved in a new table named 'PublishedAlignableTransforms-suffix'. + * @note The 'suffix' parameter is optional. If not provided, the records + * will be saved in the default table. + */ + bool addListOfPublishedAlignableTransforms( + const std::vector<std::vector<std::string>> &records, + std::string suffix = ""); - void addDBversion(std::string version); + /** + * @brief Save the list of 'published' GeoVFullPhysVol nodes to the DB. + * @details The method gets a list of records and stores them in the default + * table 'PublishedFullPhysVols". + * @parameter suffix Optional parameter. If provided, the list of records + * will be saved in a new table named 'PublishedFullPhysVols-suffix'. + * @note The 'suffix' parameter is optional. If not provided, the records + * will be saved in the default table. + */ + bool addListOfPublishedFullPhysVols( + const std::vector<std::vector<std::string>> &records, + std::string suffix = ""); + bool addRootVolume(const std::vector<std::string> &values); + // GET methods -// void loadTestData(); // for debug only + std::string getDBFilePath(); - std::string getTableNameFromTableId(unsigned int tabId); + std::vector<std::string> getRootPhysVol(); - unsigned int getTableIdFromNodeType(const std::string &nodeType); - void storeNodeType(std::string nodeType, std::string tableName); + std::vector<std::string> getItemFromTableName(std::string tableName, + unsigned int id); - std::string getTableNameFromNodeType(const std::string &nodeType); + std::vector<std::string> getItemAndType(unsigned int tableId, + unsigned int id); - void storeTableColumnNames(std::vector<std::string> input); + std::string getNodeTypeFromTableId(unsigned int id); - std::vector<std::string> getTableColumnNames(const std::string &tableName); + /// methods to dump the DB + std::vector<std::vector<std::string>> getChildrenTable(); + std::vector<std::vector<std::string>> getPublishedFPVTable( + std::string suffix = ""); + std::vector<std::vector<std::string>> getPublishedAXFTable( + std::string suffix = ""); - int getTableColIndex(const std::string &tableName, const std::string &colName); + std::vector<std::vector<std::string>> getTableFromNodeType( + std::string nodeType); - bool storeRootVolume(const unsigned int &id, const std::string &nodeType); + std::unordered_map<unsigned int, std::string> getAll_TableIDsNodeTypes(); + std::unordered_map<std::string, unsigned int> getAll_NodeTypesTableIDs(); - std::string m_dbpath; + std::vector<std::vector<std::string>> getTableRecords( + std::string tableName) const; // TODO: should be private? - bool m_dbIsOK; + /** + * @brief Create a custom DB table to store auxiliary data. + * @param tableName The name of the custom table + * @param tableColNames A vector of strings defining the names of the + * table's columns + * @param tableColTypes A vector of strings defining the types of the + * table's columns + * @param records A vector of std:variant<int,long,float,double,std::string> + * storing the table's rows' data + */ + bool createCustomTable( + const std::string tableName, + const std::vector<std::string> tableColNames, + const std::vector<std::string> tableColTypes, + const std::vector< + std::vector<std::variant<int, long, float, double, std::string>>> + &records); + // bool createCustomTable(const std::string tableName, const + // std::vector<std::string> tableColNames, const std::vector<std::string> + // tableColTypes, const std::vector<std::vector<std::string>> &records ); // + // not used anymore!! + + private: + /** + * @brief Create all the default DB tables. + */ + bool createTables(); - bool m_debug; + /** + * @brief Create a custom DB table to store a list of published nodes. + * @param tableName The table's name. + * @param keyType The type of the 'key' that identifies the linked node. + */ + bool createTableCustomPublishedNodes(const std::string tableName, + const std::string nodeType, + const std::type_info *keyType); - // verbosity level - int m_verbose; + bool addListOfRecordsToTable( + const std::string tableName, + const std::vector<std::vector<std::string>> records); + bool addListOfRecordsToTable( + const std::string tableName, + const std::vector< + std::vector<std::variant<int, long, float, double, std::string>>> + records); + // bool addListOfRecordsToTableOld(const QString tableName, const + // std::vector<QStringList> records); // for the old SQlite only - std::unordered_map<std::string, std::vector<std::string>> m_tableNames; /// stores the column names for each table - std::unordered_map<std::string, std::string> m_childType_tableName; + void addDBversion(std::string version); - std::vector<std::string> m_cache_tables; /// cache for the list of tables in the DB - std::unordered_map<unsigned int, std::string> m_cache_tableId_tableName; /// cache for tableID-->tableName - std::unordered_map<unsigned int, std::string> m_cache_tableId_nodeType; /// cache for tableID-->nodeType - std::unordered_map<std::string, std::string> m_cache_nodeType_tableName; /// cache for nodeType-->tableName - std::unordered_map<std::string, unsigned int> m_cache_nodeType_tableID; /// cache for nodeType-->tableID + // void loadTestData(); // for debug only -protected: - class Imp; - Imp * m_d; + std::string getTableNameFromTableId(unsigned int tabId); -}; + unsigned int getTableIdFromNodeType(const std::string &nodeType); + void storeNodeType(std::string nodeType, std::string tableName); + std::string getTableNameFromNodeType(const std::string &nodeType); + + void storeTableColumnNames(std::vector<std::string> input); + + std::vector<std::string> getTableColumnNames(const std::string &tableName); + + int getTableColIndex(const std::string &tableName, + const std::string &colName); + + bool storeRootVolume(const unsigned int &id, const std::string &nodeType); + + std::string m_dbpath; + + bool m_dbIsOK; + + bool m_debug; + + // verbosity level + int m_verbose; + + std::unordered_map<std::string, std::vector<std::string>> + m_tableNames; /// stores the column names for each table + std::unordered_map<std::string, std::string> m_childType_tableName; + + std::vector<std::string> + m_cache_tables; /// cache for the list of tables in the DB + std::unordered_map<unsigned int, std::string> + m_cache_tableId_tableName; /// cache for tableID-->tableName + std::unordered_map<unsigned int, std::string> + m_cache_tableId_nodeType; /// cache for tableID-->nodeType + std::unordered_map<std::string, std::string> + m_cache_nodeType_tableName; /// cache for nodeType-->tableName + std::unordered_map<std::string, unsigned int> + m_cache_nodeType_tableID; /// cache for nodeType-->tableID + + protected: + class Imp; + Imp *m_d; +}; -#endif // GMDBManager_H +#endif // GMDBManager_H diff --git a/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp b/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp index b6da484e1c4fa1b1eea59fc64eec6b1fdea5fadd..4940ac06c912aacbc56f409ce7edfe8c54ae526a 100644 --- a/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp +++ b/GeoModelIO/GeoModelDBManager/src/GMDBManager.cpp @@ -2,21 +2,21 @@ Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration */ - /* -* author: 2017, Riccardo Maria Bianchi @ CERN - <riccardo.maria.bianchi@cern.ch> -* major updates: -* - Aug 2018, R.M.Bianchi -* - Jun 2020, R.M.Bianchi -* - Aug 2020, R.M.Bianchi - Added support to publish lists of FullPhysVol and AlignableTransform nodes -* - Jun 2022 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>, -* Added support for "Verbose" output -*/ + * author: 2017, Riccardo Maria Bianchi @ CERN - + * <riccardo.maria.bianchi@cern.ch> major updates: + * - Aug 2018, R.M.Bianchi + * - Jun 2020, R.M.Bianchi + * - Aug 2020, R.M.Bianchi - Added support to publish lists of FullPhysVol and + * AlignableTransform nodes + * - Jun 2022 - Riccardo Maria Bianchi, <riccardo.maria.bianchi@cern.ch>, + * Added support for "Verbose" output + */ #include <GeoModelDBManager/GMDBManager.h> // include the 'fmt' library, which is hosted locally as header-only -#define FMT_HEADER_ONLY 1 // to use 'fmt' header-only +#define FMT_HEADER_ONLY 1 // to use 'fmt' header-only #include "fmt/format.h" // include SQLite @@ -24,515 +24,533 @@ // C++ includes #include <stdlib.h> /* exit, EXIT_FAILURE */ -#include <sstream> -#include <mutex> +#include <mutex> +#include <sstream> -static std::string dbversion = "0.6.0"; // Added new tables to store lists of published FullPhysVols and AlignableTransforms - +static std::string dbversion = + "0.6.0"; // Added new tables to store lists of published FullPhysVols and + // AlignableTransforms //// FIXME: move this to utility class/file -//std::vector<std::string> toStdVectorStrings(QStringList qlist) +// std::vector<std::string> toStdVectorStrings(QStringList qlist) //{ -// std::vector<std::string> vec; -// foreach(QString qstr, qlist) { -// vec.push_back(qstr.toStdString()); -// } -// return vec; -//} +// std::vector<std::string> vec; +// foreach(QString qstr, qlist) { +// vec.push_back(qstr.toStdString()); +// } +// return vec; +// } // FIXME: TODO: move to an utility class -std::string getEnvVar( std::string const & key ) -{ - char * val = std::getenv( key.c_str() ); - return val == NULL ? std::string("") : std::string(val); +std::string getEnvVar(std::string const& key) { + char* val = std::getenv(key.c_str()); + return val == NULL ? std::string("") : std::string(val); } // FIXME: should go to an utility class -std::string joinVectorStrings(std::vector<std::string> vec, std::string sep="") { - std::string s; - unsigned int ii = 0; - for (const auto &piece : vec) { - ++ii; - if (ii == vec.size()) { - s += (piece); - } else { - s += (piece + sep); +std::string joinVectorStrings(std::vector<std::string> vec, + std::string sep = "") { + std::string s; + unsigned int ii = 0; + for (const auto& piece : vec) { + ++ii; + if (ii == vec.size()) { + s += (piece); + } else { + s += (piece + sep); + } } - } - return s; + return s; } - - class GMDBManager::Imp { -public: + public: // constructor - Imp (GMDBManager* dbm) - : theManager(dbm), m_dbSqlite(nullptr), m_SQLiteErrMsg(0) {} - - // The class - GMDBManager* theManager; + Imp(GMDBManager* dbm) + : theManager(dbm), m_dbSqlite(nullptr), m_SQLiteErrMsg(0) {} - // Pointer to SQLite connection - sqlite3* m_dbSqlite; + // The class + GMDBManager* theManager; - /// Variable to store error messages from SQLite - char *m_SQLiteErrMsg; + // Pointer to SQLite connection + sqlite3* m_dbSqlite; - sqlite3_stmt* selectAllFromTable(std::string tableName) const; - sqlite3_stmt* selectAllFromTableSortBy(std::string tableName, std::string sortColumn="") const; - sqlite3_stmt* selectAllFromTableChildrenPositions() const; + /// Variable to store error messages from SQLite + char* m_SQLiteErrMsg; + sqlite3_stmt* selectAllFromTable(std::string tableName) const; + sqlite3_stmt* selectAllFromTableSortBy(std::string tableName, + std::string sortColumn = "") const; + sqlite3_stmt* selectAllFromTableChildrenPositions() const; }; -GMDBManager::GMDBManager(const std::string &path) : m_dbpath(path), m_dbIsOK(false), m_debug(false), m_d(new Imp(this)) -{ - // Check if the user asked for running in serial or multi-threading mode - if ( "" != getEnvVar("GEOMODEL_ENV_IO_DBMANAGER_DEBUG")) { - m_debug = true; - std::cout << "You defined the GEOMODEL_IO_DEBUG variable, so you will see a verbose output." << std::endl; - } +GMDBManager::GMDBManager(const std::string& path) + : m_dbpath(path), m_dbIsOK(false), m_debug(false), m_d(new Imp(this)) { + // Check if the user asked for running in serial or multi-threading mode + if ("" != getEnvVar("GEOMODEL_ENV_IO_DBMANAGER_DEBUG")) { + m_debug = true; + std::cout << "You defined the GEOMODEL_IO_DEBUG variable, so you will " + "see a verbose output." + << std::endl; + } - m_dbIsOK = false; + m_dbIsOK = false; - // FIXME: TODO: we should check the existence of the file, otherwise SQLite will create a new file from scratch - // Save the connection result - int exit = sqlite3_open(path.c_str(), &m_d->m_dbSqlite); + // FIXME: TODO: we should check the existence of the file, otherwise SQLite + // will create a new file from scratch Save the connection result + int exit = sqlite3_open(path.c_str(), &m_d->m_dbSqlite); - // Test if there was an error - if (exit == SQLITE_OK) { - std::cout << "The Geometry Database '"<< path << "' has been opened successfully!" << std::endl; - m_dbIsOK = true; - } else { - std::cout << "DB Open Error: " << sqlite3_errmsg(m_d->m_dbSqlite) << std::endl; - m_dbIsOK = false; - } + // Test if there was an error + if (exit == SQLITE_OK) { + std::cout << "The Geometry Database '" << path + << "' has been opened successfully!" << std::endl; + m_dbIsOK = true; + } else { + std::cout << "DB Open Error: " << sqlite3_errmsg(m_d->m_dbSqlite) + << std::endl; + m_dbIsOK = false; + } - // set verbosity level - m_verbose=0; - if(const char* env_p = std::getenv("GEOMODEL_GEOMODELIO_VERBOSE")) { - std::cout << "GeoModelDBManager -- You set the verbosity level to: " << env_p << '\n'; + // set verbosity level + m_verbose = 0; + if (const char* env_p = std::getenv("GEOMODEL_GEOMODELIO_VERBOSE")) { + std::cout << "GeoModelDBManager -- You set the verbosity level to: " + << env_p << '\n'; m_verbose = std::stoi(env_p); } -// if (m_dbIsOK) { -// if ( ! (initDB()) ) { -// std::cout << "Error: database initialization failed" << std::endl; -// m_dbIsOK = false; -// } -// } + // if (m_dbIsOK) { + // if ( ! (initDB()) ) { + // std::cout << "Error: database initialization failed" << std::endl; + // m_dbIsOK = false; + // } + // } - // populate DB with fake data, only for debug - //loadTestData(); // TODO: we should move initDB() here, only for debug and Write + // populate DB with fake data, only for debug + // loadTestData(); // TODO: we should move initDB() here, only for debug and + // Write } - -GMDBManager::~GMDBManager() -{ - sqlite3_close(m_d->m_dbSqlite); - m_d->m_dbSqlite = nullptr; - delete m_d; - m_d = nullptr; +GMDBManager::~GMDBManager() { + sqlite3_close(m_d->m_dbSqlite); + m_d->m_dbSqlite = nullptr; + delete m_d; + m_d = nullptr; } +void GMDBManager::printAllMaterials() const { printAllRecords("Materials"); } +void GMDBManager::printAllElements() const { printAllRecords("Elements"); } -void GMDBManager::printAllMaterials() const -{ - printAllRecords("Materials"); -} -void GMDBManager::printAllElements() const -{ - printAllRecords("Elements"); -} +void GMDBManager::printAllShapes() const { printAllRecords("Shapes"); } -void GMDBManager::printAllShapes() const -{ - printAllRecords("Shapes"); +void GMDBManager::printAllSerialDenominators() const { + printAllRecords("SerialDenominators"); } -void GMDBManager::printAllSerialDenominators() const -{ - printAllRecords("SerialDenominators"); +void GMDBManager::printAllSerialIdentifiers() const { + printAllRecords("SerialIdentifiers"); } -void GMDBManager::printAllSerialIdentifiers() const -{ - printAllRecords("SerialIdentifiers"); +void GMDBManager::printAllIdentifierTags() const { + printAllRecords("IdentifierTags"); } -void GMDBManager::printAllIdentifierTags() const -{ - printAllRecords("IdentifierTags"); -} - -void GMDBManager::printAllLogVols() const -{ - printAllRecords("LogVols"); -} -void GMDBManager::printAllPhysVols() const -{ - printAllRecords("PhysVols"); -} -void GMDBManager::printAllFullPhysVols() const -{ - printAllRecords("FullPhysVols"); -} -void GMDBManager::printAllSerialTransformers() const -{ - printAllRecords("SerialTransformers"); -} -void GMDBManager::printAllFunctions() const -{ - printAllRecords("Functions"); +void GMDBManager::printAllLogVols() const { printAllRecords("LogVols"); } +void GMDBManager::printAllPhysVols() const { printAllRecords("PhysVols"); } +void GMDBManager::printAllFullPhysVols() const { + printAllRecords("FullPhysVols"); } -void GMDBManager::printAllTransforms() const -{ - printAllRecords("Transforms"); +void GMDBManager::printAllSerialTransformers() const { + printAllRecords("SerialTransformers"); } -void GMDBManager::printAllAlignableTransforms() const -{ - printAllRecords("AlignableTransforms"); +void GMDBManager::printAllFunctions() const { printAllRecords("Functions"); } +void GMDBManager::printAllTransforms() const { printAllRecords("Transforms"); } +void GMDBManager::printAllAlignableTransforms() const { + printAllRecords("AlignableTransforms"); } -void GMDBManager::printAllNameTags() const -{ - printAllRecords("NameTags"); -} -void GMDBManager::printAllPublishedFullPhysVols(const std::string suffix) const -{ - if( "" == suffix ) printAllRecords("PublishedFullPhysVols"); +void GMDBManager::printAllNameTags() const { printAllRecords("NameTags"); } +void GMDBManager::printAllPublishedFullPhysVols( + const std::string suffix) const { + if ("" == suffix) + printAllRecords("PublishedFullPhysVols"); else { std::string tableName = "PublishedFullPhysVols"; - tableName += "_"; // separator - printAllRecords( tableName+suffix ); + tableName += "_"; // separator + printAllRecords(tableName + suffix); } } -void GMDBManager::printAllPublishedAlignableTransforms(const std::string suffix) const -{ - if( "" == suffix ) printAllRecords("PublishedAlignableTransforms"); +void GMDBManager::printAllPublishedAlignableTransforms( + const std::string suffix) const { + if ("" == suffix) + printAllRecords("PublishedAlignableTransforms"); else { std::string tableName = "PublishedAlignableTransforms"; - tableName += "_"; // separator - printAllRecords( tableName+suffix ); + tableName += "_"; // separator + printAllRecords(tableName + suffix); } } -void GMDBManager::printAllChildrenPositions() const -{ - printAllRecords("ChildrenPositions"); -} -void GMDBManager::printAllNodeTypes() const -{ - printAllRecords("GeoNodesTypes"); +void GMDBManager::printAllChildrenPositions() const { + printAllRecords("ChildrenPositions"); } -void GMDBManager::printRootVolumeId() const -{ - printAllRecords("RootVolume"); +void GMDBManager::printAllNodeTypes() const { + printAllRecords("GeoNodesTypes"); } -void GMDBManager::printDBVersion() const -{ - printAllRecords("dbversion"); -} - +void GMDBManager::printRootVolumeId() const { printAllRecords("RootVolume"); } +void GMDBManager::printDBVersion() const { printAllRecords("dbversion"); } -void GMDBManager::createTableDataCaches() -{ +void GMDBManager::createTableDataCaches() { getAllDBTables(); getAllDBTableColumns(); } -void GMDBManager::printAllRecords(const std::string &tableName) const -{ - // --- print table name - std::cout << "\n---" << std::endl; - std::cout << "'" << tableName << "' in db:" << std::endl; - // --- check if we stored table's data - if( m_tableNames.find(tableName) == m_tableNames.end() ) { - std::cout << "\n*** ERROR!! No table '" << tableName << "' found! ***\n\n"; - return; - } - // --- print table column names - std::cout << "- " << joinVectorStrings(m_tableNames.at(tableName), ", ") << std::endl; - // --- print records - std::vector<std::vector<std::string>> records; -// std::vector<std::string> nodeParams; - records = getTableRecords(tableName); - if (records.size()) { - for( auto& row : records) { - std::cout << "* "; - for( auto& item : row) { - std::cout << item << ", "; - } - std::cout << std::endl; - } - } - std::cout << "---" << std::endl; - // TODO: I want to have a symbol like '---' to mean empty line when query gives 0 results. -} - - -// FIXME: TODO: we now return all records as text, but should we get double/int instead when appropriate? In that case, we should create dedicated methods for all tables, I guess. -// TODO: fill a cache and returns that if asked a second time -std::vector<std::vector<std::string>> GMDBManager::getTableRecords(std::string tableName) const -{ - // container to be returned - std::vector<std::vector<std::string>> records; - // get the query statetement ready to be executed - sqlite3_stmt* stmt = nullptr; - if ("ChildrenPositions" == tableName) { - stmt = m_d->selectAllFromTableChildrenPositions(); - } - else { - stmt = m_d->selectAllFromTable(tableName); - } - // execute the query and loop over all rows and all columuns - if ( stmt ) - { - int ctotal = sqlite3_column_count(stmt); // Count the Number of Columns in the Table - int res = 0; - while ( 1 ) - { - res = sqlite3_step(stmt); // Execute SQL Statement. - if ( res == SQLITE_ROW ) - { - std::vector<std::string> nodeParams; // stores the data items contained in a single row - for ( int i = 0; i < ctotal; i++ ) // Loop times the number of columns in the table - { - std::string s; - const char* cc = (char*)sqlite3_column_text(stmt, i); // Read each Column in the row as text FIXME: is there a method to get the right type, e.g. double, instead of text? - if (cc==NULL) s = "NULL"; - else s = cc; - nodeParams.push_back( s ); - } - records.push_back(nodeParams); - } - - if ( res == SQLITE_DONE || res==SQLITE_ERROR) - { - if (res == SQLITE_ERROR) { - std::string errmsg(sqlite3_errmsg(m_d->m_dbSqlite)); - sqlite3_finalize(stmt); - throw errmsg; +void GMDBManager::printAllRecords(const std::string& tableName) const { + // --- print table name + std::cout << "\n---" << std::endl; + std::cout << "'" << tableName << "' in db:" << std::endl; + // --- check if we stored table's data + if (m_tableNames.find(tableName) == m_tableNames.end()) { + std::cout << "\n*** ERROR!! No table '" << tableName + << "' found! ***\n\n"; + return; + } + // --- print table column names + std::cout << "- " << joinVectorStrings(m_tableNames.at(tableName), ", ") + << std::endl; + // --- print records + std::vector<std::vector<std::string>> records; + // std::vector<std::string> nodeParams; + records = getTableRecords(tableName); + if (records.size()) { + for (auto& row : records) { + std::cout << "* "; + for (auto& item : row) { + std::cout << item << ", "; + } + std::cout << std::endl; } - break; - } } - } - // finalize - sqlite3_finalize(stmt); - return records; + std::cout << "---" << std::endl; + // TODO: I want to have a symbol like '---' to mean empty line when query + // gives 0 results. } +// FIXME: TODO: we now return all records as text, but should we get double/int +// instead when appropriate? In that case, we should create dedicated methods +// for all tables, I guess. +// TODO: fill a cache and returns that if asked a second time +std::vector<std::vector<std::string>> GMDBManager::getTableRecords( + std::string tableName) const { + // container to be returned + std::vector<std::vector<std::string>> records; + // get the query statetement ready to be executed + sqlite3_stmt* stmt = nullptr; + if ("ChildrenPositions" == tableName) { + stmt = m_d->selectAllFromTableChildrenPositions(); + } else { + stmt = m_d->selectAllFromTable(tableName); + } + // execute the query and loop over all rows and all columuns + if (stmt) { + int ctotal = sqlite3_column_count( + stmt); // Count the Number of Columns in the Table + int res = 0; + while (1) { + res = sqlite3_step(stmt); // Execute SQL Statement. + if (res == SQLITE_ROW) { + std::vector<std::string> + nodeParams; // stores the data items contained in a single + // row + for (int i = 0; i < ctotal; + i++) // Loop times the number of columns in the table + { + std::string s; + const char* cc = (char*)sqlite3_column_text( + stmt, i); // Read each Column in the row as text FIXME: + // is there a method to get the right type, + // e.g. double, instead of text? + if (cc == NULL) + s = "NULL"; + else + s = cc; + nodeParams.push_back(s); + } + records.push_back(nodeParams); + } -std::vector<std::vector<std::string>> GMDBManager::getTableFromNodeType(std::string nodeType) -{ - std::vector<std::vector<std::string>> out; - std::string tableName = getTableNameFromNodeType(nodeType); - if ( tableName.empty() ) { - std::mutex coutMutex; - coutMutex.lock(); - printf ("\t ===> WARNING! The geometry input file does not contain a table for the %s nodes. That means that you are probably using an old geometry file. Unless you know exactly what you are doing, please expect to see incomplete geometries or crashes.\n", nodeType.c_str() ); - coutMutex.unlock(); - } else { - out = getTableRecords(tableName); - } - return out; + if (res == SQLITE_DONE || res == SQLITE_ERROR) { + if (res == SQLITE_ERROR) { + std::string errmsg(sqlite3_errmsg(m_d->m_dbSqlite)); + sqlite3_finalize(stmt); + throw errmsg; + } + break; + } + } + } + // finalize + sqlite3_finalize(stmt); + return records; +} + +std::vector<std::vector<std::string>> GMDBManager::getTableFromNodeType( + std::string nodeType) { + std::vector<std::vector<std::string>> out; + std::string tableName = getTableNameFromNodeType(nodeType); + if (tableName.empty()) { + std::mutex coutMutex; + coutMutex.lock(); + printf( + "\t ===> WARNING! The geometry input file does not contain a table " + "for the %s nodes. That means that you are probably using an old " + "geometry file. Unless you know exactly what you are doing, please " + "expect to see incomplete geometries or crashes.\n", + nodeType.c_str()); + coutMutex.unlock(); + } else { + out = getTableRecords(tableName); + } + return out; } // TODO: simplify error reporting for SQLite -//void GMDBManager::showError(const QSqlError &err) const +// void GMDBManager::showError(const QSqlError &err) const //{ -// qWarning() << "Unable to initialize Database" << "Error initializing database: " + err.text(); +// qWarning() << "Unable to initialize Database" << "Error initializing +// database: " + err.text(); //} - -bool GMDBManager::addListOfChildrenPositions(const std::vector<std::vector<std::string>> &records) -{ - if(records.size() > 0) { +bool GMDBManager::addListOfChildrenPositions( + const std::vector<std::vector<std::string>>& records) { + if (records.size() > 0) { // NOTE: Choose the right function for your version of SQLite!! - return addListOfRecordsToTable("ChildrenPositions", records); // needs SQLite >= 3.7.11 - //return addListOfRecordsToTableOld("ChildrenPositions", records); // old SQLite versions + return addListOfRecordsToTable("ChildrenPositions", + records); // needs SQLite >= 3.7.11 + // return addListOfRecordsToTableOld("ChildrenPositions", records); // + // old SQLite versions } return false; } -bool GMDBManager::addListOfPublishedAlignableTransforms(const std::vector<std::vector<std::string>> &records, std::string suffix /* optional parameter */) -{ - std::string tableName = "PublishedAlignableTransforms"; // default table name +bool GMDBManager::addListOfPublishedAlignableTransforms( + const std::vector<std::vector<std::string>>& records, + std::string suffix /* optional parameter */) { + std::string tableName = + "PublishedAlignableTransforms"; // default table name std::string nodeType = "GeoAlignableTransform"; - const std::type_info &keyType(typeid(std::string));//TODO: type should be custom too!! - if( "" != suffix ) { + const std::type_info& keyType( + typeid(std::string)); // TODO: type should be custom too!! + if ("" != suffix) { tableName += "_"; tableName += suffix; // debug msg - //std::cout << "\nSaving the published '"<< nodeType << "' nodes to the custom table: '" + // std::cout << "\nSaving the published '"<< nodeType << "' nodes to the + // custom table: '" // << tableName << "'." << std::endl; } // create custom table first then add to it - createTableCustomPublishedNodes( tableName, nodeType, &keyType ); - return addListOfRecordsToTable( tableName, records ); // needs SQLite >= 3.7.11 - //return addListOfRecordsToTableOld( tableName, records ); // old SQLite versions + createTableCustomPublishedNodes(tableName, nodeType, &keyType); + return addListOfRecordsToTable(tableName, + records); // needs SQLite >= 3.7.11 + // return addListOfRecordsToTableOld( tableName, records ); // old SQLite + // versions } -bool GMDBManager::addListOfPublishedFullPhysVols(const std::vector<std::vector<std::string>> &records, std::string suffix /* optional parameter */) -{ - std::string tableName = "PublishedFullPhysVols"; // default table name +bool GMDBManager::addListOfPublishedFullPhysVols( + const std::vector<std::vector<std::string>>& records, + std::string suffix /* optional parameter */) { + std::string tableName = "PublishedFullPhysVols"; // default table name std::string nodeType = "GeoFullPhysVol"; - const std::type_info &keyType(typeid(std::string));//TODO: type should be custom too!! - if( "" != suffix ) { + const std::type_info& keyType( + typeid(std::string)); // TODO: type should be custom too!! + if ("" != suffix) { tableName += "_"; tableName += suffix; - //std::cout << "\nSaving the published '"<< nodeType << "' nodes to the custom table: '" - // << tableName << "'." << std::endl; + // std::cout << "\nSaving the published '"<< nodeType << "' nodes to the + // custom table: '" + // << tableName << "'." << std::endl; } // create custom table first then add to it - createTableCustomPublishedNodes( tableName, nodeType, &keyType ); - return addListOfRecordsToTable( tableName, records ); // needs SQLite >= 3.7.11 - //return addListOfRecordsToTableOld( tableName, records ); // old SQLite versions + createTableCustomPublishedNodes(tableName, nodeType, &keyType); + return addListOfRecordsToTable(tableName, + records); // needs SQLite >= 3.7.11 + // return addListOfRecordsToTableOld( tableName, records ); // old SQLite + // versions } /* -bool GMDBManager::addListOfRecordsToCustomTable(const std::vector<std::vector<std::string>> &records, std::string tableName ) +bool GMDBManager::addListOfRecordsToCustomTable(const +std::vector<std::vector<std::string>> &records, std::string tableName ) { std::string nodeType = "GeoFullPhysVol"; - const std::type_info &keyType(typeid(std::string));//TODO: type should be custom too!! + const std::type_info &keyType(typeid(std::string));//TODO: type should be +custom too!! // create custom table first createTableCustomPublishedNodes( tableName, nodeType, &keyType ); // add records to the newly-created table - return addListOfRecordsToTable( tableName, records ); // needs SQLite >= 3.7.11 - //return addListOfRecordsToTableOld( tableName, records ); // old SQLite versions + return addListOfRecordsToTable( tableName, records ); // needs SQLite +>= 3.7.11 + //return addListOfRecordsToTableOld( tableName, records ); // old SQLite +versions } */ +bool GMDBManager::addListOfRecords( + const std::string geoType, + const std::vector<std::vector<std::string>> records) { + // if (m_debug) qDebug() << "GMDBManager::addListOfRecords():" << geoType; + std::string tableName = m_childType_tableName[geoType]; -bool GMDBManager::addListOfRecords(const std::string geoType, const std::vector<std::vector<std::string>> records) -{ -// if (m_debug) qDebug() << "GMDBManager::addListOfRecords():" << geoType; - - std::string tableName = m_childType_tableName[geoType]; - - if (tableName.size() == 0) { - //qWarning() << "m_childType_tableName:" << m_childType_tableName; - std::cout << "ERROR!! could not retrieve tableName for node type '" << geoType << "'!! Aborting..." << std::endl; - exit(EXIT_FAILURE); - } + if (tableName.size() == 0) { + // qWarning() << "m_childType_tableName:" << m_childType_tableName; + std::cout << "ERROR!! could not retrieve tableName for node type '" + << geoType << "'!! Aborting..." << std::endl; + exit(EXIT_FAILURE); + } - if (records.size() > 0 ) { - // NOTE: Choose the right function!! - return addListOfRecordsToTable(tableName, records); // better, but needs SQLite >= 3.7.11 - //return addListOfRecordsToTableOld(tableName, records); // old SQLite versions - } - else { - if(m_debug) std::cout << "Info: no records to save for geoType '" << geoType << "'. Skipping..." << std::endl; - } - return true; + if (records.size() > 0) { + // NOTE: Choose the right function!! + return addListOfRecordsToTable( + tableName, records); // better, but needs SQLite >= 3.7.11 + // return addListOfRecordsToTableOld(tableName, records); // old SQLite + // versions + } else { + if (m_debug) + std::cout << "Info: no records to save for geoType '" << geoType + << "'. Skipping..." << std::endl; + } + return true; } - // ***Note*** // The syntax built here below is more convenient // but it is supported only in SQLite >= 3.7.11 // (Note: old SLC6-based Athena releases uses SQLite 3.7.9 from LCG) // // Here we build a query like this: -// queryStr = QString("INSERT INTO Materials (id, name) VALUES (1,'Air'), (2,'Silicon'), (368,'ShieldSteel');"); +// queryStr = QString("INSERT INTO Materials (id, name) VALUES (1,'Air'), +// (2,'Silicon'), (368,'ShieldSteel');"); // -bool GMDBManager::addListOfRecordsToTable(const std::string tableName, const std::vector<std::vector<std::string>> records) -{ - // get table columns and format them for query - std::string tableColString = "(" + joinVectorStrings(m_tableNames.at(tableName), ", ") + ")"; - if(m_debug) std::cout << "tableColString:" << tableColString << std::endl; - - unsigned int nRecords = records.size(); - std::cout << "Info: number of " << tableName << " records to dump into the DB: " << nRecords << std::endl; - - // preparing the SQL query - std::string sql = fmt::format("INSERT INTO {0} {1} VALUES ", tableName, tableColString); - unsigned int id = 0; - for( const std::vector<std::string>& rec : records) { - ++id; - std::vector<std::string> items; - for ( const std::string& item : rec) { - items.push_back("'" + item + "'"); // TODO: we should differentiate strings from other values when inserting them in the table, as we now do for the std::variant version! - } - std::string values = joinVectorStrings(items, ","); - sql += " (" + std::to_string(id) + "," + values + ")"; - if (id != nRecords) { - sql += ","; - } else { - sql += ";"; - } - - } - if(m_debug) std::cout << "Query string:" << sql << std::endl; // debug +bool GMDBManager::addListOfRecordsToTable( + const std::string tableName, + const std::vector<std::vector<std::string>> records) { + // get table columns and format them for query + std::string tableColString = + "(" + joinVectorStrings(m_tableNames.at(tableName), ", ") + ")"; + if (m_debug) std::cout << "tableColString:" << tableColString << std::endl; - // executing the SQL query - if ( ! (execQuery(sql)) ) { - return false; - } - return true; -} + unsigned int nRecords = records.size(); + std::cout << "Info: number of " << tableName + << " records to dump into the DB: " << nRecords << std::endl; -//TODO: use this with std::variant to replace the version with std::string only, here above, for all tables; so we can store nativel values (int, double, etc...) -- R.M.B. -bool GMDBManager::addListOfRecordsToTable(const std::string tableName, const std::vector<std::vector<std::variant<int,long,float,double,std::string>>> records) -{ - // get table columns and format them for query - std::string tableColString = "(" + joinVectorStrings(m_tableNames.at(tableName), ", ") + ")"; - if(m_debug) std::cout << "tableColString:" << tableColString << std::endl; - - unsigned int nRecords = records.size(); - std::cout << "Info: number of " << tableName << " records to dump into the DB:" << nRecords << std::endl; - - // preparing the SQL query - std::string sql = fmt::format("INSERT INTO {0} {1} VALUES ", tableName, tableColString); - unsigned int id = 0; - for( const std::vector<std::variant<int,long,float,double,std::string>>& rec : records) { - ++id; - // a vector to store string-conversions of values, to build the SQL query - std::vector<std::string> items; - // loop over all entries in a row/record - for ( const std::variant<int,long,float,double,std::string>& item : rec) { - if( std::holds_alternative<int>(item) ) - items.push_back(std::to_string( std::get<int>(item) )); // we need to encapsulate records' values into quotes for the SQL query string - else if( std::holds_alternative<long>(item) ) - items.push_back(std::to_string( std::get<long>(item) )); - else if( std::holds_alternative<float>(item) ) - items.push_back(std::to_string( std::get<float>(item) )); - else if( std::holds_alternative<double>(item) ) - items.push_back(std::to_string( std::get<double>(item) )); - else if( std::holds_alternative<std::string>(item) ) { - std::string str = std::get<std::string>(item); - // NOTE: if item is a "NULL" string, we don't encapsulate it into quotes, - // so it is taken as the SQL's NULL value in the SQL string, - // and inserted as a NULL value in the table, - // instead of as a "NULL" text string - if (str == "NULL") items.push_back( str ); - else items.push_back( "'" + str + "'" ); + // preparing the SQL query + std::string sql = + fmt::format("INSERT INTO {0} {1} VALUES ", tableName, tableColString); + unsigned int id = 0; + for (const std::vector<std::string>& rec : records) { + ++id; + std::vector<std::string> items; + for (const std::string& item : rec) { + items.push_back( + "'" + item + + "'"); // TODO: we should differentiate strings from other + // values when inserting them in the table, as we now do + // for the std::variant version! + } + std::string values = joinVectorStrings(items, ","); + sql += " (" + std::to_string(id) + "," + values + ")"; + if (id != nRecords) { + sql += ","; + } else { + sql += ";"; } - else throw std::runtime_error("No std::variant alternative found!\n"); } - // we build the long string containing all values - std::string values = joinVectorStrings(items, ","); - sql += " (" + std::to_string(id) + "," + values + ")"; - if (id != nRecords) { - sql += ","; - } else { - sql += ";"; + if (m_debug) std::cout << "Query string:" << sql << std::endl; // debug + + // executing the SQL query + if (!(execQuery(sql))) { + return false; } + return true; +} - } - if(m_debug) std::cout << "Query string:" << sql << std::endl; // debug +// TODO: use this with std::variant to replace the version with std::string +// only, here above, for all tables; so we can store nativel values (int, +// double, etc...) -- R.M.B. +bool GMDBManager::addListOfRecordsToTable( + const std::string tableName, + const std::vector< + std::vector<std::variant<int, long, float, double, std::string>>> + records) { + // get table columns and format them for query + std::string tableColString = + "(" + joinVectorStrings(m_tableNames.at(tableName), ", ") + ")"; + if (m_debug) std::cout << "tableColString:" << tableColString << std::endl; - // executing the SQL query - if ( ! (execQuery(sql)) ) { - return false; - } - return true; -} + unsigned int nRecords = records.size(); + std::cout << "Info: number of " << tableName + << " records to dump into the DB:" << nRecords << std::endl; + // preparing the SQL query + std::string sql = + fmt::format("INSERT INTO {0} {1} VALUES ", tableName, tableColString); + unsigned int id = 0; + for (const std::vector<std::variant<int, long, float, double, std::string>>& + rec : records) { + ++id; + // a vector to store string-conversions of values, to build the SQL + // query + std::vector<std::string> items; + // loop over all entries in a row/record + for (const std::variant<int, long, float, double, std::string>& item : + rec) { + if (std::holds_alternative<int>(item)) + items.push_back(std::to_string(std::get<int>( + item))); // we need to encapsulate records' values into + // quotes for the SQL query string + else if (std::holds_alternative<long>(item)) + items.push_back(std::to_string(std::get<long>(item))); + else if (std::holds_alternative<float>(item)) + items.push_back(std::to_string(std::get<float>(item))); + else if (std::holds_alternative<double>(item)) + items.push_back(std::to_string(std::get<double>(item))); + else if (std::holds_alternative<std::string>(item)) { + std::string str = std::get<std::string>(item); + // NOTE: if item is a "NULL" string, we don't encapsulate it + // into quotes, so it is taken as the SQL's NULL value in the + // SQL string, and inserted as a NULL value in the table, + // instead of as a "NULL" text string + if (str == "NULL") + items.push_back(str); + else + items.push_back("'" + str + "'"); + } else + throw std::runtime_error( + "No std::variant alternative found!\n"); + } + // we build the long string containing all values + std::string values = joinVectorStrings(items, ","); + sql += " (" + std::to_string(id) + "," + values + ")"; + if (id != nRecords) { + sql += ","; + } else { + sql += ";"; + } + } + if (m_debug) std::cout << "Query string:" << sql << std::endl; // debug + // executing the SQL query + if (!(execQuery(sql))) { + return false; + } + return true; +} -// TODO: this is for the old SQLite. Not needed anymore, I guess. ==> Just put a requirement on the newer version of SQLite3 in CMakeLists.txt. Perhaps, also check that GeoModelIO can run smoothly on older ATLAS releases, like 21.9 by taking a newer SQLite3 from LCG. +// TODO: this is for the old SQLite. Not needed anymore, I guess. ==> Just put a +// requirement on the newer version of SQLite3 in CMakeLists.txt. Perhaps, also +// check that GeoModelIO can run smoothly on older ATLAS releases, like 21.9 by +// taking a newer SQLite3 from LCG. // ***Note*** // old syntax, for SQLite in SLC6 // here below we build the syntax for multiple INSERT @@ -540,30 +558,38 @@ bool GMDBManager::addListOfRecordsToTable(const std::string tableName, const std // see: stackoverflow.com/questions/1609637 // // we want to build a query like this: -// queryStr = QString("INSERT INTO Materials (id, name) SELECT 1 as id, 'Air' as name UNION ALL SELECT 2,'Silicon' UNION ALL SELECT 368,'ShieldSteel' ") +// queryStr = QString("INSERT INTO Materials (id, name) SELECT 1 as id, 'Air' +// as name UNION ALL SELECT 2,'Silicon' UNION ALL SELECT 368,'ShieldSteel' ") // /* -bool GMDBManager::addListOfRecordsToTableOld(const QString tableName, const std::vector<QStringList> records) +bool GMDBManager::addListOfRecordsToTableOld(const QString tableName, const +std::vector<QStringList> records) { - // get table columns and format them for query - std::string tabColNames = joinVectorStrings(m_tableNames.at(tableName.toStdString()), ", "); - QString tableColString = "(" + QString::fromStdString(tabColNames) + ")"; + // get table columns and format them for query + std::string tabColNames = +joinVectorStrings(m_tableNames.at(tableName.toStdString()), ", "); QString +tableColString = "(" + QString::fromStdString(tabColNames) + ")"; QStringList colNames = m_tableNames.at(tableName); unsigned int nRecords = records.size(); - qInfo() << "number of " << tableName << "records to insert into the DB:" << nRecords; + qInfo() << "number of " << tableName << "records to insert into the DB:" << +nRecords; - // SQLite has a limit on 'union' items, set at 500. So we have to split the items if we have more. + // SQLite has a limit on 'union' items, set at 500. So we have to split the +items if we have more. // See: stackoverflow.com/questions/9527851/ unsigned int bunchSize = 500; if ( nRecords > bunchSize ) { - qWarning() << "WARNING! " << nRecords << " records of type " << tableName << "to store in the DB in one call! Call limit is " << bunchSize << " --> We split them in bunches..."; + qWarning() << "WARNING! " << nRecords << " records of type " << +tableName << "to store in the DB in one call! Call limit is " << bunchSize << " +--> We split them in bunches..."; - std::vector<QStringList> recordsCopy( records ); // TODO: maybe we should use a deque or queue, which have fast pop of first element? + std::vector<QStringList> recordsCopy( records ); // TODO: maybe we +should use a deque or queue, which have fast pop of first element? std::vector<QStringList>::const_iterator first; std::vector<QStringList>::const_iterator last; @@ -574,22 +600,26 @@ bool GMDBManager::addListOfRecordsToTableOld(const QString tableName, const std: // preparing the SQL query QString queryStr("INSERT INTO %1 %2 SELECT "); - queryStr = queryStr.arg(tableName); // insert table name - queryStr = queryStr.arg(tableColString); // insert table columns + queryStr = queryStr.arg(tableName); // insert table name + queryStr = queryStr.arg(tableColString); // insert table columns first = recordsCopy.begin(); - last = recordsCopy.size() > bunchSize ? recordsCopy.begin() + bunchSize : recordsCopy.end(); + last = recordsCopy.size() > bunchSize ? recordsCopy.begin() + bunchSize +: recordsCopy.end(); - std::vector<QStringList> recordsBunch( first, last ); // we take the first 500 records - recordsCopy.erase( first, last ); // we delete the first 500 records - if (m_debug) qDebug() << "start:" << start << "recordsBunch size:" << recordsBunch.size() << "- recordsCopy size after removal:" << recordsCopy.size(); + std::vector<QStringList> recordsBunch( first, last ); // we take the +first 500 records recordsCopy.erase( first, last ); // we delete the first 500 +records if (m_debug) qDebug() << "start:" << start << "recordsBunch size:" << +recordsBunch.size() << "- recordsCopy size after removal:" << +recordsCopy.size(); - // --- first record + // --- first record // outcome should be like: " 1 as id, 'Air' as name " unsigned int id = start+1; // set the first ID as 'start' - QStringList recFirst = recordsBunch.front(); // access first record from vector - recordsBunch.erase( recordsBunch.begin() ); // delete first record - if (m_debug) qDebug() << "after taking first record - recordsBunch size:" << recordsBunch.size(); + QStringList recFirst = recordsBunch.front(); // access first record from +vector recordsBunch.erase( recordsBunch.begin() ); // delete first record if +(m_debug) qDebug() << "after taking first record - recordsBunch size:" << +recordsBunch.size(); // first item in the first record (it is the ID) QString firstCol = colNames[0]; @@ -613,36 +643,38 @@ bool GMDBManager::addListOfRecordsToTableOld(const QString tableName, const std: foreach(QStringList recs, recordsBunch) { - // DEBUG - if (tableName == "Functions") { - if (recs[1].length() > 65000) { - std::cout << "LONG STRING! size: " << recs[1].length() << std::endl; - std::cout << "LONG STRING! string: " << recs[1].toStdString() << std::endl << std::endl; - } - } - //------ + // DEBUG + if (tableName == +"Functions") { if (recs[1].length() > 65000) { std::cout << "LONG STRING! size: +" << recs[1].length() << std::endl; std::cout << "LONG STRING! string: " << +recs[1].toStdString() << std::endl << std::endl; + } + } + //------ - ++id; + ++id; // put single quotes around items QStringList items; foreach (QString item, recs) { - items << "'" + item + "'"; - } + items << "'" + item + "'"; + } // join items into a string and add the SQL commands QString itemsStr = items.join(", "); - queryStr += " UNION ALL SELECT " + QString::number(id) + ", " + itemsStr; + queryStr += " UNION ALL SELECT " + QString::number(id) + ", " + +itemsStr; } //qDebug() << "queryStr:" << queryStr; - // executing the SQL query - QSqlQuery q; - if (!q.exec(queryStr)) { + // executing the SQL query + QSqlQuery q; + if (!q.exec(queryStr)) { qWarning() << "ERROR!!! SQL error:"; - showError(q.lastError()); - return false; - } - // JFB commented: qDebug() << bunchSize << "elements have been saved into the DB, starting at:" << start; + showError(q.lastError()); + return false; + } + // JFB commented: qDebug() << bunchSize << "elements have been saved +into the DB, starting at:" << start; start += bunchSize; // for the next iteration @@ -652,14 +684,14 @@ bool GMDBManager::addListOfRecordsToTableOld(const QString tableName, const std: else { // preparing the SQL query QString queryStr("INSERT INTO %1 %2 SELECT "); - queryStr = queryStr.arg(tableName); // insert table name - queryStr = queryStr.arg(tableColString); // insert table columns + queryStr = queryStr.arg(tableName); // insert table name + queryStr = queryStr.arg(tableColString); // insert table columns unsigned int id = 0; // loop on all records - foreach(QStringList recs, records) { + foreach(QStringList recs, records) { - ++id; + ++id; // first record // outcome should be like: " 1 as id, 'Air' as name " @@ -689,466 +721,478 @@ bool GMDBManager::addListOfRecordsToTableOld(const QString tableName, const std: // put single quotes around items QStringList items; foreach (QString item, recs) { - items << "'" + item + "'"; - } + items << "'" + item + "'"; + } // join items into a string and add the SQL commands QString itemsStr = items.join(", "); - queryStr += " UNION ALL SELECT " + QString::number(id) + ", " + itemsStr; + queryStr += " UNION ALL SELECT " + QString::number(id) + ", " + +itemsStr; } - } // end of: foreach(QStringList recs, records) + } // end of: foreach(QStringList recs, records) //qDebug() << "queryStr:" << queryStr; - // executing the SQL query - QSqlQuery q; - if (!q.exec(queryStr)) { + // executing the SQL query + QSqlQuery q; + if (!q.exec(queryStr)) { qWarning() << "ERROR!!! SQL error:"; - showError(q.lastError()); - return false; - } + showError(q.lastError()); + return false; + } } // end of (else > 500) - // JFB commented: qDebug() << "DONE. The list of " << nRecords << "records have been inserted into the DB."; - return true; + // JFB commented: qDebug() << "DONE. The list of " << nRecords << +"records have been inserted into the DB."; return true; } */ - -bool GMDBManager::addRootVolume(const std::vector<std::string> &values) -{ - if (values.size() > 0 ) { - const unsigned int volId = std::stoi(values[0]); - const std::string nodeType = values[1]; - return storeRootVolume( volId, nodeType ); - } - else { - std::cout << "ERROR! No records to save for RootVolume! All GeoModel trees must have a 'World'/'Root' volume! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } +bool GMDBManager::addRootVolume(const std::vector<std::string>& values) { + if (values.size() > 0) { + const unsigned int volId = std::stoi(values[0]); + const std::string nodeType = values[1]; + return storeRootVolume(volId, nodeType); + } else { + std::cout << "ERROR! No records to save for RootVolume! All GeoModel " + "trees must have a 'World'/'Root' volume! Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } } - -void GMDBManager::addDBversion(std::string version) -{ - checkIsDBOpen(); - sqlite3_stmt * st = nullptr; - int rc = -1; - std::string sql = "INSERT INTO dbversion(version) VALUES(?)"; - rc = sqlite3_prepare_v2( m_d->m_dbSqlite, sql.c_str(), -1, &st, NULL); - if (rc != SQLITE_OK) { - printf( "[SQLite ERR] (%s) : Error msg: %s\n", __func__, sqlite3_errmsg(m_d->m_dbSqlite) ); - exit(EXIT_FAILURE); - } - rc = sqlite3_bind_text(st, 1, version.c_str(), version.length(), SQLITE_TRANSIENT); - rc = sqlite3_step( st ); - if (rc != SQLITE_DONE) { - printf( "[SQLite ERR] (%s) : Error msg: %s\n", __func__, sqlite3_errmsg(m_d->m_dbSqlite) ); - exit(EXIT_FAILURE); - } - // finalize - sqlite3_finalize(st); - return; +void GMDBManager::addDBversion(std::string version) { + checkIsDBOpen(); + sqlite3_stmt* st = nullptr; + int rc = -1; + std::string sql = "INSERT INTO dbversion(version) VALUES(?)"; + rc = sqlite3_prepare_v2(m_d->m_dbSqlite, sql.c_str(), -1, &st, NULL); + if (rc != SQLITE_OK) { + printf("[SQLite ERR] (%s) : Error msg: %s\n", __func__, + sqlite3_errmsg(m_d->m_dbSqlite)); + exit(EXIT_FAILURE); + } + rc = sqlite3_bind_text(st, 1, version.c_str(), version.length(), + SQLITE_TRANSIENT); + rc = sqlite3_step(st); + if (rc != SQLITE_DONE) { + printf("[SQLite ERR] (%s) : Error msg: %s\n", __func__, + sqlite3_errmsg(m_d->m_dbSqlite)); + exit(EXIT_FAILURE); + } + // finalize + sqlite3_finalize(st); + return; } -bool GMDBManager::checkIsDBOpen() const -{ - if(m_d->m_dbSqlite != nullptr) { - return true; - } else { - std::cout << "ERROR! The SQLite DB is not accessible! Exiting..." << std::endl; - exit(EXIT_FAILURE); - } +bool GMDBManager::checkIsDBOpen() const { + if (m_d->m_dbSqlite != nullptr) { + return true; + } else { + std::cout << "ERROR! The SQLite DB is not accessible! Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } } - -std::vector<std::string> GMDBManager::getItemAndType(unsigned int tableId, unsigned int id) -{ - std::vector<std::string> results; - std::string tableName = getTableNameFromTableId(tableId); - std::string nodeType = getNodeTypeFromTableId(tableId); - std::vector<std::string> item = getItemFromTableName(tableName, id); - // add the type - results.push_back( nodeType ); - // add the item - results.insert(results.end(), item.begin(), item.end()); - return results; +std::vector<std::string> GMDBManager::getItemAndType(unsigned int tableId, + unsigned int id) { + std::vector<std::string> results; + std::string tableName = getTableNameFromTableId(tableId); + std::string nodeType = getNodeTypeFromTableId(tableId); + std::vector<std::string> item = getItemFromTableName(tableName, id); + // add the type + results.push_back(nodeType); + // add the item + results.insert(results.end(), item.begin(), item.end()); + return results; } - -std::vector<std::string> GMDBManager::getItemFromTableName(std::string tableName, unsigned int id) -{ - // FIXME: when you create caches for all tables, replace this method with a lookup action in the cache. - /* - * Get the object from DB. - */ - std::vector<std::string> item; - // set a SQL command string with the right table name - std::string sql = fmt::format("SELECT * FROM {0} WHERE id = (?)", tableName); - // prepare the query - sqlite3_stmt * stmt = nullptr; - int rc = -1; - rc = sqlite3_prepare_v2( m_d->m_dbSqlite, sql.c_str(), -1, &stmt, NULL); - if (rc != SQLITE_OK) { - printf( "[SQLite ERR] 'prepare' (%s) : Error msg: %s\n", __func__, sqlite3_errmsg(m_d->m_dbSqlite) ); - exit(EXIT_FAILURE); - } - // bind the parameters - rc = sqlite3_bind_int(stmt, 1, id); - // execute the query and loop over all rows and all columuns - if ( stmt ) - { - int ctotal = sqlite3_column_count(stmt); // Count the Number of Columns in the Table - int res = 0; - while ( 1 ) - { - res = sqlite3_step(stmt); // Execute SQL Statement. - if ( res == SQLITE_ROW ) - { - for ( int i = 0; i < ctotal; i++ ) // Loop times the number of columns in the table - { - std::string s = (char*)sqlite3_column_text(stmt, i); // Read each Column in the row as text FIXME: is there a method to get the right type, e.g. double, instead of text? - item.push_back( s ); - } - } - if ( res == SQLITE_DONE || res==SQLITE_ERROR) - { - if (res == SQLITE_ERROR) { - std::string errmsg(sqlite3_errmsg(m_d->m_dbSqlite)); - sqlite3_finalize(stmt); - throw errmsg; +std::vector<std::string> GMDBManager::getItemFromTableName( + std::string tableName, unsigned int id) { + // FIXME: when you create caches for all tables, replace this method with a + // lookup action in the cache. + /* + * Get the object from DB. + */ + std::vector<std::string> item; + // set a SQL command string with the right table name + std::string sql = + fmt::format("SELECT * FROM {0} WHERE id = (?)", tableName); + // prepare the query + sqlite3_stmt* stmt = nullptr; + int rc = -1; + rc = sqlite3_prepare_v2(m_d->m_dbSqlite, sql.c_str(), -1, &stmt, NULL); + if (rc != SQLITE_OK) { + printf("[SQLite ERR] 'prepare' (%s) : Error msg: %s\n", __func__, + sqlite3_errmsg(m_d->m_dbSqlite)); + exit(EXIT_FAILURE); + } + // bind the parameters + rc = sqlite3_bind_int(stmt, 1, id); + // execute the query and loop over all rows and all columuns + if (stmt) { + int ctotal = sqlite3_column_count( + stmt); // Count the Number of Columns in the Table + int res = 0; + while (1) { + res = sqlite3_step(stmt); // Execute SQL Statement. + if (res == SQLITE_ROW) { + for (int i = 0; i < ctotal; + i++) // Loop times the number of columns in the table + { + std::string s = (char*)sqlite3_column_text( + stmt, i); // Read each Column in the row as text FIXME: + // is there a method to get the right type, + // e.g. double, instead of text? + item.push_back(s); + } + } + if (res == SQLITE_DONE || res == SQLITE_ERROR) { + if (res == SQLITE_ERROR) { + std::string errmsg(sqlite3_errmsg(m_d->m_dbSqlite)); + sqlite3_finalize(stmt); + throw errmsg; + } + break; + } } - break; - } } - } - // TODO: do we need that error check here?? -// if (rc != SQLITE_DONE) { -// printf( "[SQLite ERR] 'step' (%s) : Error msg: %s\n", __func__, sqlite3_errmsg(m_d->m_dbSqlite) ); -//// exit(EXIT_FAILURE); -// } - // finalize - sqlite3_finalize(stmt); - - if (item.size()==0) { - std::cout << "ERROR!!" << "Item with ID:'" << id << "' does not exist in table" << tableName << "! Exiting..."; - exit(EXIT_FAILURE); - } + // TODO: do we need that error check here?? + // if (rc != SQLITE_DONE) { + // printf( "[SQLite ERR] 'step' (%s) : Error msg: %s\n", __func__, + // sqlite3_errmsg(m_d->m_dbSqlite) ); + //// exit(EXIT_FAILURE); + // } + // finalize + sqlite3_finalize(stmt); - return item; -} + if (item.size() == 0) { + std::cout << "ERROR!!" + << "Item with ID:'" << id << "' does not exist in table" + << tableName << "! Exiting..."; + exit(EXIT_FAILURE); + } + return item; +} // Get all parent-children data from the database in one go -std::vector<std::vector<std::string>> GMDBManager::getChildrenTable() -{ - return getTableRecords("ChildrenPositions"); +std::vector<std::vector<std::string>> GMDBManager::getChildrenTable() { + return getTableRecords("ChildrenPositions"); } - - -unsigned int GMDBManager::getTableIdFromNodeType(const std::string &nodeType) -{ - return m_cache_nodeType_tableID[nodeType]; +unsigned int GMDBManager::getTableIdFromNodeType(const std::string& nodeType) { + return m_cache_nodeType_tableID[nodeType]; } - -std::string GMDBManager::getTableNameFromNodeType(const std::string &nodeType) -{ - std::string st{""}; - if (m_cache_nodeType_tableName.count(nodeType)) { - st = m_cache_nodeType_tableName.at(nodeType); - } else { - std::mutex coutMutex; - coutMutex.lock(); - std::cout << "\t ===> WARNING! A table for nodeType '" << nodeType << "' has not been found in the input geometry file." << std::endl; - coutMutex.unlock(); - } - return st; +std::string GMDBManager::getTableNameFromNodeType(const std::string& nodeType) { + std::string st{""}; + if (m_cache_nodeType_tableName.count(nodeType)) { + st = m_cache_nodeType_tableName.at(nodeType); + } else { + std::mutex coutMutex; + coutMutex.lock(); + std::cout << "\t ===> WARNING! A table for nodeType '" << nodeType + << "' has not been found in the input geometry file." + << std::endl; + coutMutex.unlock(); + } + return st; } - // build the GeoNodeTypes cache -int GMDBManager::loadGeoNodeTypesAndBuildCache() -{ +int GMDBManager::loadGeoNodeTypesAndBuildCache() { checkIsDBOpen(); std::string queryStr; - sqlite3_stmt * st = nullptr; + sqlite3_stmt* st = nullptr; int rc = -1; - //set the SQL query string + // set the SQL query string std::string sql = "SELECT * FROM GeoNodesTypes"; // declare the data we want to fetch unsigned int id = 0; std::string nodeType = ""; std::string tableName = ""; // prepare the query - rc = sqlite3_prepare_v2( m_d->m_dbSqlite, sql.c_str(), -1, &st, NULL); + rc = sqlite3_prepare_v2(m_d->m_dbSqlite, sql.c_str(), -1, &st, NULL); if (rc != SQLITE_OK) { - printf( "[SQLite ERR] (%s) : Error msg: %s\n", __func__, sqlite3_errmsg(m_d->m_dbSqlite) ); - exit(EXIT_FAILURE); + printf("[SQLite ERR] (%s) : Error msg: %s\n", __func__, + sqlite3_errmsg(m_d->m_dbSqlite)); + exit(EXIT_FAILURE); } // execute the statement until all selected records are processed while ((rc = sqlite3_step(st)) == SQLITE_ROW) { - // get the data - id = sqlite3_column_int(st, 0); - nodeType = std::string(reinterpret_cast<const char*>(sqlite3_column_text(st, 1))); - tableName = std::string(reinterpret_cast<const char*>(sqlite3_column_text(st, 2))); - if(m_debug) std::cout << "row: " << id << "," << nodeType << "," << tableName << std::endl; - // fill the caches - m_cache_tableId_tableName.insert( std::pair<unsigned int, std::string>(id, tableName)); - m_cache_tableId_nodeType.insert( std::pair<unsigned int, std::string>(id, nodeType)); - m_cache_nodeType_tableName.insert( std::pair<std::string, std::string>(nodeType, tableName)); - m_cache_nodeType_tableID.insert( std::pair<std::string, unsigned int>(nodeType, id)); + // get the data + id = sqlite3_column_int(st, 0); + nodeType = std::string( + reinterpret_cast<const char*>(sqlite3_column_text(st, 1))); + tableName = std::string( + reinterpret_cast<const char*>(sqlite3_column_text(st, 2))); + if (m_debug) + std::cout << "row: " << id << "," << nodeType << "," << tableName + << std::endl; + // fill the caches + m_cache_tableId_tableName.insert( + std::pair<unsigned int, std::string>(id, tableName)); + m_cache_tableId_nodeType.insert( + std::pair<unsigned int, std::string>(id, nodeType)); + m_cache_nodeType_tableName.insert( + std::pair<std::string, std::string>(nodeType, tableName)); + m_cache_nodeType_tableID.insert( + std::pair<std::string, unsigned int>(nodeType, id)); } if (rc != SQLITE_DONE) { - std::string errmsg(sqlite3_errmsg(m_d->m_dbSqlite)); - sqlite3_finalize(st); - throw errmsg; + std::string errmsg(sqlite3_errmsg(m_d->m_dbSqlite)); + sqlite3_finalize(st); + throw errmsg; } // finalize sqlite3_finalize(st); - return rc; -} - -//FIXME: should throw an error if the method `loadGeoNodeTypesAndBuildCache()` was not called before calling this method -std::string GMDBManager::getTableNameFromTableId(unsigned int tabId) -{ - return m_cache_tableId_tableName[tabId]; + return rc; } -std::string GMDBManager::getNodeTypeFromTableId(unsigned int tabId) -{ - return m_cache_tableId_nodeType[tabId]; +// FIXME: should throw an error if the method `loadGeoNodeTypesAndBuildCache()` +// was not called before calling this method +std::string GMDBManager::getTableNameFromTableId(unsigned int tabId) { + return m_cache_tableId_tableName[tabId]; } -std::unordered_map<unsigned int, std::string> GMDBManager::getAll_TableIDsNodeTypes() -{ - return m_cache_tableId_nodeType; +std::string GMDBManager::getNodeTypeFromTableId(unsigned int tabId) { + return m_cache_tableId_nodeType[tabId]; } -std::unordered_map<std::string, unsigned int> GMDBManager::getAll_NodeTypesTableIDs() -{ - return m_cache_nodeType_tableID; +std::unordered_map<unsigned int, std::string> +GMDBManager::getAll_TableIDsNodeTypes() { + return m_cache_tableId_nodeType; } - - -sqlite3_stmt* GMDBManager::Imp::selectAllFromTable(std::string tableName) const -{ - return selectAllFromTableSortBy(tableName, "id"); +std::unordered_map<std::string, unsigned int> +GMDBManager::getAll_NodeTypesTableIDs() { + return m_cache_nodeType_tableID; } - -sqlite3_stmt* GMDBManager::Imp::selectAllFromTableSortBy(std::string tableName, std::string sortColumn) const -{ - theManager->checkIsDBOpen(); - if ("" == sortColumn || 0 == sortColumn.size()) { - sortColumn = "id"; - } - sqlite3_stmt * st = nullptr; // SQLite statement to be returned - int rc = -1; // SQLite return code - //set the SQL query string - std::string sql = fmt::format("SELECT * FROM {0} ORDER BY {1}", tableName, sortColumn); - // prepare the query - rc = sqlite3_prepare_v2( m_dbSqlite, sql.c_str(), -1, &st, NULL); - if (rc != SQLITE_OK) { - printf( "[SQLite ERR] (%s) : Error msg: %s\n", __func__, sqlite3_errmsg(m_dbSqlite) ); - exit(EXIT_FAILURE); - } - return st; +sqlite3_stmt* GMDBManager::Imp::selectAllFromTable( + std::string tableName) const { + return selectAllFromTableSortBy(tableName, "id"); } - -sqlite3_stmt* GMDBManager::Imp::selectAllFromTableChildrenPositions() const -{ - theManager->checkIsDBOpen(); - sqlite3_stmt * st = nullptr; - int rc = -1; - //set the SQL query string - std::string sql = "SELECT * FROM ChildrenPositions ORDER BY parentTable, parentId, parentCopyNumber, position"; - // prepare the query - rc = sqlite3_prepare_v2( m_dbSqlite, sql.c_str(), -1, &st, NULL); - if (rc != SQLITE_OK) { - printf( "[SQLite ERR] (%s) : Error msg: %s\n", __func__, sqlite3_errmsg(m_dbSqlite) ); - exit(EXIT_FAILURE); - } - return st; +sqlite3_stmt* GMDBManager::Imp::selectAllFromTableSortBy( + std::string tableName, std::string sortColumn) const { + theManager->checkIsDBOpen(); + if ("" == sortColumn || 0 == sortColumn.size()) { + sortColumn = "id"; + } + sqlite3_stmt* st = nullptr; // SQLite statement to be returned + int rc = -1; // SQLite return code + // set the SQL query string + std::string sql = + fmt::format("SELECT * FROM {0} ORDER BY {1}", tableName, sortColumn); + // prepare the query + rc = sqlite3_prepare_v2(m_dbSqlite, sql.c_str(), -1, &st, NULL); + if (rc != SQLITE_OK) { + printf("[SQLite ERR] (%s) : Error msg: %s\n", __func__, + sqlite3_errmsg(m_dbSqlite)); + exit(EXIT_FAILURE); + } + return st; } - -bool GMDBManager::initDB() -{ - // create tables - bool tablesOK = createTables(); - // store DB version - addDBversion(dbversion); - return tablesOK; +sqlite3_stmt* GMDBManager::Imp::selectAllFromTableChildrenPositions() const { + theManager->checkIsDBOpen(); + sqlite3_stmt* st = nullptr; + int rc = -1; + // set the SQL query string + std::string sql = + "SELECT * FROM ChildrenPositions ORDER BY parentTable, parentId, " + "parentCopyNumber, position"; + // prepare the query + rc = sqlite3_prepare_v2(m_dbSqlite, sql.c_str(), -1, &st, NULL); + if (rc != SQLITE_OK) { + printf("[SQLite ERR] (%s) : Error msg: %s\n", __func__, + sqlite3_errmsg(m_dbSqlite)); + exit(EXIT_FAILURE); + } + return st; } - - - - -void GMDBManager::printAllDBTables() -{ - if(m_cache_tables.size() == 0) { - getAllDBTables(); // load tables and build the cache - } - for( auto& str : m_cache_tables ) - std::cout << str << std::endl; +bool GMDBManager::initDB() { + // create tables + bool tablesOK = createTables(); + // store DB version + addDBversion(dbversion); + return tablesOK; } - - -void GMDBManager::getAllDBTables() -{ - std::string tableName; - std::vector<std::string> tables; - // define a query string containing the necessary SQL instructions - std::string queryStr = "SELECT name FROM sqlite_master WHERE type ='table' AND name NOT LIKE 'sqlite_%';"; - // prepare the query with the query string - sqlite3_stmt *stmt; - int rc = sqlite3_prepare_v2(m_d->m_dbSqlite, queryStr.c_str(), -1, &stmt, NULL); - if (rc != SQLITE_OK) { - throw std::string(sqlite3_errmsg(m_d->m_dbSqlite)); - } - // execute the statement until all selected records are processed - while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { - tableName = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0))); - //std::cout << "tableName: " << tableName << std::endl; // debug - tables.push_back(tableName); - } - if (rc != SQLITE_DONE) { - std::string errmsg(sqlite3_errmsg(m_d->m_dbSqlite)); +void GMDBManager::printAllDBTables() { + if (m_cache_tables.size() == 0) { + getAllDBTables(); // load tables and build the cache + } + for (auto& str : m_cache_tables) std::cout << str << std::endl; +} + +void GMDBManager::getAllDBTables() { + std::string tableName; + std::vector<std::string> tables; + // define a query string containing the necessary SQL instructions + std::string queryStr = + "SELECT name FROM sqlite_master WHERE type ='table' AND name NOT LIKE " + "'sqlite_%';"; + // prepare the query with the query string + sqlite3_stmt* stmt; + int rc = + sqlite3_prepare_v2(m_d->m_dbSqlite, queryStr.c_str(), -1, &stmt, NULL); + if (rc != SQLITE_OK) { + throw std::string(sqlite3_errmsg(m_d->m_dbSqlite)); + } + // execute the statement until all selected records are processed + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + tableName = std::string( + reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0))); + // std::cout << "tableName: " << tableName << std::endl; // debug + tables.push_back(tableName); + } + if (rc != SQLITE_DONE) { + std::string errmsg(sqlite3_errmsg(m_d->m_dbSqlite)); + sqlite3_finalize(stmt); + throw errmsg; + } + // finalize sqlite3_finalize(stmt); - throw errmsg; - } - // finalize - sqlite3_finalize(stmt); - m_cache_tables = tables; + m_cache_tables = tables; } - -void GMDBManager::getAllDBTableColumns() -{ - +void GMDBManager::getAllDBTableColumns() { std::vector<std::string> cols; std::string colName; // populate the cache with tables' names, if needed - if( ! m_cache_tables.size() ) { + if (!m_cache_tables.size()) { std::cout << "*** ERROR! Tables' cache is empty! ***\n"; return; } - for( auto& tableName : m_cache_tables ) { - sqlite3_stmt *stmt; + for (auto& tableName : m_cache_tables) { + sqlite3_stmt* stmt; // get the 'name' column from the PRAGMA's table's definition // see: https://stackoverflow.com/a/54962853/320369 - std::string queryStr = "select name from pragma_table_info('" + tableName + "')"; - int rc = sqlite3_prepare_v2(m_d->m_dbSqlite, queryStr.c_str() , -1, &stmt, NULL); - if (rc==SQLITE_OK) - { - //OK, now looping over table's columns... - //will continue to go down the rows (columns in your table) till there are no more - while(sqlite3_step(stmt) == SQLITE_ROW) - { - //sprintf(colName, "%s", sqlite3_column_text(stmt, 1)); - colName = std::string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0))); - - //do something with colName because it contains the column's name + std::string queryStr = + "select name from pragma_table_info('" + tableName + "')"; + int rc = sqlite3_prepare_v2(m_d->m_dbSqlite, queryStr.c_str(), -1, + &stmt, NULL); + if (rc == SQLITE_OK) { + // OK, now looping over table's columns... + // will continue to go down the rows (columns in your table) till + // there are no more + while (sqlite3_step(stmt) == SQLITE_ROW) { + // sprintf(colName, "%s", sqlite3_column_text(stmt, 1)); + colName = std::string(reinterpret_cast<const char*>( + sqlite3_column_text(stmt, 0))); + + // do something with colName because it contains the column's + // name m_tableNames[tableName].push_back(colName); } } - } // end of for loop + } // end of for loop } - - - - - -// TODO: currently, we retrieve published data as strings, but we want to retrieve that according to the original data type -std::vector<std::vector<std::string>> GMDBManager::getPublishedFPVTable( std::string suffix ) -{ - std::string tableName = "PublishedFullPhysVols"; // default table name - if( "" != suffix ) { +// TODO: currently, we retrieve published data as strings, but we want to +// retrieve that according to the original data type +std::vector<std::vector<std::string>> GMDBManager::getPublishedFPVTable( + std::string suffix) { + std::string tableName = "PublishedFullPhysVols"; // default table name + if ("" != suffix) { tableName += "_"; tableName += suffix; } - return getTableRecords( tableName ); + return getTableRecords(tableName); } -// TODO: currently, we retrieve published data as strings, but we want to retrieve that according to the original data type -std::vector<std::vector<std::string>> GMDBManager::getPublishedAXFTable( std::string suffix ) -{ - std::string tableName = "PublishedAlignableTransforms"; // default table name - if( "" != suffix ) { +// TODO: currently, we retrieve published data as strings, but we want to +// retrieve that according to the original data type +std::vector<std::vector<std::string>> GMDBManager::getPublishedAXFTable( + std::string suffix) { + std::string tableName = + "PublishedAlignableTransforms"; // default table name + if ("" != suffix) { tableName += "_"; tableName += suffix; } - return getTableRecords( tableName ); + return getTableRecords(tableName); } - // create a user-defined custom table to store the published nodes // (usually GeoFullPhysVol and AlignableTransform nodes) and their keys. -bool GMDBManager::createTableCustomPublishedNodes(const std::string tableName, const std::string nodeType, const std::type_info* keyType) -{ - - // get the right node type and referenced table - if( nodeType != "GeoFullPhysVol" && nodeType != "GeoVFullPhysVol" && nodeType != "GeoAlignableTransform" ) { - std::cout << "ERROR!! GeoModel node type '" << nodeType - << "' is not currently supported in GMDBManager::createTableCustomPublishedNodes()" - << " Please, ask to geomodel-developers@cern.ch. Exiting..." - << std::endl; - exit(EXIT_FAILURE); - } - std::string referencedTable = ""; - if( "GeoFullPhysVol" == nodeType || "GeoVFullPhysVol" == nodeType ) - referencedTable = "FullPhysVols"; - if( "GeoAlignableTransform" == nodeType) - referencedTable = "AlignableTransforms"; - - // set the right type to use in the DB, based on the type used for the published key - std::string keyTypeDB = ""; - if( typeid(std::string) == *keyType) - keyTypeDB = "varchar"; - else if( typeid(int) == *keyType || typeid(unsigned) == *keyType) - keyTypeDB = "integer"; - else { - std::cout << "ERROR!!! The key type '" << typeid(keyType).name() - << "' is not currently supported in GMDBManager::createTableCustomPublishedNodes()." - << " Please, ask to 'geomodel-developers@cern.ch'. Exiting..." - << std::endl; - exit(EXIT_FAILURE); - } +bool GMDBManager::createTableCustomPublishedNodes( + const std::string tableName, const std::string nodeType, + const std::type_info* keyType) { + // get the right node type and referenced table + if (nodeType != "GeoFullPhysVol" && nodeType != "GeoVFullPhysVol" && + nodeType != "GeoAlignableTransform") { + std::cout << "ERROR!! GeoModel node type '" << nodeType + << "' is not currently supported in " + "GMDBManager::createTableCustomPublishedNodes()" + << " Please, ask to geomodel-developers@cern.ch. Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } + std::string referencedTable = ""; + if ("GeoFullPhysVol" == nodeType || "GeoVFullPhysVol" == nodeType) + referencedTable = "FullPhysVols"; + if ("GeoAlignableTransform" == nodeType) + referencedTable = "AlignableTransforms"; + + // set the right type to use in the DB, based on the type used for the + // published key + std::string keyTypeDB = ""; + if (typeid(std::string) == *keyType) + keyTypeDB = "varchar"; + else if (typeid(int) == *keyType || typeid(unsigned) == *keyType) + keyTypeDB = "integer"; + else { + std::cout << "ERROR!!! The key type '" << typeid(keyType).name() + << "' is not currently supported in " + "GMDBManager::createTableCustomPublishedNodes()." + << " Please, ask to 'geomodel-developers@cern.ch'. Exiting..." + << std::endl; + exit(EXIT_FAILURE); + } - int rc = -1; // sqlite's return code - std::string queryStr; + int rc = -1; // sqlite's return code + std::string queryStr; - std::vector<std::string> tab; + std::vector<std::string> tab; - tab.insert(tab.begin(), {tableName, "id", "key", "nodeID", "keyType"}); - storeTableColumnNames(tab); + tab.insert(tab.begin(), {tableName, "id", "key", "nodeID", "keyType"}); + storeTableColumnNames(tab); - queryStr = fmt::format("create table {0} ({1} integer primary key, {2} {3} not null, {4} integer not null REFERENCES {5}(id), {6} varchar not null)", tab[0], tab[1], tab[2], keyTypeDB, tab[3], referencedTable, tab[4]); - //std::cout << "Creating table with query: '" << queryStr << "'..." << std::endl; // debug msg - rc = execQuery(queryStr); - tab.clear(); - //std::cout << "Created the custom table: '" << tableName << "'." << std::endl; // debug msg - return rc; + queryStr = fmt::format( + "create table {0} ({1} integer primary key, {2} {3} not null, {4} " + "integer not null REFERENCES {5}(id), {6} varchar not null)", + tab[0], tab[1], tab[2], keyTypeDB, tab[3], referencedTable, tab[4]); + // std::cout << "Creating table with query: '" << queryStr << "'..." << + // std::endl; // debug msg + rc = execQuery(queryStr); + tab.clear(); + // std::cout << "Created the custom table: '" << tableName << "'." << + // std::endl; // debug msg + return rc; } /* --- not used anymore, we now have std::variant, below --- -// create a user-defined custom table to store auxiliary data, from vector<vector<string>> -bool GMDBManager::createCustomTable(const std::string tableName, const std::vector<std::string> tableColNames, const std::vector<std::string> tableColTypes, const std::vector<std::vector<std::string>> &records ) -{ - if( tableColNames.size() == 0 ) throw std::runtime_error("GMDBManager::createCustomTable -- The list of columns' names is empty!!"); - if( tableColTypes.size() == 0 ) throw std::runtime_error("GMDBManager::createCustomTable -- The list of columns' types is empty!!"); +// create a user-defined custom table to store auxiliary data, from +vector<vector<string>> bool GMDBManager::createCustomTable(const std::string +tableName, const std::vector<std::string> tableColNames, const +std::vector<std::string> tableColTypes, const +std::vector<std::vector<std::string>> &records ) +{ + if( tableColNames.size() == 0 ) throw +std::runtime_error("GMDBManager::createCustomTable -- The list of columns' names +is empty!!"); if( tableColTypes.size() == 0 ) throw +std::runtime_error("GMDBManager::createCustomTable -- The list of columns' types +is empty!!"); int rc = -1; // sqlite's return code std::string queryStr; @@ -1163,428 +1207,516 @@ bool GMDBManager::createCustomTable(const std::string tableName, const std::vect storeTableColumnNames(tab); // prepare the dynamic query to create the custom table - queryStr = fmt::format( "create table {0} ( id integer primary key ", tab[0] ); - for( int ii=0; ii<tableColNames.size(); ++ii) { - std::string colStr = fmt::format( ", {0} {1} ", tableColNames[ii], tableColTypes[ii] ); - queryStr += colStr; + queryStr = fmt::format( "create table {0} ( id integer primary key ", tab[0] +); for( int ii=0; ii<tableColNames.size(); ++ii) { std::string colStr = +fmt::format( ", {0} {1} ", tableColNames[ii], tableColTypes[ii] ); queryStr += +colStr; } queryStr += ")"; rc = execQuery(queryStr); tab.clear(); - return addListOfRecordsToTable( tableName, records ); // needs SQLite >= 3.7.11 + return addListOfRecordsToTable( tableName, records ); // needs SQLite +>= 3.7.11 } */ -// create a user-defined custom table to store auxiliary data, from vector<vector<variant>> -bool GMDBManager::createCustomTable(const std::string tableName, const std::vector<std::string> tableColNames, const std::vector<std::string> tableColTypes, const std::vector<std::vector<std::variant<int,long,float,double,std::string>>> &records ) -{ - if( tableColNames.size() == 0 ) throw std::runtime_error("GMDBManager::createCustomTable -- The list of columns' names is empty!!"); - if( tableColTypes.size() == 0 ) throw std::runtime_error("GMDBManager::createCustomTable -- The list of columns' types is empty!!"); - - std::string queryStr; - - std::vector<std::string> tab; - - tab.push_back(tableName); - tab.push_back( "id" ); // this is the column to store the records' IDs - for( auto& colName : tableColNames ) - tab.push_back( colName ); +// create a user-defined custom table to store auxiliary data, from +// vector<vector<variant>> +bool GMDBManager::createCustomTable( + const std::string tableName, const std::vector<std::string> tableColNames, + const std::vector<std::string> tableColTypes, + const std::vector< + std::vector<std::variant<int, long, float, double, std::string>>>& + records) { + if (tableColNames.size() == 0) + throw std::runtime_error( + "GMDBManager::createCustomTable -- The list of columns' names is " + "empty!!"); + if (tableColTypes.size() == 0) + throw std::runtime_error( + "GMDBManager::createCustomTable -- The list of columns' types is " + "empty!!"); - storeTableColumnNames(tab); + std::string queryStr; - // prepare the dynamic query to create the custom table - queryStr = fmt::format( "create table {0} ( id integer primary key ", tab[0] ); - for( size_t ii=0; ii<tableColNames.size(); ++ii) { - std::string colType = ""; - - // -- Here we check the datum's type, which is more universal than using string-encoded types - // -- but this does not work if the first entry of a given column is empty. - // -- If so, the 'null' entry is taken as string, and the column is set as containing TEXT... - // convert std::variant types to SQLite data types (see SQLite documentation) - /* - if( std::holds_alternative<int>(records[0][ii]) ) colType = "INTEGER"; - else if( std::holds_alternative<long>(records[0][ii]) ) colType = "INTEGER"; - else if( std::holds_alternative<float>(records[0][ii]) ) colType = "REAL"; - else if( std::holds_alternative<double>(records[0][ii]) ) colType = "REAL"; - else if( std::holds_alternative<std::string>(records[0][ii]) ) colType = "TEXT"; - else throw std::runtime_error("No std::variant alternative has been found!\n"); - */ - - if(tableColTypes[ii] == "INT") colType = "INTEGER"; - else if(tableColTypes[ii] == "LONG") colType = "INTEGER"; - else if(tableColTypes[ii] == "FLOAT") colType = "REAL"; - else if(tableColTypes[ii] == "DOUBLE") colType = "REAL"; - else if(tableColTypes[ii] == "STRING") colType = "TEXT"; - else throw std::runtime_error("No suitable column type has been found ==> " + tableColTypes[ii] + "\n"); - - std::string colStr = fmt::format( ", {0} {1} ", tableColNames[ii], colType ); - queryStr += colStr; - } - queryStr += ")"; - if(m_verbose>0) std::cout << "- table definition: " << queryStr << std::endl; + std::vector<std::string> tab; + + tab.push_back(tableName); + tab.push_back("id"); // this is the column to store the records' IDs + for (auto& colName : tableColNames) tab.push_back(colName); + + storeTableColumnNames(tab); + + // prepare the dynamic query to create the custom table + queryStr = + fmt::format("create table {0} ( id integer primary key ", tab[0]); + for (size_t ii = 0; ii < tableColNames.size(); ++ii) { + std::string colType = ""; + + // -- Here we check the datum's type, which is more universal than using + // string-encoded types + // -- but this does not work if the first entry of a given column is + // empty. + // -- If so, the 'null' entry is taken as string, and the column is set + // as containing TEXT... convert std::variant types to SQLite data types + // (see SQLite documentation) + /* + if( std::holds_alternative<int>(records[0][ii]) ) colType = + "INTEGER"; else if( std::holds_alternative<long>(records[0][ii]) ) + colType = "INTEGER"; else if( + std::holds_alternative<float>(records[0][ii]) ) colType = "REAL"; + else if( std::holds_alternative<double>(records[0][ii]) ) colType = + "REAL"; else if( std::holds_alternative<std::string>(records[0][ii]) ) + colType = "TEXT"; else throw std::runtime_error("No std::variant + alternative has been found!\n"); + */ + + if (tableColTypes[ii] == "INT") + colType = "INTEGER"; + else if (tableColTypes[ii] == "LONG") + colType = "INTEGER"; + else if (tableColTypes[ii] == "FLOAT") + colType = "REAL"; + else if (tableColTypes[ii] == "DOUBLE") + colType = "REAL"; + else if (tableColTypes[ii] == "STRING") + colType = "TEXT"; + else + throw std::runtime_error( + "No suitable column type has been found ==> " + + tableColTypes[ii] + "\n"); + + std::string colStr = + fmt::format(", {0} {1} ", tableColNames[ii], colType); + queryStr += colStr; + } + queryStr += ")"; + if (m_verbose > 0) + std::cout << "- table definition: " << queryStr << std::endl; - (void)execQuery(queryStr); - tab.clear(); - return addListOfRecordsToTable( tableName, records ); // needs SQLite >= 3.7.11 + (void)execQuery(queryStr); + tab.clear(); + return addListOfRecordsToTable(tableName, + records); // needs SQLite >= 3.7.11 } +bool GMDBManager::createTables() { + checkIsDBOpen(); + int rc = -1; // sqlite return code + std::string queryStr; + std::string geoNode; + std::string tableName; + std::vector<std::string> tab; + + // create a table to store the relation between the types of GeoNodes and + // the name of the table + tableName = "dbversion"; + tab.insert(tab.begin(), {tableName, "id", "version"}); + storeTableColumnNames(tab); + queryStr = + fmt::format("create table {0} ({1} integer primary key, {2} integer)", + tab[0], tab[1], tab[2]); + rc = execQuery(queryStr); + tab.clear(); + + // create a table to store the relation between the types of GeoNodes and + // the name of the table + tableName = "GeoNodesTypes"; + tab.insert(tab.begin(), {tableName, "id", "nodeType", "tableName"}); + storeTableColumnNames(tab); + queryStr = fmt::format( + "create table {0}({1} integer primary key, {2} varchar, {3} varchar)", + tab[0], tab[1], tab[2], tab[3]); + rc = execQuery(queryStr); + tab.clear(); + + // create a table to store the mother-daughter relationships between nodes + // (notably, between the [Full]PhysVols as the parents and their children) + tableName = "ChildrenPositions"; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("parentId"); + tab.push_back("parentTable"); + tab.push_back("parentCopyNumber"); + tab.push_back("position"); + tab.push_back("childTable"); + tab.push_back("childId"); + tab.push_back("childCopyNumber"); + storeTableColumnNames(tab); + queryStr = fmt::format( + "create table {0}({1} integer primary key, {2} integer, {3} integer " + "not null REFERENCES GeoNodesTypes(id), {4} integer, {5} integer, {6} " + "integer not null REFERENCES GeoNodesTypes(id), {7} integer not null, " + "{8} integer not null)", + tab[0], tab[1], tab[2], tab[3], tab[4], tab[5], tab[6], tab[7], tab[8]); + rc = execQuery(queryStr); + tab.clear(); + + // create a table to store information about the 'root' volume (also known + // as the 'world' volume) + tableName = "RootVolume"; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("volId"); + tab.push_back("volTable"); + storeTableColumnNames(tab); + queryStr = fmt::format( + "create table {0}({1} integer primary key, {2} integer not null, {3} " + "integer not null REFERENCES GeoNodesTypes(id))", + tab[0], tab[1], tab[2], tab[3]); + rc = execQuery(queryStr); + tab.clear(); + + // PhysVols table + geoNode = "GeoPhysVol"; + tableName = "PhysVols"; + m_childType_tableName[geoNode] = tableName; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("logvol"); + storeTableColumnNames(tab); + queryStr = fmt::format( + "create table {0}({1} integer primary key, {2} integer not null)", + tab[0], tab[1], tab[2]); + if (0 == (rc = execQuery(queryStr))) { + storeNodeType(geoNode, tableName); + } + tab.clear(); + + // FullPhysVols table + geoNode = "GeoFullPhysVol"; + tableName = "FullPhysVols"; + m_childType_tableName[geoNode] = tableName; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("logvol"); + storeTableColumnNames(tab); + queryStr = fmt::format( + "create table {0}({1} integer primary key, {2} integer not null)", + tab[0], tab[1], tab[2]); + if (0 == (rc = execQuery(queryStr))) { + storeNodeType(geoNode, tableName); + } + tab.clear(); + + // LogVols table + geoNode = "GeoLogVol"; + tableName = "LogVols"; + m_childType_tableName[geoNode] = tableName; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("name"); + tab.push_back("shape"); + tab.push_back("material"); + storeTableColumnNames(tab); + queryStr = fmt::format( + "create table {0}({1} integer primary key, {2} varchar, {3} integer " + "not null, {4} integer not null)", + tab[0], tab[1], tab[2], tab[3], tab[4]); + if (0 == (rc = execQuery(queryStr))) { + storeNodeType(geoNode, tableName); + } + tab.clear(); + + // Materials table + geoNode = "GeoMaterial"; + tableName = "Materials"; + m_childType_tableName[geoNode] = tableName; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("name"); + tab.push_back("density"); + tab.push_back("elements"); + storeTableColumnNames(tab); + queryStr = fmt::format( + "create table {0}({1} integer primary key, {2} varchar, {3} varchar, " + "{4} varchar)", + tab[0], tab[1], tab[2], tab[3], tab[4]); + if (0 == (rc = execQuery(queryStr))) { + storeNodeType(geoNode, tableName); + } + tab.clear(); + + // Elements table + geoNode = "GeoElement"; + tableName = "Elements"; + m_childType_tableName[geoNode] = tableName; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("name"); + tab.push_back("symbol"); + tab.push_back("Z"); + tab.push_back("A"); + storeTableColumnNames(tab); + queryStr = fmt::format( + "create table {0}({1} integer primary key, {2} varchar, {3} varchar, " + "{4} varchar, {5} varchar)", + tab[0], tab[1], tab[2], tab[3], tab[4], tab[5]); + if (0 == (rc = execQuery(queryStr))) { + storeNodeType(geoNode, tableName); + } + tab.clear(); + + // Shapes table + geoNode = "GeoShape"; + tableName = "Shapes"; + m_childType_tableName[geoNode] = tableName; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("type"); + tab.push_back("parameters"); + storeTableColumnNames(tab); + queryStr = fmt::format( + "create table {0}({1} integer primary key, {2} varchar, {3} varchar)", + tab[0], tab[1], tab[2], tab[3]); + if (0 == (rc = execQuery(queryStr))) { + storeNodeType(geoNode, tableName); + } + tab.clear(); + + // SerialDenominators table + geoNode = "GeoSerialDenominator"; + tableName = "SerialDenominators"; + m_childType_tableName[geoNode] = tableName; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("baseName"); + storeTableColumnNames(tab); + queryStr = + fmt::format("create table {0}({1} integer primary key, {2} varchar)", + tab[0], tab[1], tab[2]); + if (0 == (rc = execQuery(queryStr))) { + storeNodeType(geoNode, tableName); + } + tab.clear(); + + // SerialIdentifiers table + geoNode = "GeoSerialIdentifier"; + tableName = "SerialIdentifiers"; + m_childType_tableName[geoNode] = tableName; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("baseId"); + storeTableColumnNames(tab); + queryStr = + fmt::format("create table {0}({1} integer primary key, {2} integer)", + tab[0], tab[1], tab[2]); + if (0 == (rc = execQuery(queryStr))) { + storeNodeType(geoNode, tableName); + } + tab.clear(); + + // IdentifierTags table + geoNode = "GeoIdentifierTag"; + tableName = "IdentifierTags"; + m_childType_tableName[geoNode] = tableName; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("identifier"); + storeTableColumnNames(tab); + queryStr = + fmt::format("create table {0}({1} integer primary key, {2} integer)", + tab[0], tab[1], tab[2]); + if (0 == (rc = execQuery(queryStr))) { + storeNodeType(geoNode, tableName); + } + tab.clear(); + + // Functions table + geoNode = "Function"; + tableName = "Functions"; + m_childType_tableName[geoNode] = tableName; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("expression"); + storeTableColumnNames(tab); + queryStr = + fmt::format("create table {0}({1} integer primary key, {2} varchar)", + tab[0], tab[1], tab[2]); + if (0 == (rc = execQuery(queryStr))) { + storeNodeType(geoNode, tableName); + } + tab.clear(); + + // SerialTransformers table + geoNode = "GeoSerialTransformer"; + tableName = "SerialTransformers"; + m_childType_tableName[geoNode] = tableName; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("funcId"); + tab.push_back("volId"); + tab.push_back("volTable"); + tab.push_back("copies"); + storeTableColumnNames(tab); + queryStr = fmt::format( + "create table {0}({1} integer primary key, {2} integer not null " + "REFERENCES Functions(id), {3} integer not null, {4} integer not null " + "REFERENCES GeoNodesTypes(id), {5} integer)", + tab[0], tab[1], tab[2], tab[3], tab[4], tab[5]); + if (0 == (rc = execQuery(queryStr))) { + storeNodeType(geoNode, tableName); + } + tab.clear(); + + // Transforms table + geoNode = "GeoTransform"; + tableName = "Transforms"; + m_childType_tableName[geoNode] = tableName; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("xx"); + tab.push_back("xy"); + tab.push_back("xz"); + tab.push_back("yx"); + tab.push_back("yy"); + tab.push_back("yz"); + tab.push_back("zx"); + tab.push_back("zy"); + tab.push_back("zz"); + tab.push_back("dx"); + tab.push_back("dy"); + tab.push_back("dz"); + storeTableColumnNames(tab); + queryStr = fmt::format( + "create table {0}({1} integer primary key, {2} real, {3} real, {4} " + "real, {5} real, {6} real, {7} real, {8} real, {9} real, {10} real, " + "{11} real, {12} real, {13} real)", + tab[0], tab[1], tab[2], tab[3], tab[4], tab[5], tab[6], tab[7], tab[8], + tab[9], tab[10], tab[11], tab[12], tab[13]); + if (0 == (rc = execQuery(queryStr))) { + storeNodeType(geoNode, tableName); + } + tab.clear(); + + // Transforms table + geoNode = "GeoAlignableTransform"; + tableName = "AlignableTransforms"; + m_childType_tableName[geoNode] = tableName; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("xx"); + tab.push_back("xy"); + tab.push_back("xz"); + tab.push_back("yx"); + tab.push_back("yy"); + tab.push_back("yz"); + tab.push_back("zx"); + tab.push_back("zy"); + tab.push_back("zz"); + tab.push_back("dx"); + tab.push_back("dy"); + tab.push_back("dz"); + storeTableColumnNames(tab); + queryStr = fmt::format( + "create table {0}({1} integer primary key, {2} real, {3} real, {4} " + "real, {5} real, {6} real, {7} real, {8} real, {9} real, {10} real, " + "{11} real, {12} real, {13} real)", + tab[0], tab[1], tab[2], tab[3], tab[4], tab[5], tab[6], tab[7], tab[8], + tab[9], tab[10], tab[11], tab[12], tab[13]); + if (0 == (rc = execQuery(queryStr))) { + storeNodeType(geoNode, tableName); + } + tab.clear(); + + // NameTags table + geoNode = "GeoNameTag"; + tableName = "NameTags"; + m_childType_tableName[geoNode] = tableName; + tab.push_back(tableName); + tab.push_back("id"); + tab.push_back("name"); + storeTableColumnNames(tab); + queryStr = + fmt::format("create table {0}({1} integer primary key, {2} varchar)", + tab[0], tab[1], tab[2]); + if (0 == (rc = execQuery(queryStr))) { + storeNodeType(geoNode, tableName); + } + tab.clear(); + if (m_debug) { + std::cout << "All these tables have been successfully created:" + << std::endl; // debug + printAllDBTables(); + } - - - - - -bool GMDBManager::createTables() -{ - checkIsDBOpen(); - - int rc = -1; // sqlite return code - std::string queryStr; - - std::string geoNode; - std::string tableName; - std::vector<std::string> tab; - - // create a table to store the relation between the types of GeoNodes and the name of the table - tableName = "dbversion"; - tab.insert(tab.begin(), {tableName, "id", "version"}); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0} ({1} integer primary key, {2} integer)", tab[0], tab[1], tab[2]); - rc = execQuery(queryStr); - tab.clear(); - - // create a table to store the relation between the types of GeoNodes and the name of the table - tableName = "GeoNodesTypes"; - tab.insert(tab.begin(), {tableName, "id", "nodeType", "tableName"}); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} varchar, {3} varchar)", tab[0], tab[1], tab[2], tab[3]); - rc = execQuery(queryStr); - tab.clear(); - - // create a table to store the mother-daughter relationships between nodes (notably, between the [Full]PhysVols as the parents and their children) - tableName = "ChildrenPositions"; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("parentId"); - tab.push_back("parentTable"); - tab.push_back("parentCopyNumber"); - tab.push_back("position"); - tab.push_back("childTable"); - tab.push_back("childId"); - tab.push_back("childCopyNumber"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} integer, {3} integer not null REFERENCES GeoNodesTypes(id), {4} integer, {5} integer, {6} integer not null REFERENCES GeoNodesTypes(id), {7} integer not null, {8} integer not null)", tab[0], tab[1], tab[2], tab[3], tab[4], tab[5], tab[6], tab[7], tab[8]); - rc = execQuery(queryStr); - tab.clear(); - - // create a table to store information about the 'root' volume (also known as the 'world' volume) - tableName = "RootVolume"; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("volId"); - tab.push_back("volTable"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} integer not null, {3} integer not null REFERENCES GeoNodesTypes(id))", tab[0], tab[1], tab[2], tab[3]); - rc = execQuery(queryStr); - tab.clear(); - - // PhysVols table - geoNode = "GeoPhysVol"; - tableName = "PhysVols"; - m_childType_tableName[geoNode] = tableName; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("logvol"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} integer not null)", tab[0], tab[1], tab[2]); - if ( 0==(rc = execQuery(queryStr)) ) { - storeNodeType(geoNode, tableName); } - tab.clear(); - - // FullPhysVols table - geoNode = "GeoFullPhysVol"; - tableName = "FullPhysVols"; - m_childType_tableName[geoNode] = tableName; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("logvol"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} integer not null)", tab[0], tab[1], tab[2]); - if ( 0==(rc = execQuery(queryStr))) { - storeNodeType(geoNode, tableName); } - tab.clear(); - - // LogVols table - geoNode = "GeoLogVol"; - tableName = "LogVols"; - m_childType_tableName[geoNode] = tableName; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("name"); - tab.push_back("shape"); - tab.push_back("material"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} varchar, {3} integer not null, {4} integer not null)", tab[0], tab[1], tab[2], tab[3], tab[4]); - if ( 0==(rc = execQuery(queryStr))) { - storeNodeType(geoNode, tableName); } - tab.clear(); - - // Materials table - geoNode = "GeoMaterial"; - tableName = "Materials"; - m_childType_tableName[geoNode] = tableName; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("name"); - tab.push_back("density"); - tab.push_back("elements"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} varchar, {3} varchar, {4} varchar)", tab[0], tab[1], tab[2], tab[3], tab[4]); - if ( 0==(rc = execQuery(queryStr))) { - storeNodeType(geoNode, tableName); } - tab.clear(); - - // Elements table - geoNode = "GeoElement"; - tableName = "Elements"; - m_childType_tableName[geoNode] = tableName; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("name"); - tab.push_back("symbol"); - tab.push_back("Z"); - tab.push_back("A"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} varchar, {3} varchar, {4} varchar, {5} varchar)", tab[0], tab[1], tab[2], tab[3], tab[4], tab[5]); - if ( 0==(rc = execQuery(queryStr))) { - storeNodeType(geoNode, tableName); } - tab.clear(); - - // Shapes table - geoNode = "GeoShape"; - tableName = "Shapes"; - m_childType_tableName[geoNode] = tableName; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("type"); - tab.push_back("parameters"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} varchar, {3} varchar)", tab[0], tab[1], tab[2], tab[3]); - if ( 0==(rc = execQuery(queryStr))) { - storeNodeType(geoNode, tableName); } - tab.clear(); - - // SerialDenominators table - geoNode = "GeoSerialDenominator"; - tableName = "SerialDenominators"; - m_childType_tableName[geoNode] = tableName; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("baseName"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} varchar)", tab[0], tab[1], tab[2]); - if ( 0==(rc = execQuery(queryStr))) { - storeNodeType(geoNode, tableName); } - tab.clear(); - - // SerialIdentifiers table - geoNode = "GeoSerialIdentifier"; - tableName = "SerialIdentifiers"; - m_childType_tableName[geoNode] = tableName; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("baseId"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} integer)", tab[0], tab[1], tab[2]); - if ( 0==(rc = execQuery(queryStr))) { - storeNodeType(geoNode, tableName); } - tab.clear(); - - // IdentifierTags table - geoNode = "GeoIdentifierTag"; - tableName = "IdentifierTags"; - m_childType_tableName[geoNode] = tableName; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("identifier"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} integer)", tab[0], tab[1], tab[2]); - if ( 0==(rc = execQuery(queryStr))) { - storeNodeType(geoNode, tableName); } - tab.clear(); - - // Functions table - geoNode = "Function"; - tableName = "Functions"; - m_childType_tableName[geoNode] = tableName; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("expression"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} varchar)", tab[0], tab[1], tab[2]); - if ( 0==(rc = execQuery(queryStr))) { - storeNodeType(geoNode, tableName); } - tab.clear(); - - // SerialTransformers table - geoNode = "GeoSerialTransformer"; - tableName = "SerialTransformers"; - m_childType_tableName[geoNode] = tableName; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("funcId"); - tab.push_back("volId"); - tab.push_back("volTable"); - tab.push_back("copies"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} integer not null REFERENCES Functions(id), {3} integer not null, {4} integer not null REFERENCES GeoNodesTypes(id), {5} integer)", tab[0], tab[1], tab[2], tab[3], tab[4], tab[5]); - if ( 0==(rc = execQuery(queryStr))) { - storeNodeType(geoNode, tableName); } - tab.clear(); - - // Transforms table - geoNode = "GeoTransform"; - tableName = "Transforms"; - m_childType_tableName[geoNode] = tableName; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("xx"); - tab.push_back("xy"); - tab.push_back("xz"); - tab.push_back("yx"); - tab.push_back("yy"); - tab.push_back("yz"); - tab.push_back("zx"); - tab.push_back("zy"); - tab.push_back("zz"); - tab.push_back("dx"); - tab.push_back("dy"); - tab.push_back("dz"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} real, {3} real, {4} real, {5} real, {6} real, {7} real, {8} real, {9} real, {10} real, {11} real, {12} real, {13} real)", tab[0], tab[1], tab[2], tab[3], tab[4], tab[5], tab[6], tab[7], tab[8], tab[9], tab[10], tab[11], tab[12], tab[13]); - if ( 0==(rc = execQuery(queryStr))) { - storeNodeType(geoNode, tableName); } - tab.clear(); - - // Transforms table - geoNode = "GeoAlignableTransform"; - tableName = "AlignableTransforms"; - m_childType_tableName[geoNode] = tableName; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("xx"); - tab.push_back("xy"); - tab.push_back("xz"); - tab.push_back("yx"); - tab.push_back("yy"); - tab.push_back("yz"); - tab.push_back("zx"); - tab.push_back("zy"); - tab.push_back("zz"); - tab.push_back("dx"); - tab.push_back("dy"); - tab.push_back("dz"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} real, {3} real, {4} real, {5} real, {6} real, {7} real, {8} real, {9} real, {10} real, {11} real, {12} real, {13} real)", tab[0], tab[1], tab[2], tab[3], tab[4], tab[5], tab[6], tab[7], tab[8], tab[9], tab[10], tab[11], tab[12], tab[13]); - if ( 0==(rc = execQuery(queryStr))) { - storeNodeType(geoNode, tableName); } - tab.clear(); - - // NameTags table - geoNode = "GeoNameTag"; - tableName = "NameTags"; - m_childType_tableName[geoNode] = tableName; - tab.push_back(tableName); - tab.push_back("id"); - tab.push_back("name"); - storeTableColumnNames(tab); - queryStr = fmt::format("create table {0}({1} integer primary key, {2} varchar)", tab[0], tab[1], tab[2]); - if ( 0==(rc = execQuery(queryStr))) { - storeNodeType(geoNode, tableName); } - tab.clear(); - - if(m_debug) { - std::cout << "All these tables have been successfully created:" << std::endl; // debug - printAllDBTables(); - } - - if(rc==0) { - return true; - } - return false; + if (rc == 0) { + return true; + } + return false; } - -int GMDBManager::execQuery(std::string queryStr) -{ - if(m_debug) std::cout << "queryStr to execute: " << queryStr << std::endl; // debug - checkIsDBOpen(); - int result = -1; - if( (result = sqlite3_exec(m_d->m_dbSqlite, queryStr.c_str(), NULL, 0, &m_d->m_SQLiteErrMsg)) ) - { - printf( "[ERR] : \t> CMD: %s , Error: %d\n" , queryStr.c_str() , result ); - if ( m_d->m_SQLiteErrMsg ) - { - printf( "[ERR] : Error msg: %s\n", m_d->m_SQLiteErrMsg ); - sqlite3_free(m_d->m_SQLiteErrMsg); +int GMDBManager::execQuery(std::string queryStr) { + if (m_debug) + std::cout << "queryStr to execute: " << queryStr << std::endl; // debug + checkIsDBOpen(); + int result = -1; + if ((result = sqlite3_exec(m_d->m_dbSqlite, queryStr.c_str(), NULL, 0, + &m_d->m_SQLiteErrMsg))) { + printf("[ERR] : \t> CMD: %s , Error: %d\n", queryStr.c_str(), result); + if (m_d->m_SQLiteErrMsg) { + printf("[ERR] : Error msg: %s\n", m_d->m_SQLiteErrMsg); + sqlite3_free(m_d->m_SQLiteErrMsg); + } } - } - return result; + return result; } - - - -void GMDBManager::storeTableColumnNames(std::vector<std::string> input) -{ - if (! (input.size() == 0) ) { - std::string tabName = input.at(0); // get the first element storing the name of the table - input.erase(input.begin()); // remove the first element storing the name of the table - m_tableNames[tabName] = input; - } +void GMDBManager::storeTableColumnNames(std::vector<std::string> input) { + if (!(input.size() == 0)) { + std::string tabName = + input.at(0); // get the first element storing the name of the table + input.erase(input.begin()); // remove the first element storing the + // name of the table + m_tableNames[tabName] = input; + } } - -std::vector<std::string> GMDBManager::getTableColumnNames(const std::string &tableName) -{ - return m_tableNames.at(tableName); +std::vector<std::string> GMDBManager::getTableColumnNames( + const std::string& tableName) { + return m_tableNames.at(tableName); } -void GMDBManager::storeNodeType(std::string nodeType, std::string tableName) -{ - checkIsDBOpen(); - std::string queryStr; - sqlite3_stmt * st = nullptr; - int rc = -1; - // preparing the SQL query - std::string sql = "INSERT INTO GeoNodesTypes(nodeType, tableName) VALUES(?, ?)"; - rc = sqlite3_prepare_v2( m_d->m_dbSqlite, sql.c_str(), -1, &st, NULL); - if (rc != SQLITE_OK) { - printf( "[SQLite ERR] (%s) : Error msg: %s\n", __func__, sqlite3_errmsg(m_d->m_dbSqlite) ); - exit(EXIT_FAILURE); - } - if(m_debug) std::cout << "storeNodeType - Query string:" << sql << std::endl; // debug - // bind the parameters - rc = sqlite3_bind_text(st, 1, nodeType.c_str(), nodeType.length(), SQLITE_TRANSIENT); - rc = sqlite3_bind_text(st, 2, tableName.c_str(), tableName.length(), SQLITE_TRANSIENT); - // execute the query - rc = sqlite3_step( st ); - if (rc != SQLITE_DONE) { - printf( "[SQLite ERR] (%s) : Error msg: %s\n", __func__, sqlite3_errmsg(m_d->m_dbSqlite) ); - exit(EXIT_FAILURE); - } - // finalize - sqlite3_finalize(st); - return; +void GMDBManager::storeNodeType(std::string nodeType, std::string tableName) { + checkIsDBOpen(); + std::string queryStr; + sqlite3_stmt* st = nullptr; + int rc = -1; + // preparing the SQL query + std::string sql = + "INSERT INTO GeoNodesTypes(nodeType, tableName) VALUES(?, ?)"; + rc = sqlite3_prepare_v2(m_d->m_dbSqlite, sql.c_str(), -1, &st, NULL); + if (rc != SQLITE_OK) { + printf("[SQLite ERR] (%s) : Error msg: %s\n", __func__, + sqlite3_errmsg(m_d->m_dbSqlite)); + exit(EXIT_FAILURE); + } + if (m_debug) + std::cout << "storeNodeType - Query string:" << sql + << std::endl; // debug + // bind the parameters + rc = sqlite3_bind_text(st, 1, nodeType.c_str(), nodeType.length(), + SQLITE_TRANSIENT); + rc = sqlite3_bind_text(st, 2, tableName.c_str(), tableName.length(), + SQLITE_TRANSIENT); + // execute the query + rc = sqlite3_step(st); + if (rc != SQLITE_DONE) { + printf("[SQLite ERR] (%s) : Error msg: %s\n", __func__, + sqlite3_errmsg(m_d->m_dbSqlite)); + exit(EXIT_FAILURE); + } + // finalize + sqlite3_finalize(st); + return; } - // TODO: move to sqlite3 library -//void GMDBManager::loadTestData() +// void GMDBManager::loadTestData() //{ // // create test data // QSqlQuery q; @@ -1600,9 +1732,12 @@ void GMDBManager::storeNodeType(std::string nodeType, std::string tableName) // // qWarning() << "Sample GeoElement data --> to be implemented!"; // -// QVariant airId = addMaterial(QLatin1String("Air"),QLatin1String("density"),QLatin1String("elements")); -// QVariant ironId = addMaterial(QLatin1String("Iron"),QLatin1String("density"),QLatin1String("elements")); -// QVariant leadId = addMaterial(QLatin1String("Lead"),QLatin1String("density"),QLatin1String("elements")); +// QVariant airId = +// addMaterial(QLatin1String("Air"),QLatin1String("density"),QLatin1String("elements")); +// QVariant ironId = +// addMaterial(QLatin1String("Iron"),QLatin1String("density"),QLatin1String("elements")); +// QVariant leadId = +// addMaterial(QLatin1String("Lead"),QLatin1String("density"),QLatin1String("elements")); // // QVariant worldLogId = addLogVol(QLatin1String("WorldLog"), boxId, airId); // QVariant toyLogId = addLogVol(QLatin1String("ToyLog"), coneId, leadId); @@ -1611,94 +1746,89 @@ void GMDBManager::storeNodeType(std::string nodeType, std::string tableName) // QVariant childPhysId = addPhysVol(toyLogId, rootPhysId); //} +bool GMDBManager::storeRootVolume(const unsigned int& id, + const std::string& nodeType) { + checkIsDBOpen(); + std::string tableName = "RootVolume"; + const unsigned int typeId = getTableIdFromNodeType(nodeType); + std::vector<std::string> cols = getTableColumnNames(tableName); -bool GMDBManager::storeRootVolume(const unsigned int &id, const std::string &nodeType) -{ - checkIsDBOpen(); - - std::string tableName = "RootVolume"; - const unsigned int typeId = getTableIdFromNodeType(nodeType); - std::vector<std::string> cols = getTableColumnNames(tableName); - - // set the SQL query - std::string queryStr; - std::string sql = fmt::format("INSERT INTO {0} ({1}, {2}) VALUES (?, ?)", tableName, cols[1], cols[2]); - // preparing the SQL query - sqlite3_stmt * st = nullptr; - int rc = -1; - rc = sqlite3_prepare_v2( m_d->m_dbSqlite, sql.c_str(), -1, &st, NULL); - if (rc != SQLITE_OK) { - printf( "[SQLite ERR] (%s) : Error msg: %s\n", __func__, sqlite3_errmsg(m_d->m_dbSqlite) ); // TODO: add __func__ to all error messages, as I did here - exit(EXIT_FAILURE); - } - if(m_debug) std::cout << "Query string:" << sql << std::endl; // debug - // bind the parameters - rc = sqlite3_bind_int(st, 1, id); - rc = sqlite3_bind_int(st, 2, typeId); - // execute the query - rc = sqlite3_step( st ); - if (rc != SQLITE_DONE) { - printf( "[SQLite ERR] (%s) : Error msg: %s\n", __func__, sqlite3_errmsg(m_d->m_dbSqlite) ); - exit(EXIT_FAILURE); - } - // finalize - sqlite3_finalize(st); + // set the SQL query + std::string queryStr; + std::string sql = fmt::format("INSERT INTO {0} ({1}, {2}) VALUES (?, ?)", + tableName, cols[1], cols[2]); + // preparing the SQL query + sqlite3_stmt* st = nullptr; + int rc = -1; + rc = sqlite3_prepare_v2(m_d->m_dbSqlite, sql.c_str(), -1, &st, NULL); + if (rc != SQLITE_OK) { + printf( + "[SQLite ERR] (%s) : Error msg: %s\n", __func__, + sqlite3_errmsg(m_d->m_dbSqlite)); // TODO: add __func__ to all + // error messages, as I did here + exit(EXIT_FAILURE); + } + if (m_debug) std::cout << "Query string:" << sql << std::endl; // debug + // bind the parameters + rc = sqlite3_bind_int(st, 1, id); + rc = sqlite3_bind_int(st, 2, typeId); + // execute the query + rc = sqlite3_step(st); + if (rc != SQLITE_DONE) { + printf("[SQLite ERR] (%s) : Error msg: %s\n", __func__, + sqlite3_errmsg(m_d->m_dbSqlite)); + exit(EXIT_FAILURE); + } + // finalize + sqlite3_finalize(st); - if (rc != 0) { - return false; - } - return true; + if (rc != 0) { + return false; + } + return true; } - - -std::vector<std::string> GMDBManager::getRootPhysVol() -{ - // get the ID of the ROOT vol from the table "RootVolume" - sqlite3_stmt* stmt = m_d->selectAllFromTable("RootVolume"); - // declare the data we want to fetch - unsigned int id = 0; - unsigned int typeId = 0; - // execute the statement on all rows - int rc = -1; - while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { - // get the data - id = sqlite3_column_int(stmt, 0); - typeId = sqlite3_column_int(stmt, 1); - // TODO: fill a cache - } - if (rc != SQLITE_DONE) { - std::string errmsg(sqlite3_errmsg(m_d->m_dbSqlite)); +std::vector<std::string> GMDBManager::getRootPhysVol() { + // get the ID of the ROOT vol from the table "RootVolume" + sqlite3_stmt* stmt = m_d->selectAllFromTable("RootVolume"); + // declare the data we want to fetch + unsigned int id = 0; + unsigned int typeId = 0; + // execute the statement on all rows + int rc = -1; + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + // get the data + id = sqlite3_column_int(stmt, 0); + typeId = sqlite3_column_int(stmt, 1); + // TODO: fill a cache + } + if (rc != SQLITE_DONE) { + std::string errmsg(sqlite3_errmsg(m_d->m_dbSqlite)); + sqlite3_finalize(stmt); + throw errmsg; + } + // finalize sqlite3_finalize(stmt); - throw errmsg; - } - // finalize - sqlite3_finalize(stmt); - return getItemAndType(typeId, id); + return getItemAndType(typeId, id); } - -std::string GMDBManager::getDBFilePath() -{ - return m_dbpath; -} +std::string GMDBManager::getDBFilePath() { return m_dbpath; } // FIXME: TODO: move to an utility class int lastIndexOf(std::vector<std::string> v, std::string str, int pos = 0) { - auto it = std::find(std::next(v.rbegin(), v.size() - pos), v.rend(), str); - if (it != v.rend()) - { - auto idx = std::distance(v.begin(), it.base() - 1); -// std::cout << idx << std::endl; - return idx; - } - return -1; // no item matched + auto it = std::find(std::next(v.rbegin(), v.size() - pos), v.rend(), str); + if (it != v.rend()) { + auto idx = std::distance(v.begin(), it.base() - 1); + // std::cout << idx << std::endl; + return idx; + } + return -1; // no item matched } -int GMDBManager::getTableColIndex(const std::string &tableName, const std::string &colName) -{ - std::vector<std::string> colFields = m_tableNames.at(tableName); - return lastIndexOf(colFields, colName); +int GMDBManager::getTableColIndex(const std::string& tableName, + const std::string& colName) { + std::vector<std::string> colFields = m_tableNames.at(tableName); + return lastIndexOf(colFields, colName); } diff --git a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h index 403138e1c1b59edeccd611b34bfdf076711c79c0..1b45039c88efaf258eb1975fa94d6a29e011ec03 100644 --- a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h +++ b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h @@ -13,18 +13,21 @@ * - 2019 Feb, R.M.Bianchi * - 2020 May, R.M.Bianchi - Added parallel read * - 2020 Aug, R.M.Bianchi - Added support for reading back published nodes - * - 2021 Aug, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> - Added support GeoIdentifierTag and GeoSerialIdentifier nodes + * - 2021 Aug, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> - Added support + * GeoIdentifierTag and GeoSerialIdentifier nodes * - Jun 2022, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> - * Fixed the duplication of VPhysVol instances due to a wrong key used for caching volumes that were built already - * The copyNumber was wrongly used together with tableID and volID - * For details, see: https://gitlab.cern.ch/GeoModelDev/GeoModel/-/issues/39 + * Fixed the duplication of VPhysVol instances due to a wrong key + * used for caching volumes that were built already The copyNumber was wrongly + * used together with tableID and volID For details, see: + * https://gitlab.cern.ch/GeoModelDev/GeoModel/-/issues/39 + * - 2023 Jan, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> + * Added method to get records out of custom tables from client code. * */ #ifndef GeoModelRead_ReadGeoModel_H_ #define GeoModelRead_ReadGeoModel_H_ - // **************************************************************** // *** PERSISTIFICATION SETTINGS FOR GeoModel BOOLEAN SHAPES ****** // **************************************************************** @@ -38,28 +41,28 @@ #define _GeoShapePersistification_On_ // fwd declaration of namespace::class we want to use to persistify // the GeoModel boolean shapes -namespace GeoModelIO { class ReadGeoModel; } +namespace GeoModelIO { +class ReadGeoModel; +} // the 'Persistifier' class name is used by GeoModel boolean shapes // to grant access to friend classes typedef GeoModelIO::ReadGeoModel Persistifier; // **************************************************************** // **************************************************************** - // local includes #include "GeoModelDBManager/GMDBManager.h" #include "GeoModelKernel/GeoXF.h" // C++ includes -#include <string> -#include <set> -#include <tuple> -#include <vector> #include <deque> #include <map> +#include <set> +#include <string> +#include <tuple> #include <unordered_map> #include <unordered_set> - +#include <vector> // FWD declarations class GeoVPhysVol; @@ -80,218 +83,244 @@ class GeoGraphNode; class GeoShapeSubtraction; class GeoBox; - // type definitions -typedef const GeoXF::Function & TRANSFUNCTION; +typedef const GeoXF::Function& TRANSFUNCTION; // containers for boolean shapes' information -typedef std::tuple<unsigned int/*shape ID*/, GeoShape*, unsigned int/*opA ID*/, unsigned int/*opB ID*/> tuple_shapes_boolean_info; +typedef std::tuple<unsigned int /*shape ID*/, GeoShape*, + unsigned int /*opA ID*/, unsigned int /*opB ID*/> + tuple_shapes_boolean_info; typedef std::vector<tuple_shapes_boolean_info> type_shapes_boolean_info; - namespace GeoModelIO { class ReadGeoModel { -public: + public: + ReadGeoModel(GMDBManager* db, unsigned long* progress = nullptr); + virtual ~ReadGeoModel(); - ReadGeoModel(GMDBManager* db, unsigned long* progress = nullptr); - virtual ~ReadGeoModel(); + GeoPhysVol* buildGeoModel(); - GeoPhysVol* buildGeoModel(); + template <typename T, class N> + std::map<T, N> getPublishedNodes( + std::string publisherName = "" /*optional variable*/); - template <typename T, class N> std::map<T,N> getPublishedNodes( std::string publisherName = "" /*optional variable*/); - - void printDBTable(const std::string &tableName) { m_dbManager->printAllRecords(tableName); } + void printDBTable(const std::string& tableName) { + m_dbManager->printAllRecords(tableName); + } void printAllDBTables() { m_dbManager->printAllDBTables(); } - - -private: - - void buildAllShapes(); - void buildAllElements(); - void buildAllMaterials(); - void buildAllLogVols(); - void buildAllPhysVols(); - void buildAllFullPhysVols(); - // void buildAllFunctions(); // FIXME: - void buildAllTransforms(); - void buildAllAlignableTransforms(); - void buildAllSerialDenominators(); - void buildAllSerialIdentifiers(); - void buildAllIdentifierTags(); - void buildAllSerialTransformers(); - void buildAllNameTags(); - - - - GeoPhysVol* buildGeoModelPrivate(); - - GeoBox* buildDummyShape(); - - void loopOverAllChildrenInBunches(); - void loopOverAllChildrenRecords(std::vector<std::vector<std::string>> records); - void processParentChild(const std::vector<std::string> &parentchild); - - GeoPhysVol* getRootVolume(); - - - GeoVPhysVol* buildVPhysVolInstance(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber); - GeoVPhysVol* buildVPhysVol(const unsigned int id, const unsigned int tableId, unsigned int logVol_ID=0); - - GeoLogVol* buildLogVol(const unsigned int id); - GeoShape* buildShape(const unsigned int id, type_shapes_boolean_info* shapes_info_sub); - GeoMaterial* buildMaterial(const unsigned id); - GeoElement* buildElement(const unsigned int id); - GeoAlignableTransform* buildAlignableTransform(const unsigned int id); - GeoTransform* buildTransform(const unsigned int id); - GeoSerialTransformer* buildSerialTransformer(const unsigned int id); - TRANSFUNCTION buildFunction(const unsigned int id); - - - void checkNodePtr(GeoGraphNode* nodePtr, std::string varName="", std::string funcName="", std::string funcSignature="");//TODO: to be moved to an utility class - void volAddHelper(GeoVPhysVol* vol, GeoGraphNode* volChild); - - // methods for shapes - std::string getShapeType(const unsigned int shapeId); - bool isShapeOperator(const unsigned int shapeId); - bool isShapeOperator(const std::string type); - bool isShapeBoolean(const unsigned int shapeId); - bool isShapeBoolean(const std::string type); - void createBooleanShapeOperands(type_shapes_boolean_info* shapes_info_sub); - std::pair<unsigned int, unsigned int> getBooleanShapeOperands(const unsigned int shape); - GeoShape* addEmptyBooleanShapeForCompletion(const unsigned int shapeID, type_shapes_boolean_info* shapes_info_sub); - GeoShape* getBooleanReferencedShape(const unsigned int shapeID, type_shapes_boolean_info* shapes_info_sub); - - - // caching methods - // TODO: perhaps we could merge all those 'isBuiltYYY' methods in a single one, with the GeoModel class as a second argument ? (RMB) - bool isBuiltShape(const unsigned int id); - void storeBuiltShape(const unsigned int, GeoShape* node); - GeoShape* getBuiltShape(const unsigned int id); - - bool isBuiltTransform(const unsigned int id); - void storeBuiltTransform(GeoTransform* node); - GeoTransform* getBuiltTransform(const unsigned int id); - - bool isBuiltAlignableTransform(const unsigned int id); - void storeBuiltAlignableTransform(GeoAlignableTransform* node); - GeoAlignableTransform* getBuiltAlignableTransform(const unsigned int id); - - //void storeVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber, GeoGraphNode* node); - //GeoGraphNode* getVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber); - void storeVPhysVol(const unsigned int id, const unsigned int tableId, GeoGraphNode* node); - GeoGraphNode* getVPhysVol(const unsigned int id, const unsigned int tableId); - - bool isBuiltLog(const unsigned int id); - void storeBuiltLog(GeoLogVol* nodePtr); - GeoLogVol* getBuiltLog(const unsigned int id); - - bool isBuiltMaterial(const unsigned int id); - void storeBuiltMaterial(GeoMaterial* nodePtr); - GeoMaterial* getBuiltMaterial(const unsigned int id); - - bool isBuiltElement(const unsigned int id); - void storeBuiltElement(GeoElement* nodePtr); - GeoElement* getBuiltElement(const unsigned int id); - - bool isBuiltFunction(const unsigned int id); - //void storeBuiltFunction(const unsigned int id, GeoXF::Function* nodePtr); // TODO: implement this - //GeoXF::Function* getBuiltFunction(const unsigned int id); // TODO: implement this - - bool isBuiltPhysVol(const unsigned int id); - void storeBuiltPhysVol(GeoPhysVol* nodePtr); - GeoPhysVol* getBuiltPhysVol(const unsigned int id); - - bool isBuiltFullPhysVol(const unsigned int id); - void storeBuiltFullPhysVol(GeoFullPhysVol* nodePtr); - GeoFullPhysVol* getBuiltFullPhysVol(const unsigned int id); - - bool isBuiltSerialDenominator(const unsigned int id); - void storeBuiltSerialDenominator(GeoSerialDenominator* nodePtr); - GeoSerialDenominator* getBuiltSerialDenominator(const unsigned int id); - - bool isBuiltSerialIdentifier(const unsigned int id); - void storeBuiltSerialIdentifier(GeoSerialIdentifier* nodePtr); - GeoSerialIdentifier* getBuiltSerialIdentifier(const unsigned int id); - - bool isBuiltIdentifierTag(const unsigned int id); - void storeBuiltIdentifierTag(GeoIdentifierTag* nodePtr); - GeoIdentifierTag* getBuiltIdentifierTag(const unsigned int id); - - bool isBuiltNameTag(const unsigned int id); - void storeBuiltNameTag(GeoNameTag* nodePtr); - GeoNameTag* getBuiltNameTag(const unsigned int id); - - bool isBuiltSerialTransformer(const unsigned int id); - void storeBuiltSerialTransformer(GeoSerialTransformer* nodePtr); - GeoSerialTransformer* getBuiltSerialTransformer(const unsigned int id); - - - // Utility functions - std::string getEnvVar( std::string const & key ) const; - std::vector<std::string> splitString(const std::string& s, char delimiter); - void printStdVectorStrings(std::vector<std::string> vec); //TODO: move it to utility class - - // void printTransformationValues(QStringList t); // TODO: move to a Qt utility class - // QList<double> convertQstringListToDouble(QStringList listin); // TODO: move to a Qt utility class - // std::vector<std::string> toStdVectorStrings(QStringList qlist); // TODO: move to a Qt utility class - // QStringList toQStringList(std::vector<std::string> vec); // TODO: move to a Qt utility class - // void checkInputString(QString input); // TODO: move to an utility class - - - // input arguments - std::string _dbName; - GMDBManager* m_dbManager; - bool m_deepDebug; - bool m_debug; - bool m_timing; - bool m_runMultithreaded; - int m_runMultithreaded_nThreads; - - // callback handles - unsigned long* m_progress; - - //! containers to store the list of GeoModel nodes coming from the DB - std::vector<std::vector<std::string>> m_physVols; - std::vector<std::vector<std::string>> m_fullPhysVols; - std::vector<std::vector<std::string>> m_transforms; - std::vector<std::vector<std::string>> m_alignableTransforms; - std::vector<std::vector<std::string>> m_serialDenominators; - std::vector<std::vector<std::string>> m_serialIdentifiers; - std::vector<std::vector<std::string>> m_identifierTags; - std::vector<std::vector<std::string>> m_serialTransformers; - std::vector<std::vector<std::string>> m_nameTags; - std::vector<std::vector<std::string>> m_logVols; - std::vector<std::vector<std::string>> m_materials; - std::vector<std::vector<std::string>> m_elements; - std::vector<std::vector<std::string>> m_shapes; - std::vector<std::vector<std::string>> m_functions; - std::vector<std::vector<std::string>> m_allchildren; - - std::unordered_map<unsigned int, std::string> m_tableID_toTableName; // to look for node's type name starting from a table ID - std::unordered_map<std::string, unsigned int> m_tableName_toTableID; // to look for table ID starting from node's type name - - std::vector<std::string> m_root_vol_data; - - //! memory chaches - std::vector<GeoPhysVol*> m_memMapPhysVols; - std::vector<GeoFullPhysVol*> m_memMapFullPhysVols; - std::vector<GeoTransform*> m_memMapTransforms; - std::vector<GeoAlignableTransform*> m_memMapAlignableTransforms; - std::vector<GeoSerialDenominator*> m_memMapSerialDenominators; - std::vector<GeoSerialIdentifier*> m_memMapSerialIdentifiers; - std::vector<GeoIdentifierTag*> m_memMapIdentifierTags; - std::vector<GeoSerialTransformer*> m_memMapSerialTransformers; - std::vector<GeoNameTag*> m_memMapNameTags; - std::vector<GeoLogVol*> m_memMapLogVols; - std::vector<GeoMaterial*> m_memMapMaterials; - std::vector<GeoElement*> m_memMapElements; - // std::vector<GeoXF::Function*> m_memMapFunctions; // FIXME: - std::unordered_map<unsigned int, GeoShape*> m_memMapShapes; // we need keys, because shapes are not built following the ID order - std::unordered_map<std::string, GeoGraphNode*> m_memMap; // we need keys, to keep track of the volume's copyNumber - - //! container to store unknown shapes - std::set<std::string> m_unknown_shapes; + std::vector<std::vector<std::string>> getTableFromTableName( + std::string tableName) { + return m_dbManager->getTableRecords(tableName); + }; + + private: + void buildAllShapes(); + void buildAllElements(); + void buildAllMaterials(); + void buildAllLogVols(); + void buildAllPhysVols(); + void buildAllFullPhysVols(); + // void buildAllFunctions(); // FIXME: + void buildAllTransforms(); + void buildAllAlignableTransforms(); + void buildAllSerialDenominators(); + void buildAllSerialIdentifiers(); + void buildAllIdentifierTags(); + void buildAllSerialTransformers(); + void buildAllNameTags(); + + GeoPhysVol* buildGeoModelPrivate(); + + GeoBox* buildDummyShape(); + + void loopOverAllChildrenInBunches(); + void loopOverAllChildrenRecords( + std::vector<std::vector<std::string>> records); + void processParentChild(const std::vector<std::string>& parentchild); + + GeoPhysVol* getRootVolume(); + + GeoVPhysVol* buildVPhysVolInstance(const unsigned int id, + const unsigned int tableId, + const unsigned int copyNumber); + GeoVPhysVol* buildVPhysVol(const unsigned int id, + const unsigned int tableId, + unsigned int logVol_ID = 0); + + GeoLogVol* buildLogVol(const unsigned int id); + GeoShape* buildShape(const unsigned int id, + type_shapes_boolean_info* shapes_info_sub); + GeoMaterial* buildMaterial(const unsigned id); + GeoElement* buildElement(const unsigned int id); + GeoAlignableTransform* buildAlignableTransform(const unsigned int id); + GeoTransform* buildTransform(const unsigned int id); + GeoSerialTransformer* buildSerialTransformer(const unsigned int id); + TRANSFUNCTION buildFunction(const unsigned int id); + + void checkNodePtr(GeoGraphNode* nodePtr, std::string varName = "", + std::string funcName = "", + std::string funcSignature = + ""); // TODO: to be moved to an utility class + void volAddHelper(GeoVPhysVol* vol, GeoGraphNode* volChild); + + // methods for shapes + std::string getShapeType(const unsigned int shapeId); + bool isShapeOperator(const unsigned int shapeId); + bool isShapeOperator(const std::string type); + bool isShapeBoolean(const unsigned int shapeId); + bool isShapeBoolean(const std::string type); + void createBooleanShapeOperands(type_shapes_boolean_info* shapes_info_sub); + std::pair<unsigned int, unsigned int> getBooleanShapeOperands( + const unsigned int shape); + GeoShape* addEmptyBooleanShapeForCompletion( + const unsigned int shapeID, type_shapes_boolean_info* shapes_info_sub); + GeoShape* getBooleanReferencedShape( + const unsigned int shapeID, type_shapes_boolean_info* shapes_info_sub); + + // caching methods + // TODO: perhaps we could merge all those 'isBuiltYYY' methods in a single + // one, with the GeoModel class as a second argument ? (RMB) + bool isBuiltShape(const unsigned int id); + void storeBuiltShape(const unsigned int, GeoShape* node); + GeoShape* getBuiltShape(const unsigned int id); + + bool isBuiltTransform(const unsigned int id); + void storeBuiltTransform(GeoTransform* node); + GeoTransform* getBuiltTransform(const unsigned int id); + + bool isBuiltAlignableTransform(const unsigned int id); + void storeBuiltAlignableTransform(GeoAlignableTransform* node); + GeoAlignableTransform* getBuiltAlignableTransform(const unsigned int id); + + // void storeVPhysVol(const unsigned int id, const unsigned int tableId, + // const unsigned int copyNumber, GeoGraphNode* node); GeoGraphNode* + // getVPhysVol(const unsigned int id, const unsigned int tableId, const + // unsigned int copyNumber); + void storeVPhysVol(const unsigned int id, const unsigned int tableId, + GeoGraphNode* node); + GeoGraphNode* getVPhysVol(const unsigned int id, + const unsigned int tableId); + + bool isBuiltLog(const unsigned int id); + void storeBuiltLog(GeoLogVol* nodePtr); + GeoLogVol* getBuiltLog(const unsigned int id); + + bool isBuiltMaterial(const unsigned int id); + void storeBuiltMaterial(GeoMaterial* nodePtr); + GeoMaterial* getBuiltMaterial(const unsigned int id); + + bool isBuiltElement(const unsigned int id); + void storeBuiltElement(GeoElement* nodePtr); + GeoElement* getBuiltElement(const unsigned int id); + + bool isBuiltFunction(const unsigned int id); + // void storeBuiltFunction(const unsigned int id, GeoXF::Function* nodePtr); + // // TODO: implement this GeoXF::Function* getBuiltFunction(const unsigned + // int id); // TODO: implement this + + bool isBuiltPhysVol(const unsigned int id); + void storeBuiltPhysVol(GeoPhysVol* nodePtr); + GeoPhysVol* getBuiltPhysVol(const unsigned int id); + + bool isBuiltFullPhysVol(const unsigned int id); + void storeBuiltFullPhysVol(GeoFullPhysVol* nodePtr); + GeoFullPhysVol* getBuiltFullPhysVol(const unsigned int id); + + bool isBuiltSerialDenominator(const unsigned int id); + void storeBuiltSerialDenominator(GeoSerialDenominator* nodePtr); + GeoSerialDenominator* getBuiltSerialDenominator(const unsigned int id); + + bool isBuiltSerialIdentifier(const unsigned int id); + void storeBuiltSerialIdentifier(GeoSerialIdentifier* nodePtr); + GeoSerialIdentifier* getBuiltSerialIdentifier(const unsigned int id); + + bool isBuiltIdentifierTag(const unsigned int id); + void storeBuiltIdentifierTag(GeoIdentifierTag* nodePtr); + GeoIdentifierTag* getBuiltIdentifierTag(const unsigned int id); + + bool isBuiltNameTag(const unsigned int id); + void storeBuiltNameTag(GeoNameTag* nodePtr); + GeoNameTag* getBuiltNameTag(const unsigned int id); + + bool isBuiltSerialTransformer(const unsigned int id); + void storeBuiltSerialTransformer(GeoSerialTransformer* nodePtr); + GeoSerialTransformer* getBuiltSerialTransformer(const unsigned int id); + + // Utility functions + std::string getEnvVar(std::string const& key) const; + std::vector<std::string> splitString(const std::string& s, char delimiter); + void printStdVectorStrings( + std::vector<std::string> vec); // TODO: move it to utility class + + // void printTransformationValues(QStringList t); // TODO: move to a Qt + // utility class QList<double> convertQstringListToDouble(QStringList + // listin); // TODO: move to a Qt utility class std::vector<std::string> + // toStdVectorStrings(QStringList qlist); // TODO: move to a Qt utility + // class QStringList toQStringList(std::vector<std::string> vec); // TODO: + // move to a Qt utility class void checkInputString(QString input); // TODO: + // move to an utility class + + // input arguments + std::string _dbName; + GMDBManager* m_dbManager; + bool m_deepDebug; + bool m_debug; + bool m_timing; + bool m_runMultithreaded; + int m_runMultithreaded_nThreads; + + // callback handles + unsigned long* m_progress; + + //! containers to store the list of GeoModel nodes coming from the DB + std::vector<std::vector<std::string>> m_physVols; + std::vector<std::vector<std::string>> m_fullPhysVols; + std::vector<std::vector<std::string>> m_transforms; + std::vector<std::vector<std::string>> m_alignableTransforms; + std::vector<std::vector<std::string>> m_serialDenominators; + std::vector<std::vector<std::string>> m_serialIdentifiers; + std::vector<std::vector<std::string>> m_identifierTags; + std::vector<std::vector<std::string>> m_serialTransformers; + std::vector<std::vector<std::string>> m_nameTags; + std::vector<std::vector<std::string>> m_logVols; + std::vector<std::vector<std::string>> m_materials; + std::vector<std::vector<std::string>> m_elements; + std::vector<std::vector<std::string>> m_shapes; + std::vector<std::vector<std::string>> m_functions; + std::vector<std::vector<std::string>> m_allchildren; + + std::unordered_map<unsigned int, std::string> + m_tableID_toTableName; // to look for node's type name starting from a + // table ID + std::unordered_map<std::string, unsigned int> + m_tableName_toTableID; // to look for table ID starting from node's + // type name + + std::vector<std::string> m_root_vol_data; + + //! memory chaches + std::vector<GeoPhysVol*> m_memMapPhysVols; + std::vector<GeoFullPhysVol*> m_memMapFullPhysVols; + std::vector<GeoTransform*> m_memMapTransforms; + std::vector<GeoAlignableTransform*> m_memMapAlignableTransforms; + std::vector<GeoSerialDenominator*> m_memMapSerialDenominators; + std::vector<GeoSerialIdentifier*> m_memMapSerialIdentifiers; + std::vector<GeoIdentifierTag*> m_memMapIdentifierTags; + std::vector<GeoSerialTransformer*> m_memMapSerialTransformers; + std::vector<GeoNameTag*> m_memMapNameTags; + std::vector<GeoLogVol*> m_memMapLogVols; + std::vector<GeoMaterial*> m_memMapMaterials; + std::vector<GeoElement*> m_memMapElements; + // std::vector<GeoXF::Function*> m_memMapFunctions; // FIXME: + std::unordered_map<unsigned int, GeoShape*> + m_memMapShapes; // we need keys, because shapes are not built following + // the ID order + std::unordered_map<std::string, GeoGraphNode*> + m_memMap; // we need keys, to keep track of the volume's copyNumber + + //! container to store unknown shapes + std::set<std::string> m_unknown_shapes; }; } /* namespace GeoModelIO */ @@ -299,5 +328,4 @@ private: // include the implementation of the class' template functions #include "ReadGeoModel.tpp" - #endif /* GeoModelRead_ReadGeoModel_H_ */