diff --git a/GeoModelIO/GeoModelCppHelpers/CMakeLists.txt b/GeoModelIO/GeoModelCppHelpers/CMakeLists.txt
index f56a3ad5349bcaa59699ee83327433a92097a247..9a8262afab2138f94ae33dee72ce09959448021e 100644
--- a/GeoModelIO/GeoModelCppHelpers/CMakeLists.txt
+++ b/GeoModelIO/GeoModelCppHelpers/CMakeLists.txt
@@ -11,7 +11,7 @@ file( GLOB HEADERS GeoModelCppHelpers/*.h )
 # Set up the library.
 add_library( GeoModelCppHelpers SHARED ${HEADERS} ${SOURCES} )
 # target_link_libraries( GeoModelCppHelpers PUBLIC
-#     GeoModelRead GeoModelWrite )
+#      GeoModelHelpers )
 
 # We link those to carry on the needed libs when including GeoModelCppHelpers,
 # even if the latter is headers only
diff --git a/GeoModelIO/GeoModelCppHelpers/GeoModelCppHelpers/GMCppHelpers.h b/GeoModelIO/GeoModelCppHelpers/GeoModelCppHelpers/GMCppHelpers.h
index 982bfcc6e5f473ba74274e05407c7dd05e668068..f928076a23b60da5967e7b05a704c03dc02200d4 100644
--- a/GeoModelIO/GeoModelCppHelpers/GeoModelCppHelpers/GMCppHelpers.h
+++ b/GeoModelIO/GeoModelCppHelpers/GeoModelCppHelpers/GMCppHelpers.h
@@ -13,11 +13,15 @@
 #ifndef GMCPPHelper_H
 #define GMCPPHelper_H
 
+
 // C++ includes
 #include <cstdlib>  // EXIT_FAILURE
 #include <fstream>
 #include <string>
 #include <sstream>
+#include <iostream>
+#include <variant> 
+#include <type_traits> 
 
 namespace GeoModelIO {
 
@@ -74,25 +78,97 @@ namespace GeoModelIO {
             return val == NULL ? std::string("") : std::string(val);
         }
 
-        static void printStdVectorVariants(const std::vector<std::variant<int, long, float, double, std::string>> vec)
-        {
-            for (const auto &item : vec)
-            {
-                if (std::holds_alternative<int>(item))
-                    std::cout << std::get<int>(item); // INT
-                else if (std::holds_alternative<long>(item))
-                    std::cout << std::get<long>(item);
-                else if (std::holds_alternative<float>(item))
-                    std::cout << std::get<float>(item);
-                else if (std::holds_alternative<double>(item))
-                    std::cout << std::get<double>(item);
-                else if (std::holds_alternative<std::string>(item))
-                    std::cout << std::get<std::string>(item);
-
-                std::cout << ", ";
-            }
-                std::cout << std::endl;
-        }
+        // static void printStdVectorVariants(const std::vector<std::variant<int, long, float, double, std::string>> vec)
+        // {
+        //     for (const auto &item : vec)
+        //     {
+        //         if (std::holds_alternative<int>(item))
+        //             std::cout << std::get<int>(item); // INT
+        //         else if (std::holds_alternative<long>(item))
+        //             std::cout << std::get<long>(item);
+        //         else if (std::holds_alternative<float>(item))
+        //             std::cout << std::get<float>(item);
+        //         else if (std::holds_alternative<double>(item))
+        //             std::cout << std::get<double>(item);
+        //         else if (std::holds_alternative<std::string>(item))
+        //             std::cout << std::get<std::string>(item);
+
+        //         std::cout << ", ";
+        //     }
+        //         std::cout << std::endl;
+        // }
+
+        // static std::string getFromVariant_String(const std::variant<int, long, float, double, std::string> &record, std::string_view logMsg = "")
+        // {
+        //     std::string_view type{"string"};
+        //     std::string ret;
+        //     try
+        //     {
+        //         ret = std::get<std::string>(record);
+        //     }
+        //     catch (std::bad_variant_access const &ex)
+        //     {
+        //         std::cout << ex.what() << ": '" << logMsg << "'  is not a 'string'!\n";
+        //     }
+        //     return ret;
+        // }
+        // static int getFromVariant_Int(const std::variant<int, long, float, double, std::string> &record, std::string_view logMsg = "")
+        // {
+        //     std::string_view type{"int"};
+        //     int ret;
+            
+        //     try
+        //     {
+        //         ret = std::get<int>(record);
+        //     }
+        //     catch (std::bad_variant_access const &ex)
+        //     {
+        //         std::cout << ex.what() << ": '" << logMsg << "'  is not a '" << type << "'!\n";
+        //     }
+        //     return ret;
+        // }
+        // static int getFromVariant_Double(const std::variant<int, long, float, double, std::string> &record, std::string_view logMsg = "")
+        // {
+        //     std::string_view type{"double"};
+        //     double ret;
+        //     try
+        //     {
+        //         ret = std::get<double>(record);
+        //     }
+        //     catch (std::bad_variant_access const &ex)
+        //     {
+        //         std::cout << ex.what() << ": '" << logMsg << "'  is not a '" << type << "'!\n";
+        //     }
+        //     return ret;
+        // }
+        // static std::string getFromVariant_Type(const std::variant<int, long, float, double, std::string> &record)
+        // {
+        //     std::string type;
+        //     if (std::holds_alternative<int>(record))
+        //     {
+        //         type = "int";
+        //     }
+        //     else if (std::holds_alternative<long>(record))
+        //     {
+        //         type = "long";
+        //     }
+        //     else if (std::holds_alternative<float>(record))
+        //     {
+        //         type = "float";
+        //     }
+        //     else if (std::holds_alternative<double>(record))
+        //     {
+        //         type = "double";
+        //     }
+        //     else if (std::holds_alternative<std::string>(record))
+        //     {
+        //         type = "string";
+        //     } else {
+        //         type = "UNKOWN";
+        //     }
+        //     std::cout << "Variant is of type '" << type << "'" << std::endl;
+        //     return type;
+        // }
     };
 } // namespace GeoModelIO
 
diff --git a/GeoModelIO/GeoModelRead/CMakeLists.txt b/GeoModelIO/GeoModelRead/CMakeLists.txt
index 904b659790da82ef70b2fda58fc6fdd750099c5a..5db6153b0611fde1effdb51928372aec6aae27c8 100644
--- a/GeoModelIO/GeoModelRead/CMakeLists.txt
+++ b/GeoModelIO/GeoModelRead/CMakeLists.txt
@@ -12,7 +12,7 @@ file( GLOB HEADERS GeoModelRead/*.h GeoModelRead/*.tpp )
 # Set up the library.
 add_library( GeoModelRead SHARED ${HEADERS} ${SOURCES} )
 target_link_libraries( GeoModelRead PUBLIC
-GeoModelKernel GeoModelDBManager TFPersistification )
+GeoModelKernel GeoModelDBManager TFPersistification GeoModelCppHelpers GeoModelHelpers )
 target_include_directories( GeoModelRead PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> )
diff --git a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
index 717c2808d7129373beaac98bb0218efda489d54a..c689d3d598793027962c1350342d7aa3d0669887 100644
--- a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
+++ b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
@@ -53,8 +53,10 @@ typedef GeoModelIO::ReadGeoModel Persistifier;
 // ****************************************************************
 // ****************************************************************
 
-// local includes
+// GeoModel includes
 #include "GeoModelDBManager/GMDBManager.h"
+#include "GeoModelDBManager/definitions.h"
+
 #include "GeoModelKernel/GeoXF.h"
 
 // C++ includes
@@ -86,6 +88,11 @@ class GeoGraphNode;
 class GeoShapeSubtraction;
 class GeoBox;
 
+class BuildGeoShapes_Box;
+class BuildGeoShapes_Tube;
+class BuildGeoShapes_Pcon;
+class BuildGeoShapes_Cons;
+
 // type definitions
 typedef const GeoXF::Function& TRANSFUNCTION;
 // containers for boolean shapes' information
@@ -94,6 +101,8 @@ typedef std::tuple<unsigned int /*shape ID*/, GeoShape*,
     tuple_shapes_boolean_info;
 typedef std::vector<tuple_shapes_boolean_info> type_shapes_boolean_info;
 
+
+
 namespace GeoModelIO {
 
 class ReadGeoModel {
@@ -156,6 +165,11 @@ class ReadGeoModel {
     };
 
    private:
+    void buildAllShapes_Box();
+    void buildAllShapes_Tube();
+    void buildAllShapes_Pcon();
+    void buildAllShapes_Cons();
+
     void buildAllShapes();
     void buildAllElements();
     void buildAllMaterials();
@@ -224,7 +238,7 @@ class ReadGeoModel {
     // 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);
+    GeoShape* getBuiltShape(const unsigned int shapeId, std::string_view shapeType = "");
 
     bool isBuiltTransform(const unsigned int id);
     void storeBuiltTransform(GeoTransform* node);
@@ -314,6 +328,14 @@ class ReadGeoModel {
     // callback handles
     unsigned long* m_progress;
 
+    //! builders
+    // std::unique_ptr<BuildGeoShapes_Box> m_builderShape_Box;
+    BuildGeoShapes_Box* m_builderShape_Box;
+    BuildGeoShapes_Tube* m_builderShape_Tube;
+    BuildGeoShapes_Pcon* m_builderShape_Pcon;
+    BuildGeoShapes_Cons* m_builderShape_Cons;
+
+
     //! 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;
@@ -324,12 +346,23 @@ class ReadGeoModel {
     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_allchildren;
 
+    // std::vector<std::vector<std::variant<int, long, float, double, std::string>>> m_logVols;
+    DBRowsList m_logVols;
+
+    // containers to store shapes' parameters
+    std::vector<std::vector<std::variant<int, long, float, double, std::string>>> m_shapes_Box;
+    std::vector<std::vector<std::variant<int, long, float, double, std::string>>> m_shapes_Tube;
+    std::vector<std::vector<std::variant<int, long, float, double, std::string>>> m_shapes_Pcon;
+    std::vector<std::vector<std::variant<int, long, float, double, std::string>>> m_shapes_Cons;
+
+    // containers to store shapes' data, for shapes with a variable number of build parameters
+    DBRowsList m_shapes_Pcon_data;
+
     // std::vector<std::vector<std::string>> m_functions;
     std::vector<std::vector<std::variant<int, long, float, double, std::string>>> m_functions;
     std::deque<double> m_funcExprData;
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes.cpp b/GeoModelIO/GeoModelRead/src/BuildGeoShapes.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f29b3fffdcd623ad5509a8ebc70e8e20b24e8cc6
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes.cpp
@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * Created on: May 7, 2024
+ * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
+ */
+
+#include "BuildGeoShapes.h"
+
+#include "GeoModelKernel/GeoShape.h"
+
+#include <vector>
+#include <iostream>
+
+BuildGeoShapes::BuildGeoShapes(std::string_view shapeType, const unsigned size)
+{
+    m_shapeType = shapeType;
+    m_memMapShapes.reserve(size);
+}
+
+BuildGeoShapes::BuildGeoShapes(std::string_view shapeType, const unsigned size, const DBRowsList shapeData)
+{
+    m_shapeType = shapeType;
+    m_memMapShapes.reserve(size);
+    m_shape_data = shapeData;
+}
+
+bool BuildGeoShapes::isBuiltShape(const unsigned id) {
+    return (!(m_memMapShapes.find(id) == m_memMapShapes.end()));
+}
+void BuildGeoShapes::storeBuiltShape(const unsigned id, GeoShape* nodePtr) {
+    m_memMapShapes[id] = nodePtr;
+}
+GeoShape* BuildGeoShapes::getBuiltShape(const unsigned id) {
+    return m_memMapShapes[id];  // this is a map, and 'id' is the key
+}
+
+void BuildGeoShapes::printBuiltShapes() {
+    for (unsigned id{1}; id<=m_memMapShapes.size(); ++id) {
+        std::cout << "shape " << m_shapeType << " -- id: " << id << ", shapePtr: " << m_memMapShapes[id] << std::endl;
+    }
+}
\ No newline at end of file
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes.h b/GeoModelIO/GeoModelRead/src/BuildGeoShapes.h
new file mode 100644
index 0000000000000000000000000000000000000000..14be15faca89de0c7782148ea5db55d997bc98fc
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes.h
@@ -0,0 +1,47 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * BuildGeoShapes.h
+ *
+ * Created on: May 7, 2024
+ * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
+ *
+ */
+
+#ifndef GEOMODELREAD_BUILDGEOSHAPES_H
+#define GEOMODELREAD_BUILDGEOSHAPES_H
+
+#include "GeoModelDBManager/definitions.h"
+
+#include <vector>
+#include <variant>
+#include <string>
+#include <unordered_map>
+
+class GeoShape;
+
+class BuildGeoShapes
+{
+protected:
+  std::unordered_map<unsigned, GeoShape *> m_memMapShapes;
+  std::string m_shapeType;
+  DBRowsList m_shape_data;
+
+public:
+  //! contructors
+  BuildGeoShapes(std::string_view shapeType, const unsigned size);
+  BuildGeoShapes(std::string_view shapeType, const unsigned size, DBRowsList shapesData);
+
+  virtual void buildShape(const std::vector<std::variant<int, long, float, double, std::string>> row) = 0;
+
+  // --- methods for caching GeoShape nodes ---
+  void storeBuiltShape(const unsigned id, GeoShape *nodePtr);
+  bool isBuiltShape(const unsigned id);
+  GeoShape *getBuiltShape(const unsigned id);
+  // --- print the list of built/cached shapes
+  void printBuiltShapes();
+};
+
+#endif
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Box.cpp b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Box.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e352753e0d1e20979711d41e701580efbb6ada14
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Box.cpp
@@ -0,0 +1,36 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * Created on: May 7, 2024
+ * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
+ */
+
+#include "BuildGeoShapes_Box.h"
+
+#include "GeoModelKernel/GeoBox.h"
+#include "GeoModelHelpers/variantHelpers.h"
+
+#include <vector>
+#include <iostream>
+
+void BuildGeoShapes_Box::buildShape(const std::vector<std::variant<int, long, float, double, std::string>> row)
+{
+    // === get shape numeric data from the DB row
+    // shape ID
+    const unsigned shapeId = GeoModelHelpers::variantHelper::getFromVariant_Int(row[0], "Tube:shapeID");
+    // shape volume
+    const double shapeVolume = GeoModelHelpers::variantHelper::getFromVariant_Double(row[1], "Tube:shapeVolume");
+    // shape parameters
+    const double XHalfLength = GeoModelHelpers::variantHelper::getFromVariant_Double(row[2], "Tube:XHalfLength");
+    const double YHalfLength = GeoModelHelpers::variantHelper::getFromVariant_Double(row[3], "Tube:YHalfLength");
+    const double ZHalfLength = GeoModelHelpers::variantHelper::getFromVariant_Double(row[4], "Tube:ZHalfLength");
+
+    GeoBox *shape = new GeoBox(XHalfLength, YHalfLength, ZHalfLength);
+
+    storeBuiltShape(shapeId, shape);
+
+    // return shape;
+    return;
+}
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Box.h b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Box.h
new file mode 100644
index 0000000000000000000000000000000000000000..1489796a32101e7401348aae023136c17c50e7bf
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Box.h
@@ -0,0 +1,28 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * BuildGeoShapes_Box.h
+ *
+ * Created on: May 7, 2024
+ * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
+ *
+ */
+
+#ifndef GEOMODELREAD_BUILDGEOSHAPES_BOX_H
+#define GEOMODELREAD_BUILDGEOSHAPES_BOX_H
+
+#include "BuildGeoShapes.h"
+
+#include <vector>
+#include <variant>
+
+class BuildGeoShapes_Box : public BuildGeoShapes
+{
+public:
+  BuildGeoShapes_Box(const unsigned size):BuildGeoShapes("Box", size){};
+  void buildShape(const std::vector<std::variant<int, long, float, double, std::string>> row) override;
+};
+
+#endif
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Cons.cpp b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Cons.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9645e2a787df403c347ff5ef693676c69baa8f4a
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Cons.cpp
@@ -0,0 +1,39 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * Created on: May 7, 2024
+ * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
+ */
+
+#include "BuildGeoShapes_Cons.h"
+
+#include "GeoModelKernel/GeoCons.h"
+#include "GeoModelHelpers/variantHelpers.h"
+
+#include <vector>
+#include <iostream>
+
+void BuildGeoShapes_Cons::buildShape(const std::vector<std::variant<int, long, float, double, std::string>> row)
+{
+    // === get shape numeric data from the DB row
+    // shape ID
+    const int shapeId = GeoModelHelpers::variantHelper::getFromVariant_Int(row[0], "Cons:shapeID");
+    // shape volume
+    const double shapeVolume = GeoModelHelpers::variantHelper::getFromVariant_Double(row[1], "Cons:shapeVolume");
+    // shape parameters
+    const double RMin1 = GeoModelHelpers::variantHelper::getFromVariant_Double(row[2], "Cons:RMin1");
+    const double RMin2 = GeoModelHelpers::variantHelper::getFromVariant_Double(row[3], "Cons:RMin2");
+    const double RMax1 = GeoModelHelpers::variantHelper::getFromVariant_Double(row[4], "Cons:RMax1");
+    const double RMax2 = GeoModelHelpers::variantHelper::getFromVariant_Double(row[4], "Cons:RMax2");
+    const double DZ = GeoModelHelpers::variantHelper::getFromVariant_Double(row[4], "Cons:DZ");
+    const double SPhi = GeoModelHelpers::variantHelper::getFromVariant_Double(row[4], "Cons:SPhi");
+    const double DPhi = GeoModelHelpers::variantHelper::getFromVariant_Double(row[4], "Cons:DPhi");
+
+    GeoCons *shape = new GeoCons(RMin1, RMin2, RMax1, RMax2, DZ, SPhi, DPhi);
+
+    storeBuiltShape(shapeId, shape);
+
+    return;
+}
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Cons.h b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Cons.h
new file mode 100644
index 0000000000000000000000000000000000000000..b54b849b4bc0b6b61661ec19a91568f13ed61a6e
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Cons.h
@@ -0,0 +1,29 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * BuildGeoShapes_Cons.h
+ *
+ * Created on: May 7, 2024
+ * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
+ *
+ */
+
+#ifndef GEOMODELREAD_BuildGeoShapes_Cons_H
+#define GEOMODELREAD_BuildGeoShapes_Cons_H
+
+#include "BuildGeoShapes.h"
+
+#include <vector>
+#include <variant>
+#include <string>
+
+class BuildGeoShapes_Cons : public BuildGeoShapes
+{
+public:
+  BuildGeoShapes_Cons(const unsigned size):BuildGeoShapes("Cons", size){};
+  void buildShape(const std::vector<std::variant<int, long, float, double, std::string>> row) override;
+};
+
+#endif
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Pcon.cpp b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Pcon.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0d9cf455f21ba566aa20f8a24d120aa185ec5ee0
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Pcon.cpp
@@ -0,0 +1,80 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * Created on: May 7, 2024
+ * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
+ */
+
+#include "BuildGeoShapes_Pcon.h"
+
+#include "GeoModelKernel/GeoPcon.h"
+#include "GeoModelHelpers/variantHelpers.h"
+#include "GeoModelHelpers/throwExcept.h"
+
+#include <vector>
+#include <iostream>
+
+void BuildGeoShapes_Pcon::buildShape(const std::vector<std::variant<int, long, float, double, std::string>> row)
+{
+    if (!(m_shape_data.size())) {
+        THROW_EXCEPTION("ERROR! GeoPcon shape has no ZPlanes data!! [m_shape_data.size() == 0]");
+    }
+
+    // === get shape numeric data from the DB row
+    // shape ID
+    const int shapeId = GeoModelHelpers::variantHelper::getFromVariant_Int(row[0], "Pcon:shapeID");
+    // shape volume
+    const double shapeVolume = GeoModelHelpers::variantHelper::getFromVariant_Double(row[1], "Pcon:shapeVolume");
+    // shape parameters
+    const double SPhi = GeoModelHelpers::variantHelper::getFromVariant_Double(row[2], "Pcon:SPhi");
+    const double DPhi = GeoModelHelpers::variantHelper::getFromVariant_Double(row[3], "Pcon:DPhi");
+    const int NZPlanes = GeoModelHelpers::variantHelper::getFromVariant_Int(row[4], "Pcon:NZPlanes");
+    // pointers to variable shape data stored in a separate table
+    const int dataStart = GeoModelHelpers::variantHelper::getFromVariant_Int(row[5], "Pcon:dataStart");
+    const int dataEnd = GeoModelHelpers::variantHelper::getFromVariant_Int(row[6], "Pcon:dataEnd");
+
+    // build the basic GeoPcon shape
+    GeoPcon *pcon = new GeoPcon(SPhi, DPhi);
+
+    // and now loop over the additional shape's data, 
+    // to get the parameters of all Z planes
+
+    // get ZPlanes' data, extract subvector
+    // NOTE: we use (dataStart-1) to cope with the difference between the DB rows starting from '1', 
+    //       which is what the 'dataStart' stores, and the vector items, which start '0'; 
+    //       also, the constructor of the sub-vector takes the element from 'begin+dataStart-1' included
+    //       and 'begin+dataEnd' excluded.
+    const DBRowsList zplanesData(m_shape_data.begin() + (dataStart-1),
+                                 m_shape_data.begin() + (dataEnd) );
+    if (!(zplanesData.size())) {
+        THROW_EXCEPTION("ERROR! GeoPcon shape ZPlanes data have not been retrieved!!");
+    }
+    if (!( NZPlanes == zplanesData.size())) {
+        THROW_EXCEPTION("ERROR! GeoPcon shape : size of ZPlanes data does not correspond to the number of ZPlanes declared!!");
+    }
+    // loop over the data defining the ZPlanes
+    for (const DBRowEntry &dataRow : zplanesData)
+    {
+        const double zpos = GeoModelHelpers::variantHelper::getFromVariant_Double(dataRow[1], "Pcon:data_ZPos");
+        const double rmin = GeoModelHelpers::variantHelper::getFromVariant_Double(dataRow[2], "Pcon:data_RMin");
+        const double rmax = GeoModelHelpers::variantHelper::getFromVariant_Double(dataRow[3], "Pcon:data_RMax");
+        // add a Z plane to the GeoPcon
+        pcon->addPlane(zpos, rmin, rmax);
+    }
+
+    // sanity checks on the resulting Pcon shape
+    if (pcon->getNPlanes() != NZPlanes)
+    {
+        THROW_EXCEPTION("ERROR! GeoPcon actual number of planes: " + std::to_string(pcon->getNPlanes()) + " is not equal to the original size! --> " + std::to_string(NZPlanes));
+    }
+    if (!pcon->isValid())
+    {
+        THROW_EXCEPTION("ERROR! GeoPcon shape is not valid!!");
+    }
+
+    storeBuiltShape(shapeId, pcon);
+
+    return;
+}
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Pcon.h b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Pcon.h
new file mode 100644
index 0000000000000000000000000000000000000000..6721ba1eab740d5eb80e435f37a0b4eee2ef5b65
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Pcon.h
@@ -0,0 +1,30 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * BuildGeoShapes_Pcon.h
+ *
+ * Created on: May 7, 2024
+ * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
+ *
+ */
+
+#ifndef GEOMODELREAD_BuildGeoShapes_Pcon_H
+#define GEOMODELREAD_BuildGeoShapes_Pcon_H
+
+#include "BuildGeoShapes.h"
+
+#include "GeoModelDBManager/definitions.h"
+
+#include <vector>
+#include <variant>
+
+class BuildGeoShapes_Pcon : public BuildGeoShapes
+{
+public:
+  BuildGeoShapes_Pcon(const unsigned size, DBRowsList shapeData):BuildGeoShapes("Pcon", size, shapeData){};
+  void buildShape(const std::vector<std::variant<int, long, float, double, std::string>> row) override;
+};
+
+#endif
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Tube.cpp b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Tube.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6897821271abee6690544a75bcd6d23758f9fc30
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Tube.cpp
@@ -0,0 +1,35 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * Created on: May 7, 2024
+ * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
+ */
+
+#include "BuildGeoShapes_Tube.h"
+
+#include "GeoModelKernel/GeoTube.h"
+#include "GeoModelHelpers/variantHelpers.h"
+
+#include <vector>
+#include <iostream>
+
+void BuildGeoShapes_Tube::buildShape(const std::vector<std::variant<int, long, float, double, std::string>> row)
+{
+    // === get shape numeric data from the DB row
+    // shape ID
+    const int shapeId = GeoModelHelpers::variantHelper::getFromVariant_Int(row[0], "Tube:shapeID");
+    // shape volume
+    const double shapeVolume = GeoModelHelpers::variantHelper::getFromVariant_Double(row[1], "Tube:shapeVolume");
+    // shape parameters
+    const double RMin = GeoModelHelpers::variantHelper::getFromVariant_Double(row[2], "Tube:RMin");
+    const double RMax = GeoModelHelpers::variantHelper::getFromVariant_Double(row[3], "Tube:RMax");
+    const double ZHalfLength = GeoModelHelpers::variantHelper::getFromVariant_Double(row[4], "Tube:ZHalfLength");
+
+    GeoTube *shape = new GeoTube(RMin, RMax, ZHalfLength);
+
+    storeBuiltShape(shapeId, shape);
+
+    return;
+}
diff --git a/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Tube.h b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Tube.h
new file mode 100644
index 0000000000000000000000000000000000000000..fa1933e12d9b1482ff242428be288b01a54f2c08
--- /dev/null
+++ b/GeoModelIO/GeoModelRead/src/BuildGeoShapes_Tube.h
@@ -0,0 +1,28 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * BuildGeoShapes_Tube.h
+ *
+ * Created on: May 7, 2024
+ * Author: Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
+ *
+ */
+
+#ifndef GEOMODELREAD_BuildGeoShapes_Tube_H
+#define GEOMODELREAD_BuildGeoShapes_Tube_H
+
+#include "BuildGeoShapes.h"
+
+#include <vector>
+#include <variant>
+
+class BuildGeoShapes_Tube : public BuildGeoShapes
+{
+public:
+  BuildGeoShapes_Tube(const unsigned size):BuildGeoShapes("Tube", size){};
+  void buildShape(const std::vector<std::variant<int, long, float, double, std::string>> row) override;
+};
+
+#endif
diff --git a/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp b/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
index b71a69fdb053398b999565132d530f1888087220..01543f9f1b0d7d73adcc6b0aaf63a6a176f9f63e 100644
--- a/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
+++ b/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
@@ -26,6 +26,11 @@
  */
 
 // local includes
+#include "BuildGeoShapes_Box.h"
+#include "BuildGeoShapes_Tube.h"
+#include "BuildGeoShapes_Pcon.h"
+#include "BuildGeoShapes_Cons.h"
+
 #include "GeoModelRead/ReadGeoModel.h"
 
 // TFPersistification includes
@@ -70,6 +75,9 @@
 #include "GeoModelKernel/GeoTwistedTrap.h"
 #include "GeoModelKernel/GeoUnidentifiedShape.h"
 
+#include "GeoModelHelpers/variantHelpers.h"
+#include "GeoModelHelpers/throwExcept.h"
+
 // Units
 #include "GeoModelKernel/Units.h"
 #define SYSTEM_OF_UNITS \
@@ -94,6 +102,8 @@
 #include <unordered_map>
 #include <unordered_set>
 #include <vector>
+#include <variant>
+#include <memory>
 
 // mutexes for synchronized access to containers and output streams in
 // multi-threading mode
@@ -162,6 +172,9 @@ ReadGeoModel::ReadGeoModel(GMDBManager* db, unsigned long* progress)
     m_dbManager->loadGeoNodeTypesAndBuildCache();
     m_dbManager->createTableDataCaches();
 
+    // prepare builders
+    // m_builderShape_Box = std::make_unique<BuildGeoShapes_Box>();
+
     // Check if the user asked for running in serial or multi-threading mode
     if ("" != getEnvVar("GEOMODEL_ENV_IO_NTHREADS")) {
         int nThreads = std::stoi(getEnvVar("GEOMODEL_ENV_IO_NTHREADS"));
@@ -201,7 +214,14 @@ ReadGeoModel::ReadGeoModel(GMDBManager* db, unsigned long* progress)
 }
 
 ReadGeoModel::~ReadGeoModel() {
-    // FIXME: some cleaning...??
+    delete m_builderShape_Box;
+    delete m_builderShape_Tube;
+    delete m_builderShape_Pcon;
+    delete m_builderShape_Cons;
+    m_builderShape_Box = nullptr;
+    m_builderShape_Tube = nullptr;
+    m_builderShape_Pcon = nullptr;
+    m_builderShape_Cons = nullptr;
 }
 
 // FIXME: TODO: move to an utility class
@@ -236,11 +256,9 @@ void ReadGeoModel::loadDB() {
     std::chrono::system_clock::time_point start =
         std::chrono::system_clock::now();  // timing: get start time
     // get all GeoModel nodes from the DB
-    m_logVols = m_dbManager->getTableFromNodeType("GeoLogVol");
     m_shapes = m_dbManager->getTableFromNodeType("GeoShape");
     m_materials = m_dbManager->getTableFromNodeType("GeoMaterial");
     m_elements = m_dbManager->getTableFromNodeType("GeoElement");
-    m_functions = m_dbManager->getTableFromNodeType_VecVecData("Function");
     m_physVols = m_dbManager->getTableFromNodeType("GeoPhysVol");
     m_fullPhysVols = m_dbManager->getTableFromNodeType("GeoFullPhysVol");
     m_transforms = m_dbManager->getTableFromNodeType("GeoTransform");
@@ -254,9 +272,25 @@ void ReadGeoModel::loadDB() {
     m_serialTransformers =
         m_dbManager->getTableFromNodeType("GeoSerialTransformer");
     m_nameTags = m_dbManager->getTableFromNodeType("GeoNameTag");
+
+    // containers to store data that have been moved to the new DB schema
+    m_functions = m_dbManager->getTableFromNodeType_VecVecData("Function");
+    m_logVols = m_dbManager->getTableFromNodeType_VecVecData("GeoLogVol");
+
+    // shapes from the new DB schema
+    m_shapes_Box = m_dbManager->getTableFromNodeType_VecVecData("GeoBox");
+    m_shapes_Tube = m_dbManager->getTableFromNodeType_VecVecData("GeoTube");
+    m_shapes_Pcon = m_dbManager->getTableFromNodeType_VecVecData("GeoPcon");
+    m_shapes_Cons = m_dbManager->getTableFromNodeType_VecVecData("GeoCons");
+    
+    // shapes' data, when needed by shapes that have variable numbers of build parameters
+    m_shapes_Pcon_data = m_dbManager->getTableFromTableName_VecVecData("Shapes_Pcon_Data");
+
     // get the Function's expression data
     // m_funcExprData = m_dbManager->getTableFromTableNameVecVecData("FuncExprData");
     m_funcExprData = m_dbManager->getTableFromTableName_DequeDouble("FuncExprData");
+    
+
     // get the children table from DB
     m_allchildren = m_dbManager->getChildrenTable();
     // get the root volume data
@@ -295,14 +329,21 @@ GeoVPhysVol* ReadGeoModel::buildGeoModelPrivate() {
 
         t8.join();  // ok, all Transforms have been built
         t9.join();  // ok, all AlignableTransforms have been built
+        
         // needs Transforms and AlignableTransforms for Shift boolean shapes
         std::thread t1(&ReadGeoModel::buildAllShapes, this);
+        std::thread t15(&ReadGeoModel::buildAllShapes_Box, this);
+        std::thread t16(&ReadGeoModel::buildAllShapes_Tube, this);
+        std::thread t17(&ReadGeoModel::buildAllShapes_Pcon, this);
+        std::thread t18(&ReadGeoModel::buildAllShapes_Cons, this);
 
         t2.join();  // ok, all Elements have been built
         // needs Elements
         std::thread t3(&ReadGeoModel::buildAllMaterials, this);
 
         t1.join();  // ok, all Shapes have been built
+        t15.join();  // ok, all Shapes-Box have been built
+        t16.join();  // ok, all Shapes-Tube have been built
         t3.join();  // ok, all Materials have been built
         // needs Shapes and Materials
         std::thread t4(&ReadGeoModel::buildAllLogVols, this);
@@ -337,6 +378,10 @@ GeoVPhysVol* ReadGeoModel::buildGeoModelPrivate() {
         buildAllIdentifierTags();
         buildAllNameTags();
         buildAllShapes();
+        buildAllShapes_Box();
+        buildAllShapes_Tube();
+        buildAllShapes_Pcon();
+        buildAllShapes_Cons();
         buildAllMaterials();
         buildAllLogVols();
         buildAllPhysVols();
@@ -419,6 +464,84 @@ void ReadGeoModel::buildAllShapes() {
     if (nSize > 0) std::cout << "All " << nSize << " Shapes have been built!\n";
 }
 
+//! Iterate over the list of shapes, build them all, and store their
+//! pointers
+void ReadGeoModel::buildAllShapes_Box()
+{
+    if (m_loglevel >= 1) {
+        std::cout << "Building all shapes -- Box ...\n";
+    }
+
+    // create a builder and reserve size of memory map
+    size_t nSize = m_shapes_Box.size();
+    m_builderShape_Box = new BuildGeoShapes_Box(nSize);
+
+    // loop over the DB rows and build the shapes
+    for (const auto &row : m_shapes_Box)
+    {
+        // GeoModelIO::CppHelper::printStdVectorVariants(row); // DEBUG MSG
+        m_builderShape_Box->buildShape(row);
+    }
+    m_builderShape_Box->printBuiltShapes(); // DEBUG MSG
+    if (nSize > 0) {
+        std::cout << "All " << nSize << " Shapes-Box have been built!\n";
+    }
+}
+//! Iterate over the list of shapes, build them all, and store their
+//! pointers
+void ReadGeoModel::buildAllShapes_Tube()
+{
+    // create a builder and reserve size of memory map
+    size_t nSize = m_shapes_Tube.size();
+    m_builderShape_Tube = new BuildGeoShapes_Tube(nSize);
+    // loop over the DB rows and build the shapes
+    for (const auto &row : m_shapes_Tube)
+    {
+        // GeoModelIO::CppHelper::printStdVectorVariants(row); // DEBUG MSG
+        m_builderShape_Tube->buildShape(row);
+    }
+    m_builderShape_Tube->printBuiltShapes(); // DEBUG MSG
+    if (nSize > 0) {
+        std::cout << "All " << nSize << " Shapes-Tube have been built!\n";
+    }
+}
+//! Iterate over the list of shapes, build them all, and store their
+//! pointers
+void ReadGeoModel::buildAllShapes_Pcon()
+{
+    // create a builder and reserve size of memory map
+    size_t nSize = m_shapes_Pcon.size();
+    m_builderShape_Pcon = new BuildGeoShapes_Pcon(nSize, m_shapes_Pcon_data);
+    // loop over the DB rows and build the shapes
+    for (const auto &row : m_shapes_Pcon)
+    {
+        // GeoModelIO::CppHelper::printStdVectorVariants(row); // DEBUG MSG
+        m_builderShape_Pcon->buildShape(row);
+    }
+    m_builderShape_Pcon->printBuiltShapes(); // DEBUG MSG
+    if (nSize > 0) {
+        std::cout << "All " << nSize << " Shapes-Pcon have been built!\n";
+    }
+}
+//! Iterate over the list of shapes, build them all, and store their
+//! pointers
+void ReadGeoModel::buildAllShapes_Cons()
+{
+    // create a builder and reserve size of memory map
+    size_t nSize = m_shapes_Cons.size();
+    m_builderShape_Cons = new BuildGeoShapes_Cons(nSize);
+    // loop over the DB rows and build the shapes
+    for (const auto &row : m_shapes_Cons)
+    {
+        // GeoModelIO::CppHelper::printStdVectorVariants(row); // DEBUG MSG
+        m_builderShape_Cons->buildShape(row);
+    }
+    m_builderShape_Cons->printBuiltShapes(); // DEBUG MSG
+    if (nSize > 0) {
+        std::cout << "All " << nSize << " Shapes-Cons have been built!\n";
+    }
+}
+
 //! Iterate over the list of GeoSerialDenominator nodes, build them all, and
 //! store their pointers
 void ReadGeoModel::buildAllSerialDenominators() {
@@ -446,8 +569,7 @@ void ReadGeoModel::buildAllSerialIdentifiers() {
     if (m_loglevel >= 1)
         std::cout << "Building all SerialIdentifier nodes...\n";
     size_t nSize = m_serialIdentifiers.size();
-    m_memMapSerialIdentifiers.reserve(
-        nSize * 2);  // TODO: check if *2 is good or redundant...
+    m_memMapSerialIdentifiers.reserve(nSize);
     for (unsigned int ii = 0; ii < nSize; ++ii) {
         // const unsigned int nodeID = std::stoi(m_seriaIdentifiers[ii][0]);
         // // RMB: not used at the moment, commented to avoid warnings
@@ -464,8 +586,7 @@ void ReadGeoModel::buildAllSerialIdentifiers() {
 void ReadGeoModel::buildAllIdentifierTags() {
     if (m_loglevel >= 1) std::cout << "Building all IdentifierTag nodes...\n";
     size_t nSize = m_identifierTags.size();
-    m_memMapIdentifierTags.reserve(
-        nSize * 2);  // TODO: check if *2 is good or redundant...
+    m_memMapIdentifierTags.reserve(nSize);
     for (unsigned int ii = 0; ii < nSize; ++ii) {
         // const unsigned int nodeID = std::stoi(m_identifierTags[ii][0]);
         // // RMB: not used at the moment, commented to avoid warnings
@@ -482,8 +603,7 @@ void ReadGeoModel::buildAllIdentifierTags() {
 void ReadGeoModel::buildAllNameTags() {
     if (m_loglevel >= 1) std::cout << "Building all NameTag nodes...\n";
     size_t nSize = m_nameTags.size();
-    m_memMapNameTags.reserve(nSize *
-                             2);  // TODO: check if *2 is good or redundant...
+    m_memMapNameTags.reserve(nSize);
     for (unsigned int ii = 0; ii < nSize; ++ii) {
         // const unsigned int nodeID = std::stoi(m_nameTags[ii][0]); // RMB:
         // not used at teh moment, commented to avoid warnings
@@ -499,8 +619,7 @@ void ReadGeoModel::buildAllNameTags() {
 void ReadGeoModel::buildAllElements() {
     if (m_loglevel >= 1) std::cout << "Building all Elements...\n";
     size_t nSize = m_elements.size();
-    m_memMapElements.reserve(nSize *
-                             2);  // TODO: check if *2 is good or redundant...
+    m_memMapElements.reserve(nSize);
     for (unsigned int ii = 0; ii < nSize; ++ii) {
         const unsigned int nodeID = std::stoi(m_elements[ii][0]);
         buildElement(nodeID);  // nodes' IDs start from 1
@@ -513,8 +632,7 @@ void ReadGeoModel::buildAllElements() {
 void ReadGeoModel::buildAllMaterials() {
     if (m_loglevel >= 1) std::cout << "Building all Materials...\n";
     size_t nSize = m_materials.size();
-    m_memMapMaterials.reserve(nSize *
-                              2);  // TODO: check if *2 is good or redundant...
+    m_memMapMaterials.reserve(nSize);
     for (unsigned int ii = 0; ii < nSize; ++ii) {
         const unsigned int nodeID = std::stoi(m_materials[ii][0]);
         buildMaterial(nodeID);  // nodes' IDs start from 1
@@ -524,14 +642,23 @@ void ReadGeoModel::buildAllMaterials() {
 }
 
 //! Iterate over the list of nodes, build them all, and store their pointers
-void ReadGeoModel::buildAllLogVols() {
-    if (m_loglevel >= 1) std::cout << "Building all LogVols...\n";
+void ReadGeoModel::buildAllLogVols()
+{
+    if (m_loglevel >= 1)
+        std::cout << "Building all LogVols...\n";
     size_t nSize = m_logVols.size();
-    m_memMapLogVols.reserve(nSize *
-                            2);  // TODO: check if *2 is good or redundant...
-    for (unsigned int ii = 0; ii < nSize; ++ii) {
-        const unsigned int nodeID = std::stoi(m_logVols[ii][0]);
-        buildLogVol(nodeID);
+    m_memMapLogVols.reserve(nSize);
+    for (unsigned int ii = 0; ii < nSize; ++ii)
+    {
+        try
+        {
+            const unsigned int nodeID = std::get<int>(m_logVols[ii][0]);
+            buildLogVol(nodeID);
+        }
+        catch (std::bad_variant_access const &ex)
+        {
+            std::cout << ex.what() << ": logVol 'ID' is not an 'int' value!\n";
+        }
     }
     if (nSize > 0)
         std::cout << "All " << nSize << " LogVols have been built!\n";
@@ -555,8 +682,7 @@ void ReadGeoModel::buildAllPhysVols() {
     }
     const unsigned int tableID = m_tableName_toTableID["GeoPhysVol"];
     size_t nSize = m_physVols.size();
-    m_memMapPhysVols.reserve(nSize *
-                             2);  // TODO: check if *2 is good or redundant...
+    m_memMapPhysVols.reserve(nSize);
     for (unsigned int ii = 0; ii < nSize; ++ii) {
         const unsigned int volID = std::stoi(m_physVols[ii][0]);
         const unsigned int logVolID = std::stoi(m_physVols[ii][1]);
@@ -573,8 +699,7 @@ void ReadGeoModel::buildAllFullPhysVols() {
     if (m_debug) std::cout << "Building all FullPhysVols...\n";
     const unsigned int tableID = m_tableName_toTableID["GeoFullPhysVol"];
     size_t nSize = m_fullPhysVols.size();
-    m_memMapFullPhysVols.reserve(
-        nSize * 2);  // TODO: check if *2 is good or redundant...
+    m_memMapFullPhysVols.reserve(nSize);
     for (unsigned int ii = 0; ii < nSize; ++ii) {
         const unsigned int volID = std::stoi(m_fullPhysVols[ii][0]);
         const unsigned int logVolID = std::stoi(m_fullPhysVols[ii][1]);
@@ -591,8 +716,7 @@ void ReadGeoModel::buildAllFullPhysVols() {
 void ReadGeoModel::buildAllAlignableTransforms() {
     if (m_debug) std::cout << "Building all AlignableTransforms...\n";
     size_t nSize = m_alignableTransforms.size();
-    m_memMapAlignableTransforms.reserve(
-        nSize * 2);  // TODO: check if *2 is good or redundant...
+    m_memMapAlignableTransforms.reserve(nSize);
     for (unsigned int ii = 0; ii < nSize; ++ii) {
         const unsigned int volID = std::stoi(m_alignableTransforms[ii][0]);
         buildAlignableTransform(volID);
@@ -607,8 +731,7 @@ void ReadGeoModel::buildAllAlignableTransforms() {
 void ReadGeoModel::buildAllTransforms() {
     if (m_debug) std::cout << "Building all Transforms...\n";
     size_t nSize = m_transforms.size();
-    m_memMapTransforms.reserve(nSize *
-                               2);  // TODO: check if *2 is good or redundant...
+    m_memMapTransforms.reserve(nSize);
     for (unsigned int ii = 0; ii < nSize; ++ii) {
         const unsigned int volID = std::stoi(m_transforms[ii][0]);
         buildTransform(volID);
@@ -622,8 +745,7 @@ void ReadGeoModel::buildAllTransforms() {
 void ReadGeoModel::buildAllSerialTransformers() {
     if (m_debug) std::cout << "Building all SerialTransformers...\n";
     size_t nSize = m_serialTransformers.size();
-    m_memMapSerialTransformers.reserve(
-        nSize * 2);  // TODO: check if 2 is good or redundant...
+    m_memMapSerialTransformers.reserve(nSize);
     for (unsigned int ii = 0; ii < nSize; ++ii) {
         const unsigned int volID = std::stoi(m_serialTransformers[ii][0]);
         buildSerialTransformer(volID);
@@ -1301,6 +1423,7 @@ std::string ReadGeoModel::getShapeType(const unsigned int shapeId) {
     return type;
 }
 
+
 // TODO: move shapes in different files, so code here is more managable
 /// Recursive function, to build GeoShape nodes
 GeoShape* ReadGeoModel::buildShape(const unsigned int shapeId,
@@ -1330,7 +1453,9 @@ GeoShape* ReadGeoModel::buildShape(const unsigned int shapeId,
 
     GeoShape* shape = nullptr;
 
-    if (type == "Box") {
+    if (false) {
+    } 
+    else if (type == "Box") {
         // shape parameters
         double XHalfLength = 0.;
         double YHalfLength = 0.;
@@ -1348,38 +1473,40 @@ GeoShape* ReadGeoModel::buildShape(const unsigned int shapeId,
                 ZHalfLength = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
         }
         shape = new GeoBox(XHalfLength, YHalfLength, ZHalfLength);
-    } else if (type == "Cons") {
-        // shape parameters
-        double RMin1 = 0.;
-        double RMin2 = 0.;
-        double RMax1 = 0.;
-        double RMax2 = 0.;
-        double DZ = 0.;
-        double SPhi = 0.;
-        double DPhi = 0.;
-        // get parameters from DB string
-        for (auto& par : shapePars) {
-            std::vector<std::string> vars = splitString(par, '=');
-            std::string varName = vars[0];
-            std::string varValue = vars[1];
-            // std::cout << "varValue Cons:" << varValue;
-            if (varName == "RMin1")
-                RMin1 = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
-            if (varName == "RMin2")
-                RMin2 = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
-            if (varName == "RMax1")
-                RMax1 = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
-            if (varName == "RMax2")
-                RMax2 = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
-            if (varName == "DZ")
-                DZ = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
-            if (varName == "SPhi")
-                SPhi = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
-            if (varName == "DPhi")
-                DPhi = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
-        }
-        shape = new GeoCons(RMin1, RMin2, RMax1, RMax2, DZ, SPhi, DPhi);
-    } else if (type == "Torus") {
+    } 
+    // else if (type == "Cons") {
+    //     // shape parameters
+    //     double RMin1 = 0.;
+    //     double RMin2 = 0.;
+    //     double RMax1 = 0.;
+    //     double RMax2 = 0.;
+    //     double DZ = 0.;
+    //     double SPhi = 0.;
+    //     double DPhi = 0.;
+    //     // get parameters from DB string
+    //     for (auto& par : shapePars) {
+    //         std::vector<std::string> vars = splitString(par, '=');
+    //         std::string varName = vars[0];
+    //         std::string varValue = vars[1];
+    //         // std::cout << "varValue Cons:" << varValue;
+    //         if (varName == "RMin1")
+    //             RMin1 = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
+    //         if (varName == "RMin2")
+    //             RMin2 = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
+    //         if (varName == "RMax1")
+    //             RMax1 = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
+    //         if (varName == "RMax2")
+    //             RMax2 = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
+    //         if (varName == "DZ")
+    //             DZ = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
+    //         if (varName == "SPhi")
+    //             SPhi = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
+    //         if (varName == "DPhi")
+    //             DPhi = std::stod(varValue);  // * SYSTEM_OF_UNITS::mm;
+    //     }
+    //     shape = new GeoCons(RMin1, RMin2, RMax1, RMax2, DZ, SPhi, DPhi);
+    // } 
+    else if (type == "Torus") {
         // Member Data:
         // * Rmax - outside radius of the torus tube
         // * Rmin - inside radius  of the torus tube (Rmin=0 if not hollow)
@@ -1439,127 +1566,129 @@ GeoShape* ReadGeoModel::buildShape(const unsigned int shapeId,
         }
         shape = new GeoPara(XHalfLength, YHalfLength, ZHalfLength, Alpha, Theta,
                             Phi);
-    } else if (type == "Pcon") {
-        // shape parameters
-        double SPhi = 0.;
-        double DPhi = 0.;
-        unsigned int NZPlanes = 0;
-
-        bool error = 0;
-        std::string par;
-        std::vector<std::string> vars;
-        std::string varName;
-        std::string varValue;
-
-        GeoPcon* pcon = nullptr;
-
-        int sizePars = shapePars.size();
-        // check if we have more than 3 parameters
-        if (sizePars > 3) {
-            // get the three first GeoPcon parameters: the SPhi and DPhi angles,
-            // plus the number of Z planes
-            for (int it = 0; it < 3; it++) {
-                par = shapePars[it];
-                vars = splitString(par, '=');
-                varName = vars[0];
-                varValue = vars[1];
-                if (varName == "SPhi") SPhi = std::stod(varValue);
-                if (varName == "DPhi") DPhi = std::stod(varValue);
-                if (varName == "NZPlanes") NZPlanes = std::stoi(varValue);
-            }
-            // build the basic GeoPcon shape
-            pcon = new GeoPcon(SPhi, DPhi);
-
-            // and now loop over the rest of the list, to get the parameters of
-            // all Z planes
-            for (int it = 3; it < sizePars; it++) {
-                par = shapePars[it];
-                vars = splitString(par, '=');
-                varName = vars[0];
-                varValue = vars[1];
-
-                if (varName == "ZPos") {
-                    double zpos = std::stod(varValue);
-                    double rmin = 0., rmax = 0.;
-
-                    it++;  // go to next variable
-
-                    par = shapePars[it];
-                    vars = splitString(par, '=');
-                    varName = vars[0];
-                    varValue = vars[1];
-                    if (varName == "ZRmin")
-                        rmin = std::stod(varValue);
-                    else
-                        error = 1;
-                    it++;  // go to next variable
-
-                    par = shapePars[it];
-                    vars = splitString(par, '=');
-                    varName = vars[0];
-                    varValue = vars[1];
-                    if (varName == "ZRmax")
-                        rmax = std::stod(varValue);
-                    else
-                        error = 1;
-
-                    if (error) {
-                        muxCout.lock();
-                        std::cout << "ERROR! GeoPcon 'ZRmin' and 'ZRmax' "
-                                     "values are not at the right place! --> ";
-                        printStdVectorStrings(shapePars);
-                        muxCout.unlock();
-                    }
-
-                    // add a Z plane to the GeoPcon
-                    pcon->addPlane(zpos, rmin, rmax);
-                } else {
-                    error = 1;
-                    muxCout.lock();
-                    std::cout << "ERROR! GeoPcon 'ZPos' value is not at the "
-                                 "right place! --> ";
-                    printStdVectorStrings(shapePars);
-                    muxCout.unlock();
-                }
-            }
-
-            // sanity check on the resulting Pcon shape
-            if (pcon->getNPlanes() != NZPlanes) {
-                error = 1;
-                muxCout.lock();
-                std::cout << "ERROR! GeoPcon number of planes: "
-                          << pcon->getNPlanes()
-                          << " is not equal to the original size! --> ";
-                printStdVectorStrings(shapePars);
-                muxCout.unlock();
-            }
-            if (!pcon->isValid()) {
-                error = 1;
-                muxCout.lock();
-                std::cout << "ERROR! GeoPcon shape is not valid!! -- input: ";
-                printStdVectorStrings(shapePars);
-                muxCout.unlock();
-            }
-        }  // end if (size>3)
-        else {
-            muxCout.lock();
-            std::cout << "ERROR!! GeoPcon has no Z planes!! --> shape input "
-                         "parameters: ";
-            printStdVectorStrings(shapePars);
-            muxCout.unlock();
-            error = 1;
-        }
-
-        if (error) {
-            muxCout.lock();
-            std::cout << "FATAL ERROR!!! - GeoPcon shape error!!! Aborting..."
-                      << std::endl;
-            muxCout.unlock();
-            exit(EXIT_FAILURE);
-        }
-
-        shape = pcon;
-    } else if (type == "Pgon") {
+    } 
+    // else if (type == "Pcon") {
+        // // shape parameters
+        // double SPhi = 0.;
+        // double DPhi = 0.;
+        // unsigned int NZPlanes = 0;
+
+        // bool error = 0;
+        // std::string par;
+        // std::vector<std::string> vars;
+        // std::string varName;
+        // std::string varValue;
+
+        // GeoPcon* pcon = nullptr;
+
+        // int sizePars = shapePars.size();
+        // // check if we have more than 3 parameters
+        // if (sizePars > 3) {
+        //     // get the three first GeoPcon parameters: the SPhi and DPhi angles,
+        //     // plus the number of Z planes
+        //     for (int it = 0; it < 3; it++) {
+        //         par = shapePars[it];
+        //         vars = splitString(par, '=');
+        //         varName = vars[0];
+        //         varValue = vars[1];
+        //         if (varName == "SPhi") SPhi = std::stod(varValue);
+        //         if (varName == "DPhi") DPhi = std::stod(varValue);
+        //         if (varName == "NZPlanes") NZPlanes = std::stoi(varValue);
+        //     }
+        //     // build the basic GeoPcon shape
+        //     pcon = new GeoPcon(SPhi, DPhi);
+
+        //     // and now loop over the rest of the list, to get the parameters of
+        //     // all Z planes
+        //     for (int it = 3; it < sizePars; it++) {
+        //         par = shapePars[it];
+        //         vars = splitString(par, '=');
+        //         varName = vars[0];
+        //         varValue = vars[1];
+
+        //         if (varName == "ZPos") {
+        //             double zpos = std::stod(varValue);
+        //             double rmin = 0., rmax = 0.;
+
+        //             it++;  // go to next variable
+
+        //             par = shapePars[it];
+        //             vars = splitString(par, '=');
+        //             varName = vars[0];
+        //             varValue = vars[1];
+        //             if (varName == "ZRmin")
+        //                 rmin = std::stod(varValue);
+        //             else
+        //                 error = 1;
+        //             it++;  // go to next variable
+
+        //             par = shapePars[it];
+        //             vars = splitString(par, '=');
+        //             varName = vars[0];
+        //             varValue = vars[1];
+        //             if (varName == "ZRmax")
+        //                 rmax = std::stod(varValue);
+        //             else
+        //                 error = 1;
+
+        //             if (error) {
+        //                 muxCout.lock();
+        //                 std::cout << "ERROR! GeoPcon 'ZRmin' and 'ZRmax' "
+        //                              "values are not at the right place! --> ";
+        //                 printStdVectorStrings(shapePars);
+        //                 muxCout.unlock();
+        //             }
+
+        //             // add a Z plane to the GeoPcon
+        //             pcon->addPlane(zpos, rmin, rmax);
+        //         } else {
+        //             error = 1;
+        //             muxCout.lock();
+        //             std::cout << "ERROR! GeoPcon 'ZPos' value is not at the "
+        //                          "right place! --> ";
+        //             printStdVectorStrings(shapePars);
+        //             muxCout.unlock();
+        //         }
+        //     }
+
+        //     // sanity check on the resulting Pcon shape
+        //     if (pcon->getNPlanes() != NZPlanes) {
+        //         error = 1;
+        //         muxCout.lock();
+        //         std::cout << "ERROR! GeoPcon number of planes: "
+        //                   << pcon->getNPlanes()
+        //                   << " is not equal to the original size! --> ";
+        //         printStdVectorStrings(shapePars);
+        //         muxCout.unlock();
+        //     }
+        //     if (!pcon->isValid()) {
+        //         error = 1;
+        //         muxCout.lock();
+        //         std::cout << "ERROR! GeoPcon shape is not valid!! -- input: ";
+        //         printStdVectorStrings(shapePars);
+        //         muxCout.unlock();
+        //     }
+        // }  // end if (size>3)
+        // else {
+        //     muxCout.lock();
+        //     std::cout << "ERROR!! GeoPcon has no Z planes!! --> shape input "
+        //                  "parameters: ";
+        //     printStdVectorStrings(shapePars);
+        //     muxCout.unlock();
+        //     error = 1;
+        // }
+
+        // if (error) {
+        //     muxCout.lock();
+        //     std::cout << "FATAL ERROR!!! - GeoPcon shape error!!! Aborting..."
+        //               << std::endl;
+        //     muxCout.unlock();
+        //     exit(EXIT_FAILURE);
+        // }
+
+        // shape = pcon;
+    // } 
+    else if (type == "Pgon") {
         // shape parameters
         double SPhi = 0.;
         double DPhi = 0.;
@@ -3005,23 +3134,24 @@ GeoLogVol* ReadGeoModel::buildLogVol(const unsigned int id) {
     }
 
     // get logVol properties from the DB
-    std::vector<std::string> values = m_logVols[id - 1];
-
-    // get the parameters to build the GeoLogVol node
-    std::string logVolName = values[1];
-
-    // build the referenced GeoShape node
-    const unsigned int shapeId = std::stoi(values[2]);
-    GeoShape* shape = getBuiltShape(shapeId);
+    // std::vector<std::string> values = m_logVols[id - 1];
+    DBRowEntry values = m_logVols[id - 1];
+
+    // --- get the parameters to build the GeoLogVol node
+    // get the name of the LogVol
+    const std::string logVolName = GeoModelHelpers::variantHelper::getFromVariant_String(values[1], "LogVol_name");
+    // get the ID and the type of the referenced GeoShape node
+    const int shapeId = GeoModelHelpers::variantHelper::getFromVariant_Int(values[2], "LogVol_shapeID");
+    const std::string shapeType = GeoModelHelpers::variantHelper::getFromVariant_String(values[3], "LogVol_shapeType");
+    GeoShape* shape = getBuiltShape(shapeId, shapeType);
     if (!shape) {
-        std::cout
-            << "ERROR!! While building a LogVol, Shape is NULL! Exiting..."
-            << std::endl;
-        exit(EXIT_FAILURE);
+            THROW_EXCEPTION("ERROR!! While building a LogVol, Shape of type '" + shapeType + "' is NULL! Exiting...");
     }
 
     // build the referenced GeoMaterial node
-    const unsigned int matId = std::stoi(values[3]);
+    // const unsigned int matId = std::stoi(values[3]);
+    const int matId = GeoModelHelpers::variantHelper::getFromVariant_Int(values[4], "LogVol_MaterialID");
+
     if (m_loglevel >= 2) {
         muxCout.lock();
         std::cout << "buildLogVol() - material Id:" << matId << std::endl;
@@ -3029,10 +3159,7 @@ GeoLogVol* ReadGeoModel::buildLogVol(const unsigned int id) {
     }
     GeoMaterial* mat = getBuiltMaterial(matId);
     if (!mat) {
-        std::cout
-            << "ERROR!! While building a LogVol, Material is NULL! Exiting..."
-            << std::endl;
-        exit(EXIT_FAILURE);
+            THROW_EXCEPTION("ERROR!! While building a LogVol, Material of ID '" + std::to_string(matId) + "' is NULL! Exiting...");
     }
 
     GeoLogVol* logPtr = new GeoLogVol(logVolName, shape, mat);
@@ -3046,6 +3173,7 @@ GeoLogVol* ReadGeoModel::buildLogVol(const unsigned int id) {
     return logPtr;
 }
 
+
 //// TODO: should go in a QtUtils header-only class, to be used in other
 /// packages
 // QList<double> ReadGeoModel::convertQstringListToDouble(QStringList listin) {
@@ -3231,15 +3359,17 @@ TRANSFUNCTION ReadGeoModel::buildFunction(const unsigned int id) {
 
     if (0 == expr.size()) {
         muxCout.lock();
-        std::cout << "FATAL ERROR!! Function expression is empty!! Aborting..."
-                  << std::endl;
+        THROW_EXCEPTION("FATAL ERROR!! Function expression is empty!! Aborting...");
         muxCout.unlock();
-        exit(EXIT_FAILURE);
     }
 
     // get exprData, extract subvector
-    std::deque<double> sub_vector(m_funcExprData.begin() + dataStart,
-                           m_funcExprData.begin() + dataEnd);
+    // NOTE: we use (dataStart-1) to cope with the difference between the DB rows starting from '1', 
+    //       which is what the 'dataStart' stores, and the vector items, which start '0'; 
+    //       also, the constructor of the sub-vector takes the element from 'begin+dataStart-1' included
+    //       and 'begin+dataEnd' excluded.
+    std::deque<double> sub_vector(m_funcExprData.begin() + (dataStart-1),
+                           m_funcExprData.begin() + (dataEnd) );
 
     TransFunctionInterpreter interpreter;
     TFPTR func = interpreter.interpret(expr, &sub_vector);
@@ -3269,8 +3399,35 @@ bool ReadGeoModel::isBuiltShape(const unsigned int id) {
 void ReadGeoModel::storeBuiltShape(const unsigned int id, GeoShape* nodePtr) {
     m_memMapShapes[id] = nodePtr;
 }
-GeoShape* ReadGeoModel::getBuiltShape(const unsigned int id) {
-    return m_memMapShapes[id];  // this is a map, and 'id' is the key
+GeoShape *ReadGeoModel::getBuiltShape(const unsigned int shapeId, std::string_view shapeType)
+{
+
+    const std::set<std::string> shapesNewDB{"Box", "Tube", "Pcon", "Cons"};
+    // get shape parameters
+    if (std::count(shapesNewDB.begin(), shapesNewDB.end(), shapeType))
+    {
+        if ("Box" == shapeType)
+        {
+            return m_builderShape_Box->getBuiltShape(shapeId);
+        }
+        else if ("Tube" == shapeType)
+        {
+            return m_builderShape_Tube->getBuiltShape(shapeId);
+        }
+        else if ("Pcon" == shapeType)
+        {
+            return m_builderShape_Pcon->getBuiltShape(shapeId);
+        } 
+        else if ("Cons" == shapeType)
+        {
+            return m_builderShape_Cons->getBuiltShape(shapeId);
+        } 
+        else {
+            THROW_EXCEPTION("ERROR!!! Shape '" + std::string(shapeType) + "' is not handled correctly!");
+        }
+    }
+    std::cout << "WARNING! For the shape '" << shapeType << "' we're using the old DB schema..." << std::endl;
+    return m_memMapShapes[shapeId]; // this is a map, and 'id' is the key
 }
 
 // --- methods for caching GeoLogVol nodes ---