From d4aab6891dcf1e7f6bd7b1dfb2a8e7f5348c69f2 Mon Sep 17 00:00:00 2001 From: stedif <stefano.difrischia@inaf.it> Date: Tue, 14 Dec 2021 16:21:38 +0100 Subject: [PATCH] L2SS-528: implement inheritance --- .../toolkit/archiver_base_ts.py | 56 ++--- .../tangostationcontrol/toolkit/retriever.py | 234 +++++++++++------- 2 files changed, 175 insertions(+), 115 deletions(-) diff --git a/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py b/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py index f73ca2abc..048077723 100644 --- a/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py +++ b/tangostationcontrol/tangostationcontrol/toolkit/archiver_base_ts.py @@ -90,7 +90,7 @@ class Scalar_Boolean(Scalar): 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}')>" + 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): """ @@ -102,7 +102,7 @@ class Scalar_Double(Scalar): 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}')>" + 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): """ @@ -114,7 +114,7 @@ class Scalar_Encoded(Scalar): 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}')>" + 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): """ @@ -128,7 +128,7 @@ class Scalar_Enum(Scalar): 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}')>" + 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): """ @@ -140,7 +140,7 @@ class Scalar_Float(Scalar): 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}')>" + 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): """ @@ -152,7 +152,7 @@ class Scalar_Long(Scalar): 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}')>" + 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): """ @@ -164,7 +164,7 @@ class Scalar_Long64(Scalar): 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}')>" + 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): """ @@ -176,7 +176,7 @@ class Scalar_Short(Scalar): 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}')>" + 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): """ @@ -188,7 +188,7 @@ class Scalar_State(Scalar): 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}')>" + 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): """ @@ -200,7 +200,7 @@ class Scalar_String(Scalar): 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}')>" + 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): """ @@ -212,7 +212,7 @@ class Scalar_UChar(Scalar): 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}')>" + 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): """ @@ -224,7 +224,7 @@ class Scalar_ULong(Scalar): 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}')>" + 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): """ @@ -236,7 +236,7 @@ class Scalar_ULong64(Scalar): 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}')>" + 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): """ @@ -248,7 +248,7 @@ class Scalar_UShort(Scalar): 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}')>" + 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): """ @@ -274,7 +274,7 @@ class Array_Boolean(Array): 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}')>" + 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): """ @@ -286,7 +286,7 @@ class Array_Double(Array): 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}')>" + 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): """ @@ -298,7 +298,7 @@ class Array_Encoded(Array): 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}')>" + 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): """ @@ -312,7 +312,7 @@ class Array_Enum(Array): 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}')>" + 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): """ @@ -324,7 +324,7 @@ class Array_Float(Array): 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}')>" + 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): """ @@ -336,7 +336,7 @@ class Array_Long(Array): 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}')>" + 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): """ @@ -348,7 +348,7 @@ class Array_Long64(Array): 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}')>" + 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): """ @@ -360,7 +360,7 @@ class Array_Short(Array): 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}')>" + 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): """ @@ -372,7 +372,7 @@ class Array_State(Array): 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}')>" + 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): """ @@ -384,7 +384,7 @@ class Array_String(Array): 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}')>" + 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): """ @@ -396,7 +396,7 @@ class Array_UChar(Array): 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}')>" + 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): """ @@ -408,7 +408,7 @@ class Array_ULong(Array): 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}')>" + 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): """ @@ -420,7 +420,7 @@ class Array_ULong64(Array): 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}')>" + 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): """ @@ -432,7 +432,7 @@ class Array_UShort(Array): 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}')>" + 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): """ diff --git a/tangostationcontrol/tangostationcontrol/toolkit/retriever.py b/tangostationcontrol/tangostationcontrol/toolkit/retriever.py index 2905abee5..b84802cde 100644 --- a/tangostationcontrol/tangostationcontrol/toolkit/retriever.py +++ b/tangostationcontrol/tangostationcontrol/toolkit/retriever.py @@ -13,7 +13,7 @@ import numpy class Retriever(ABC): """ - The Retriever class implements retrieve operations on a given DBMS + The Retriever abstract class implements retrieve operations on a given DBMS """ def get_db_credentials(self): @@ -38,6 +38,14 @@ class Retriever(ABC): engine = create_engine(connection_string) Session = sessionmaker(bind=engine) return Session + + @abstractmethod + def set_archiver_base(self): + return + + @abstractmethod + def connect_to_archiving_db(self): + return def get_all_archived_attributes(self): """ @@ -70,67 +78,19 @@ class Retriever(ABC): raise Exception(f"Attribute {attribute_fqname} 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_datatype(self,attribute_fqname: str): - """ - Takes as input the fully-qualified name of an attribute and returns its Data-Type. - Data Type name indicates the type (e.g. string, int, ...) and the read/write property. The name is used - as DB table name suffix in which values are stored. - """ - domain, family, member, name = split_tango_name(attribute_fqname,"attribute") - try: - 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(f"Attribute not {attribute_fqname} 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 * - """ - domain, family, member, name = split_tango_name(attribute_fqname,"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): - domain, family, member, name = split_tango_name(attribute_fqname,"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 + @abstractmethod + def get_attribute_datatype(self,attribute_fqname: str): + return - def get_attribute_value_by_hours(self,attribute_fqname: str, hours: float = 1.0): + def get_attribute_value_by_hours(self, attribute_fqname: str, hours: float, tablename:str): """ Takes as input the attribute fully-qualified name and the number of past hours since the actual time (e.g. hours=1 retrieves values in the last hour, hours=8.5 retrieves values in the last eight hours and half). Returns a list of timestamps and a list of values """ attr_id = self.get_attribute_id(attribute_fqname) - attr_datatype = self.get_attribute_datatype(attribute_fqname) # Retrieves the class that maps the DB table given the tablename - if self.dbms=='mysql': - tablename = f"att_{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() @@ -147,19 +107,14 @@ class Retriever(ABC): raise Exception(f"Empty result: Attribute {attribute_fqname} not found") from e return result - def get_attribute_value_by_interval(self,attribute_fqname: str, start_time: datetime, stop_time: datetime): + def get_attribute_value_by_interval(self,attribute_fqname: str, start_time: datetime, stop_time: datetime, tablename:str): """ Takes as input the attribute name and a certain starting and ending point-time. The datetime format is pretty flexible (e.g. "YYYY-MM-dd hh:mm:ss"). Returns a list of timestamps and a list of values """ attr_id = self.get_attribute_id(attribute_fqname) - attr_datatype = self.get_attribute_datatype(attribute_fqname) # Retrieves the class that maps the DB table given the tablename - if self.dbms=='mysql': - tablename = f"att_{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).\ @@ -169,7 +124,73 @@ class Retriever(ABC): except AttributeError as e: raise Exception(f"Empty result: Attribute {attribute_fqname} not found") from e return result + +class RetrieverMySQL(Retriever): + + def __init__(self, cm_name: str = 'archiving/hdbpp/confmanager01'): + self.cm_name = cm_name + self.session = self.connect_to_archiving_db() + self.ab = self.set_archiver_base() + + def connect_to_archiving_db(self): + """ + Returns a session to a MySQL DBMS using default credentials. + """ + host,dbname,port,user,pw = super().get_db_credentials() + # Set sqlalchemy library connection + if host=='archiver-maria-db': + libname = 'mysql+pymysql' + else: + raise ValueError(f"Invalid hostname: {host}") + Session = super().create_session(libname,user,pw,host,port,dbname) + return Session() + def set_archiver_base(self): + """ + Sets the right mapper class following the DBMS connection + """ + return importlib.import_module('.archiver_base_mysql', package=__package__) + + def get_attribute_datatype(self,attribute_fqname: str): + """ + Takes as input the fully-qualified name of an attribute and returns its Data-Type. + Data Type name indicates the type (e.g. string, int, ...) and the read/write property. The name is used + as DB table name suffix in which values are stored. + """ + domain, family, member, name = split_tango_name(attribute_fqname,"attribute") + try: + 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() + return result[0] + except TypeError as e: + raise Exception(f"Attribute not {attribute_fqname} 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 + (e.g. hours=1 retrieves values in the last hour, hours=8.5 retrieves values in the last eight hours and half). + Returns a list of timestamps and a list of values + """ + attr_datatype = self.get_attribute_datatype(attribute_fqname) + # Retrieves the class that maps the DB table given the tablename + tablename = f"att_{attr_datatype}" + return super().get_attribute_value_by_hours(attribute_fqname,hours,tablename) + + + def get_attribute_value_by_interval(self,attribute_fqname: str, start_time: datetime, stop_time: datetime): + """ + Takes as input the attribute name and a certain starting and ending point-time. + The datetime format is pretty flexible (e.g. "YYYY-MM-dd hh:mm:ss"). + Returns a list of timestamps and a list of values + """ + attr_datatype = self.get_attribute_datatype(attribute_fqname) + # Retrieves the class that maps the DB table given the tablename + tablename = f"att_{attr_datatype}" + return super().get_attribute_value_by_interval(attribute_fqname,start_time,stop_time,tablename) + + # DRAFT # 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'): """ @@ -200,11 +221,11 @@ class Retriever(ABC): masked_values = numpy.ma.masked_array(temp_array_values,mask=numpy.invert(mask_array_values.astype(bool))) return masked_values, mask_values, temp_values -class Retriever_MySQL(Retriever): +class RetrieverTimescale(Retriever): - 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.dbms = self.connect_to_archiving_db() + self.session = self.connect_to_archiving_db() self.ab = self.set_archiver_base() def connect_to_archiving_db(self): @@ -212,9 +233,9 @@ class Retriever_MySQL(Retriever): Returns a session to a MySQL DBMS using default credentials. """ host,dbname,port,user,pw = super().get_db_credentials() - # Set sqlalchemy library connection - if host=='archiver-maria-db': - libname = 'mysql+pymysql' + # Set sqlalchemy library connection + if host=='archiver-timescale': + libname = 'postgresql+psycopg2' else: raise ValueError(f"Invalid hostname: {host}") Session = super().create_session(libname,user,pw,host,port,dbname) @@ -223,32 +244,71 @@ class Retriever_MySQL(Retriever): def set_archiver_base(self): """ Sets the right mapper class following the DBMS connection - """ - return importlib.import_module('.archiver_base_mysql', package=__package__) - -class Retriever_Timescale(Retriever): + """ + return importlib.import_module('.archiver_base_ts', package=__package__) - def __init__(self, cm_name: str = 'archiving/hdbppts/confmanager01'): - self.cm_name = cm_name - self.session, self.dbms = self.connect_to_archiving_db() - self.ab = self.set_archiver_base() + def get_attribute_datatype(self,attribute_fqname: str): + """ + Takes as input the fully-qualified name of an attribute and returns its Data-Type. + Data Type name indicates the type (e.g. string, int, ...) and the read/write property. The name is used + as DB table name suffix in which values are stored. + """ + domain, family, member, name = split_tango_name(attribute_fqname,"attribute") + try: + 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(f"Attribute not {attribute_fqname} found!") from e + except NoResultFound as e: + raise Exception(f"No records of attribute {attribute_fqname} found in DB") from e - def connect_to_archiving_db(self): + def get_attribute_format(self,attribute_fqname: str): """ - Returns a session to a MySQL DBMS using default credentials. + 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 * """ - host,dbname,port,user,pw = super().get_db_credentials() - # Set sqlalchemy library connection - if host=='archiver-timescale': - libname = 'postgresql+psycopg2' - else: - raise ValueError(f"Invalid hostname: {host}") - Session = super().create_session(libname,user,pw,host,port,dbname) - return Session() + domain, family, member, name = split_tango_name(attribute_fqname,"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 set_archiver_base(self): + def get_attribute_tablename(self,attribute_fqname: str): """ - Sets the right mapper class following the DBMS connection + Takes as input the fully-qualified name of an attribute and returns the tablename where it is stored. + * Works only for POSTGRESQL * """ - return importlib.import_module('.archiver_base_ts', package=__package__) - \ No newline at end of file + domain, family, member, name = split_tango_name(attribute_fqname,"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 + (e.g. hours=1 retrieves values in the last hour, hours=8.5 retrieves values in the last eight hours and half). + Returns a list of timestamps and a list of values + """ + tablename = self.get_attribute_tablename(attribute_fqname) + return super().get_attribute_value_by_hours(attribute_fqname,hours,tablename) + + def get_attribute_value_by_interval(self,attribute_fqname: str, start_time: datetime, stop_time: datetime): + """ + Takes as input the attribute name and a certain starting and ending point-time. + The datetime format is pretty flexible (e.g. "YYYY-MM-dd hh:mm:ss"). + Returns a list of timestamps and a list of values + """ + tablename = self.get_attribute_tablename(attribute_fqname) + return super().get_attribute_value_by_interval(attribute_fqname,start_time,stop_time,tablename) + \ No newline at end of file -- GitLab