a
    µb  ã                   @   s´   d dl mZ d dlmZ d dlmZmZ d dlmZ G dd„ dƒZ	e	ƒ a
dd„ Zdd
d„Zdd„ Zdd„ ZG dd„ dƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZdd„ Zd	S )é    )Údefaultdict)Úapps)ÚconnectionsÚrouter)ÚDatabaseErrorc                   @   s(   e Zd Zg Zdd„ Zdd„ Zdd„ ZdS )ÚTriggerRegistryc                 C   s   | j  |jjj|jjg¡ d S ©N)Ú_fieldsÚappendÚmodelÚ_metaÚ	app_labelÚ__name__©ÚselfÚfield© r   úQ/home/httpd/docs/test/DocsMgr/lib/python3.9/site-packages/concurrency/triggers.pyr
      s    zTriggerRegistry.appendc                 C   s
   t | jƒS r   )Úiterr	   ©r   r   r   r   Ú__iter__   s    zTriggerRegistry.__iter__c                 C   s   |j jj|j jg}|| jv S r   )r   r   r   r   r	   )r   r   Útargetr   r   r   Ú__contains__   s    zTriggerRegistry.__contains__N)r   Ú
__module__Ú__qualname__r	   r
   r   r   r   r   r   r   r   
   s   r   c                 C   s(   | j r| j }nd | | jj¡}d |¡S )z<

    :param field: Field instance
    :return: unicode
    z{1.db_table}_{0.name}zconcurrency_{})Z_trigger_nameÚformatr   r   )r   Únamer   r   r   Úget_trigger_name   s    r   Nc                 C   sH   | d u rdd„ t D ƒ} i }| D ]$}t | }t|ƒ}| ¡ }|||< q|S )Nc                 S   s   g | ]}|‘qS r   r   )Ú.0Úaliasr   r   r   Ú
<listcomp>*   ó    z get_triggers.<locals>.<listcomp>)r   ÚfactoryÚget_list)Ú	databasesÚretr   Ú
connectionÚfÚrr   r   r   Úget_triggers(   s    
r)   c            	      G   s|   t dd„ ƒ}tD ]f\}}t ||¡}|jj}t |¡}|| v rt| }t	|ƒ}| 
|¡ d|_||  |||jg¡ qq|S )Nc                   S   s   g S r   r   r   r   r   r   Ú<lambda>7   r!   zdrop_triggers.<locals>.<lambda>F)r   Ú	_TRIGGERSr   Ú	get_modelÚ_concurrencymetar   r   Údb_for_writer   r"   ÚdropÚ_trigger_existsr
   Útrigger_name)	r$   r%   r   Ú
model_namer   r   r   r&   r'   r   r   r   Údrop_triggers5   s    

r3   c           
      C   s�   t dd„ ƒ}tD ]z\}}t ||¡}|jj}|jj}t |¡}|| v r||vr| 	|¡ t
| }t|ƒ}	|	 |¡ ||  	|||jg¡ qq|S )Nc                   S   s   g S r   r   r   r   r   r   r*   I   r!   z!create_triggers.<locals>.<lambda>)r   r+   r   r,   r-   r   Ztriggersr   r.   r
   r   r"   Úcreater1   )
r$   r%   r   r2   r   r   Zstorager   r&   r'   r   r   r   Úcreate_triggersG   s    


r5   c                   @   sL   e Zd ZdZdZdZdZdd„ Zdd„ Zdd„ Z	d	d
„ Z
dd„ Zdd„ ZdS )ÚTriggerFactorya  
    Abstract Factory class to create triggers.
    Implemementations need to set the following attributes

    `update_clause`, `drop_clause` and `list_clause`

    Those will be formatted using standard python `format()` as::

         self.update_clause.format(trigger_name=field.trigger_name,
                                            opts=field.model._meta,
                                            field=field)
    So as example::

        update_clause =  """CREATE TRIGGER {trigger_name}
                    AFTER UPDATE ON {opts.db_table}
                    BEGIN UPDATE {opts.db_table}
                    SET {field.column} = {field.column}+1
                    WHERE {opts.pk.column} = NEW.{opts.pk.column};
                    END;
                    """

    Ú c                 C   s
   || _ d S r   )r&   )r   r&   r   r   r   Ú__init__w   s    zTriggerFactory.__init__c                 C   s   |j |  ¡ v r|j S d S r   )r1   r#   r   r   r   r   Úget_triggerz   s    zTriggerFactory.get_triggerc              
   C   s|   |j |  ¡ vrr| jj|j |jj|d�}z| j ¡  |¡ W qr t	yn } zt
d ||¡ƒ‚W Y d }~qrd }~0 0 n d|_d S )N©r1   Úoptsr   zError executing:
{1}
{0}T)r1   r#   Úupdate_clauser   r   r   r&   ÚcursorÚexecuteÚBaseExceptionr   r0   )r   r   ÚstmÚexcr   r   r   r4      s    
þþzTriggerFactory.createc                 C   s@   |j j}g }| jj|j||d�}| j ¡  |¡ | |j¡ |S )Nr:   )	r   r   Údrop_clauser   r1   r&   r=   r>   r
   )r   r   r;   r%   r@   r   r   r   r/   Ž   s    
þzTriggerFactory.dropc                 C   s   | j  ¡ }| | j¡ | ¡ S r   )r&   r=   r>   Úlist_clauseZfetchall)r   r=   r   r   r   Ú_list˜   s    
zTriggerFactory._listc                 C   s   t dd„ |  ¡ D ƒƒS )Nc                 S   s   g | ]}|d  ‘qS )r   r   )r   Úmr   r   r   r    ž   r!   z+TriggerFactory.get_list.<locals>.<listcomp>)ÚsortedrD   r   r   r   r   r#   �   s    zTriggerFactory.get_listN)r   r   r   Ú__doc__r<   rB   rC   r8   r9   r4   r/   rD   r#   r   r   r   r   r6   \   s   
r6   c                   @   s   e Zd ZdZdZdZdS )ÚSqlite3ú&DROP TRIGGER IF EXISTS {trigger_name};z´CREATE TRIGGER {trigger_name}
AFTER UPDATE ON {opts.db_table}
BEGIN UPDATE {opts.db_table} SET {field.column} = {field.column}+1 WHERE {opts.pk.column} = NEW.{opts.pk.column};
END;z4select name from sqlite_master where type='trigger';N©r   r   r   rB   r<   rC   r   r   r   r   rH   ¡   s   rH   c                   @   s   e Zd ZdZdZdZdS )Ú
PostgreSQLz9DROP TRIGGER IF EXISTS {trigger_name} ON {opts.db_table};aD  CREATE OR REPLACE FUNCTION func_{trigger_name}()
    RETURNS TRIGGER as
    '
    BEGIN
       NEW.{field.column} = OLD.{field.column} +1;
        RETURN NEW;
    END;
    ' language 'plpgsql';

CREATE TRIGGER {trigger_name} BEFORE UPDATE
    ON {opts.db_table} FOR EACH ROW
    EXECUTE PROCEDURE func_{trigger_name}();
    zBselect tgname from pg_trigger where tgname LIKE 'concurrency_%%'; NrJ   r   r   r   r   rK   ¬   s   rK   c                   @   s   e Zd ZdZdZdZdS )ÚMySQLrI   z|
CREATE TRIGGER {trigger_name} BEFORE UPDATE ON {opts.db_table}
FOR EACH ROW SET NEW.{field.column} = OLD.{field.column}+1;
zSHOW TRIGGERSNrJ   r   r   r   r   rL   À   s   rL   c                 C   sH   ddl m} |j}z|| j | ƒW S  tyB   td | ¡ƒ‚Y n0 d S )Nr   )Úconfz*{} is not supported by TriggerVersionField)Zconcurrency.configrM   ZTRIGGERS_FACTORYÚvendorÚKeyErrorÚ
ValueErrorr   )ZconnrM   Úmappingr   r   r   r"   Ë   s    r"   )N)Úcollectionsr   Zdjango.appsr   Z	django.dbr   r   Zdjango.db.utilsr   r   r+   r   r)   r3   r5   r6   rH   rK   rL   r"   r   r   r   r   Ú<module>   s   
E