#!/usr/bin/env python2.4 #-*- coding: iso8859-15 -*- ########################################################## # DB_SQL v1.0 # ########################################################## # Autor: Juan Miguel Taboada Godoy # # Fecha: Málaga, 07 de Agosto de 2006 # # Descripción: Cargador de datos de base de datos MySQL # # Versión: 2006080700 # # # # Codigo fuente bajo licencia GNU/GPL # # Centrologic (Computational Logistic Center) # # http://www.centrologic.com - info@centrologic.com # ########################################################## # Librerías que voy a usar {{{1 import MySQLdb import time import datetime from lib.INTERFACES import READABLE from lib.HERENCIA import BASE,DEFAULTCONFIG from lib.MATH_GRA import digitos # }}}1 # ### CONFIG ### ###################################### ## \internal ## Lector de la base de datos: configuracion por defecto class CONFIG(DEFAULTCONFIG): # Constructor {{{1 def __init__(self): # Cargo las acciones del padre DEFAULTCONFIG.__init__(self,"GRAFICAS_DBMYSQL") # }}}1 # Config SQL {{{1 # Host {{{2 ## Host ## \param self - ## \param arg Nombre o direccion IP de acceso a la Base de Datos def host(self,arg=None): if (arg!=None): self._host=arg else: return self._host # }}}2 # Port {{{2 ## Puerto ## \param self - ## \param arg Puerto de acceso a la Base de Datos def port(self,arg=None): if (arg!=None): self._port=arg else: return self._port # }}}2 # Socket {{{2 ## Socket ## \param self - ## \param arg Socket de acceso a la Base de Datos def socket(self,arg=None): if (arg!=None): self._socket=arg else: return self._socket # }}}2 # User {{{2 ## Usuario ## \param self - ## \param arg Usuario de acceso a la Base de Datos def user(self,arg=None): if (arg!=None): self._user=arg else: return self._user # }}}2 # Passwd {{{2 ## Clave ## \param self - ## \param arg Clave de acceso a la Base de Datos def passwd(self,arg=None): if (arg!=None): self._passwd=arg else: return self._passwd # }}}2 # DB {{{2 ## Nombre de la Base de Datos ## \param self - ## \param arg Nombre de la Base de Datos def db(self,arg=None): if (arg!=None): self._db=arg else: return self._db # }}}2 # Table {{{2 ## Tabla con los datos ## \param self - ## \param arg Nombre de la tabla que contiene los datos def table(self,arg=None): if (arg!=None): self._table=arg else: return self._table # }}}2 # }}}1 # Checker {{{1 ## Comprueba que el conjunto minimo de datos requeridos por la clase han sido declarados por el usuario: \n ## - host() ## - port() ## - socket() ## - user() ## - passwd() ## - db() ## - table() ## \param self - def check(self): self._check("host") self._check("port") self._check("socket") self._check("user") self._check("passwd") self._check("db") self._check("table") self.check_default() # }}}1 # ### LECTOR ### ###################################### ## \internal ## Lector de la base de datos: lector class LECTOR(READABLE,BASE): # Constructor {{{1 def __init__(self): # Cargo las acciones del padre BASE.__init__(self,id,"GRAFICAS_DBMYSQL") # No hay conexión a la Base de Datos self.__BD=None self.__BDconnection=None # No aun resutados que procesar self.__BDresult=None # }}}1 # Destructor {{{1 def __del__(self): # Desconecta de la Base de Datos self.disconnect() # }}}1 # Host {{{1 ## Host ## \param self - ## \param arg Nombre o direccion IP de acceso a la Base de Datos def host(self,arg=None): if (arg!=None): self._host=arg else: return self._host # }}}1 # Port {{{1 ## Puerto ## \param self - ## \param arg Puerto de acceso a la Base de Datos def port(self,arg=None): if (arg!=None): self._port=arg else: return self._port # }}}1 # Socket {{{1 ## Socket ## \param self - ## \param arg Socket de acceso a la Base de Datos def socket(self,arg=None): if (arg!=None): self._socket=arg else: return self._socket # }}}1 # User {{{1 ## Usuario ## \param self - ## \param arg Usuario de acceso a la Base de Datos def user(self,arg=None): if (arg!=None): self._user=arg else: return self._user # }}}1 # Passwd {{{1 ## Clave ## \param self - ## \param arg Clave de acceso a la Base de Datos def passwd(self,arg=None): if (arg!=None): self._passwd=arg else: return self._passwd # }}}1 # DB {{{1 ## Nombre de la Base de Datos ## \param self - ## \param arg Nombre de la Base de Datos def db(self,arg=None): if (arg!=None): self._db=arg else: return self._db # }}}1 # Table {{{1 ## Tabla con los datos ## \param self - ## \param arg Nombre de la tabla que contiene los datos def table(self,arg=None): if (arg!=None): self._table=arg else: return self._table # }}}1 # Conecta al gestor de Bases de datos {{{1 ## Realiza la conexion a la Base de Datos ## \param self - def connect(self): # Abro la conexión SQL self.debug("Abro la conexion SQL") # Control de reconexiones if ((self.__BD!=None) or (self.__BDconnection!=None)): self.debug("El sistema ya tiene un objeto de Base de Datos abierto, no se hace nada.") # Algo no fue bien, pero se ha seguido return False try: # Control sobre autodetección del socket if (self.valor("socket")=="auto"): # MySQL socket por defecto self.debug(" Conectando con socket autoconfigurado (BDconnection)") self.__BDconnection = MySQLdb.connect(host=self.valor("host"),port=self.valor("port"), user=self.valor("user"), passwd=self.valor("passwd"), db=self.valor("db")) else: # MySQL socket definido en la configuración self.debug(" Conectando con socket manual (BDconnection)") self.__BDconnection = MySQLdb.connect(host=self.valor("host"),port=self.valor("port"), user=self.valor("user"), passwd=self.valor("passwd"), db=self.valor("db"), unix_socket=self.valor("socket")) # Activo el cursor self.debug(" Cargando cursor (BD)") self.__BD = self.__BDconnection.cursor() except MySQLdb.OperationalError, message: raise IOError,"DB_MYSQL ERROR: Error número %d al conectar a la Base de Datos:\n%s" % (message[0],message[1]) # Todo fue bien return True # }}}1 # Desconecta del gestor de Bases de datos {{{1 ## Realiza la desconexion de la Base de Datos ## \param self - def disconnect(self): # Cierro la conexión SQL sin importar errores self.debug("Desconectando de la Base de Datos") if ((self.__BD==None) and (self.__BDconnection==None)): self.debug("El sistema no se encuentra conectado a la Base de Datos, no se hace nada.") # Algo no fue bien, pero se ha seguido return False try: if (self.__BD!=None): self.debug(" Cerrando cursor de la Base de Datos (BD)") self.__BD.close() if (self.__BDconnection!=None): self.debug(" Cerrando conexion a la Base de Datos (BDconnection)") self.__BDconnection.close() except Exception,e: raise IOError,"DB_MYSQL ERROR: al cerrar la conexión a la Base de Datos: %s" % (e[1]) # Limpio los conectores self.__BD=None self.__BDconnection=None # }}}1 # Lanza un query a la Bases de datos {{{1 ## Carga los datos de la Base de Datos en la memoria ## \param self - ## \param cadena Contiene los datos de la busqueda (id,tipo,ini,fin): (ID de la senal, 'a' analogica o 'd' digital, fecha inicio, fecha fin) def load(self,cadena): # Obtengo los datos (id,tipo,ini,fin)=cadena self.__lastid=id self.__ini=ini self.__fin=fin # Genero las variables fecha_ini_data=datetime.datetime.fromtimestamp(ini) fecha_fin_data=datetime.datetime.fromtimestamp(fin) tini=fecha_ini_data.timetuple() tfin=fecha_fin_data.timetuple() fecha_ini="%s-%s-%s" % (tini[0],digitos(tini[1],2),digitos(tini[2],2)) fecha_fin="%s-%s-%s" % (tfin[0],digitos(tfin[1],2),digitos(tfin[2],2)) hora_ini="%s:%s:%s" % (digitos(tini[3],2),digitos(tini[4],2),digitos(tini[5],2)) hora_fin="%s:%s:%s" % (digitos(tfin[3],2),digitos(tfin[4],2),digitos(tfin[5],2)) if (tipo=='d'): tipo_query="valord" self.__tipo='d' else: tipo_query="valora" self.__tipo='a' # Creo el query query="" query="%s%s" % (query,"SELECT fecha,hora,%s AS valor " % (tipo_query)) query="%s%s" % (query,"FROM datos WHERE id=%s " % (id)) query="%s%s" % (query,"AND ((fecha='%s' AND hora>='%s') OR fecha>'%s') " % (fecha_ini,hora_ini,fecha_ini)) query="%s%s" % (query,"AND ((fecha='%s' AND hora<='%s') OR fecha<'%s') " % (fecha_fin,hora_fin,fecha_fin)) query="%s%s" % (query,"ORDER BY fecha,hora,server ASC") # Envío el query a la base de datos #self.debug("Enviando QUERY: %s" % (query)) if ((self.__BD==None) or (self.__BDconnection==None)): raise IOError,"DB_MYSQL: Se intentó un QUERY pero el sistema no esta correctamente conectado a la Base de Datos (%s)" % (query) try: self.__BD.execute(query) self.__DBresult=self.__BD.rowcount except MySQLdb.OperationalError, message: # No hubo resultados de la busqueda self.debug("No se han encontrado resultados") self.__DBresult=None except Exception, message: # Error en la operación raise IOError,"DB_MYSQL OPERATIONAL ERROR: Error %d: %s\n(QUERY: %s)" % (message[0],message[1],query) # }}}1 # Localiza el valor anterio a la fecha de inicio {{{1 def _localizar_valor_anterior(self): # Obtengo los datos # ini=self.__ini ini=self.__ini tipo=self.__tipo id=self.__lastid # Genero las variables fecha_ini_data=datetime.datetime.fromtimestamp(ini) tini=fecha_ini_data.timetuple() fecha_ini="%s-%s-%s" % (tini[0],digitos(tini[1],2),digitos(tini[2],2)) hora_ini="%s:%s:%s" % (digitos(tini[3],2),digitos(tini[4],2),digitos(tini[5],2)) if (tipo=='d'): tipo_query="valord" else: tipo_query="valora" # Creo el query query="" query="%s%s" % (query,"SELECT fecha,hora,%s AS valor " % (tipo_query)) query="%s%s" % (query,"FROM datos WHERE id=%s " % (id)) query="%s%s" % (query,"AND ((fecha='%s' AND hora<'%s') OR fecha<'%s') " % (fecha_ini,hora_ini,fecha_ini)) query="%s%s" % (query,"ORDER BY fecha DESC,hora DESC,server DESC LIMIT 1") # Envío el query a la base de datos #self.debug("Enviando QUERY: %s" % (query)) if ((self.__BD==None) or (self.__BDconnection==None)): raise IOError,"DB_MYSQL: Se intentó un QUERY pero el sistema no esta correctamente conectado a la Base de Datos (%s)" % (query) try: self.__BD.execute(query) self.__DBresult=self.__BD.rowcount except MySQLdb.OperationalError, message: # No hubo resultados de la busqueda self.debug("No se han encontrado resultados") self.__DBresult=None except Exception, message: # Error en la operación raise IOError,"DB_MYSQL OPERATIONAL ERROR: Error %d: %s\n(QUERY: %s)" % (message[0],message[1],query) # Compruebo que se encontró el resultado if ((self.__DBresult!=None) and (self.__DBresult>0)): # Extraigo todos todos=self.__BD.fetchall() # Extraigo el primero elemento=None for elemento in todos: break; return elemento[2] else: return None # }}}1 # Obtiene una lista de elementos de los datos leidos de la Base de Datos {{{1 ## Obtiene una lista de elementos de los datos leidos de la Base de Datos ## \param self - def getall(self): nueva=[] if ((self.__DBresult==None) or (self.__DBresult==0)): tupla_ini=(self.__ini,self._localizar_valor_anterior()) tupla_fin=(self.__fin,tupla_ini[1]) nueva.append(tupla_ini) nueva.append(tupla_fin) else: # Anota que no queda nada por leer self.__DBresult=None # Recoje todos los valores todos=self.__BD.fetchall() # Transforma los valores a EPOCH primera=True for pieza in todos: # Extraigo la fecha pfecha=str(pieza[0]) fecha=pfecha.split("-") anyo=fecha[0] mes=fecha[1] dia=fecha[2] # Extraigo la hora phora=str(pieza[1]) thora=phora.split(":") hora=thora[0] minuto=thora[1] segundo=thora[2] # Recojo los valores valor=pieza[2] # Creo la nueva fecha nfecha=datetime.datetime(int(anyo),int(mes),int(dia),int(hora),int(minuto),int(segundo)) # Transformo la fecha a EPOCH epoch=time.mktime(nfecha.timetuple()) # Ajusto el primer elemento if (primera): primera=False if (epoch!=self.__ini): tupla_ini=(self.__ini,self._localizar_valor_anterior()) nueva.append(tupla_ini) # Creo la tupla tupla=(epoch,valor) # Almaceno la tupla nueva.append(tupla) # Ajusto el último valor if ((nueva!=[]) and (nueva[-1][0]!=self.__fin)): tupla_fin=(self.__fin,tupla[1]) nueva.append(tupla_fin) # Devuelve el resultado return nueva # }}}1 # ### EXCEPTIONS ### ################################## # EXCEPTION CLASSES {{{1 # Excepciones básicas # Except (General Exception) {{{2 class Except(Exception): def __init__(self,string): self.string=string def __str__(self): return self.string #}}}2 # IOError (Error de entrada/salida) {{{2 class IOError(Exception): def __init__(self,string): self.string=string def __str__(self): return self.string # }}}2 # ExecutionError (Error de ejecucción) {{{2 class ExecutionError(Exception): def __init__(self,string): self.string=string def __str__(self): return self.string # }}}2 # TypeError (Error de tipo) {{{2 class TypeError(Exception): def __init__(self,string): self.string=string def __str__(self): return self.string # }}}2 # }}}1