papo-hackers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Papo-hackers] Diagrama de base de datos ?


From: John Lenton
Subject: Re: [Papo-hackers] Diagrama de base de datos ?
Date: Fri, 5 Dec 2003 15:56:58 -0300
User-agent: Mutt/1.3.28i

On Fri, Dec 05, 2003 at 12:01:30PM -0300, Maximiliano Curia wrote:
> On Thu, 2003-12-04 at 18:31, John Lenton wrote:
> > cómo lo hicieron?
> 
> Con postgres_autodoc, es una herramienta que genera html, dia, a partir
> de la base de datos.  De todas maneras el dia que genera no está
> ordenado, sino que lo estuvimos ordenando a mano... Igual, todavía no se
> entiende nada.

con más razón entonces usá la salida de exotic. Fijate que tenés
distintas opciones en cuanto al grafo generado; algunas combinaciones
no funcionan (no he tenido tiempo de dejarlo igual de pulido que el
generador de .zot (xot es zot en xml...)), pero hay varias que sí. La
verdad es que ni recuerdo cuáles son las que no andan... :(

Lo que sí recuerdo es que la salida full-full (con los históricos
desenrrollados y con atributos) dispara un bug del dotty, que hace
como un año lo reporté y todavía no lo resolvieron; es bastante
oscuro, aparentemente.

> >  el der de papo sale de una descripción de un nivel
> > un poco más alto, que encontrarán en PAPO-ER.xot. Hay una herramienta,
> > exotic, que puede llevar esa descripción a un formato .dot que pueden
> > ser llevadas a diagramas utilizando las herramientas adecuadas
> > (graphviz, o si no les gusta su licencia, springgraph).
> 
> Lo estamos viendo, en graphviz no queda muy lindo, y el springraph se
> está generando...

en el graphviz, en la salida que es solamente las tablas (sin
atributos), queda más o menos claro con lneato:

    exotic -eGV PAPO-ER.xot | lneato -

pero queda un poco más manejable si le agregan el atributo de grafo
"pack", sea editando el archivo resultando, sea con

    exotic -eGV PAPO-ER.xot | neato -Gpack | lneato -

> > > Bueno mis preguntas, ¿alguien hizo algún diagrama de la base?
> > > Muchas de las tablas/campos comienzan sus nombres con _ o __, ¿tienen
> > > algún significado especial?
> > Las tablas que empiezan con _ y terminan con _data son una mitad de
> > una "tabla histórica". Es implementación, y no lo vas a encontrar en
> > el .xot.
> 
> ¿En que sentido histórica? ¿Que se guarda el historial o que están
> deprecadas?  Algunas tienen relaciones con otras varias tablas, de hecho
> por eso es que el diagrama está tan feo...

"histórica" en el sentido "transaccional".

> ¿Y los campos que empiezan con _ ? (_state, _table, etc).

Hmmm... cómo empezar...

Antes que nada, un disclaimer: lo que sigue describe el estado actual,
y sabemos que está muy lejos de ser óptimo, y una de las prioridades
más altas apenas saquemos 0.2.0 va a ser sentarnos y darlo vuelta para
que sea menos complejo y más rápido y fácil de explicar. Tenemos
varias ideas, y lo vamos a discutir acá en la lista también. Tratá de
no vomitar cuando leas la descripción, porque me da mucha impresión.

Bueno, te tiro con el más complicado: supongamos que estás armando una
factura tuya (un own_document). La tabla de facturas es
histórica-en-sí-misma: no hay que hacerle nada para poder reproducir
su estado en cualquier momento del pasado. Esta tabla en particular,
own_document, apunta (entre otras muchas cosas) al cliente para quien
es el documento: recipient. Ahora bien, recipient puede ser cualquier
subclase de entidad, pero para el tipo de own_document "factura", va a
ser un cliente. Los clientes son personas (esto se refiere a "personas
jurídicas"), que a su vez son alien_entity (entidades que no son parte
de la empresa o grupo de quien es la base), que son, finalmente,
entity (esencialmente, cosas a las que se le envían o de quien se
reciben documentos). En este momento toda esta estructura de herencia
se refleja en la base de datos. Además, como Entity no es
histórica-en-sí-misma, cada una de esas tablas mencionadas son dos
tablas: una con los datos de instancia, y otra con los datos de
revisión o versión; en este momento el único dato de instancia es el
id, con lo cual la tabla de instancia es bastante rala. Las tablas de
revisión o versión se llaman igual que la tabla de instancias, con un
"_" antes y un "_data" después; el campo _table de la tabla de
revisión apunta a la instancia de la cual es versión; el campo
_start_t es la fecha de inicio de esa revisión, y el campo _end_t es
la fecha de fin; para cada instancia hay una única revisión con _end_t
nulo, que es la revisión "actual". Un ejemplo para tratar de que se
entienda: tenemos una tabla hipotética de nombre "fubar", con
atributos "id" (clave primaria), "foo", y "bar":

        fubar
        ------
        @id
         foo
         bar

si quisiéramos que esta tabla fuera histórica o transaccional, con
este esquema antes presentado, tendríamos entonces dos tablas:

        fubar        _fubar_data
        ------       ------------
        @id          @id
                      foo
                      bar
                      _start_t
                      _end_t
                     #_table -> fubar

_state tiene que ver con un modelo de tablas transaccionales hacia el
cual vamos a migrar en cuanto saquemos 0.2.0 (ya estamos en 0.2.0-rc3,
y parece que rc4 va a ser el último :). El modelo que estamos usando
en este momento tiene varios inconvenientes; quizás haya sido
apresurado agregarla tan temprano (si se fijan, todos los _state son
-1, "UNDEFINED", en este momento).

Otra cosa: toda tabla tiene una clave primaria única, numérica,
autogenerada, que se llama "id".

Volviendo al ejemplo con el que empezamos: dado que, como dije, toda
la estructura de herencia se refleja en este momento en la base de
datos (y que toda referencia externa a una estructura de herencia
apunta al id de la clase más abstracta), para obtener todos los datos
de un cliente hay que hacer el siguiente join "lógico":

   client --[ persona ]--> persona
     persona --[ alien_entity ]--> alien_entity
       alien_entity --[ entity ]--> entity

o en SQL,

   SELECT ... FROM
   client
     INNER JOIN persona      ON (client.persona = persona.id)
     INNER JOIN alien_entity ON (persona.alien_entity = alien_entity.id)
     INNER JOIN entity       ON (alien_entity.entity = entity.id)

(no hace falta hacerlo con INNER, pero queda más claro para explicarlo
así). Este join se pued ver en

    https://mail.vialibre.org.ar/~john/PAPO-ER.avi

Es una animación hecha a partir del xot, con springgraph y povray;
ocupa menos de 600k.

Sin embargo, no es tan simple: entity no es una tabla histórica en sí
misma, entonces cada una de estas tablas está partida en dos, y el
join, con el dato adicional de que las tablas históricas en sí mismas
apuntan a las revisiones y no a las instancias, crece un poco más:

   _client_data --[ _table ]--> client
     client --[ persona ]--> 
       persona --[ alien_entity ]-->
         alien_entity --[ entity ]--> entity

o en SQL,

   SELECT ... FROM
   _client_data
     INNER JOIN client       ON (_client_data._table=client.id)
     INNER JOIN persona      ON (client.persona = persona.id)
     INNER JOIN alien_entity ON (persona.alien_entity = alien_entity.id)
     INNER JOIN entity       ON (alien_entity.entity = entity.id)

sin embargo esto no alcanza a traer todos los datos, porque los datos
están en las _data. El join se puede hacer por lado de los _data
también, que es como lo vas a encontrar en las pantallas. Si solamente
nos interesa la revisión "actual", es dentro de todo sencillo:

   SELECT ... FROM
   _client_data
     INNER JOIN _persona_data
         ON (_client_data.persona = _persona_data._table
                AND _persona_data._end_t IS NULL)
     INNER JOIN _alien_entity_data
         ON (_persona_data.alien_entity = _alien_entity_data._table
                AND _alien_entity_data._end_t IS NULL)
     INNER JOIN _entity_data
         ON (_alien_entity_data.entity = _entity_data._table
                AND _entity_data._end_t IS NULL)

si en vez de interesarnos el actual nos interesa el que corresponde a
una fecha en particular, la condición del join se complica más
todavía; si te interesa la pongo, pero el join es *largo*. Esto es una
de las cosas que queremos simplificar, obviamente.

-- 
John Lenton (address@hidden) -- Random fortune:
revolutionary, adj.:
        Repackaged.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]