diff --git a/tangostationcontrol/tangostationcontrol/toolkit/archiver.py b/tangostationcontrol/tangostationcontrol/toolkit/archiver.py
index 6c0cd3baa8e2c708d39858191bc56e73e84a9eff..0de191499b9700c725885b645faa1a339c4d3bc6 100644
--- a/tangostationcontrol/tangostationcontrol/toolkit/archiver.py
+++ b/tangostationcontrol/tangostationcontrol/toolkit/archiver.py
@@ -1,6 +1,5 @@
 #! /usr/bin/env python3
 
-#from logging import raiseExceptions
 import logging
 
 from tango import DeviceProxy, AttributeProxy
@@ -11,7 +10,8 @@ import json, os
 from sqlalchemy import create_engine, and_
 from sqlalchemy.orm import sessionmaker
 from sqlalchemy.orm.exc import NoResultFound
-from .archiver_base import *
+import importlib
+import numpy as np
 
 logger = logging.getLogger()
 
@@ -52,7 +52,7 @@ class Archiver():
     dev_polling_time = None
     dev_archive_time = None
 
-    def __init__(self, selector_filename:str = None, cm_name: str = 'archiving/hdbpp/confmanager01', context: str = 'RUN'):
+    def __init__(self, selector_filename:str = None, cm_name: str = 'archiving/hdbppts/confmanager01', context: str = 'RUN'):
         self.cm_name = cm_name
         self.cm = DeviceProxy(cm_name)
         try: 
@@ -468,16 +468,19 @@ class Retriever():
     """
     The Retriever class implements retrieve operations on a given DBMS
     """
-    def __init__(self, cm_name: str = 'archiving/hdbpp/confmanager01'):
+    def __init__(self, cm_name: str = 'archiving/hdbppts/confmanager01'):
         self.cm_name = cm_name
-        self.session = self.connect_to_archiving_db()
+        self.session, self.dbms = self.connect_to_archiving_db()
+        self.ab = self.set_archiver_base()
+        
     
     def get_db_credentials(self):
         """
         Retrieves the DB credentials from the Tango properties of Configuration Manager
         """
         cm = DeviceProxy(self.cm_name)
-        config_list = cm.get_property('LibConfiguration')['LibConfiguration'] # dictionary {'LibConfiguration': list of strings}
+        config_list = list(cm.get_property('LibConfiguration')['LibConfiguration']) # dictionary {'LibConfiguration': list of strings}
+        if 'connect_string=' in config_list[0]: config_list.pop(0)  # possibly remove connect string because it causes errors
         host = str([s for s in config_list if "host" in s][0].split('=')[1])
         dbname = str([s for s in config_list if "dbname" in s][0].split('=')[1])
         port = str([s for s in config_list if "port" in s][0].split('=')[1])
@@ -490,15 +493,34 @@ class Retriever():
         Returns a session to a MySQL DBMS using default credentials.
         """
         host,dbname,port,user,pw = self.get_db_credentials()
-        engine = create_engine('mysql+pymysql://'+user+':'+pw+'@'+host+':'+port+'/'+dbname)
+        # Set sqlalchemy library connection
+        if host=='archiver-maria-db':
+            libname = 'mysql+pymysql' 
+            dbms = 'mysql'         
+        elif host=='archiver-timescale':
+            libname = 'postgresql+psycopg2'
+            dbms = 'postgres'
+        else:
+            raise Exception(f"Invalid hostname! {host}")
+        engine = create_engine(libname+'://'+user+':'+pw+'@'+host+':'+port+'/'+dbname)
         Session = sessionmaker(bind=engine)
-        return Session()
+        return Session(),dbms
+    
+    def set_archiver_base(self):
+        """
+        Sets the right mapper class following the DBMS connection
+        """
+        if self.dbms == 'postgres':
+            ab = importlib.import_module('.archiver_base_ts', package=__package__)
+        elif self.dbms == 'mysql':
+            ab = importlib.import_module('.archiver_base_mysql', package=__package__)
+        return ab
 
     def get_all_archived_attributes(self):
         """
         Returns a list of the archived attributes in the DB.
         """
-        attrs = self.session.query(Attribute).order_by(Attribute.att_conf_id).all()
+        attrs = self.session.query(self.ab.Attribute).order_by(self.ab.Attribute.att_conf_id).all()
         # Returns the representation as set in __repr__ method of the mapper class
         return attrs
 
@@ -510,8 +532,8 @@ class Retriever():
             [domain, family, member] = device_fqname.split('/')
         except:
             raise AttributeFormatException(f"Could not parse device name {device_fqname}. Please provide FQDN, e.g. STAT/Device/1")
-        attrs = self.session.query(Attribute).filter(and_(Attribute.domain == domain, Attribute.family == family, \
-                                Attribute.member == member)).all()
+        attrs = self.session.query(self.ab.Attribute).filter(and_(self.ab.Attribute.domain == domain, self.ab.Attribute.family == family, \
+                                self.ab.Attribute.member == member)).all()
         # Returns the representation as set in __repr__ method of the mapper class
         return attrs
 
@@ -524,8 +546,8 @@ class Retriever():
         except:
             raise AttributeFormatException(f"Could not parse attribute name {attribute_fqname}. Please provide FQDN, e.g. STAT/Device/1/Attribute")
         try:
-            result = self.session.query(Attribute.att_conf_id).filter(and_(Attribute.domain == domain, Attribute.family == family, \
-                                    Attribute.member == member, Attribute.name == name)).one()
+            result = self.session.query(self.ab.Attribute.att_conf_id).filter(and_(self.ab.Attribute.domain == domain, self.ab.Attribute.family == family, \
+                                    self.ab.Attribute.member == member, self.ab.Attribute.name == name)).one()
             return result[0]
         except TypeError as e:
             raise Exception("Attribute not found!") from e
@@ -543,14 +565,51 @@ class Retriever():
         except:
             raise AttributeFormatException(f"Could not parse attribute name {attribute_fqname}. Please provide FQDN, e.g. STAT/Device/1/Attribute")
         try:
-            result = self.session.query(DataType.data_type).join(Attribute,Attribute.att_conf_data_type_id==DataType.att_conf_data_type_id).\
-                        filter(and_(Attribute.domain == domain, Attribute.family == family, Attribute.member == member, Attribute.name == name)).one()
+            if self.dbms=='mysql': 
+                result = self.session.query(self.ab.DataType.data_type).join(self.ab.Attribute,self.ab.Attribute.att_conf_data_type_id==self.ab.DataType.att_conf_data_type_id).\
+                            filter(and_(self.ab.Attribute.domain == domain, self.ab.Attribute.family == family, self.ab.Attribute.member == member, self.ab.Attribute.name == name)).one()
+            elif self.dbms=='postgres':
+                result = self.session.query(self.ab.DataType.type).join(self.ab.Attribute,self.ab.Attribute.att_conf_type_id==self.ab.DataType.att_conf_type_id).\
+                            filter(and_(self.ab.Attribute.domain == domain, self.ab.Attribute.family == family, self.ab.Attribute.member == member, self.ab.Attribute.name == name)).one()
             return result[0]
         except TypeError as e:
             raise Exception("Attribute not found!") from e
         except NoResultFound as e:
             raise Exception(f"No records of attribute {attribute_fqname} found in DB") from e
 
+    def get_attribute_format(self,attribute_fqname: str):
+        """
+        Takes as input the fully-qualified name of an attribute and returns its format.
+        Formats are basically three: Scalar, Spectrum and Image.
+        * Works only for POSTGRESQL * 
+        """
+        try:
+            [domain, family, member, name] = attribute_fqname.split('/')
+        except:
+            raise AttributeFormatException(f"Could not parse attribute name {attribute_fqname}. Please provide FQDN, e.g. STAT/Device/1/Attribute")
+        try:
+            result = self.session.query(self.ab.Format.format).join(self.ab.Attribute,self.ab.Attribute.att_conf_format_id==self.ab.Format.att_conf_format_id).\
+                filter(and_(self.ab.Attribute.domain == domain, self.ab.Attribute.family == family, self.ab.Attribute.member == member, self.ab.Attribute.name == name)).one()
+            return result[0]
+        except TypeError as e:
+            raise Exception("Attribute not found!") from e
+        except NoResultFound as e:
+            raise Exception(f"No records of attribute {attribute_fqname} found in DB") from e
+    
+    def get_attribute_tablename(self,attribute_fqname: str):
+        try:
+            [domain, family, member, name] = attribute_fqname.split('/')
+        except:
+            raise AttributeFormatException(f"Could not parse attribute name {attribute_fqname}. Please provide FQDN, e.g. STAT/Device/1/Attribute")
+        try:
+            result = self.session.query(self.ab.Attribute.table_name).filter(and_(self.ab.Attribute.domain == domain, self.ab.Attribute.family == family, \
+                                    self.ab.Attribute.member == member, self.ab.Attribute.name == name)).one()
+            return result[0]
+        except TypeError as e:
+            raise Exception("Attribute not found!") from e
+        except NoResultFound as e:
+            raise Exception(f"No records of attribute {attribute_fqname} found in DB") from e
+    
     def get_attribute_value_by_hours(self,attribute_fqname: str, hours: float = 1.0):
         """
         Takes as input the attribute fully-qualified name and the number of past hours since the actual time 
@@ -559,9 +618,12 @@ class Retriever():
         """
         attr_id = self.get_attribute_id(attribute_fqname)
         attr_datatype = self.get_attribute_datatype(attribute_fqname)
-        attr_table_name = 'att_'+str(attr_datatype)
         # Retrieves the class that maps the DB table given the tablename
-        base_class = get_class_by_tablename(attr_table_name)
+        if self.dbms=='mysql':
+            tablename = 'att_'+str(attr_datatype)           
+        elif self.dbms=='postgres':
+            tablename = self.get_attribute_tablename(attribute_fqname)
+        base_class = self.ab.get_class_by_tablename(tablename)    
         # Retrieves the timestamp 
         time_now = datetime.now()
         time_delta = time_now - timedelta(hours=hours)
@@ -570,8 +632,8 @@ class Retriever():
         time_delta_db = str(time_delta.strftime("%Y-%m-%d %X"))
         try:
             result = self.session.query(base_class).\
-                    join(Attribute,Attribute.att_conf_id==base_class.att_conf_id).\
-                    filter(and_(Attribute.att_conf_id == attr_id,base_class.data_time >= time_delta_db, \
+                    join(self.ab.Attribute,self.ab.Attribute.att_conf_id==base_class.att_conf_id).\
+                    filter(and_(self.ab.Attribute.att_conf_id == attr_id,base_class.data_time >= time_delta_db, \
                             base_class.data_time <= time_now_db)).order_by(base_class.data_time).all()
         except AttributeError as e:
             raise Exception(f"Empty result! Attribute {attribute_fqname} not found") from e
@@ -587,18 +649,22 @@ class Retriever():
         attr_datatype = self.get_attribute_datatype(attribute_fqname)
         attr_table_name = 'att_'+str(attr_datatype)
         # Retrieves the class that maps the DB table given the tablename
-        base_class = get_class_by_tablename(attr_table_name)
+        if self.dbms=='mysql':
+            tablename = 'att_'+str(attr_datatype)           
+        elif self.dbms=='postgres':
+            tablename = self.get_attribute_tablename(attribute_fqname)
+        base_class = self.ab.get_class_by_tablename(tablename)
         try:
             result = self.session.query(base_class).\
-                    join(Attribute,Attribute.att_conf_id==base_class.att_conf_id).\
-                        filter(and_(Attribute.att_conf_id == attr_id,base_class.data_time >= str(start_time), \
+                    join(self.ab.Attribute,self.ab.Attribute.att_conf_id==base_class.att_conf_id).\
+                        filter(and_(self.ab.Attribute.att_conf_id == attr_id,base_class.data_time >= str(start_time), \
                                 base_class.data_time <= str(stop_time))).order_by(base_class.data_time).all()
         except AttributeError as e:
             raise Exception(f"Empty result! Attribute {attribute_fqname} not found") from e
         return result
     
-    def get_masked_fpga_temp(self,start_time: datetime, stop_time: datetime,temp_attr_name:str='LTS/SDP/1/fpga_temp_r',
-        mask_attr_name:str='LTS/SDP/1/tr_fpga_mask_r'):
+    def get_masked_fpga_temp(self,start_time: datetime, stop_time: datetime,temp_attr_name:str='stat/sdp/1/fpga_temp_r',
+                    mask_attr_name:str='stat/sdp/1/tr_fpga_mask_r'):
         """
         Returns a list of SDP/fpga_temp_r values, but only if SDP/tr_fpga_mask_r values are TRUE
         """
@@ -617,11 +683,11 @@ class Retriever():
         else:
             raise Exception
         # Convert DB Array records into Python lists
-        mask_data = build_array_from_record(mask_values,mask_values[0].dim_x_r)
-        temp_data = build_array_from_record(temp_values,temp_values[0].dim_x_r)
+        mask_data = self.ab.build_array_from_record(mask_values,mask_values[0].dim_x_r)
+        temp_data = self.ab.build_array_from_record(temp_values,temp_values[0].dim_x_r)
         # Extract only the value from the array 
-        mask_array_values = get_values_from_record(mask_data)
-        temp_array_values = get_values_from_record(temp_data)
+        mask_array_values = self.ab.get_values_from_record(mask_data)
+        temp_array_values = self.ab.get_values_from_record(temp_data)
         # Multiply the matrix
         #masked_values = np.multiply(temp_array_values,mask_array_values)
         masked_values = np.ma.masked_array(temp_array_values,mask=np.invert(mask_array_values.astype(bool)))
diff --git a/tangostationcontrol/tangostationcontrol/toolkit/archiver_base.py b/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_mysql.py
similarity index 99%
rename from tangostationcontrol/tangostationcontrol/toolkit/archiver_base.py
rename to tangostationcontrol/tangostationcontrol/toolkit/archiver_base_mysql.py
index 4440957bb8546a9e42638a0a6b441e43119fa601..0e85ad5ec377536d2e50f4323e60ca9ddb9d76e1 100644
--- a/tangostationcontrol/tangostationcontrol/toolkit/archiver_base.py
+++ b/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_mysql.py
@@ -28,10 +28,9 @@ class Attribute(Base):
     family = Column(String)
     member = Column(String)
     name = Column(String)
-    
-    
+     
     def __repr__(self):
-        return f"<Attribute(fullname='{self.att_name}',data_type ='{self.att_conf_data_type_id}',ttl='{self.att_ttl}',facility ='{elf.facility}',domain ='{self.domain}',family ='{self.family}',member ='{self.member}',name ='{self.name}')>"
+        return f"<Attribute(fullname='{self.att_name}',data_type ='{self.att_conf_data_type_id}',ttl='{self.att_ttl}',facility ='{self.facility}',domain ='{self.domain}',family ='{self.family}',member ='{self.member}',name ='{self.name}')>"
     
 class DataType(Base):
     """
diff --git a/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py b/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py
new file mode 100644
index 0000000000000000000000000000000000000000..e86473df231e1e39604c154ea4883392a3866a08
--- /dev/null
+++ b/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py
@@ -0,0 +1,473 @@
+#! /usr/bin/env python3
+
+from sqlalchemy.dialects.postgresql import ARRAY,TIMESTAMP,FLOAT, JSON
+from sqlalchemy.dialects.postgresql.base import BYTEA
+from sqlalchemy.dialects.postgresql.ranges import INT4RANGE, INT8RANGE
+from sqlalchemy.sql.sqltypes import INTEGER, TEXT, Boolean
+from sqlalchemy.orm import declarative_base
+from sqlalchemy import Column, Integer, String
+from sqlalchemy.sql.expression import table
+from typing import List
+from itertools import groupby
+import numpy as np
+
+#Declarative system used to define classes mapped to relational DB tables
+Base = declarative_base()
+
+class Attribute(Base):
+    """
+    Class that represents a Tango Attribute mapped to table 'att_conf'
+    """
+    __tablename__ = 'att_conf'
+    __table_args__ = {'extend_existing': True}
+    
+    att_conf_id = Column(Integer, primary_key=True)
+    att_name = Column(String)
+    att_conf_type_id = Column(Integer)
+    att_conf_format_id = Column(Integer)
+    table_name = Column(String)
+    cs_name = Column(String)
+    domain = Column(String)
+    family = Column(String)
+    member = Column(String)
+    name = Column(String)
+    ttl = Column(Integer)
+     
+    def __repr__(self):
+        return f"<Attribute(fullname='{self.att_name}',data_type ='{self.att_conf_type_id}',format='{self.att_conf_format_id}',table_name='{self.table_name}',cs_name ='{self.cs_name}',domain ='{self.domain}',family ='{self.family}',member ='{self.member}',name ='{self.name}'),ttl='{self.ttl}'>"
+    
+class DataType(Base):
+    """
+    Class that represents a Tango Data Type mapped to table 'att_conf_data_type'
+    """
+    __tablename__ = 'att_conf_type'
+    __table_args__ = {'extend_existing': True}
+    
+    att_conf_type_id = Column(Integer, primary_key=True)
+    type = Column(String)
+    
+    def __repr__(self):
+        return f"<DataType(type='{self.type}')>"
+
+class Format(Base):
+    """
+    Class that represents a Tango Format mapped to table 'att_conf_format'
+    """
+    __tablename__ = 'att_conf_format'
+    __table_args__ = {'extend_existing': True}
+
+    att_conf_format_id = Column(Integer, primary_key=True)
+    format = Column(String)
+    format_num = Column(Integer)
+
+    def __repr__(self):
+        return f"<Format(format='{self.format}', format_num='{self.format_num}')>"
+
+class Scalar(Base):
+    """
+    Abstract class that represents Super-class of Scalar mapper classes
+    """
+    # In the concrete inheritance use case, it is common that the base class is not represented 
+    # within the database, only the subclasses. In other words, the base class is abstract.
+    __abstract__ = True 
+
+    # Primary key is not defined for tables which store values, but SQLAlchemy requires a mandatory 
+    # primary key definition. Anyway, this definition is on Python-side and does not compromise
+    # DBMS architecture
+    att_conf_id = Column(Integer, primary_key=True)
+    data_time = Column(TIMESTAMP, primary_key=True)
+    quality = Column(Integer)
+    att_error_desc_id = Column(Integer)
+    details = Column(JSON)
+
+class Scalar_Boolean(Scalar):
+    """
+    Class that represents a Tango Boolean mapped to table 'att_scalar_devboolean'
+    """
+    __tablename__ = 'att_scalar_devboolean'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(Boolean)
+    value_w = Column(Boolean)
+
+    def __repr__(self):
+        return f"<Scalar_Boolean(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Scalar_Double(Scalar):
+    """
+    Class that represents a Tango Double mapped to table 'att_scalar_devdouble'
+    """
+    __tablename__ = 'att_scalar_devdouble'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(FLOAT)
+    value_w = Column(FLOAT)
+
+    def __repr__(self):
+        return f"<Scalar_Double(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Scalar_Encoded(Scalar):
+    """
+    Class that represents a Tango Encoded mapped to table 'att_scalar_devencoded'
+    """
+    __tablename__ = 'att_scalar_devencoded'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(BYTEA)
+    value_w = Column(BYTEA)
+
+    def __repr__(self):
+        return f"<Scalar_Encoded(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Scalar_Enum(Scalar):
+    """
+    Class that represents a Tango Enum mapped to table 'att_scalar_devenum'
+    """
+    __tablename__ = 'att_scalar_devenum'
+    __table_args__ = {'extend_existing': True}
+    value_r_label = Column(TEXT)
+    value_r = Column(INTEGER)
+    value_w_label = Column(TEXT)
+    value_w = Column(INTEGER)
+
+    def __repr__(self):
+        return f"<Scalar_Enum(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r_label='{self.value_r_label}',value_r='{self.value_r}',value_w_label='{self.value_w_label},value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Scalar_Float(Scalar):
+    """
+    Class that represents a Tango Float mapped to table 'att_scalar_devfloat'
+    """
+    __tablename__ = 'att_scalar_devfloat'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(FLOAT)
+    value_w = Column(FLOAT)
+
+    def __repr__(self):
+        return f"<Scalar_Float(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Scalar_Long(Scalar):
+    """
+    Class that represents a Tango Long mapped to table 'att_scalar_devlong'
+    """
+    __tablename__ = 'att_scalar_devlong'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(INT4RANGE)
+    value_w = Column(INT4RANGE)
+
+    def __repr__(self):
+        return f"<Scalar_Long(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Scalar_Long64(Scalar):
+    """
+    Class that represents a Tango Long64 mapped to table 'att_scalar_devlong64'
+    """
+    __tablename__ = 'att_scalar_devlong64'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(INT8RANGE)
+    value_w = Column(INT8RANGE)
+
+    def __repr__(self):
+        return f"<Scalar_Long64(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Scalar_Short(Scalar):
+    """
+    Class that represents a Tango Short mapped to table 'att_scalar_devshort'
+    """
+    __tablename__ = 'att_scalar_devshort'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(INTEGER)
+    value_w = Column(INTEGER)
+
+    def __repr__(self):
+        return f"<Scalar_Short(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Scalar_State(Scalar):
+    """
+    Class that represents a Tango State mapped to table 'att_scalar_devstate'
+    """
+    __tablename__ = 'att_scalar_devstate'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(INTEGER)
+    value_w = Column(INTEGER)
+
+    def __repr__(self):
+        return f"<Scalar_State(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Scalar_String(Scalar):
+    """
+    Class that represents a Tango String mapped to table 'att_scalar_devstring'
+    """
+    __tablename__ = 'att_scalar_devstring'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(TEXT)
+    value_w = Column(TEXT)
+
+    def __repr__(self):
+        return f"<Scalar_String(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Scalar_UChar(Scalar):
+    """
+    Class that represents a Tango UChar mapped to table 'att_scalar_devuchar'
+    """
+    __tablename__ = 'att_scalar_devuchar'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(INTEGER)
+    value_w = Column(INTEGER)
+
+    def __repr__(self):
+        return f"<Scalar_UChar(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Scalar_ULong(Scalar):
+    """
+    Class that represents a Tango ULong mapped to table 'att_scalar_devulong'
+    """
+    __tablename__ = 'att_scalar_devulong'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(INTEGER)
+    value_w = Column(INTEGER)
+
+    def __repr__(self):
+        return f"<Scalar_ULong(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Scalar_ULong64(Scalar):
+    """
+    Class that represents a Tango ULong64 mapped to table 'att_scalar_devulong64'
+    """
+    __tablename__ = 'att_scalar_devulong64'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(INTEGER)
+    value_w = Column(INTEGER)
+
+    def __repr__(self):
+        return f"<Scalar_ULong64(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Scalar_UShort(Scalar):
+    """
+    Class that represents a Tango UShort mapped to table 'att_scalar_devushort'
+    """
+    __tablename__ = 'att_scalar_devushort'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(INTEGER)
+    value_w = Column(INTEGER)
+
+    def __repr__(self):
+        return f"<Scalar_UShort(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Array(Base):
+    """
+    Abstract class that represents Super-class of Array mapper classes
+    """
+    __abstract__ = True
+    # Primary key is not defined for tables which store values, but SQLAlchemy requires a mandatory 
+    # primary key definition. Anyway, this definition is on Python-side and does not compromise
+    # DBMS architecture
+    att_conf_id = Column(Integer, primary_key=True)
+    data_time = Column(TIMESTAMP, primary_key=True)
+    quality = Column(Integer)
+    att_error_desc_id = Column(Integer)
+    details = Column(JSON)
+
+class Array_Boolean(Array):
+    """
+    Class that represents a Tango Boolean Array mapped to table 'att_array_devboolean'
+    """
+    __tablename__ = 'att_array_devboolean'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(ARRAY(Boolean))
+    value_w = Column(ARRAY(Boolean))
+
+    def __repr__(self):
+        return f"<Array_Boolean(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Array_Double(Array):
+    """
+    Class that represents a Tango Double Array mapped to table 'att_array_devdouble'
+    """
+    __tablename__ = 'att_array_devdouble'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(ARRAY(FLOAT))
+    value_w = Column(ARRAY(FLOAT))
+
+    def __repr__(self):
+        return f"<Array_Double(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Array_Encoded(Array):
+    """
+    Class that represents a Tango Encoded Array mapped to table 'att_array_devencoded'
+    """
+    __tablename__ = 'att_array_devencoded'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(ARRAY(BYTEA))
+    value_w = Column(ARRAY(BYTEA))
+
+    def __repr__(self):
+        return f"<Array_Encoded(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Array_Enum(Array):
+    """
+    Class that represents a Tango Enum Array mapped to table 'att_array_devenum'
+    """
+    __tablename__ = 'att_array_devenum'
+    __table_args__ = {'extend_existing': True}
+    value_r_label = Column(ARRAY(TEXT))
+    value_r = Column(ARRAY(INTEGER))
+    value_w_label = Column(ARRAY(TEXT))
+    value_w = Column(ARRAY(INTEGER))
+
+    def __repr__(self):
+        return f"<Array_Enum(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r_label='{self.value_r_label}',value_r='{self.value_r}',value_w_label='{self.value_w_label},value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Array_Float(Array):
+    """
+    Class that represents a Tango Float Array mapped to table 'att_array_devfloat'
+    """
+    __tablename__ = 'att_array_devfloat'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(ARRAY(FLOAT))
+    value_w = Column(ARRAY(FLOAT))
+
+    def __repr__(self):
+        return f"<Array_Float(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Array_Long(Array):
+    """
+    Class that represents a Tango Long Array mapped to table 'att_array_devlong'
+    """
+    __tablename__ = 'att_array_devlong'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(ARRAY(INT4RANGE))
+    value_w = Column(ARRAY(INT4RANGE))
+
+    def __repr__(self):
+        return f"<Array_Long(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Array_Long64(Array):
+    """
+    Class that represents a Tango Long64 Array mapped to table 'att_array_devlong64'
+    """
+    __tablename__ = 'att_array_devlong64'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(ARRAY(INT8RANGE))
+    value_w = Column(ARRAY(INT8RANGE))
+
+    def __repr__(self):
+        return f"<Array_Long64(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Array_Short(Array):
+    """
+    Class that represents a Tango Short Array mapped to table 'att_array_devshort'
+    """
+    __tablename__ = 'att_array_devshort'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(ARRAY(INTEGER))
+    value_w = Column(ARRAY(INTEGER))
+
+    def __repr__(self):
+        return f"<Array_Short(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Array_State(Array):
+    """
+    Class that represents a Tango State Array mapped to table 'att_array_devstate'
+    """
+    __tablename__ = 'att_array_devstate'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(ARRAY(INT4RANGE))
+    value_w = Column(ARRAY(INT4RANGE))
+
+    def __repr__(self):
+        return f"<Array_State(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Array_String(Array):
+    """
+    Class that represents a Tango String Array mapped to table 'att_array_devstring'
+    """
+    __tablename__ = 'att_array_devstring'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(ARRAY(TEXT))
+    value_w = Column(ARRAY(TEXT))
+
+    def __repr__(self):
+        return f"<Array_String(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Array_UChar(Array):
+    """
+    Class that represents a Tango UChar Array mapped to table 'att_array_devuchar'
+    """
+    __tablename__ = 'att_array_devuchar'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(ARRAY(INTEGER))
+    value_w = Column(ARRAY(INTEGER))
+
+    def __repr__(self):
+        return f"<Array_UChar(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Array_ULong(Array):
+    """
+    Class that represents a Tango ULong Array mapped to table 'att_array_devulong'
+    """
+    __tablename__ = 'att_array_devulong'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(ARRAY(INTEGER))
+    value_w = Column(ARRAY(INTEGER))
+
+    def __repr__(self):
+        return f"<Array_ULong(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Array_ULong64(Array):
+    """
+    Class that represents a Tango ULong64 Array mapped to table 'att_array_devulong64'
+    """
+    __tablename__ = 'att_array_devulong64'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(ARRAY(INTEGER))
+    value_w = Column(ARRAY(INTEGER))
+
+    def __repr__(self):
+        return f"<Array_ULong64(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+class Array_UShort(Array):
+    """
+    Class that represents a Tango UShort Array mapped to table 'att_array_devushort'
+    """
+    __tablename__ = 'att_array_devushort'
+    __table_args__ = {'extend_existing': True}
+    value_r = Column(ARRAY(INTEGER))
+    value_w = Column(ARRAY(INTEGER))
+
+    def __repr__(self):
+        return f"<Array_UShort(att_conf_id='{self.att_conf_id}',data_time='{self.data_time}',value_r='{self.value_r}',value_w='{self.value_w},quality='{self.quality}',att_error_desc_id='{self.att_error_desc_id}',details='{self.details}')>"
+
+def get_class_by_tablename(tablename: str):
+    """
+    Returns class reference mapped to a table.    
+    """
+    for mapper in Base.registry.mappers:
+        c = mapper.class_
+        classname = c.__name__
+        if not classname.startswith('_'):
+            if hasattr(c, '__tablename__') and c.__tablename__ == tablename:
+                return c
+    return None
+
+def build_array_from_record(rows: List[Array], dim_x: int):
+    """
+    Converts Array database items in Python lists
+    """
+    matrix = np.array([])
+    for i in range(0,dim_x):
+        x = np.array([item for item in rows if item.idx==i]) #group records by array index
+        if i==0:
+            matrix = np.append(matrix,x)    #append first row
+        else:
+            matrix = np.vstack([matrix,x])  #stack vertically
+    result = np.transpose(matrix)   #transpose -> each row is a distinct array of value
+    list_result = result.tolist()
+    return list_result
+    
+def get_values_from_record(data_matrix: List[Array]):
+    """
+    Returns a matrix of values from a matrix of Array records
+    """
+    array_matrix = np.matrix(data_matrix)
+    value_matrix = np.empty(array_matrix.shape)
+    for index in range(array_matrix.size):    # for each object element
+        value_matrix.itemset(index,array_matrix.item(index).value_r) # extract the value from object and put in the matrix
+    return value_matrix
+