Ñò
(ËÅPc        	   @   sß   d  Z  d d k l Z d d k l Z l Z l Z d d k l Z d d k	 l
 Z
 l Z l Z l Z d d k l Z d d k Z e i d ƒ Z d	 d d
 „  ƒ  YZ d d d „  ƒ  YZ d d d „  ƒ  YZ d d d „  ƒ  YZ d S(   s>  
TABLE-TREE MODULE for DB table-structure representation
**************************
***  TABLE-TREE MODULE
***         for
***  DB table-structure
***    representation
**************************
$RCSfile: tablegraph.py,v $
$Revision: 1248 $
$Author: j.holetschek $
$Date: 2012-12-10 12:44:40 +0100 (Mo, 10. Dez 2012) $

Class representing a database structure in the form of a graph-tree. It knows about the tables, their relations.
The function "getJoinTableList" returns a list of tables and their relation defined by a relationObject to produce dynamic joins of tables.
iÿÿÿÿ(   t   join(   t   treet   grapht   CircleExistingError(   t   ColNotExistingError(   t   CMFErrort   MissingRootTableErrort   TableConfigErrort   TableConfigCircleError(   t
   intersectsNs   pywrapper.grapht   foreignKeyClassc           B   s2   e  Z d  Z d „  Z d „  Z d „  Z d „  Z RS(   sU   Class to store all data about a foreign key potentially including several attributes.c         C   s   d  |  _ g  |  _ d  S(   N(   t   Nonet   targett   attrList(   t   self(    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   __init__"   s    	c         C   s   |  i  i | ƒ d  S(   N(   R   t   append(   R   t	   dbAttrObj(    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   addKey&   s    c         C   s*   t  |  i ƒ d j o |  i d Sd  Sd  S(   Ni    iÿÿÿÿ(   t   lenR   R   (   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt
   getLastKey)   s    c         C   s   d |  i  t |  i ƒ f S(   Ns&   (ForeignKeyObject: target=%s, attr=%s)(   R   t   strR   (   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   __repr__/   s    (   t   __name__t
   __module__t   __doc__R   R   R   R   (    (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyR
       s
   			t   tableAliasClassc           B   s8   e  Z d  Z d „  Z d g  d „ Z d „  Z d „  Z RS(   sñ   This class holds all information regarding one table in a DB.
    self.alias     = aliasname or None
    self.table     = tablename or None
    self.pk     = pks, list of DBAttrObjs
    self.fks    = fks, list of foreignKeyClass objects
    c         C   s(   d  |  _ d  |  _ g  |  _ g  |  _ d  S(   N(   R   t   aliast   tablet   pkt   fks(   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyR   :   s    			c         C   s/   t  ƒ  } | | _ | | _ |  i i | ƒ d  S(   N(   R
   R   R   R   R   (   R   R   t   DBAttrObjListt   fkObj(    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   addFK@   s    			c         C   s*   t  |  i ƒ d j o |  i d Sd  Sd  S(   Ni    iÿÿÿÿ(   R   R   R   (   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt	   getLastFkF   s    c         C   s,   d |  i  |  i t |  i ƒ t |  i ƒ f S(   Ns6   (TableAliasObject: alias=%s, table=%s, pks=%s, fks=%s)(   R   R   R   R   R   (   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyR   L   s    N(   R   R   R   R   R   R!   R"   R   (    (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyR   3   s
   		t   tableGraphClassc           B   sª   e  Z d  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z	 d „  Z
 d	 „  Z d
 „  Z d „  Z d „  Z d „  Z d „  Z g  d „ Z d „  Z d „  Z RS(   sS  This class holds the table structure of a DB in a easy usable way to create dynamic SQL. It relies on one root table that is not defined in the table configuration, but in every CMF file. The DB structure is represented as a tree, with list of lists whereby a single table is a tuple made of 3 values: [0]=table-alias name, [1]=list of child tuples, [2]=LOP/COP object defining the relation to the parental tuple (for building joins). If the DB table structure is a closed graph, different spanning trees are possible and an error is produced, as no circle relations are allowed in the DB setup.c         C   s   d  |  _ h  |  _ h  |  _ d  S(   N(   R   R   t   alias2tableObjt   alias2tablename(   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyR   W   s    		c         C   s    d t  |  i ƒ t  |  i ƒ f S(   s8   return simple string output of the object and the graph.s   GRAPH: %s  +++  ALIAS2TABLE: %s(   R   R   R%   (   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyR   _   s    c         C   sH   |  i  i ƒ  } | i ƒ  g  } x" | D] } | i |  i  | ƒ q& W| S(   s2   Returns a list of all table alias objects or None.(   R$   t   keyst   sortR   (   R   t   aliasest   retlistt   a(    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   getTableAliasListd   s    
 c         C   s   |  i  i | d ƒ S(   s9   Returns the table alias object for a given alias or None.N(   R$   t   getR   (   R   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   getTableAliasObjn   s    c         C   s   |  i  i ƒ  S(   s    Returns all table alias objects.(   R$   t   values(   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   getTableAliasObjectss   s    c         C   s4   h  } x' |  i  i ƒ  D] } | i | | i <q W| S(   sX   return a dictionary of all tablealiases with their primary keys as a list of DBAttrObjs.(   R$   R.   R   R   (   R   t   pkDictt   tabInfo(    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   getTablePKsDictx   s
     c         C   s   |  i  | =|  i | =d S(   s¸   Remove a tablealias from the object.
        Currently the graph is not changed, just the dictionaries are modified.
        SO the written PSF file does not contain the alias anymore.N(   R$   R%   (   R   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   delAlias€   s    
c      
   C   sê   t  ƒ  } | i g  } | D] } | | i q ~ ƒ h  |  _ h  |  _ x1 | D]) } | |  i | i <| i |  i | i <qM Wx` | D]X } xO | i D]D } |  i | i |  i | i	 i
 ƒ } | i | i | i	 f | ƒ q‘ Wq W| |  _  d S(   s9   Create the graph matrix from a list of tableAliasObjects.N(   R   t   addNodesR   R$   R%   R   R   t   _makeWhereObjR   R   R   t   addEdge(   R   t   tableAliasListt   graphObjt   _[1]t   taoR    t   relObj(    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt
   buildGraphˆ   s    	+		  
 "$c         C   s   |  i  S(   s-   Method returning a clones matrix of the graph(   R   (   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   getGraphMatrixš   s    c         C   s   |  i  i ƒ  i ƒ  S(   sA   Method returning a list of node-tuples for the graph as its edges(   R   t	   listEdgesR.   (   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   getGraphEdgesListž   s    c         C   s   |  i  i ƒ  S(   sl   Method returning a list of node names which are isolated, that is they dont have any edge connected to them.(   R   t   listIsolatedNodes(   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   getGraphIsolatedNodesList¢   s    c         C   sý   d d k  l } l } d } t | ƒ t | ƒ j oÄ t | ƒ d j ov | d | d | d ƒ } x t t | ƒ d ƒ D]= } | d | | d | | d ƒ } | d | | g ƒ } qy Wqù t | ƒ d j o | d | d | d ƒ } qù d } n | S(   sF   translates a relation (fks & pks DBAttrObj lists) into a whereobject .iÿÿÿÿ(   t   logicalOperatort   comparisonOperatori   t   equalsi    t   andN(   t   biocase.wrapper.sql.operatorsRB   RC   R   R   t   range(   R   R   R   RB   RC   t   clopt   it   cop(    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyR5   §   s     "
c         C   s¨   x¡ |  i  i ƒ  D] \ } } t | i ƒ d j p |  i  | =q g  } xN | i D]C } t | i ƒ d j o' |  i  i | i ƒ o | i | ƒ qP qP W| | _ q Wd S(   s%   Remove nonsense data from tablegraph.i    N(	   R$   t   itemsR   R   R   R   t   has_keyR   R   (   R   R   R:   t   tmpR    (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt
   clearGraphº   s     
 ,c         C   s   |  i  i ƒ  S(   s9   Returns 1 if the tablegraph contains circular structures.(   R   t   hasClosedWalk(   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   circlesExistÊ   s    c         C   sX   t  ƒ  } |  i | | ƒ x8 | D]0 } y |  i | | ƒ Wq  t j
 o q  Xq  W| S(   sÕ   function to create and return a tabletree object with
        - a given root table-alias name and
        - an optional list of static table aliases.
        Throws an error if a circular graph was given.
        (   t   tableTreeClasst   _setRoott   _addStaticTableR   (   R   t   rootTableAliasNamet   staticTableAliasListt   tableTreeObjt   staticTA(    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   getTableTreeÕ   s    	 	c         C   sñ   | d j o t ƒ  ‚ n5 |  i | ƒ d j o t i d | ƒ t ƒ  ‚ n y" |  i i | ƒ | _ | | _	 Wn( t
 j
 o d | _	 t | ƒ ‚ n Xt |  i | i ƒ d j o t i d | ƒ t ƒ  ‚ n |  i | i d | _ d S(   s•   function to initialize a tabletree object
        with a given root table-alias name.
        Throws an error if a circular graph was given.
        s:   Root table %s is not listed in the provider configuration.i   s‘   Your DB root table %s contains more than one primary key. This is not allowed. Please assign a single, unique primary key for your 'root' recordsi    N(   R   R   R-   t   logt   warnR   R   t   makeTreeR   t   rootTableAliasR   R   R   R$   R   t   errorR   t   rootTableAliasPK(   R   RV   R\   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyRR   å   s    	c         C   s  y |  i  i | ƒ } WnK t j
 o t | ƒ ‚ n. t j
 o! t i d | ƒ t ƒ  ‚ n X| i i	 ƒ  } x' | i
 i ƒ  D] } | | i	 ƒ  7} qƒ Wt | | i	 ƒ  ƒ } t | ƒ d j o; t i d t | ƒ d t | d ƒ d f ƒ t ƒ  ‚ n | | i
 | <d S(   s   Takes a table alias and tries to create
        a subtree of the graph with this table as its root.
        Then adds this tree to the list of static tables.s;   The static table '%s' does not exist in your providersetup.i    s±   The following tables of your static table tree '%s' are existing at least twice and are ignored. Please reconfigure your providersetup by adding a new alias for these tables: %st   's   ', 'N(   R   R[   R   R   R   RY   RZ   R   R   t	   listNodest   staticTablesR.   R	   R   t   unicodeR    (   R   RV   t   stR   t	   oldTablest   tt   shared(    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyRS   þ   s      .(   R   R   R   R   R   R+   R-   R/   R2   R3   R<   R=   R?   RA   R5   RN   RP   RX   RR   RS   (    (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyR#   T   s$   			
												RQ   c           B   s;   e  Z d  Z d „  Z d „  Z g  d „ Z g  d d „ Z RS(   sæ  This class holds the table structure of a DB for a specific CMF
    in a easy usable way to create dynamic SQL.
    It relies on one root table that is not defined in the table configuration, but in every CMF file.
    The DB structure is represented as a tree,
    with list of lists whereby a single table is a tuple made of 3 values:
    [0]=table-alias name,
    [1]=list of child tuples,
    [2]=LOP/COP object
    defining the relation to the parental tuple (for building joins). c         C   s(   d  |  _ d  |  _ d  |  _ h  |  _ d  S(   N(   R   R   R\   R^   Ra   (   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyR   %  s    			c         C   s,   d t  |  i ƒ t  |  i ƒ t  |  i ƒ f S(   s8   return simple string output of the object and the graph.s.   ROOT: %s TREE: %s  +++  STATIC TABLE TREES: %s(   R   R\   R   Ra   (   R   (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyR   -  s    c         C   s£   g  } xz |  i  i ƒ  D]i } t | | i ƒ  ƒ } t | ƒ d j o; | i |  i | | ƒ ƒ x | D] } | i | ƒ qd Wq q W| |  i | |  i ƒ g 7} | S(   s«   returns a list of table-lists, that have to be joined via a full outer join.
        That is the root table tree and all relevant static table tree dericed lists.
        i    (	   Ra   R.   R	   R`   R   R   t   getJoinTableListt   removeR   (   R   t   tablest   TreeJoinListsR   t   intersectiont   tbl(    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   getJoinTableListOfLists3  s      c         C   s#  | d j o g  S| i | ƒ } g  } xõ t t | ƒ ƒ D]á } | | } | d j o | i | d f ƒ q: | d | !} x | i | ƒ D]Œ } | d | j ou | i | d ƒ d }	 |	 i i | j o3 t	 i
 d | ƒ |	 i }
 |	 i |	 _ |
 |	 _ n | i | |	 f ƒ Pq‹ q‹ Wq: W| S(   sˆ   returns a list of (table-alias names, whereObj) tuples to be used in a join chain. Pass any number of table-alias names to this funtion.i    i   s7   Swapped COP args at node %s to build correct Left JoinsN(   R   t    listOrderedNodesConnectedViaRootRG   R   R   t   listAdjacentEdgest   getEdget   arg1R   RY   t   debugt   arg2(   R   Ri   R   t   nodest   resultRI   t   nodet
   upperNodest   edget   whereObjt   tmpArg(    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyRg   D  s,     
 	N(   R   R   R   R   R   Rm   R   Rg   (    (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyRQ     s
   			(    (    (    (    (   R   t   stringR    t   biocase.wrapper.graph.graphR   R   R   t   biocase.wrapper.graph.matrixR   t   biocase.wrapper.errorclassesR   R   R   R   t   biocase.tools.various_functionsR	   t   loggingt	   getLoggerRY   R
   R   R#   RQ   (    (    (    sH   /srv/www/vhosts/sammlung/BioCase/lib/biocase/wrapper/graph/tablegraph.pyt   <module>   s   "!Å