U
    ڲg                     @  s   U d Z ddlmZ ddlmZmZ ddlmZmZm	Z	 ddl
mZ ddlmZ ddlmZ dd	lmZmZ dd
lmZ e	rddlmZ ddlmZ dZded< ejjZejjZG dd deZG dd dZdS )z!
Support for prepared statements
    )annotations)IntEnumauto)AnySequenceTYPE_CHECKING)OrderedDict   )pq)PQGen)Deque	TypeAlias)PostgresQuery)PGresult)BaseConnectionztuple[bytes, tuple[int, ...]]r   Keyc                   @  s   e Zd Ze Ze Ze ZdS )PrepareN)__name__
__module____qualname__r   NOYESSHOULD r   r   6/tmp/pip-unpacked-wheel-b_ea6rx_/psycopg/_preparing.pyr      s   r   c                   @  s   e Zd ZU dZded< dZded< ddd	d
ZedddddZd0ddddddZ	ddddddZ
edddddZdddd Zddd!d"d#d$d%Zddd!ddd&d'd(Zddd)d*Zd+d,d-d.d/ZdS )1PrepareManager   z
int | Noneprepare_thresholdd   intprepared_maxNone)returnc                 C  s&   t  | _t  | _d| _td  | _d S )Nr   zbytes | None)r   _counts_names_prepared_idxr   	_to_flushselfr   r   r   __init__)   s    zPrepareManager.__init__r   r   )queryr"   c                 C  s   | j | jfS )N)r*   types)r*   r   r   r   key5   s    zPrepareManager.keyNzbool | Noneztuple[Prepare, bytes])r*   preparer"   c                 C  s   |dks| j dkrtjdfS | |}| j|}|r@tj|fS | j|d}|| j ks\|rd| j 	 }|  jd7  _tj
|fS tjdfS dS )zP
        Check if a query is prepared, tell back whether to prepare it.
        FN    r   Z_pg3_r	   )r   r   r   r,   r$   getr   r#   r%   encoder   )r(   r*   r-   r,   namecountr   r   r   r/   9   s    



zPrepareManager.getr   zSequence[PGresult]bool)prepresultsr"   c                 C  sR   | j s|tjkrN|D ]8}|jtkr$q|j}|r|ds@|dkr|    S qdS )zCheck if we need to discard our entire state: it should happen on
        rollback or on dropping objects, because the same object may get
        recreated and postgres would fail internal lookups.
        s   DROP s   ROLLBACKF)r$   r   r   status
COMMAND_OKZcommand_status
startswithclear)r(   r4   r5   resultZcmdstatr   r   r   _should_discardS   s    
zPrepareManager._should_discard)r5   r"   c                 C  s:   t | dkrdS | d j}t|  kr.tkr6n ndS dS )zCReturn False if 'results' are invalid for prepared statement cache.r	   Fr   T)lenr6   r7   	TUPLES_OK)r5   r6   r   r   r   _check_resultsa   s    
zPrepareManager._check_resultsc                 C  sP   t | j| jkr| jjdd t | j| jkrL| jjddd }| j| dS )zEvict an old value from the cache.

        If it was prepared, deallocate it. Do it only once: if the cache was
        resized, deallocate gradually.
        F)lastr	   N)r<   r#   r    popitemr$   r&   append)r(   r1   r   r   r   _rotateo   s
    zPrepareManager._rotatebytesz
Key | None)r*   r4   r1   r"   c                 C  s   | j dkrdS | |}|| jkrb|tjkr@| j|= || j|< n| j|  d7  < | j| dS || jkr|| j| dS |tjkr|| j|< n
d| j|< |S dS )zHandle 'query' for possible addition to the cache.

        If a new entry has been added, return its key. Return None otherwise
        (meaning the query is already in cache or cache is not enabled).
        Nr	   )r   r,   r#   r   r   r$   move_to_end)r(   r*   r4   r1   r,   r   r   r   maybe_add_to_cache|   s"    	






z!PrepareManager.maybe_add_to_cache)r,   r4   r1   r5   r"   c                 C  sD   |  ||rdS | |s8| j|d | j|d n|   dS )zValidate cached entry with 'key' by checking query 'results'.

        Possibly record a command to perform maintenance on database side.
        N)r;   r>   r$   popr#   rB   )r(   r,   r4   r1   r5   r   r   r   validate   s    
zPrepareManager.validatec                 C  s<   | j   | jr4| j  | j  | jd dS dS dS )zClear the cache of the maintenance commands.

        Clear the internal state and prepare a command to clear the state of
        the server.
        NTF)r#   r9   r$   r&   rA   r'   r   r   r   r9      s    


zPrepareManager.clearzBaseConnection[Any]zPQGen[None])connr"   c                 c  s&   | j r"| j  }||E dH  q dS )z
        Generator to send the commands to perform periodic maintenance

        Deallocate unneeded command in the server, or flush the prepared
        statements server state entirely if necessary.
        N)r&   popleftZ_deallocate)r(   rH   r1   r   r   r   maintain_gen   s    
zPrepareManager.maintain_gen)N)r   r   r   r   __annotations__r    r)   staticmethodr,   r/   r;   r>   rB   rE   rG   r9   rJ   r   r   r   r   r   "   s   
 !r   N) __doc__
__future__r   enumr   r   typingr   r   r   collectionsr    r
   abcr   _compatr   r   Z_queriesr   Zpq.abcr   Z_connection_baser   r   rK   Z
ExecStatusr7   r=   r   r   r   r   r   r   <module>   s    