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_ */