B
    þ¦†\¹´  ã               @   sì   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlm	Z	 ddlm
Z
 dd	lmZ d
dlmZ d
dlmZ d
dlmZ G dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZeee
ee	eiZdS )zRelationship dependencies.

é   )Ú
attributes)Úexc)Úsync)Ú
unitofwork)Úutil)Ú
MANYTOMANY)Ú	MANYTOONE)Ú	ONETOMANYé   )Úsqlc               @   sš   e Zd Zdd„ Zedd„ ƒZdd„ Zdd„ Zd	d
„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd%dd„Zd d!„ Zd"d#„ Zd$S )&ÚDependencyProcessorc             C   s¢   || _ |j| _|j| _|j| _|j| _|j| _|j| _|j| _|j| _|j	| _	| jr^t
j| _nt
j| _| jrvt
j| _nt
j| _|j| _| j jsžt d| j  ¡‚d S )Nz|Can't build a DependencyProcessor for relationship %s. No target attributes to populate between parent and child are present)ÚpropÚcascadeÚmapperÚparentÚ	secondaryÚ	directionÚpost_updateÚpassive_deletesÚpassive_updatesÚenable_typechecksr   ÚPASSIVE_NO_INITIALIZEÚ_passive_delete_flagÚPASSIVE_OFFÚ_passive_update_flagÚkeyÚsynchronize_pairsÚsa_excZArgumentError)Úselfr   © r   ú8lib/python3.7/site-packages/sqlalchemy/orm/dependency.pyÚ__init__   s*    

zDependencyProcessor.__init__c             C   s   t |j |ƒS )N)Ú_direction_to_processorr   )Úclsr   r   r   r    Úfrom_relationship6   s    z%DependencyProcessor.from_relationshipc             C   s   | j j | j¡ |¡S )z¤return True if the given object instance has a parent,
        according to the ``InstrumentedAttribute`` handled by this
        ``DependencyProcessor``.

        )r   Zclass_managerÚget_implr   Ú	hasparent)r   Ústater   r   r    r&   :   s    zDependencyProcessor.hasparentc             C   s   |  | d¡ dS )z•establish actions and dependencies related to a flush.

        These actions will operate on all relevant states in
        the aggregate.

        TN)Úregister_preprocessor)r   Úuowr   r   r    Úper_property_preprocessorsB   s    z.DependencyProcessor.per_property_preprocessorsc          	   C   sz   t  || dd¡}t  || dd¡}t  || jj¡}t  || jj¡}t  || jj¡}t  || jj¡}|  |||||||¡ d S )NFT)r   Ú
ProcessAllÚSaveUpdateAllr   Úprimary_base_mapperr   Ú	DeleteAllÚper_property_dependencies)r   r)   Ú
after_saveÚbefore_deleteÚparent_savesÚchild_savesÚparent_deletesÚchild_deletesr   r   r    Úper_property_flush_actionsK   s$    z.DependencyProcessor.per_property_flush_actionsc             C   s  | j j}t ||¡}t ||¡}|r<t || dd¡}d|_nt || dd¡}d|_||jkr€||jksjt‚|df|dfg}	d}
nd}
|s°t || j	j
¡}d }}||jkrÖd}n&t || j	j
¡}d }}||jkrÖd}x&|D ]}|j| j j ||j|r| jntj¡}|sqÞ|r>t || d|¡}|r`t ||¡}n"t || d|¡}|r`t ||¡}|
rÐg }	xd|D ]\\}}||jkrŠd}n6|j| \}}|r°t ||¡df}nt ||¡df}|	 |¡ qpW x*|	D ]"\}}|  ||||||||¡ qÖW qÞW dS )zèestablish actions and dependencies related to a flush.

        These actions will operate on all relevant states
        individually.    This occurs only if there are cycles
        in the 'aggregated' version of events.

        TFN)NN)r   r-   r   r,   r.   r+   ZdisabledZcyclesÚAssertionErrorr   Úbase_mapperZmanagerr   ÚimplZget_all_pendingÚdictr   r   r   ZProcessStateZDeleteStateZSaveUpdateStateÚstatesÚappendÚper_state_dependencies)r   r)   r;   ÚisdeleteZchild_base_mapperr3   r5   r1   r0   Zchild_actionsZchild_in_cyclesr2   r4   Zparent_in_cyclesr'   Zsum_Zchild_stateÚchildÚchild_actionÚdeletedZlistonlyÚchildisdeleter   r   r    Úper_state_flush_actionsg   sx    	




z+DependencyProcessor.per_state_flush_actionsc             C   s   dS )NFr   )r   Ú	uowcommitr;   r   r   r    Úpresort_deletes×   s    z#DependencyProcessor.presort_deletesc             C   s   dS )NFr   )r   rD   r;   r   r   r    Úpresort_savesÚ   s    z!DependencyProcessor.presort_savesc             C   s   d S )Nr   )r   rD   r;   r   r   r    Úprocess_deletesÝ   s    z#DependencyProcessor.process_deletesc             C   s   d S )Nr   )r   rD   r;   r   r   r    Úprocess_savesà   s    z!DependencyProcessor.process_savesc             C   sv   |r
| j rtj}n| jtkr$tj}ntj}xF|D ]$}| || j|¡}|r0| 	¡ s0dS q0W |op| j
j op| j|jkS d S )NT)r   r   r   r   r   ZPASSIVE_NO_FETCH_RELATEDr   Úget_attribute_historyr   Úemptyr   Z_is_self_referentialr   Zmappers)r   rD   r;   r>   ÚpassiveÚsÚhistoryr   r   r    Úprop_has_changesã   s    



z$DependencyProcessor.prop_has_changesc             C   s–   | j jr$|d kr$t d| j f ¡‚nn|d k	r’| jj|| j ds’| jj|ddrtt d|j| j | jj| jdœ ¡‚nt d|j| j | jjdœ ¡‚d S )Nz-Can't flush None value found in collection %s)Zallow_subtypesTaE  Attempting to flush an item of type %(x)s as a member of collection "%(y)s". Expected an object of type %(z)s or a polymorphic subclass of this type. If %(x)s is a subclass of %(z)s, configure mapper "%(zm)s" to load this subtype polymorphically, or set enable_typechecks=False to allow any subtype to be accepted for flush. )ÚxÚyÚzZzmz•Attempting to flush an item of type %(x)s as a member of collection "%(y)s". Expected an object of type %(z)s or a polymorphic subclass of this type.)rO   rP   rQ   )r   Zuselistr   Z
FlushErrorr   Z_canloadr   Úclass_)r   r'   r   r   r    Ú_verify_canloadù   s$    
z#DependencyProcessor._verify_canloadc             C   s
   t ƒ ‚d S )N)ÚNotImplementedError)r   r'   r?   ÚassociationrowÚ	clearkeysrD   r   r   r    Ú_synchronize"  s    z DependencyProcessor._synchronizec             C   s>   | j jsd S tt| jgdd„ | j jD ƒ ƒƒ}| d|ft¡S )Nc             S   s   g | ]
}|j ‘qS r   )r   )Ú.0Úpr   r   r    ú
<listcomp>*  s    zCDependencyProcessor._get_reversed_processed_set.<locals>.<listcomp>Zreverse_key)r   Ú_reverse_propertyÚtupleÚsortedr   ÚmemoÚset)r   r)   Zprocess_keyr   r   r    Ú_get_reversed_processed_set%  s
     z/DependencyProcessor._get_reversed_processed_setFc             C   s:   x4|D ],}|r|d k	r|  |dd„ | jjD ƒ¡ P qW d S )Nc             S   s   g | ]\}}|‘qS r   r   )rX   ÚlÚrr   r   r    rZ   2  s    z4DependencyProcessor._post_update.<locals>.<listcomp>)Zregister_post_updater   r   )r   r'   rD   ÚrelatedÚis_m2o_deleterO   r   r   r    Ú_post_update.  s
    
z DependencyProcessor._post_updatec             C   s
   t ƒ ‚d S )N)rT   )r   rD   r'   r   r   r    Ú_pks_changed6  s    z DependencyProcessor._pks_changedc             C   s   d| j j| jf S )Nz%s(%s))Ú	__class__Ú__name__r   )r   r   r   r    Ú__repr__9  s    zDependencyProcessor.__repr__N)F)rh   Ú
__module__Ú__qualname__r!   Úclassmethodr$   r&   r*   r6   rC   rE   rF   rG   rH   rN   rS   rW   r`   re   rf   ri   r   r   r   r    r      s"   	p)	
r   c               @   sL   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dd„ Z
dS )ÚOneToManyDPc       
   
   C   s–   | j r\t || jjd¡}t || jjd¡}	|j ||f||f||f||	f|	|f|	|fg¡ n6|j ||f||f||f||f||f||f||fg¡ d S )NFT)r   r   ÚPostUpdateAllr   r-   ÚdependenciesÚupdate)
r   r)   r2   r3   r4   r5   r0   r1   Úchild_post_updatesÚchild_pre_updatesr   r   r    r/   >  s(    
z%OneToManyDP.per_property_dependenciesc	             C   sä   | j r¤t || jjd¡}	t || jjd¡}
|sl|rL|j ||f||	fg¡ q¢|j ||f||f||	fg¡ qà|rŠ|j ||
f|
|fg¡ qà|j ||
f|
|fg¡ n<|sÈ|j ||f||f||fg¡ n|j ||f||fg¡ d S )NFT)r   r   rn   r   r-   ro   rp   )r   r)   Úsave_parentÚdelete_parentr@   r0   r1   r>   rB   rq   rr   r   r   r    r=   g  s8    z"OneToManyDP.per_state_dependenciesc             C   s´   | j j o| jdk }x˜|D ]}| || j| j¡}|rxF|jD ]<}|d k	r>|  |¡dkr>| j jrp|j	|dd q>| 	|¡ q>W |rx(|j
D ]}|d k	rŠ|j	|d| jd qŠW qW d S )NÚallFT)r>   Údelete)Ú	operationr   )r   rv   r   rI   r   r   rA   r&   Údelete_orphanÚregister_objectÚ	unchangedr   )r   rD   r;   Úshould_null_fksr'   rM   r?   r   r   r    rE   ª  s    
zOneToManyDP.presort_deletesc          	   C   sn  |  d| ft¡}| jj o$| jdk }x@|D ]6}|  ||¡}|rJ| jrRtj}ntj	}| 
|| j|¡}|r*x*|jD ] }	|	d k	rv|j|	dd| jd qvW | |j¡ x‚|jD ]x}	| jjsÔ|rÒ|j|	dd| jd q®|  |	¡dkr®|j|	dd| jd x.| j d|	¡D ]\}
}}}|j|dd	 qW q®W |r.|r.x2|jD ](}	|	d k	r:|j|	d| jd
| jd q:W q.W d S )NÚchildren_addedru   TÚadd)Zcancel_deleterw   r   Frv   )r>   rw   r   )r>   z	pk change)rw   r   )r^   r_   r   rx   r   rf   r   r   r   r   rI   r   Úaddedry   r   rp   rA   r&   r   Úcascade_iteratorrz   )r   rD   r;   r|   r{   r'   Úpks_changedrK   rM   r?   ÚcÚmÚst_Údct_r   r   r    rF   Å  sZ    



zOneToManyDP.presort_savesc          
   C   sú   | j s| jdksö| d| ft¡}xÔ|D ]Ì}| || j| j¡}|r&xR|jD ]H}|d k	rH|  |¡dkrH|  	||d d|d¡ | j rH|rH|  
|||g¡ qHW | j s¢| jjs&xNt|jƒ |¡D ]:}|d k	r´|  	||d d|d¡ | j r´|r´|  
|||g¡ q´W q&W d S )Nru   r|   FT)r   r   r^   r_   rI   r   r   rA   r&   rW   re   r   rv   rz   Ú
difference)r   rD   r;   r|   r'   rM   r?   r   r   r    rG     s,    



zOneToManyDP.process_deletesc          
   C   sê   | j j o| jdk }xÎ|D ]Æ}| || jtj¡}|rx@|jD ]6}|  ||d d|d¡ |d k	r>| j	r>|  
|||g¡ q>W x8|jD ].}|r€| j js€|  |¡s€|  ||d d|d¡ q€W |  ||¡rx"|jD ]}|  ||d d|d¡ qÆW qW d S )Nru   FT)r   rx   r   rI   r   r   r   r~   rW   r   re   rA   r&   rf   rz   )r   rD   r;   r{   r'   rM   r?   r   r   r    rH   /  s*    


zOneToManyDP.process_savesc       	   	   C   sp   |}|}|   |¡ |d ks*| js.| |¡r.d S |rHt || j| jj¡ n$t || j	|| j| jj|| j
oh|¡ d S )N)rS   r   Ú
is_deletedr   Úclearr   r   r   Úpopulater   r   )	r   r'   r?   rU   rV   rD   r€   ÚsourceÚdestr   r   r    rW   Q  s     
zOneToManyDP._synchronizec             C   s   t  ||| j| jj¡S )N)r   Úsource_modifiedr   r   r   )r   rD   r'   r   r   r    rf   h  s    zOneToManyDP._pks_changedN)rh   rj   rk   r/   r=   rE   rF   rG   rH   rW   rf   r   r   r   r    rm   =  s   )C>,"rm   c               @   sN   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	ddd„Z
dS )ÚManyToOneDPc             C   s"   t  | |¡ | jj t|ƒ¡ d S )N)r   r!   r   Z_dependency_processorsr<   ÚDetectKeySwitch)r   r   r   r   r    r!   o  s    zManyToOneDP.__init__c       
   
   C   sŠ   | j rbt || jjd¡}t || jjd¡}	|j ||f||f||f||	f||	f|	|f|	|fg¡ n$|j ||f||f||f||fg¡ d S )NFT)r   r   rn   r   r-   ro   rp   )
r   r)   r2   r3   r4   r5   r0   r1   Úparent_post_updatesÚparent_pre_updatesr   r   r    r/   s  s$    z%ManyToOneDP.per_property_dependenciesc	             C   sÜ   | j rŒ|sZt || jjd¡}	|r:|j ||	f|	|fg¡ qŠ|j ||f||f||	fg¡ qØt || jjd¡}
|j ||
f|
|f|
|fg¡ nL|sÂ|s®|j ||f||fg¡ qØ|j ||fg¡ n|rØ|j ||fg¡ d S )NFT)r   r   rn   r   r-   ro   rp   )r   r)   rs   rt   r@   r0   r1   r>   rB   rŽ   r   r   r   r    r=   ›  s2    z"ManyToOneDP.per_state_dependenciesc             C   s°   | j js| j jr¬xš|D ]’}| || j| j¡}|r| j jrB| ¡ }n| ¡ }x\|D ]T}|d kr^qP|j|dd| j	d | j
 d|¡}x"|D ]\}}	}
}|j|
dd q†W qPW qW d S )NTrv   )r>   rw   r   )r>   )r   rv   rx   rI   r   r   ÚsumZnon_deletedry   r   r   r   )r   rD   r;   r'   rM   Ztodeleter?   Útr   r‚   rƒ   r„   r   r   r    rE   Õ  s&    



zManyToOneDP.presort_deletesc             C   s¦   x |D ]˜}|j |d| jd | jjr| || j| j¡}|rxb|jD ]X}|  |¡dkrB|j |dd| jd | j	 
d|¡}x"|D ]\}}}	}
|j |	dd q|W qBW qW d S )Nr}   )rw   r   FTrv   )r>   rw   r   )r>   )ry   r   r   rx   rI   r   r   rA   r&   r   r   )r   rD   r;   r'   rM   r?   r‘   r   r‚   rƒ   r„   r   r   r    rF   í  s     

zManyToOneDP.presort_savesc             C   sr   | j rn| jjsn| jdksnxT|D ]L}|  |d d d|¡ |r| j r| || j| j¡}|r| j||| 	¡ dd qW d S )Nru   T)rd   )
r   r   rx   r   rW   rI   r   r   re   r   )r   rD   r;   r'   rM   r   r   r    rG     s    


zManyToOneDP.process_deletesc          
   C   s†   x€|D ]x}|  || jtj¡}|r|jrLx>|jD ]}|  ||d d|d¡ q.W n|jrf|  |d d d|d¡ | jr|  ||| 	¡ ¡ qW d S )NFr}   Trv   )
rI   r   r   r   r~   rW   rA   r   re   r   )r   rD   r;   r'   rM   r?   r   r   r    rH     s    
zManyToOneDP.process_savesNc          	   C   s¦   |d ks| j s| |¡rd S |d k	rX|d k	rX|j |¡sXt dt |¡|| jf ¡ d S |sd|d krzt	 
|| j| jj¡ n(|  |¡ t	 || j|| j| jj|d¡ d S )NzGObject of type %s not in session, %s operation along '%s' won't proceedF)r   r†   ÚsessionÚ_contains_stater   ÚwarnÚ
mapperutilÚstate_class_strr   r   r‡   r   r   rS   rˆ   r   )r   r'   r?   rU   rV   rD   rw   r   r   r    rW   )  s*    	
zManyToOneDP._synchronize)N)rh   rj   rk   r!   r/   r=   rE   rF   rG   rH   rW   r   r   r   r    rŒ   n  s   (:rŒ   c               @   sh   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ ZdS )r   a”  For many-to-one relationships with no one-to-many backref,
    searches for parents through the unit of work when a primary
    key has changed and updates them.

    Theoretically, this approach could be expanded to support transparent
    deletion of objects referenced via many-to-one as well, although
    the current attribute system doesn't do enough bookkeeping for this
    to be efficient.

    c             C   s<   | j jr,| jrd S ddd„ | j jD ƒkr,d S | | d¡ d S )NFc             s   s   | ]}|j V  qd S )N)r   )rX   r   r   r   r    ú	<genexpr>d  s   z=DetectKeySwitch.per_property_preprocessors.<locals>.<genexpr>)r   r[   r   r(   )r   r)   r   r   r    r*   ^  s    z*DetectKeySwitch.per_property_preprocessorsc             C   s6   t  || jj¡}t  || dd¡}|j ||fg¡ d S )NF)r   r,   r   r8   r+   ro   rp   )r   r)   r2   r0   r   r   r    r6   k  s    z*DetectKeySwitch.per_property_flush_actionsc             C   s   d S )Nr   )r   r)   r;   r>   r   r   r    rC   p  s    z'DetectKeySwitch.per_state_flush_actionsc             C   s   d S )Nr   )r   rD   r;   r   r   r    rE   s  s    zDetectKeySwitch.presort_deletesc             C   s   | j s|  ||¡ d S )N)r   Ú_process_key_switches)r   r)   r;   r   r   r    rF   v  s    zDetectKeySwitch.presort_savesc             C   s"   |s| j r|  ||¡}t|ƒS dS )NF)r   Ú_key_switchersÚbool)r   r)   r;   r>   Údr   r   r    rN   |  s    
z DetectKeySwitch.prop_has_changesc             C   s   dst ‚d S )NF)r7   )r   rD   r;   r   r   r    rG   ƒ  s    zDetectKeySwitch.process_deletesc             C   s   | j s
t‚|  ||¡ d S )N)r   r7   r˜   )r   rD   r;   r   r   r    rH   †  s    
zDetectKeySwitch.process_savesc             C   s^   |  d| fdd„ ¡\}}| |¡}x6|D ].}||kr(|  ||¡rL| |¡ q(| |¡ q(W |S )NZpk_switchersc               S   s   t ƒ t ƒ fS )N)r_   r   r   r   r    Ú<lambda>  s    z0DetectKeySwitch._key_switchers.<locals>.<lambda>)r^   Úunionrf   r}   )r   r)   r;   ZswitchedZnotswitchedZ	allstatesrL   r   r   r    r™   Ž  s    

zDetectKeySwitch._key_switchersc          
   C   s¶   |   ||¡}|r²x |jj ¡ D ]}t|j| jjƒs4q|j}| | j	¡j
||| jd}|tjk	r|d k	rt || j	 ¡}||kr| |d| j¡ t || j|| j| jj|| j¡ qW d S )N)rK   F)r™   r’   Zidentity_mapZ
all_statesÚ
issubclassrR   r   r:   r%   r   Úgetr   r   ZPASSIVE_NO_RESULTZinstance_statery   r   r   rˆ   r   r   r   )r   ZdeplistrD   Z	switchersr'   Zdict_rc   Zrelated_stater   r   r    r˜   œ  s,    
z%DetectKeySwitch._process_key_switchesc             C   s    t |jƒot ||| j| jj¡S )N)rš   r   r   r‹   r   r   r   )r   rD   r'   r   r   r    rf   »  s    zDetectKeySwitch._pks_changedN)rh   rj   rk   Ú__doc__r*   r6   rC   rE   rF   rN   rG   rH   r™   r˜   rf   r   r   r   r    r   R  s   
r   c               @   sT   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dd„ Z
dd„ ZdS )ÚManyToManyDPc          
   C   s:   |j  ||f||f||f||f||f||f||fg¡ d S )N)ro   rp   )r   r)   r2   r3   r4   r5   r0   r1   r   r   r    r/   Â  s    z&ManyToManyDP.per_property_dependenciesc	       	      C   sX   |s<|r"|j  ||f||fg¡ qT|j  ||f||fg¡ n|j  ||f||fg¡ d S )N)ro   rp   )	r   r)   rs   rt   r@   r0   r1   r>   rB   r   r   r    r=   Þ  s    z#ManyToManyDP.per_state_dependenciesc             C   s*   | j s&x|D ]}| || j| j¡ qW d S )N)r   rI   r   r   )r   rD   r;   r'   r   r   r    rE   ÷  s    
zManyToManyDP.presort_deletesc       
      C   sÆ   | j s2x*|D ]"}|  ||¡r| || jtj¡}qW | jjs>d S x‚|D ]z}| || jtj¡}|rDx^|j	D ]T}|  
|¡dkrf|j|dd| jd x,| j d|¡D ]\}}}}	|j|dd qœW qfW qDW d S )NFTrv   )r>   rw   r   )r>   )r   rf   rI   r   r   r   r   rx   r   rA   r&   ry   r   r   r   )
r   rD   r;   r'   rM   r?   r   r‚   rƒ   r„   r   r   r    rF     s*    


zManyToManyDP.presort_savesc          
      sÖ   g }g }g }|   |¡}tƒ }x’|D ]Š‰ | ˆ | j| j¡}|r"xR| ¡ D ]F}	|	d ksF|d k	rhˆ |	f|krhqFi }
|  ˆ |	|
d|d¡s‚qF| |
¡ qFW | ‡ fdd„| ¡ D ƒ¡ q"W |d k	rÂ| |¡ |  	||||¡ d S )NFrv   c             3   s   | ]}|ˆ fV  qd S )Nr   )rX   r   )r'   r   r    r—   D  s    z/ManyToManyDP.process_deletes.<locals>.<genexpr>)
r`   r_   rI   r   r   Z	non_addedrW   r<   rp   Ú	_run_crud)r   rD   r;   Úsecondary_deleteÚsecondary_insertÚsecondary_updateÚ	processedÚtmprM   r?   rU   r   )r'   r    rG   %  s8    

 
zManyToManyDP.process_deletesc          
      s˜  g }g }g }|   |¡}tƒ }xP|D ]F‰ | j o<|  |ˆ ¡}|rJtj}	ntj}	| ˆ | j|	¡}
|
r$xH|
j	D ]>}|d k	r†ˆ |f|kr†qli }|  
ˆ ||d|d¡s ql| |¡ qlW xH|
jD ]>}|d k	rÐˆ |f|krÐq¶i }|  
ˆ ||d|d¡sêq¶| |¡ q¶W | ‡ fdd„|
j	|
j D ƒ¡ |r$xN|
jD ]D}i }t ˆ | j|d| jj¡ t || j|d| jj¡ | |¡ q$W q$W |d k	r„| |¡ |  ||||¡ d S )NFr}   rv   c             3   s   | ]}|ˆ fV  qd S )Nr   )rX   r   )r'   r   r    r—   w  s    z-ManyToManyDP.process_saves.<locals>.<genexpr>Úold_)r`   r_   r   rf   r   r   r   rI   r   r~   rW   r<   rA   rp   rz   r   r   r   r   r   Úsecondary_synchronize_pairsr¢   )r   rD   r;   r£   r¤   r¥   r¦   r§   Zneed_cascade_pksrK   rM   r?   rU   r   )r'   r    rH   M  sn    
 



zManyToManyDP.process_savesc                s  |j  | j¡}|r~|d ‰ | j tj‡ fdd„| jjD ƒŽ ¡}| ||¡}| 	¡ r~|j
t|ƒkr~t d| jjt|ƒ|j
f ¡‚|rî|d ‰ | j tj‡ fdd„| jjD ƒŽ ¡}| ||¡}| 	¡ rî|j
t|ƒkrît d| jjt|ƒ|j
f ¡‚|r
| j ¡ }| ||¡ d S )Né    c                s,   g | ]$}|j ˆ kr|tj|j |jd k‘qS ))Útype_)r   r   Ú	bindparamÚtype)rX   r   )rU   r   r    rZ   Ÿ  s   z*ManyToManyDP._run_crud.<locals>.<listcomp>zRDELETE statement on table '%s' expected to delete %d row(s); Only %d were matched.c                s0   g | ](}|j ˆ kr|tjd |j  |jdk‘qS )r¨   )r«   )r   r   r¬   r­   )rX   r   )rU   r   r    rZ   ¹  s   zRUPDATE statement on table '%s' expected to update %d row(s); Only %d were matched.)ZtransactionÚ
connectionr   r   rv   r   Úand_r   ZexecuteZsupports_sane_multi_rowcountZrowcountÚlenr   ZStaleDataErrorZdescriptionrp   Úinsert)r   rD   r¤   r¥   r£   r®   Z	statementÚresultr   )rU   r    r¢   •  s@    


zManyToManyDP._run_crudc             C   s€   |   |¡ |d krdS |d k	rP|j |¡sP|jsLt dt |¡|| jf ¡ dS t	 
|| j|| jj¡ t	 
|| j|| jj¡ dS )NFzGObject of type %s not in session, %s operation along '%s' won't proceedT)rS   r’   r“   rA   r   r”   r•   r–   r   r   Zpopulate_dictr   r   r   r©   )r   r'   r?   rU   rV   rD   rw   r   r   r    rW   Ò  s"    

zManyToManyDP._synchronizec             C   s   t  ||| j| jj¡S )N)r   r‹   r   r   r   )r   rD   r'   r   r   r    rf   ó  s    zManyToManyDP._pks_changedN)rh   rj   rk   r/   r=   rE   rF   rG   rH   r¢   rW   rf   r   r   r   r    r¡   Á  s   "(H=!r¡   N)r    Ú r   r   r   r   r   r•   Z
interfacesr   r   r	   r   r   Úobjectr   rm   rŒ   r   r¡   r"   r   r   r   r    Ú<module>
   s4     &  3 eo  ;