U
    ڲg\                     @  s  U d Z ddlmZ ddlZddlZddlmZmZmZm	Z	 ddl
mZ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mZmZ ddlmZ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'm(Z(m)Z)m*Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0 ddl1m2Z2 ddl3m4Z4 e	r\ddl5m6Z6m7Z7 ddl8m9Z9 e*dZ:ej;j<Z<ej;j=Z=ej>j?Z?ej>j@Z@ejAjBZBejAjCZCejAjDZDejEjFZFejEjGZGe2H ZIeJdZKG dd deZLdeL_MeejNgdf ZOdePd < eeLgdf ZQdePd!< G d"d# d#ee! ZRdS )$z
psycopg connection objects
    )annotationsN)CallableGeneric
NamedTupleTYPE_CHECKING)refReferenceType)warn)partial   )pq)errors)postgres)
generators)PQGen	PQGenConnQuery)
ComposableSQL)Xid)Row)AdaptersMap)IsolationLevel)LiteralStringSelf	TypeAliasTypeVar)connection_summary)BasePipeline)PrepareManager)capabilities)ConnectionInfo)PGconnPGresult)BasePool	CursorRowZpsycopgc                   @  s*   e Zd ZU dZded< ded< ded< dS )Notifyz8An asynchronous notification received from the database.strZchannelpayloadintpidN)__name__
__module____qualname____doc____annotations__ r0   r0   </tmp/pip-unpacked-wheel-b_ea6rx_/psycopg/_connection_base.pyr&   ;   s
   
r&   r   NoticeHandlerNotifyHandlerc                   @  s  e Zd ZdZejZejZejZejZej	Z	ej
Z
ejZejZejZejZddddZdddd	Zd
dddZeddddZeddddZeddddZejdddddZdddddZdddddZeddddZejdddddZddddd Zdddd!d"Zed#dd$d%Zejd#ddd&d%Zd#ddd'd(Zd#ddd)d*Zed#dd+d,Zejd#ddd-d,Zd#ddd.d/Z d#ddd0d1Z!d
dd2d3d4Z"ed5dd6d7Z#ed8dd9d:Z$ed;dd<d=Z%d>dd?d@Z&dddAdBZ'dddCdDZ(dEdFdGdHdIZ)dJddKdLdMZ*dJddKdNdOZ+e,dPdQddRdSdTZ-dUddKdVdWZ.dUddKdXdYZ/e,dPdZdd[d\d]Z0ed^dd_d`Z1e1jd^dddad`Z1ed^ddbdcZ2e2jd^dddddcZ2e3ddfdgd
dEdhdidjdkZ4e5fdldmdndodpdqZ6drddsdtduZ7dddvdwZ8dddxdyZ9dzdd{d|Z:ddd}d~Z;ddddZ<d>d
d
ddddZ=dddddZ>ddddZ?ddddddZ@ddddZAdS )BaseConnectionz
    Base class for different types of connections.

    Share common functionalities such as access to the wrapped PGconn, but
    allow different interfaces (sync/async).
    r"   )pgconnc                 C  s   || _ d| _d | _g | _g | _d| _d| _t | _d | _	t
| }ttj||_ttj||_|  d | _|  d | _d | _d | _d| _d S )NFr       )r5   _autocommit	_adapters_notice_handlers_notify_handlers_num_transactions_closedr   	_prepared_tpcr   r
   r4   _notice_handlerZnotice_handler_notify_handlerZnotify_handler	_pipeline_isolation_level
_read_only_deferrable_begin_statement)selfr5   wselfr0   r0   r1   __init__b   s&    zBaseConnection.__init__None)returnc                 C  s<   t | dsd S | jrd S t | dr&d S td|  dt d S )Nr5   _poolzconnection zV was deleted while still open. Please use 'with' or '.close()' to close the connection)hasattrclosedr	   ResourceWarningrF   r0   r0   r1   __del__   s    


zBaseConnection.__del__r'   c                 C  s>   | j j d| j j }t| j}d| d| dt| ddS )N.< z at 0xx>)	__class__r,   r-   r   r5   id)rF   clsinfor0   r0   r1   __repr__   s    
zBaseConnection.__repr__boolc                 C  s   | j jtkS )z$`!True` if the connection is closed.)r5   statusBADrO   r0   r0   r1   rM      s    zBaseConnection.closedc                 C  s   | j jtko| j S )z
        `!True` if the connection was interrupted.

        A broken connection is always `closed`, but wasn't closed in a clean
        way, such as using `close()` or a `!with` block.
        )r5   r\   r]   r<   rO   r0   r0   r1   broken   s    zBaseConnection.brokenc                 C  s   | j S )z'The autocommit state of the connection.)r7   rO   r0   r0   r1   
autocommit   s    zBaseConnection.autocommit)valuerJ   c                 C  s   |  | d S N)_set_autocommitrF   r`   r0   r0   r1   r_      s    c                 C  s   t d S ra   NotImplementedErrorrc   r0   r0   r1   rb      s    zBaseConnection._set_autocommitzPQGen[None]c                 c  s   |  dE d H  t|| _d S )Nr_   )_check_intrans_genr[   r7   rc   r0   r0   r1   _set_autocommit_gen   s    z"BaseConnection._set_autocommit_genzIsolationLevel | Nonec                 C  s   | j S )zX
        The isolation level of the new transactions started on the connection.
        )rB   rO   r0   r0   r1   isolation_level   s    zBaseConnection.isolation_levelc                 C  s   |  | d S ra   )_set_isolation_levelrc   r0   r0   r1   rh      s    c                 C  s   t d S ra   rd   rc   r0   r0   r1   ri      s    z#BaseConnection._set_isolation_levelc                 c  s0   |  dE d H  |d k	r t|nd | _d| _d S )Nrh   r6   )rf   r   rB   rE   rc   r0   r0   r1   _set_isolation_level_gen   s    z'BaseConnection._set_isolation_level_genzbool | Nonec                 C  s   | j S )zX
        The read-only state of the new transactions started on the connection.
        )rC   rO   r0   r0   r1   	read_only   s    zBaseConnection.read_onlyc                 C  s   |  | d S ra   )_set_read_onlyrc   r0   r0   r1   rk      s    c                 C  s   t d S ra   rd   rc   r0   r0   r1   rl      s    zBaseConnection._set_read_onlyc                 c  s0   |  dE d H  |d k	r t|nd | _d| _d S )Nrk   r6   )rf   r[   rC   rE   rc   r0   r0   r1   _set_read_only_gen   s    z!BaseConnection._set_read_only_genc                 C  s   | j S )zY
        The deferrable state of the new transactions started on the connection.
        )rD   rO   r0   r0   r1   
deferrable   s    zBaseConnection.deferrablec                 C  s   |  | d S ra   )_set_deferrablerc   r0   r0   r1   rn      s    c                 C  s   t d S ra   rd   rc   r0   r0   r1   ro      s    zBaseConnection._set_deferrablec                 c  s0   |  dE d H  |d k	r t|nd | _d| _d S )Nrn   r6   )rf   r[   rD   rE   rc   r0   r0   r1   _set_deferrable_gen   s    z"BaseConnection._set_deferrable_gen)	attributerJ   c                 c  sr   | j j}|tkr.| jr.| j E d H  | j j}|tkrn| jrPtd|dntd|dt	|j
 d S )Nzcan't change z2 now: connection.transaction() context in progressz' now: connection in transaction status )r5   transaction_statusIDLErA   	_sync_genr;   eProgrammingErrorr   TransactionStatusname)rF   rq   r\   r0   r0   r1   rf      s    
z!BaseConnection._check_intrans_genr!   c                 C  s
   t | jS )z>A `ConnectionInfo` attribute to inspect connection properties.)r!   r5   rO   r0   r0   r1   rY     s    zBaseConnection.infor   c                 C  s   | j sttj| _ | j S ra   )r8   r   r   adaptersrO   r0   r0   r1   ry     s    zBaseConnection.adapterszBaseConnection[Row]c                 C  s   | S ra   r0   rO   r0   r0   r1   
connection  s    zBaseConnection.connectionr)   c                 C  s   | j jS )zReturn the file descriptor of the connection.

        This function allows to use the connection as file-like object in
        functions waiting for readiness, such as the ones defined in the
        `selectors` module.
        )r5   socketrO   r0   r0   r1   fileno  s    zBaseConnection.filenoc                 C  s   |   r| j }|  dS )z/Cancel the current operation on the connection.N)_should_cancelr5   Z
get_cancelcancel)rF   cr0   r0   r1   r~   "  s    
zBaseConnection.cancelc                 C  s(   | j r
dS | jr$| jd r$tddS )zhCheck whether the current command should actually be cancelled when
        invoking cancel*().
        Fr   z=cancel() cannot be used with a prepared two-phase transactionT)rM   r>   ru   rv   rO   r0   r0   r1   r}   (  s    zBaseConnection._should_cancelfloatzPQGenConn[None])timeoutrJ   c                c  s*   | j  }|  tj||dE d H  d S )Nr   )r5   cancel_connstartr   r~   )rF   r   r   r0   r0   r1   _cancel_gen7  s    
zBaseConnection._cancel_genr2   )callbackrJ   c                 C  s   | j | dS )z
        Register a callable to be invoked when a notice message is received.

        :param callback: the callback to call upon message received.
        :type callback: Callable[[~psycopg.errors.Diagnostic], None]
        N)r9   appendrF   r   r0   r0   r1   add_notice_handler<  s    z!BaseConnection.add_notice_handlerc                 C  s   | j | dS )z
        Unregister a notice message callable previously registered.

        :param callback: the callback to remove.
        :type callback: Callable[[~psycopg.errors.Diagnostic], None]
        N)r9   remover   r0   r0   r1   remove_notice_handlerE  s    z$BaseConnection.remove_notice_handlerz"ReferenceType[BaseConnection[Row]]r#   )rG   resrJ   c                 C  sr   |  }|r|j sd S t||jj}|j D ]B}z|| W q* tk
rj } ztd|| W 5 d }~X Y q*X q*d S )Nz)error processing notice callback '%s': %s)r9   ru   
Diagnosticr5   	_encoding	Exceptionlogger	exception)rG   r   rF   Zdiagcbexr0   r0   r1   r?   N  s    

zBaseConnection._notice_handlerr3   c                 C  s   | j | dS )z
        Register a callable to be invoked whenever a notification is received.

        :param callback: the callback to call upon notification received.
        :type callback: Callable[[~psycopg.Notify], None]
        N)r:   r   r   r0   r0   r1   add_notify_handler]  s    z!BaseConnection.add_notify_handlerc                 C  s   | j | dS )z
        Unregister a notification callable previously registered.

        :param callback: the callback to remove.
        :type callback: Callable[[~psycopg.Notify], None]
        N)r:   r   r   r0   r0   r1   remove_notify_handlerf  s    z$BaseConnection.remove_notify_handlerzpq.PGnotify)rG   pgnrJ   c                 C  sR   |  }|r|j sd S |jj}t|j||j||j}|j D ]}|| q@d S ra   )r:   r5   r   r&   ZrelnamedecodeextraZbe_pid)rG   r   rF   encnr   r0   r0   r1   r@   o  s    

zBaseConnection._notify_handlerz
int | Nonec                 C  s   | j jS )a&  
        Number of times a query is executed before it is prepared.

        - If it is set to 0, every query is prepared the first time it is
          executed.
        - If it is set to `!None`, prepared statements are disabled on the
          connection.

        Default value: 5
        r=   prepare_thresholdrO   r0   r0   r1   r   |  s    z BaseConnection.prepare_thresholdc                 C  s   || j _d S ra   r   rc   r0   r0   r1   r     s    c                 C  s   | j j}|tjkr|S dS )z
        Maximum number of prepared statements on the connection.

        `!None` means no max number of prepared statements. The default value
        is 100.
        N)r=   prepared_maxsysmaxsize)rF   rvr0   r0   r1   r     s    zBaseConnection.prepared_maxc                 C  s   |d krt j}|| j_d S ra   )r   r   r=   r   rc   r0   r0   r1   r     s     g        r   zPQGenConn[Self])conninfor   rJ   c                c  s    t j||dE dH }| |}|S )z?Generator to connect to the database and create a new instance.r   N)r   connect)rX   r   r   r5   connr0   r0   r1   _connect_gen  s    zBaseConnection._connect_genr   z	pq.FormatzPQGen[PGresult | None])commandresult_formatrJ   c                 c  s  |    t|tr"|| jj}nt|tr6|| }| jrpt	| jj
|d|d}| jj| | jjd dS |tkr| j| n| jj
|d|d t| jE dH d }|jtkr|jtkr|jtkrtj|| jjdn$tdt|jj d| |S )z
        Generator to send a command and receive the result to the backend.

        Only used to implement internal commands such as "commit", with eventual
        arguments bound client-side. The cursor can do more complex stuff.
        N)r   encodingunexpected result z from command )_check_connection_ok
isinstancer'   encoder5   r   r   as_bytesrA   r
   Zsend_query_paramscommand_queuer   result_queueTEXTZ
send_queryr   executer\   
COMMAND_OK	TUPLES_OKFATAL_ERRORru   error_from_resultInterfaceErrorr   
ExecStatusrx   r   )rF   r   r   cmdresultr0   r0   r1   _exec_command  s4    	



zBaseConnection._exec_commandzbytes | None)rx   rJ   c                 c  s   |dkst s4|dk	rd| nd}| |E dH  dS |   | jrpt| jj|}| jj| | jj	d dS | j| t
| jE dH d }|jtkr|jtkrtj|| jjdntdt|jj ddS )ae  
        Deallocate one, or all, prepared statement in the session.

        ``name == None`` stands for DEALLOCATE ALL.

        If possible, use protocol-level commands; otherwise use SQL statements.

        Note that PgBouncer doesn't support DEALLOCATE name, but it supports
        protocol-level Close from 1.21 and DEALLOCATE ALL from 1.22.
        Ns   DEALLOCATE s   DEALLOCATE ALLr   r   r   z0 from sending closing prepared statement message)_HAS_SEND_CLOSEr   r   rA   r
   r5   Zsend_close_preparedr   r   r   r   r   r\   r   r   ru   r   r   r   r   r   rx   )rF   rx   Zstmtr   r   r0   r0   r1   _deallocate  s*    

zBaseConnection._deallocatec                 C  s>   | j jtkrd S | j jtkr&tdtd| j j d S )Nzthe connection is closedz7cannot execute operations: the connection is in status )r5   r\   OKr]   ru   OperationalErrorr   rO   r0   r0   r1   r     s    
z#BaseConnection._check_connection_okc                 c  sH   | j r
dS | jjtkrdS | |  E dH  | jrD| j E dH  dS )z.Generator to start a transaction if necessary.N)r7   r5   rr   rs   r   _get_tx_start_commandrA   rt   rO   r0   r0   r1   _start_query  s    zBaseConnection._start_querybytesc                 C  s   | j r| j S dg}| jd k	rHt| j}|d ||jdd  | jd k	rf|| jr`dnd | jd k	r|| jr~dnd d		|| _ | j S )
Ns   BEGINs   ISOLATION LEVEL_rS   s	   READ ONLYs
   READ WRITEs
   DEFERRABLEs   NOT DEFERRABLE    )
rE   rh   r   r   rx   replacer   rk   rn   join)rF   partsvalr0   r0   r1   r     s    




z$BaseConnection._get_tx_start_commandc                 c  sZ   | j rtd| jr td| jjtkr0dS | dE dH  | jrV| j	 E dH  dS )z-Generator implementing `Connection.commit()`.zExplicit commit() forbidden within a Transaction context. (Transaction will be automatically committed on successful exit from context.)z6commit() cannot be used during a two-phase transactionNs   COMMIT)
r;   ru   rv   r>   r5   rr   rs   r   rA   rt   rO   r0   r0   r1   _commit_gen2  s    zBaseConnection._commit_genc                 c  s   | j rtd| jr td| jr6| j E dH  | jjtkrFdS | 	dE dH  | j
  | j
| E dH  | jr| j E dH  dS )z/Generator implementing `Connection.rollback()`.zExplicit rollback() forbidden within a Transaction context. (Either raise Rollback() or allow an exception to propagate out of the context.)z8rollback() cannot be used during a two-phase transactionNs   ROLLBACK)r;   ru   rv   r>   rA   rt   r5   rr   rs   r   r=   clearZmaintain_genrO   r0   r0   r1   _rollback_genF  s"    
zBaseConnection._rollback_genr   )	format_idgtridbqualrJ   c                 C  s   |    t|||S )aL  
        Returns a `Xid` to pass to the `!tpc_*()` methods of this connection.

        The argument types and constraints are explained in
        :ref:`two-phase-commit`.

        The values passed to the method will be available on the returned
        object as the members `~Xid.format_id`, `~Xid.gtrid`, `~Xid.bqual`.
        )
_check_tpcr   Z
from_parts)rF   r   r   r   r0   r0   r1   xida  s    
zBaseConnection.xidz	Xid | str)r   rJ   c                 c  sv   |    t|tst|}| jjtkrDtdt	
| jjj | jrTtd|df| _| |  E d H  d S )Nz8can't start two-phase transaction: connection in status z3can't use two-phase transactions in autocommit modeF)r   r   r   from_stringr5   rr   rs   ru   rv   r   rw   rx   r7   r>   r   r   rF   r   r0   r0   r1   _tpc_begin_genn  s    


zBaseConnection._tpc_begin_genc                 c  sp   | j std| j d r$td| j d }|df| _ | tdt|E d H  | jrl| j E d H  d S )Nz='tpc_prepare()' must be called inside a two-phase transactionr   zF'tpc_prepare()' cannot be used during a prepared two-phase transactionr   TzPREPARE TRANSACTION {})	r>   ru   rv   r   r   formatr'   rA   rt   r   r0   r0   r1   _tpc_prepare_gen  s    


zBaseConnection._tpc_prepare_genr   zXid | str | None)actionr   rJ   c                 c  s   d|   d}|d kr:| js.t| d| jd }n*| jrPt| dt|tsdt|}| jr| jd st| d|   d}d | _| E d H  n*| t	d	
t	|t|E d H  d | _d S )
NZtpc_z()z? without xid must must be called inside a two-phase transactionr   z= with xid must must be called outside a two-phase transactionr   r   _genz{} PREPARED {})lowerr>   ru   rv   r   r   r   getattrr   r   r   r'   )rF   r   r   fnamemethr0   r0   r1   _tpc_finish_gen  s*    


zBaseConnection._tpc_finish_genc                 C  s   dS )z0Raise NotSupportedError if TPC is not supported.Nr0   rO   r0   r0   r1   r     s    zBaseConnection._check_tpcN)r   )Br+   r,   r-   r.   ru   WarningErrorr   ZDatabaseErrorZ	DataErrorr   ZIntegrityErrorZInternalErrorrv   ZNotSupportedErrorrH   rP   rZ   propertyrM   r^   r_   setterrb   rg   rh   ri   rj   rk   rl   rm   rn   ro   rp   rf   rY   ry   rz   r|   r~   r}   r   r   r   staticmethodr?   r   r   r@   r   r   classmethodr   r   r   r   r   r   r   r   r   r   r   r   r   r   r0   r0   r0   r1   r4   N   s   #						
 	.'r4   )Sr.   
__future__r   r   loggingtypingr   r   r   r   weakrefr   r   warningsr	   	functoolsr
   r   r   r   ru   r   r   abcr   r   r   Zsqlr   r   r>   r   Zrowsr   Zadaptr   Z_enumsr   _compatr   r   r   r   Zpq.miscr   rA   r   Z
_preparingr   Z_capabilitiesr    Z_connection_infor!   Zpq.abcr"   r#   Zpsycopg_pool.baser$   r%   ZFormatr   ZBINARYZ
ConnStatusr   r]   r   r   r   r   rw   rs   ZINTRANSZhas_send_close_preparedr   	getLoggerr   r&   r,   r   r2   r/   r3   r4   r0   r0   r0   r1   <module>   sV   
