o
    h                    @   s  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlZd dlZd dlZd dl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dZd2ddddddddddddddeejdddddddZG dd dZG dd dZ G dd dej!Z"G dd  d Z#G d!d" d"Z$e%d#g d$Z&d%e&_'e%d&g d'Z(d(e(_'d)d* Z)d3d,d-Z*d.d/ Z+d0d1 Z,d a-dS )4    N   )compat)connect_utils)cursor)
exceptions)introspection)prepared_stmt)protocol)serverversion)transaction)utilsc                   @   s   e Zd Zdd ZdS )ConnectionMetac                 C   s   t |j}t|v pt|v S N)type__mro__
Connection_ConnectionProxy)clsinstancemro r   f/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/asyncpg/connection.py__instancecheck__&   s   
z ConnectionMeta.__instancecheck__N)__name__
__module____qualname__r   r   r   r   r   r   $   s    r   c                   @   s  e Zd ZdZdZdejdejf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 d!d"d#Zd$d% Zdd&d'ed(ed)efd*d+Zdd&d,ed(efd-d.Zd d/d dd0d1d2Zd3d4 Zd5d6 Zdddd7d8d9Zdddd:d;d<Zddd dd=d>e fd?d@Z!dddAd)e"fdBdCZ#dDddEdFdGZ$dddAdHdIZ%dddAd(efdJdKZ&dddddddddddddLdMdNZ'dddddddddddO
dPdQZ(dddddddddddddddddRdSdTZ)dddddUdVdWZ*dXdY Z+dddddddddddddZd[d\Z,d]d^ Z-d_d` Z.dadbdcdddeZ/dadfdgdhZ0daddcdidjZ1dkdl Z2dd&dmdnZ3dodp Z4dqdr Z5dd&dsdtZ6dudv Z7dwdx Z8dydz Z9d{d| Z:d}d~ Z;dd Z<dd Z=dd Z>dd Z?dd Z@dd ZAdd ZBdd ZCdd ZDdd ZEdd ZFdd ZGdddZHdd ZIdd ZJdd ZKdd ZLdd ZMd d ddddZNeOjPdd ZQeOjPdd ZRd d ddddZS	 	dddZT	/dd ddddZUdS )r   zyA representation of a database session.

    Connections are created by calling :func:`~asyncpg.connection.connect`.
    )	_protocol
_transport_loop	_top_xact_aborted_pool_release_ctr_stmt_cache_stmts_to_close_stmt_cache_enabled
_listeners_server_version_server_caps_intro_query_reset_query_proxy_stmt_exclusive_section_config_params_addr_log_listeners_termination_listeners_cancellations_source_traceback_query_loggers__weakref__configparamsc           	   	   C   s  || _ || _|| _d | _d| _d| _|| _|| _|| _t	||j
ttt| |jd| _t | _|j
dk| _i | _t | _t | _t | _t | _| j  }|j}t|| _t| j|| _ | jdk rit!j"| _#nt!j$| _#d | _%d | _&t' | _(|) rt* | _+d S d | _+d S )NFr   )loopmax_size	on_removemax_lifetime)   r   ),r   r   r   r   r    r!   r.   r,   r-   _StatementCachestatement_cache_size	functoolspartial_weak_maybe_gc_stmtweakrefrefmax_cached_statement_lifetimer"   setr#   r$   r%   r/   r1   r0   r3   get_settingsserver_versionr
   split_server_version_stringr&   _detect_server_capabilitiesr'   r   INTRO_LOOKUP_TYPES_13r(   INTRO_LOOKUP_TYPESr)   r*   _Atomicr+   	get_debug_extract_stackr2   )	selfr	   	transportr7   addrr5   r6   settings
ver_stringr   r   r   __init__;   sP   



	
zConnection.__init__c                 C   s`   |   s*| jd ur,| jrd| | j}nd| }t|t | j  s.|   d S d S d S d S )Nz)unclosed connection {!r}; created at:
 {}z^unclosed connection {!r}; run in asyncio debug mode to show the traceback of connection origin)		is_closedr   r2   formatwarningswarnResourceWarningr   	terminate)rN   msgr   r   r   __del__{   s   
zConnection.__del__c                    sV   |    || jvr| dt|I dH  t | j|< | j| t	| dS )aU  Add a listener for Postgres notifications.

        :param str channel: Channel to listen on.

        :param callable callback:
            A callable or a coroutine function receiving the following
            arguments:
            **connection**: a Connection the callback is registered with;
            **pid**: PID of the Postgres server that sent the notification;
            **channel**: name of the channel the notification was sent to;
            **payload**: the payload.

        .. versionchanged:: 0.24.0
            The ``callback`` argument may be a coroutine function.
        z	LISTEN {}N)
_check_openr%   fetchrU   r   _quote_identrD   add	_Callbackfrom_callable)rN   channelcallbackr   r   r   add_listener   s   
zConnection.add_listenerc                    s~   |   rdS || jvrdS t|}|| j| vrdS | j| | | j| s=| j|= | dt|I dH  dS dS )z5Remove a listening callback on the specified channel.NzUNLISTEN {})	rT   r%   r`   ra   remover]   rU   r   r^   )rN   rb   rc   cbr   r   r   remove_listener   s   


 zConnection.remove_listenerc                 C   s(   |   r	td| jt| dS )a{  Add a listener for Postgres log messages.

        It will be called when asyncronous NoticeResponse is received
        from the connection.  Possible message types are: WARNING, NOTICE,
        DEBUG, INFO, or LOG.

        :param callable callback:
            A callable or a coroutine function receiving the following
            arguments:
            **connection**: a Connection the callback is registered with;
            **message**: the `exceptions.PostgresLogMessage` message.

        .. versionadded:: 0.12.0

        .. versionchanged:: 0.24.0
            The ``callback`` argument may be a coroutine function.
        connection is closedN)rT   r   InterfaceErrorr/   r_   r`   ra   rN   rc   r   r   r   add_log_listener   s   
zConnection.add_log_listenerc                 C      | j t| dS )zXRemove a listening callback for log messages.

        .. versionadded:: 0.12.0
        N)r/   discardr`   ra   rj   r   r   r   remove_log_listener   s   zConnection.remove_log_listenerc                 C   rl   )a  Add a listener that will be called when the connection is closed.

        :param callable callback:
            A callable or a coroutine function receiving one argument:
            **connection**: a Connection the callback is registered with.

        .. versionadded:: 0.21.0

        .. versionchanged:: 0.24.0
            The ``callback`` argument may be a coroutine function.
        N)r0   r_   r`   ra   rj   r   r   r   add_termination_listener   s   z#Connection.add_termination_listenerc                 C   rl   )a   Remove a listening callback for connection termination.

        :param callable callback:
            The callable or coroutine function that was passed to
            :meth:`Connection.add_termination_listener`.

        .. versionadded:: 0.21.0
        N)r0   rm   r`   ra   rj   r   r   r   remove_termination_listener      	z&Connection.remove_termination_listenerc                 C   rl   )aa  Add a logger that will be called when queries are executed.

        :param callable callback:
            A callable or a coroutine function receiving one argument:
            **record**, a LoggedQuery containing `query`, `args`, `timeout`,
            `elapsed`, `exception`, `conn_addr`, and `conn_params`.

        .. versionadded:: 0.29.0
        N)r3   r_   r`   ra   rj   r   r   r   add_query_logger   s   
zConnection.add_query_loggerc                 C   rl   )zRemove a query logger callback.

        :param callable callback:
            The callable or coroutine function that was passed to
            :meth:`Connection.add_query_logger`.

        .. versionadded:: 0.29.0
        N)r3   rm   r`   ra   rj   r   r   r   remove_query_logger   rq   zConnection.remove_query_loggerc                 C   
   | j  S )zAReturn the PID of the Postgres server the connection is bound to.)r   get_server_pidrN   r   r   r   ru      s   
zConnection.get_server_pidc                 C      | j S )av  Return the version of the connected PostgreSQL server.

        The returned value is a named tuple similar to that in
        ``sys.version_info``:

        .. code-block:: pycon

            >>> con.get_server_version()
            ServerVersion(major=9, minor=6, micro=1,
                          releaselevel='final', serial=0)

        .. versionadded:: 0.8.0
        )r&   rv   r   r   r   get_server_version   s   zConnection.get_server_versionc                 C   rt   )z\Return connection settings.

        :return: :class:`~asyncpg.ConnectionSettings`.
        )r   rE   rv   r   r   r   rE     s   
zConnection.get_settingsNF)	isolationreadonly
deferrablec                C   s   |    t| |||S )al  Create a :class:`~transaction.Transaction` object.

        Refer to `PostgreSQL documentation`_ on the meaning of transaction
        parameters.

        :param isolation: Transaction isolation mode, can be one of:
                          `'serializable'`, `'repeatable_read'`,
                          `'read_uncommitted'`, `'read_committed'`. If not
                          specified, the behavior is up to the server and
                          session, which is usually ``read_committed``.

        :param readonly: Specifies whether or not this transaction is
                         read-only.

        :param deferrable: Specifies whether or not this transaction is
                           deferrable.

        .. _`PostgreSQL documentation`:
                https://www.postgresql.org/docs/
                current/static/sql-set-transaction.html
        )r\   r   Transaction)rN   ry   rz   r{   r   r   r   r     s   zConnection.transactionc                 C   rt   )zReturn True if Connection is currently inside a transaction.

        :return bool: True if inside transaction, False otherwise.

        .. versionadded:: 0.16.0
        )r   is_in_transactionrv   r   r   r   r}   1  s   
zConnection.is_in_transaction)timeoutqueryr~   returnc                   s   |    |s:| jr.| ||| | j||I dH }W d   |S 1 s'w   Y  |S | j||I dH }|S | j||d|ddI dH \}}}| S )a  Execute an SQL command (or commands).

        This method can execute many SQL commands at once, when no arguments
        are provided.

        Example:

        .. code-block:: pycon

            >>> await con.execute('''
            ...     CREATE TABLE mytab (a int);
            ...     INSERT INTO mytab (a) VALUES (100), (200), (300);
            ... ''')
            INSERT 0 3

            >>> await con.execute('''
            ...     INSERT INTO mytab (a) VALUES ($1), ($2)
            ... ''', 10, 20)
            INSERT 0 2

        :param args: Query arguments.
        :param float timeout: Optional timeout value in seconds.
        :return str: Status of the last SQL command.

        .. versionchanged:: 0.5.4
           Made it possible to pass query arguments.
        Nr   T)return_status)r\   r3   _time_and_logr   r   _executedecode)rN   r   r~   argsresult_statusr   r   r   execute:  s(   
zConnection.executecommandc                   s   |    | |||I dH S )a  Execute an SQL *command* for each sequence of arguments in *args*.

        Example:

        .. code-block:: pycon

            >>> await con.executemany('''
            ...     INSERT INTO mytab (a) VALUES ($1, $2, $3);
            ... ''', [(1, 2, 3), (4, 5, 6)])

        :param command: Command to execute.
        :param args: An iterable containing sequences of arguments.
        :param float timeout: Optional timeout value in seconds.
        :return None: This method discards the results of the operations.

        .. versionadded:: 0.7.0

        .. versionchanged:: 0.11.0
           `timeout` became a keyword-only parameter.

        .. versionchanged:: 0.22.0
           ``executemany()`` is now an atomic operation, which means that
           either all executions succeed, or none at all.  This is in contrast
           to prior versions, where the effect of already-processed iterations
           would remain in place when an error has occurred, unless
           ``executemany()`` was called in a transaction.
        Nr\   _executemany)rN   r   r   r~   r   r   r   executemanyi  s   zConnection.executemanyT)named	use_cacheignore_custom_codecrecord_classc                   sn  |d u r| j  }nt| |r0| j|||f}|d ur |S | jo/| jj p/t|| jjk}t	|t
r8|}n|s<|rB| d}nd}| j j|||||dI d H }d}	| }
d}|
r| j  }| |
|I d H \}}|| |j ox|j }	| }
|d7 }|dkrtd||
s\|  |	s|js| js|  |r| j|||f| | jr|  I d H  |S )	Nstmt r   r   Fr   r      zCcould not resolve query result and/or argument types in {} attempts)r   get_record_class_check_record_classr"   getr$   r,   max_cacheable_statement_sizelen
isinstancestr_get_unique_idprepare_init_typesrE   _introspect_typesregister_data_typesnamer   InternalClientErrorrU   _init_codecsmark_unpreparedputr#   _cleanup_stmts)rN   r   r~   r   r   r   r   	statement	stmt_nameneed_repreparetypes_with_missing_codecstriesrQ   types
intro_stmtr   r   r   _get_statement  sv   




	
zConnection._get_statementc                    s   | j jr)z| jddd|ddI d H \}}|d d }W n tjy(   d}Y nw d}| j| jt|fd|ddI d H }|dkrN| jd|fd|ddI d H  |S )	Nz
                    SELECT
                        current_setting('jit') AS cur,
                        set_config('jit', 'off', false) AS new
                    r   r   T)r   curoffzY
                SELECT
                    set_config('jit', $1, false)
                )r'   jit_Connection__executer   UndefinedObjectErrorr(   list)rN   typeoidsr~   cfgrowr   	jit_stater   r   r   r   r     s>   zConnection._introspect_typesc                    s   |dkr#|  tjv r#tj|   }| jtj|gdd ddI d H }n| jtj||gdd ddI d H }|s=td|||d S )N
pg_catalogr   T)limitr~   r   r   zunknown type: {}.{})	lowerr	   BUILTIN_TYPE_NAME_MAPr   r   TYPE_BY_OIDTYPE_BY_NAME
ValueErrorrU   )rN   typenameschematypeoidrowsr   r   r   _introspect_type  s.   
zConnection._introspect_type)prefetchr~   r   c             	   G   s   |    t| |d||||S )a  Return a *cursor factory* for the specified query.

        :param args:
            Query arguments.
        :param int prefetch:
            The number of rows the *cursor iterator*
            will prefetch (defaults to ``50``.)
        :param float timeout:
            Optional timeout in seconds.
        :param type record_class:
            If specified, the class to use for records returned by this cursor.
            Must be a subclass of :class:`~asyncpg.Record`.  If not specified,
            a per-connection *record_class* is used.

        :return:
            A :class:`~cursor.CursorFactory` object.

        .. versionchanged:: 0.22.0
            Added the *record_class* parameter.
        N)r\   r   CursorFactory)rN   r   r   r~   r   r   r   r   r   r   4  s   zConnection.cursor)r   r~   r   c                   s   | j |||d|dI dH S )a}  Create a *prepared statement* for the specified query.

        :param str query:
            Text of the query to create a prepared statement for.
        :param str name:
            Optional name of the returned prepared statement.  If not
            specified, the name is auto-generated.
        :param float timeout:
            Optional timeout value in seconds.
        :param type record_class:
            If specified, the class to use for records returned by the
            prepared statement.  Must be a subclass of
            :class:`~asyncpg.Record`.  If not specified, a per-connection
            *record_class* is used.

        :return:
            A :class:`~prepared_stmt.PreparedStatement` instance.

        .. versionchanged:: 0.22.0
            Added the *record_class* parameter.

        .. versionchanged:: 0.25.0
            Added the *name* parameter.
        Fr   r~   r   r   N)_prepare)rN   r   r   r~   r   r   r   r   r   [  s    zConnection.preparer   r   c                   s>   |    | j|||d u rdn|||dI d H }t| ||S )NT)r   r   r   )r\   r   r   PreparedStatement)rN   r   r   r~   r   r   r   r   r   r   r     s   	zConnection._prepare)r~   r   c                   s$   |    | j||d||dI dH S )a  Run a query and return the results as a list of :class:`Record`.

        :param str query:
            Query text.
        :param args:
            Query arguments.
        :param float timeout:
            Optional timeout value in seconds.
        :param type record_class:
            If specified, the class to use for records returned by this method.
            Must be a subclass of :class:`~asyncpg.Record`.  If not specified,
            a per-connection *record_class* is used.

        :return list:
            A list of :class:`~asyncpg.Record` instances.  If specified, the
            actual type of list elements would be *record_class*.

        .. versionchanged:: 0.22.0
            Added the *record_class* parameter.
        r   r   Nr\   r   )rN   r   r~   r   r   r   r   r   r]     s   zConnection.fetchr   )columnr~   c                   s4   |    | ||d|I dH }|sdS |d | S )a  Run a query and return a value in the first row.

        :param str query: Query text.
        :param args: Query arguments.
        :param int column: Numeric index within the record of the value to
                           return (defaults to 0).
        :param float timeout: Optional timeout value in seconds.
                            If not specified, defaults to the value of
                            ``command_timeout`` argument to the ``Connection``
                            instance constructor.

        :return: The value of the specified column of the first record, or
                 None if no records were returned by the query.
        r   Nr   r   )rN   r   r   r~   r   datar   r   r   fetchval  s   zConnection.fetchvalc                   s4   |    | j||d||dI dH }|sdS |d S )a  Run a query and return the first row.

        :param str query:
            Query text
        :param args:
            Query arguments
        :param float timeout:
            Optional timeout value in seconds.
        :param type record_class:
            If specified, the class to use for the value returned by this
            method.  Must be a subclass of :class:`~asyncpg.Record`.
            If not specified, a per-connection *record_class* is used.

        :return:
            The first row as a :class:`~asyncpg.Record` instance, or None if
            no records were returned by the query.  If specified,
            *record_class* is used as the type for the result value.

        .. versionchanged:: 0.22.0
            Added the *record_class* parameter.
        r   r   Nr   r   )rN   r   r~   r   r   r   r   r   r   fetchrow  s   zConnection.fetchrowc                   s$   |    | j|||d|dI dH S )aa  Run a query for each sequence of arguments in *args*
        and return the results as a list of :class:`Record`.

        :param query:
            Query to execute.
        :param args:
            An iterable containing sequences of arguments for the query.
        :param float timeout:
            Optional timeout value in seconds.
        :param type record_class:
            If specified, the class to use for records returned by this method.
            Must be a subclass of :class:`~asyncpg.Record`.  If not specified,
            a per-connection *record_class* is used.

        :return list:
            A list of :class:`~asyncpg.Record` instances.  If specified, the
            actual type of list elements would be *record_class*.

        Example:

        .. code-block:: pycon

            >>> rows = await con.fetchmany('''
            ...         INSERT INTO mytab (a, b) VALUES ($1, $2) RETURNING a;
            ...     ''', [('x', 1), ('y', 2), ('z', 3)])
            >>> rows
            [<Record row=('x',)>, <Record row=('y',)>, <Record row=('z',)>]

        .. versionadded:: 0.30.0
        T)return_rowsr   Nr   )rN   r   r   r~   r   r   r   r   	fetchmany  s
   !
zConnection.fetchmany)columnsschema_namer~   rU   oids	delimiternullheaderquoteescapeforce_quoteencodingc                   s   t |}|rt |d | }|r!dddd |D }nd}| j||||	|
||||d	}dj|||d	}| |||I d
H S )a  Copy table contents to a file or file-like object.

        :param str table_name:
            The name of the table to copy data from.

        :param output:
            A :term:`path-like object <python:path-like object>`,
            or a :term:`file-like object <python:file-like object>`, or
            a :term:`coroutine function <python:coroutine function>`
            that takes a ``bytes`` instance as a sole argument.

        :param list columns:
            An optional list of column names to copy.

        :param str schema_name:
            An optional schema name to qualify the table.

        :param float timeout:
            Optional timeout value in seconds.

        The remaining keyword arguments are ``COPY`` statement options,
        see `COPY statement documentation`_ for details.

        :return: The status string of the COPY command.

        Example:

        .. code-block:: pycon

            >>> import asyncpg
            >>> import asyncio
            >>> async def run():
            ...     con = await asyncpg.connect(user='postgres')
            ...     result = await con.copy_from_table(
            ...         'mytable', columns=('foo', 'bar'),
            ...         output='file.csv', format='csv')
            ...     print(result)
            ...
            >>> asyncio.run(run())
            'COPY 100'

        .. _`COPY statement documentation`:
            https://www.postgresql.org/docs/current/static/sql-copy.html

        .. versionadded:: 0.11.0
        .({}), c                 s       | ]}t |V  qd S r   r   r^   .0cr   r   r   	<genexpr>V      z-Connection.copy_from_table.<locals>.<genexpr>r   	rU   r   r   r   r   r   r   r   r   z!COPY {tab}{cols} TO STDOUT {opts})tabcolsoptsN)r   r^   rU   join_format_copy_opts	_copy_out)rN   
table_nameoutputr   r   r~   rU   r   r   r   r   r   r   r   r   tabnamer   r   	copy_stmtr   r   r   copy_from_table  s$   
3zConnection.copy_from_table)
r~   rU   r   r   r   r   r   r   r   r   c                   sX   | j ||||||	|
||d	}|rt| ||I dH }dj||d}| |||I dH S )a  Copy the results of a query to a file or file-like object.

        :param str query:
            The query to copy the results of.

        :param args:
            Query arguments.

        :param output:
            A :term:`path-like object <python:path-like object>`,
            or a :term:`file-like object <python:file-like object>`, or
            a :term:`coroutine function <python:coroutine function>`
            that takes a ``bytes`` instance as a sole argument.

        :param float timeout:
            Optional timeout value in seconds.

        The remaining keyword arguments are ``COPY`` statement options,
        see `COPY statement documentation`_ for details.

        :return: The status string of the COPY command.

        Example:

        .. code-block:: pycon

            >>> import asyncpg
            >>> import asyncio
            >>> async def run():
            ...     con = await asyncpg.connect(user='postgres')
            ...     result = await con.copy_from_query(
            ...         'SELECT foo, bar FROM mytable WHERE foo > $1', 10,
            ...         output='file.csv', format='csv')
            ...     print(result)
            ...
            >>> asyncio.run(run())
            'COPY 10'

        .. _`COPY statement documentation`:
            https://www.postgresql.org/docs/current/static/sql-copy.html

        .. versionadded:: 0.11.0
        r   NzCOPY ({query}) TO STDOUT {opts})r   r   )r   r   _mogrifyrU   r   )rN   r   r   r~   rU   r   r   r   r   r   r   r   r   r   r   r   r   r   r   copy_from_querye  s   0zConnection.copy_from_query)r   r   r~   rU   r   freezer   r   r   r   r   r   force_not_null
force_nullr   wherec                   s   t |}|rt |d | }|r!dddd |D }nd}| |}| j||||	|
||||||d}dj||||d	}| |||I d
H S )aT  Copy data to the specified table.

        :param str table_name:
            The name of the table to copy data to.

        :param source:
            A :term:`path-like object <python:path-like object>`,
            or a :term:`file-like object <python:file-like object>`, or
            an :term:`asynchronous iterable <python:asynchronous iterable>`
            that returns ``bytes``, or an object supporting the
            :ref:`buffer protocol <python:bufferobjects>`.

        :param list columns:
            An optional list of column names to copy.

        :param str schema_name:
            An optional schema name to qualify the table.

        :param str where:
            An optional SQL expression used to filter rows when copying.

            .. note::

                Usage of this parameter requires support for the
                ``COPY FROM ... WHERE`` syntax, introduced in
                PostgreSQL version 12.

        :param float timeout:
            Optional timeout value in seconds.

        The remaining keyword arguments are ``COPY`` statement options,
        see `COPY statement documentation`_ for details.

        :return: The status string of the COPY command.

        Example:

        .. code-block:: pycon

            >>> import asyncpg
            >>> import asyncio
            >>> async def run():
            ...     con = await asyncpg.connect(user='postgres')
            ...     result = await con.copy_to_table(
            ...         'mytable', source='datafile.tbl')
            ...     print(result)
            ...
            >>> asyncio.run(run())
            'COPY 140000'

        .. _`COPY statement documentation`:
            https://www.postgresql.org/docs/current/static/sql-copy.html

        .. versionadded:: 0.11.0

        .. versionadded:: 0.29.0
            Added the *where* parameter.
        r   r   r   c                 s   r   r   r   r   r   r   r   r     r   z+Connection.copy_to_table.<locals>.<genexpr>r   )rU   r   r   r   r   r   r   r   r   r   r   )COPY {tab}{cols} FROM STDIN {opts} {cond}r   r   r   condN)r   r^   rU   r   _format_copy_wherer   _copy_in)rN   r   sourcer   r   r~   rU   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   copy_to_table  s(   
A
zConnection.copy_to_table)r   r   r~   r   c                   s   t |}|rt |d | }|r#ddd |D }d|}	nd}d}	dj||d	}
| j|
d
dI dH }| |}d}dj||	||d}| j|dd||j|I dH S )a	  Copy a list of records to the specified table using binary COPY.

        :param str table_name:
            The name of the table to copy data to.

        :param records:
            An iterable returning row tuples to copy into the table.
            :term:`Asynchronous iterables <python:asynchronous iterable>`
            are also supported.

        :param list columns:
            An optional list of column names to copy.

        :param str schema_name:
            An optional schema name to qualify the table.

        :param str where:
            An optional SQL expression used to filter rows when copying.

            .. note::

                Usage of this parameter requires support for the
                ``COPY FROM ... WHERE`` syntax, introduced in
                PostgreSQL version 12.


        :param float timeout:
            Optional timeout value in seconds.

        :return: The status string of the COPY command.

        Example:

        .. code-block:: pycon

            >>> import asyncpg
            >>> import asyncio
            >>> async def run():
            ...     con = await asyncpg.connect(user='postgres')
            ...     result = await con.copy_records_to_table(
            ...         'mytable', records=[
            ...             (1, 'foo', 'bar'),
            ...             (2, 'ham', 'spam')])
            ...     print(result)
            ...
            >>> asyncio.run(run())
            'COPY 2'

        Asynchronous record iterables are also supported:

        .. code-block:: pycon

            >>> import asyncpg
            >>> import asyncio
            >>> async def run():
            ...     con = await asyncpg.connect(user='postgres')
            ...     async def record_gen(size):
            ...         for i in range(size):
            ...             yield (i,)
            ...     result = await con.copy_records_to_table(
            ...         'mytable', records=record_gen(100))
            ...     print(result)
            ...
            >>> asyncio.run(run())
            'COPY 100'

        .. versionadded:: 0.11.0

        .. versionchanged:: 0.24.0
            The ``records`` argument may be an asynchronous iterable.

        .. versionadded:: 0.29.0
            Added the *where* parameter.
        r   r   c                 s   r   r   r   r   r   r   r   r   M  r   z3Connection.copy_records_to_table.<locals>.<genexpr>r   *r   z SELECT {cols} FROM {tab} LIMIT 1)r   r   T)r   Nz(FORMAT binary)r   r   )	r   r^   r   rU   r   r   r   copy_in_state)rN   r   recordsr   r   r~   r   r   col_listr   intro_queryintro_psr   r   r   r   r   r   copy_records_to_table  s*   
M

z Connection.copy_records_to_tablec                 C   s.   |r| j jstd|rd| }|S d}|S )Nz5the `where` parameter requires PostgreSQL 12 or laterzWHERE r   )r'   sql_copy_from_wherer   UnsupportedServerFeatureError)rN   r   where_clauser   r   r   r   a  s   zConnection._format_copy_where)rU   r   r   r   r   r   r   r   r   r   r   r   c                C   s   t t }|d g }|	d ur!t|	tr!|d |	r!|d | D ]4\}}|d urY|dv r@dddd |D  d	 }n|d
v rIt|}nt	
|}|d| | q%|redd| d	 S dS )NrN   r   zFORCE_QUOTE *)r   r   r   (r   c                 s   r   r   r   r   r   r   r   r   }  r   z/Connection._format_copy_opts.<locals>.<genexpr>))r   r   r   z{} {}r   )dictlocalspopr   boolappenditemsr   r   r   _quote_literalrU   upper)rN   rU   r   r   r   r   r   r   r   r   r   r   r   kwargsr   kvr   r   r   r   m  s&   





zConnection._format_copy_optsc                    s   zt |}W n ty   d }Y nw d }d}| jj|d ur-d t|dI d H  d}nt|dr5| nt|r<|}n
tdt	|j
|d u rS fdd}|}z| j|||I d H W |rf   S S |rn   w w )NFwbTwritez_output is expected to be a file-like object, a path-like object or a coroutine function, not {}c                    s   d  j | I d H  d S r   )r  )r   frun_in_executorr   r   _writer  s   z%Connection._copy_out.<locals>._writer)osfspath	TypeErrorr   r  openhasattrcallablerU   r   r   r   copy_outclose)rN   r   r   r~   pathwriteropened_by_usr  r   r  r   r     s<   


zConnection._copy_outc           	   	      s   zt |}W n ty   d }Y nw d  d }d }d}| jj|d ur1d t|dI d H  d}nt|dr9| nt|tj	j
rC|}n|} d urVG  fddd}| }z| j|||d d |I d H W |rqd  jI d H  S S |r~d  jI d H  w w )NFrbTreadc                       s"   e Zd Zdd Z fddZdS )z$Connection._copy_in.<locals>._Readerc                 S   s   | S r   r   rv   r   r   r   	__aiter__  s   z.Connection._copy_in.<locals>._Reader.__aiter__c                    s*   d  j dI d H }t|dkrt|S )Ni   r   )r)  r   StopAsyncIteration)rN   r   r  r   r   	__anext__  s
   z.Connection._copy_in.<locals>._Reader.__anext__N)r   r   r   r*  r,  r   r  r   r   _Reader  s    r-  )r  r  r  r   r  r   r!  r   collectionsabcAsyncIterabler   r   r$  )	rN   r   r   r~   r%  readerr   r'  r-  r   r  r   r     s>   

zConnection._copy_inpublictext)r   rU   c             
      s   |    | j }| ||I dH }g }t|rd}	n-t|r>|dkr-tjdddd}	| 	|d fd	I dH \}}
nt
d
| d| dt|rWtjdddd|d }||||||	||| |   dS )a2  Set an encoder/decoder pair for the specified data type.

        :param typename:
            Name of the data type the codec is for.

        :param schema:
            Schema name of the data type the codec is for
            (defaults to ``'public'``)

        :param format:
            The type of the argument received by the *decoder* callback,
            and the type of the *encoder* callback return value.

            If *format* is ``'text'`` (the default), the exchange datum is a
            ``str`` instance containing valid text representation of the
            data type.

            If *format* is ``'binary'``, the exchange datum is a ``bytes``
            instance containing valid _binary_ representation of the
            data type.

            If *format* is ``'tuple'``, the exchange datum is a type-specific
            ``tuple`` of values.  The table below lists supported data
            types and their format for this mode.

            +-----------------+---------------------------------------------+
            |  Type           |                Tuple layout                 |
            +=================+=============================================+
            | ``interval``    | (``months``, ``days``, ``microseconds``)    |
            +-----------------+---------------------------------------------+
            | ``date``        | (``date ordinal relative to Jan 1 2000``,)  |
            |                 | ``-2^31`` for negative infinity timestamp   |
            |                 | ``2^31-1`` for positive infinity timestamp. |
            +-----------------+---------------------------------------------+
            | ``timestamp``   | (``microseconds relative to Jan 1 2000``,)  |
            |                 | ``-2^63`` for negative infinity timestamp   |
            |                 | ``2^63-1`` for positive infinity timestamp. |
            +-----------------+---------------------------------------------+
            | ``timestamp     | (``microseconds relative to Jan 1 2000      |
            | with time zone``| UTC``,)                                     |
            |                 | ``-2^63`` for negative infinity timestamp   |
            |                 | ``2^63-1`` for positive infinity timestamp. |
            +-----------------+---------------------------------------------+
            | ``time``        | (``microseconds``,)                         |
            +-----------------+---------------------------------------------+
            | ``time with     | (``microseconds``,                          |
            | time zone``     | ``time zone offset in seconds``)            |
            +-----------------+---------------------------------------------+
            | any composite   | Composite value elements                    |
            | type            |                                             |
            +-----------------+---------------------------------------------+

        :param encoder:
            Callable accepting a Python object as a single argument and
            returning a value encoded according to *format*.

        :param decoder:
            Callable accepting a single argument encoded according to *format*
            and returning a decoded Python object.

        Example:

        .. code-block:: pycon

            >>> import asyncpg
            >>> import asyncio
            >>> import datetime
            >>> from dateutil.relativedelta import relativedelta
            >>> async def run():
            ...     con = await asyncpg.connect(user='postgres')
            ...     def encoder(delta):
            ...         ndelta = delta.normalized()
            ...         return (ndelta.years * 12 + ndelta.months,
            ...                 ndelta.days,
            ...                 ((ndelta.hours * 3600 +
            ...                    ndelta.minutes * 60 +
            ...                    ndelta.seconds) * 1000000 +
            ...                  ndelta.microseconds))
            ...     def decoder(tup):
            ...         return relativedelta(months=tup[0], days=tup[1],
            ...                              microseconds=tup[2])
            ...     await con.set_type_codec(
            ...         'interval', schema='pg_catalog', encoder=encoder,
            ...         decoder=decoder, format='tuple')
            ...     result = await con.fetchval(
            ...         "SELECT '2 years 3 mons 1 day'::interval")
            ...     print(result)
            ...     print(datetime.datetime(2002, 1, 1) + result)
            ...
            >>> asyncio.run(run())
            relativedelta(years=+2, months=+3, days=+1)
            2004-04-02 00:00:00

        .. versionadded:: 0.12.0
            Added the ``format`` keyword argument and support for 'tuple'
            format.

        .. versionchanged:: 0.12.0
            The ``binary`` keyword argument is deprecated in favor of
            ``format``.

        .. versionchanged:: 0.13.0
            The ``binary`` keyword argument was removed in favor of
            ``format``.

        .. versionchanged:: 0.29.0
            Custom codecs for composite types are now supported with
            ``format='tuple'``.

        .. note::

           It is recommended to use the ``'binary'`` or ``'tuple'`` *format*
           whenever possible and if the underlying type supports it. Asyncpg
           currently does not support text I/O for composite and range types,
           and some other functionality, such as
           :meth:`Connection.copy_to_table`, does not support types with text
           codecs.
        Nscalartuplez7only tuple-format codecs can be used on composite typeszUse `set_type_codec(..., format='tuple')` and pass/interpret data as a Python tuple.  See an example at https://magicstack.github.io/asyncpg/current/usage.html#example-decoding-complex-types)hint	compositeoid
   z cannot use custom codec on type r   z2: it is neither a scalar type nor a composite typez/custom codecs on domain types are not supportedzSet the codec on the base type.zePostgreSQL does not distinguish domains from their base types in query results at the protocol level.)r6  detail)r\   r   rE   r   r   is_scalar_typeis_composite_typer   UnsupportedClientFeatureErrorr   ri   is_domain_typeadd_python_codec_drop_local_statement_cache)rN   r   r   encoderdecoderrU   rQ   typeinfofull_typeinfoskindr   r8  r   r   r   set_type_codec  s@   y




	
zConnection.set_type_codec)r   c                   s8   |  ||I dH }| j |d || |   dS )a'  Reset *typename* codec to the default implementation.

        :param typename:
            Name of the data type the codec is for.

        :param schema:
            Schema name of the data type the codec is for
            (defaults to ``'public'``)

        .. versionadded:: 0.12.0
        Nr8  )r   r   rE   remove_python_codecr@  )rN   r   r   rC  r   r   r   reset_type_codec  s   

zConnection.reset_type_codecc                   sf   |    | ||I dH }t|std|||d }| j 	|||d|| | 
  dS )a  Set a builtin codec for the specified scalar data type.

        This method has two uses.  The first is to register a builtin
        codec for an extension type without a stable OID, such as 'hstore'.
        The second use is to declare that an extension type or a
        user-defined type is wire-compatible with a certain builtin
        data type and should be exchanged as such.

        :param typename:
            Name of the data type the codec is for.

        :param schema:
            Schema name of the data type the codec is for
            (defaults to ``'public'``).

        :param codec_name:
            The name of the builtin codec to use for the type.
            This should be either the name of a known core type
            (such as ``"int"``), or the name of a supported extension
            type.  Currently, the only supported extension type is
            ``"pg_contrib.hstore"``.

        :param format:
            If *format* is ``None`` (the default), all formats supported
            by the target codec are declared to be supported for *typename*.
            If *format* is ``'text'`` or ``'binary'``, then only the
            specified format is declared to be supported for *typename*.

        .. versionchanged:: 0.18.0
            The *codec_name* argument can be the name of any known
            core data type.  Added the *format* keyword argument.
        Nz"cannot alias non-scalar type {}.{}r8  r4  )r\   r   r   r;  r   ri   rU   r   rE   set_builtin_type_codecr@  )rN   r   r   
codec_namerU   rC  r8  r   r   r   rI    s   #

z!Connection.set_builtin_type_codecc                 C   s   | j p| j  S )zReturn ``True`` if the connection is closed, ``False`` otherwise.

        :return bool: ``True`` if the connection is closed, ``False``
                      otherwise.
        )r    r   is_connectedrv   r   r   r   rT     s   zConnection.is_closedc             	      sZ   z&z|   s| j|I dH  W n ttjfy    |    w W |   dS |   w )zClose the connection gracefully.

        :param float timeout:
            Optional timeout value in seconds.

        .. versionchanged:: 0.14.0
           Added the *timeout* parameter.
        N)rT   r   r$  	ExceptionasyncioCancelledError_abort_cleanup)rN   r~   r   r   r   r$    s   	zConnection.closec                 C   s   |   s|   |   dS )z:Terminate the connection without waiting for pending data.N)rT   rO  rP  rv   r   r   r   rY     s   zConnection.terminatec                    sx   |    | j  | j  | j s| jd ur:| jd u s"| jjs-| j	dd
| i d | _| dI d H  d S d S )Nmessagez4Resetting connection with an active transaction {!r}ROLLBACK)r\   r%   clearr/   r   r}   r   _managedr   call_exception_handlerrU   r   rv   r   r   r   _reset  s   

zConnection._resetc             	      s   t |4 I dH , |  I dH  |  }|r+| |I dH  W d  I dH  dS W d  I dH  dS 1 I dH s<w   Y  dS )a.  Reset the connection state.

        Calling this will reset the connection session state to a state
        resembling that of a newly obtained connection.  Namely, an open
        transaction (if any) is rolled back, open cursors are closed,
        all `LISTEN <https://www.postgresql.org/docs/current/sql-listen.html>`_
        registrations are removed, all session configuration
        variables are reset to their default values, and all advisory locks
        are released.

        Note that the above describes the default query returned by
        :meth:`Connection.get_reset_query`.  If one overloads the method
        by subclassing ``Connection``, then this method will do whatever
        the overloaded method returns, except open transactions are always
        terminated and any callbacks registered by
        :meth:`Connection.add_listener` or :meth:`Connection.add_log_listener`
        are removed.

        :param float timeout:
            A timeout for resetting the connection.  If not specified, defaults
            to no timeout.
        N)r   r~   rV  get_reset_queryr   )rN   r~   reset_queryr   r   r   reset  s   .zConnection.resetc                 C   s   d| _ | j  d | _d S )NT)r    r   abortrv   r   r   r   rO    s   

zConnection._abortc                 C   sP   |    | jd ur| jj  |   | j  | j  | j  | 	  d S r   )
_call_termination_listenersr*   _holder_release_on_close_mark_stmts_as_closedr%   rS  r/   r3   _clean_tasksrv   r   r   r   rP  "  s   



zConnection._cleanupc                 C   s4   | j r| j D ]
}| s|  q| j   d S d S r   )r1   donecancelrS  )rN   futr   r   r   r_  2  s   
zConnection._clean_tasksc                 C   s   |   r	tdd S )Nrh   )rT   r   ri   rv   r   r   r   r\   :  s   
zConnection._check_openc                 C   s   t d7 a d|t S )Nr   z__asyncpg_{}_{:x}__)_uidrU   )rN   prefixr   r   r   r   >  s   zConnection._get_unique_idc                 C   sD   | j  D ]}|  q| jD ]}|  q| j   | j  d S r   )r"   iter_statementsmark_closedr#   rS  rN   r   r   r   r   r^  C  s   



z Connection._mark_stmts_as_closedc                 C   sL   |j dkr |jr"| j|j|j|jfs$|  | j	| d S d S d S d S Nr   )
refsr   r"   hasr   r   r   rf  r#   r_   rg  r   r   r   _maybe_gc_stmtM  s   
zConnection._maybe_gc_stmtc                    s4   | j }t | _ |D ]}| j|tjI d H  q
d S r   )r#   rD   r   close_statementr	   
NO_TIMEOUT)rN   to_closer   r   r   r   r   `  s   zConnection._cleanup_stmtsc                    s  zpzt j| j| j| j| jj| jjdI d H  W nA ty3 } z|	 s)|
| W Y d }~n+d }~w tjy<   Y n ttjfyY } z|	 sO|
| W Y d }~nd }~ww W | jt| j |	 sp|d  d S d S | jt| j |	 s|d  w w )N)r7   rP   r6   backend_pidbackend_secret)r   _cancelr   r.   r-   r   ro  rp  ConnectionResetErrorr`  set_exceptionrM  rN  rL  r1   rm   current_task
set_result)rN   waiterexr   r   r   rq  k  s>   



zConnection._cancelc                 C   s   | j | j| | d S r   )r1   r_   r   create_taskrq  )rN   rv  r   r   r   _cancel_current_command  s   z"Connection._cancel_current_commandc                 C   s`   | j sd S tjj||d}|  }| j D ]}|jr$| j||| q| j	|j|| qd S )N)r   )
r/   r   PostgresLogMessagenew_unwrapis_asyncr   rx  rf   	call_soon)rN   fields
last_queryrQ  con_refrf   r   r   r   _process_log_message  s   
zConnection._process_log_messagec                 C   sV   | j sd S |  }| j D ]}|jr| j|| q| j|j| q| j   d S r   )r0   r|  r}  r   rx  rf   r~  rS  )rN   r  rf   r   r   r   r[    s   
z&Connection._call_termination_listenersc              	   C   s`   || j vrd S |  }| j | D ]}|jr"| j||||| q| j|j|||| qd S r   )r%   r|  r}  r   rx  rf   r~  )rN   pidrb   payloadr  rf   r   r   r   _process_notification  s   
z Connection._process_notificationc                 C   s   | j d u r	| }|S | j }|S r   )r*   )rN   r  r   r   r   r|    s
   
zConnection._unwrapc                 C   st   | j dur| j S | j}g }|jr|d |jr|d |jr(|jr(|d |jr0|d d|}|| _ |S )a4  Return the query sent to server on connection release.

        The query returned by this method is used by :meth:`Connection.reset`,
        which is, in turn, used by :class:`~asyncpg.pool.Pool` before making
        the connection available to another acquirer.

        .. versionadded:: 0.30.0
        Nz SELECT pg_advisory_unlock_all();z
CLOSE ALL;zUNLISTEN *;z
RESET ALL;
)	r)   r'   advisory_locksr  sql_close_allnotificationsplpgsql	sql_resetr   )rN   capsr)   r   r   r   rW    s   
	




zConnection.get_reset_queryc                 C   s&   | j d ur|d urtd|| _ d S )Nz5internal asyncpg error: connection is already proxied)r*   r   ri   )rN   proxyr   r   r   
_set_proxy  s
   
zConnection._set_proxyc                 C   sB   |rt |}tdj| |||dkrdndd}t| d S d S )NzL{conn!r} is being released to the pool but has {c} active {type} listener{s}r   sr   )connr   r   r  )r   r   InterfaceWarningrU   rV   rW   )rN   	listenerslistener_typecountwr   r   r   _check_listeners  s   zConnection._check_listenersr   c                 C   s>   |  j d7  _ | ttj| j d | | jd d S )Nr   notificationlog)	r!   r  r   	itertoolschainfrom_iterabler%   valuesr/   )rN   
stacklevelr   r   r   _on_release  s   zConnection._on_releasec                 C   s   | j   d S r   )r"   rS  rv   r   r   r   r@    s   z&Connection._drop_local_statement_cachec                 C   ,   | j d ur| j jj}|  d S |   d S r   )r*   r\  _pool_drop_statement_cacher@  rN   poolr   r   r   _drop_global_statement_cache     

z'Connection._drop_global_statement_cachec                 C   s   | j    d S r   )r   rE   clear_type_cacherv   r   r   r   _drop_local_type_cache     z!Connection._drop_local_type_cachec                 C   r  r   )r*   r\  r  _drop_type_cacher  r  r   r   r   _drop_global_type_cache  r  z"Connection._drop_global_type_cachec                    s   |    |   dS )aW  Indicate that the database schema information must be reloaded.

        For performance reasons, asyncpg caches certain aspects of the
        database schema, such as the layout of composite types.  Consequently,
        when the database schema changes, and asyncpg is not able to
        gracefully recover from an error caused by outdated schema
        assumptions, an :exc:`~asyncpg.exceptions.OutdatedSchemaCacheError`
        is raised.  To prevent the exception, this method may be used to inform
        asyncpg that the database schema has changed.

        Example:

        .. code-block:: pycon

            >>> import asyncpg
            >>> import asyncio
            >>> async def change_type(con):
            ...     result = await con.fetch('SELECT id, info FROM tbl')
            ...     # Change composite's attribute type "int"=>"text"
            ...     await con.execute('ALTER TYPE custom DROP ATTRIBUTE y')
            ...     await con.execute('ALTER TYPE custom ADD ATTRIBUTE y text')
            ...     await con.reload_schema_state()
            ...     for id_, info in result:
            ...         new = (info['x'], str(info['y']))
            ...         await con.execute(
            ...             'UPDATE tbl SET info=$2 WHERE id=$1', id_, new)
            ...
            >>> async def run():
            ...     # Initial schema:
            ...     # CREATE TYPE custom AS (x int, y int);
            ...     # CREATE TABLE tbl(id int, info custom);
            ...     con = await asyncpg.connect(user='postgres')
            ...     async with con.transaction():
            ...         # Prevent concurrent changes in the table
            ...         await con.execute('LOCK TABLE tbl')
            ...         await change_type(con)
            ...
            >>> asyncio.run(run())

        .. versionadded:: 0.14.0
        N)r  r  rv   r   r   r   reload_schema_state  s   *zConnection.reload_schema_state)r   r   r   c          
   
      sP   | j  | j|||||||dI d H \}}	W d    |S 1 s!w   Y  |S )N)r   r   r   )r+   r   )
rN   r   r   r   r~   r   r   r   r   r   r   r   r   r   <  s   


zConnection._executec                 c   s     |  | dV  | | dS )a=  Context manager that adds `callback` to the list of query loggers,
        and removes it upon exit.

        :param callable callback:
            A callable or a coroutine function receiving one argument:
            **record**, a LoggedQuery containing `query`, `args`, `timeout`,
            `elapsed`, `exception`, `conn_addr`, and `conn_params`.

        Example:

        .. code-block:: pycon

            >>> class QuerySaver:
                    def __init__(self):
                        self.queries = []
                    def __call__(self, record):
                        self.queries.append(record.query)
            >>> with con.query_logger(QuerySaver()):
            >>>     await con.execute("SELECT 1")
            >>> print(log.queries)
            ['SELECT 1']

        .. versionadded:: 0.29.0
        N)rr   rs   rj   r   r   r   query_loggerS  s   
zConnection.query_loggerc           
      c   s    t  }d }zFzd V  W n ty } z|} d }~ww W t  | }t|||||| j| jd}| jD ]}	|	jrC| j	|	
| q4| j|	j
| q4d S t  | }t|||||| j| jd}| jD ]}	|	jrs| j	|	
| qd| j|	j
| qdw )Nr   r   r~   elapsed	exception	conn_addrconn_params)time	monotonicBaseExceptionLoggedQueryr.   r-   r3   r}  r   rx  rf   r~  )
rN   r   r   r~   startr  rw  r  recordrf   r   r   r   r   q  sR   

	
	zConnection._time_and_logc                   s    fdd}j |}jr@| | j|||||dI d H \}	}
W d    |	|
fS 1 s7w   Y  |	|
fS j|||||dI d H \}	}
|	|
fS )Nc                    s   j j|  d|dS )Nr   )stater   portal_namer   return_extrar~   )r   bind_executer   r~   r   r   r   rN   r   r   <lambda>  s    z&Connection.__execute.<locals>.<lambda>r   )r   _get_timeoutr3   r   _do_execute)rN   r   r   r   r~   r   r   r   executorr   r   r   r  r   	__execute  s0   
zConnection.__executec           	   	      s    fdd}j |}j6 | | j||||dI d H \}}W d    n1 s3w   Y  W d    |S W d    |S 1 sKw   Y  |S )Nc                    s   j j|  d|dS )Nr   )r  r   r  r~   r   )r   bind_execute_manyr  r   r   rN   r   r   r    s    z)Connection._executemany.<locals>.<lambda>r   )r   r  r+   r   r  )	rN   r   r   r~   r   r   r  r   r   r   r  r   r     s    

zConnection._executemany)r   r   c             	      s.  |d u r| j |d ||dI d H }nt }| j ||||dI d H }t }	||	| 8 }|	}z7|d u r<||d I d H }
n z|||I d H }
W t }	||	| 8 }nt }	||	| 8 }w W |
|fS W |
|fS  tjyu   |  I d H    tjy   |   | j	 s|s | j
|||ddI d H  Y S w )Nr   F)retry)r   r  r  r   OutdatedSchemaCacheErrorr  InvalidCachedStatementErrorr  r   r}   r  )rN   r   r  r~   r  r   r   r   beforeafterr   r   r   r   r    sT   
/)zConnection._do_execute)r   )FN)T)Vr   r   r   __doc__	__slots__r   _ClientConfiguration_ConnectionParametersrS   r[   rd   rg   rk   rn   ro   rp   rr   rs   ru   rx   rE   r   r}   r   floatr   r   r   r   r   r   r   r  r   r   r]   r   r   r   r   r   r   r  r   r   r   r   rF  rH  rI  rT   r$  rY   rV  rY  rO  rP  r_  r\   r   r^  rk  r   rq  ry  r  r[  r  r|  rW  r  r  r  r@  r  r  r  r  r   
contextlibcontextmanagerr  r   r   r   r  r   r   r   r   r   +   s"   

@	/$f* +,

$)
'I?Yf'5 #2

		4

 ,
r   )	metaclass<   d   i,  i <  )hostportuserpasswordpassfiledatabaser7   r~   r=   rC   r   command_timeoutssl
direct_tlsconnection_classr   server_settingstarget_session_attrs
krbsrvnamegsslibc             	      s
  t |tstd||tjurt| |du rt	 }t
|4 I dH P tjdi d|d|d|d| d|d|d	|d
|d|d|d|d|d|d|d|	d|
d|d|d|d|I dH W  d  I dH  S 1 I dH s~w   Y  dS )a2  A coroutine to establish a connection to a PostgreSQL server.

    The connection parameters may be specified either as a connection
    URI in *dsn*, or as specific keyword arguments, or both.
    If both *dsn* and keyword arguments are specified, the latter
    override the corresponding values parsed from the connection URI.
    The default values for the majority of arguments can be specified
    using `environment variables <postgres envvars_>`_.

    Returns a new :class:`~asyncpg.connection.Connection` object.

    :param dsn:
        Connection arguments specified using as a single string in the
        `libpq connection URI format`_:
        ``postgres://user:password@host:port/database?option=value``.
        The following options are recognized by asyncpg: ``host``,
        ``port``, ``user``, ``database`` (or ``dbname``), ``password``,
        ``passfile``, ``sslmode``, ``sslcert``, ``sslkey``, ``sslrootcert``,
        and ``sslcrl``.  Unlike libpq, asyncpg will treat unrecognized
        options as `server settings`_ to be used for the connection.

        .. note::

           The URI must be *valid*, which means that all components must
           be properly quoted with :py:func:`urllib.parse.quote_plus`, and
           any literal IPv6 addresses must be enclosed in square brackets.
           For example:

           .. code-block:: text

              postgres://dbuser@[fe80::1ff:fe23:4567:890a%25eth0]/dbname

    :param host:
        Database host address as one of the following:

        - an IP address or a domain name;
        - an absolute path to the directory containing the database
          server Unix-domain socket (not supported on Windows);
        - a sequence of any of the above, in which case the addresses
          will be tried in order, and the first successful connection
          will be returned.

        If not specified, asyncpg will try the following, in order:

        - host address(es) parsed from the *dsn* argument,
        - the value of the ``PGHOST`` environment variable,
        - on Unix, common directories used for PostgreSQL Unix-domain
          sockets: ``"/run/postgresql"``, ``"/var/run/postgresl"``,
          ``"/var/pgsql_socket"``, ``"/private/tmp"``, and ``"/tmp"``,
        - ``"localhost"``.

    :param port:
        Port number to connect to at the server host
        (or Unix-domain socket file extension).  If multiple host
        addresses were specified, this parameter may specify a
        sequence of port numbers of the same length as the host sequence,
        or it may specify a single port number to be used for all host
        addresses.

        If not specified, the value parsed from the *dsn* argument is used,
        or the value of the ``PGPORT`` environment variable, or ``5432`` if
        neither is specified.

    :param user:
        The name of the database role used for authentication.

        If not specified, the value parsed from the *dsn* argument is used,
        or the value of the ``PGUSER`` environment variable, or the
        operating system name of the user running the application.

    :param database:
        The name of the database to connect to.

        If not specified, the value parsed from the *dsn* argument is used,
        or the value of the ``PGDATABASE`` environment variable, or the
        computed value of the *user* argument.

    :param password:
        Password to be used for authentication, if the server requires
        one.  If not specified, the value parsed from the *dsn* argument
        is used, or the value of the ``PGPASSWORD`` environment variable.
        Note that the use of the environment variable is discouraged as
        other users and applications may be able to read it without needing
        specific privileges.  It is recommended to use *passfile* instead.

        Password may be either a string, or a callable that returns a string.
        If a callable is provided, it will be called each time a new connection
        is established.

    :param passfile:
        The name of the file used to store passwords
        (defaults to ``~/.pgpass``, or ``%APPDATA%\postgresql\pgpass.conf``
        on Windows).

    :param loop:
        An asyncio event loop instance.  If ``None``, the default
        event loop will be used.

    :param float timeout:
        Connection timeout in seconds.

    :param int statement_cache_size:
        The size of prepared statement LRU cache.  Pass ``0`` to
        disable the cache.

    :param int max_cached_statement_lifetime:
        The maximum time in seconds a prepared statement will stay
        in the cache.  Pass ``0`` to allow statements be cached
        indefinitely.

    :param int max_cacheable_statement_size:
        The maximum size of a statement that can be cached (15KiB by
        default).  Pass ``0`` to allow all statements to be cached
        regardless of their size.

    :param float command_timeout:
        The default timeout for operations on this connection
        (the default is ``None``: no timeout).

    :param ssl:
        Pass ``True`` or an `ssl.SSLContext <SSLContext_>`_ instance to
        require an SSL connection.  If ``True``, a default SSL context
        returned by `ssl.create_default_context() <create_default_context_>`_
        will be used.  The value can also be one of the following strings:

        - ``'disable'`` - SSL is disabled (equivalent to ``False``)
        - ``'prefer'`` - try SSL first, fallback to non-SSL connection
          if SSL connection fails
        - ``'allow'`` - try without SSL first, then retry with SSL if the first
          attempt fails.
        - ``'require'`` - only try an SSL connection.  Certificate
          verification errors are ignored
        - ``'verify-ca'`` - only try an SSL connection, and verify
          that the server certificate is issued by a trusted certificate
          authority (CA)
        - ``'verify-full'`` - only try an SSL connection, verify
          that the server certificate is issued by a trusted CA and
          that the requested server host name matches that in the
          certificate.

        The default is ``'prefer'``: try an SSL connection and fallback to
        non-SSL connection if that fails.

        .. note::

           *ssl* is ignored for Unix domain socket communication.

        Example of programmatic SSL context configuration that is equivalent
        to ``sslmode=verify-full&sslcert=..&sslkey=..&sslrootcert=..``:

        .. code-block:: pycon

            >>> import asyncpg
            >>> import asyncio
            >>> import ssl
            >>> async def main():
            ...     # Load CA bundle for server certificate verification,
            ...     # equivalent to sslrootcert= in DSN.
            ...     sslctx = ssl.create_default_context(
            ...         ssl.Purpose.SERVER_AUTH,
            ...         cafile="path/to/ca_bundle.pem")
            ...     # If True, equivalent to sslmode=verify-full, if False:
            ...     # sslmode=verify-ca.
            ...     sslctx.check_hostname = True
            ...     # Load client certificate and private key for client
            ...     # authentication, equivalent to sslcert= and sslkey= in
            ...     # DSN.
            ...     sslctx.load_cert_chain(
            ...         "path/to/client.cert",
            ...         keyfile="path/to/client.key",
            ...     )
            ...     con = await asyncpg.connect(user='postgres', ssl=sslctx)
            ...     await con.close()
            >>> asyncio.run(main())

        Example of programmatic SSL context configuration that is equivalent
        to ``sslmode=require`` (no server certificate or host verification):

        .. code-block:: pycon

            >>> import asyncpg
            >>> import asyncio
            >>> import ssl
            >>> async def main():
            ...     sslctx = ssl.create_default_context(
            ...         ssl.Purpose.SERVER_AUTH)
            ...     sslctx.check_hostname = False
            ...     sslctx.verify_mode = ssl.CERT_NONE
            ...     con = await asyncpg.connect(user='postgres', ssl=sslctx)
            ...     await con.close()
            >>> asyncio.run(main())

    :param bool direct_tls:
        Pass ``True`` to skip PostgreSQL STARTTLS mode and perform a direct
        SSL connection. Must be used alongside ``ssl`` param.

    :param dict server_settings:
        An optional dict of server runtime parameters.  Refer to
        PostgreSQL documentation for
        a `list of supported options <server settings_>`_.

    :param type connection_class:
        Class of the returned connection object.  Must be a subclass of
        :class:`~asyncpg.connection.Connection`.

    :param type record_class:
        If specified, the class to use for records returned by queries on
        this connection object.  Must be a subclass of
        :class:`~asyncpg.Record`.

    :param SessionAttribute target_session_attrs:
        If specified, check that the host has the correct attribute.
        Can be one of:

        - ``"any"`` - the first successfully connected host
        - ``"primary"`` - the host must NOT be in hot standby mode
        - ``"standby"`` - the host must be in hot standby mode
        - ``"read-write"`` - the host must allow writes
        - ``"read-only"`` - the host most NOT allow writes
        - ``"prefer-standby"`` - first try to find a standby host, but if
          none of the listed hosts is a standby server,
          return any of them.

        If not specified, the value parsed from the *dsn* argument is used,
        or the value of the ``PGTARGETSESSIONATTRS`` environment variable,
        or ``"any"`` if neither is specified.

    :param str krbsrvname:
        Kerberos service name to use when authenticating with GSSAPI. This
        must match the server configuration. Defaults to 'postgres'.

    :param str gsslib:
        GSS library to use for GSSAPI/SSPI authentication. Can be 'gssapi'
        or 'sspi'. Defaults to 'sspi' on Windows and 'gssapi' otherwise.

    :return: A :class:`~asyncpg.connection.Connection` instance.

    Example:

    .. code-block:: pycon

        >>> import asyncpg
        >>> import asyncio
        >>> async def run():
        ...     con = await asyncpg.connect(user='postgres')
        ...     types = await con.fetch('SELECT * FROM pg_type')
        ...     print(types)
        ...
        >>> asyncio.run(run())
        [<Record typname='bool' typnamespace=11 ...

    .. versionadded:: 0.10.0
       Added ``max_cached_statement_use_count`` parameter.

    .. versionchanged:: 0.11.0
       Removed ability to pass arbitrary keyword arguments to set
       server settings.  Added a dedicated parameter ``server_settings``
       for that.

    .. versionadded:: 0.11.0
       Added ``connection_class`` parameter.

    .. versionadded:: 0.16.0
       Added ``passfile`` parameter
       (and support for password files in general).

    .. versionadded:: 0.18.0
       Added ability to specify multiple hosts in the *dsn*
       and *host* arguments.

    .. versionchanged:: 0.21.0
       The *password* argument now accepts a callable or an async function.

    .. versionchanged:: 0.22.0
       Added the *record_class* parameter.

    .. versionchanged:: 0.22.0
       The *ssl* argument now defaults to ``'prefer'``.

    .. versionchanged:: 0.24.0
       The ``sslcert``, ``sslkey``, ``sslrootcert``, and ``sslcrl`` options
       are supported in the *dsn* argument.

    .. versionchanged:: 0.25.0
       The ``sslpassword``, ``ssl_min_protocol_version``,
       and ``ssl_max_protocol_version`` options are supported in the *dsn*
       argument.

    .. versionchanged:: 0.25.0
       Default system root CA certificates won't be loaded when specifying a
       particular sslmode, following the same behavior in libpq.

    .. versionchanged:: 0.25.0
       The ``sslcert``, ``sslkey``, ``sslrootcert``, and ``sslcrl`` options
       in the *dsn* argument now have consistent default values of files under
       ``~/.postgresql/`` as libpq.

    .. versionchanged:: 0.26.0
       Added the *direct_tls* parameter.

    .. versionchanged:: 0.28.0
       Added the *target_session_attrs* parameter.

    .. versionchanged:: 0.30.0
       Added the *krbsrvname* and *gsslib* parameters.

    .. _SSLContext: https://docs.python.org/3/library/ssl.html#ssl.SSLContext
    .. _create_default_context:
        https://docs.python.org/3/library/ssl.html#ssl.create_default_context
    .. _server settings:
        https://www.postgresql.org/docs/current/static/runtime-config.html
    .. _postgres envvars:
        https://www.postgresql.org/docs/current/static/libpq-envars.html
    .. _libpq connection URI format:
        https://www.postgresql.org/docs/current/static/
        libpq-connect.html#LIBPQ-CONNSTRING
    zMconnection_class is expected to be a subclass of asyncpg.Connection, got {!r}Nr7   r  r   dsnr  r  r  r  r  r  r  r  r  r  r=   rC   r   r  r  r  r   )
issubclassr   r   ri   rU   r	   Recordr   rM  get_event_loopr   r~   r   _connect)r  r  r  r  r  r  r  r7   r~   r=   rC   r   r  r  r  r  r   r  r  r  r  r   r   r   connect  sn     
Q

	
0r  c                   @   s   e Zd ZdZdd ZdS )_StatementCacheEntry)_query
_statement_cache_cleanup_cbc                 C   s   || _ || _|| _d | _d S r   )r  r  r  r  )rN   cacher   r   r   r   r   rS   	  s   
z_StatementCacheEntry.__init__N)r   r   r   r  rS   r   r   r   r   r  	  s    r  c                   @   s   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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<   )r   _entries	_max_size
_on_remove_max_lifetimec                C   s&   || _ || _|| _|| _t | _d S r   )r   r  r  r  r.  OrderedDictr  )rN   r7   r8   r9   r:   r   r   r   rS   	  s
   z_StatementCache.__init__c                 C   s
   t | jS r   )r   r  rv   r   r   r   __len__	     
z_StatementCache.__len__c                 C   rw   r   )r  rv   r   r   r   get_max_size	     z_StatementCache.get_max_sizec                 C   s   |dksJ || _ |   d S rh  )r  _maybe_cleanup)rN   new_sizer   r   r   set_max_size	  s   z_StatementCache.set_max_sizec                 C   rw   r   )r  rv   r   r   r   get_max_lifetime	  r  z _StatementCache.get_max_lifetimec                 C   s0   |dksJ || _ | j D ]}| | qd S rh  )r  r  r  _set_entry_timeout)rN   new_lifetimeentryr   r   r   set_max_lifetime	  s
   z _StatementCache.set_max_lifetimeTpromotec                C   s^   | j sd S | j|}|d u rd S |jjr"| j| | | d S |r,| jj|dd |jS )NTlast)r  r  r   r  closedr  _clear_entry_callbackmove_to_end)rN   r   r   r  r   r   r   r   	  s   
z_StatementCache.getc                 C   s   | j |ddd uS )NFr  )r   )rN   r   r   r   r   rj  	  r  z_StatementCache.hasc                 C   s(   | j sd S | ||| j|< |   d S r   )r  
_new_entryr  r  )rN   r   r   r   r   r   r   	  s   z_StatementCache.putc                 C   s   dd | j  D S )Nc                 s   s    | ]}|j V  qd S r   )r  )r   er   r   r   r   	  s    z2_StatementCache.iter_statements.<locals>.<genexpr>)r  r  rv   r   r   r   re  	  s   z_StatementCache.iter_statementsc                 C   s<   t | j }| j  |D ]}| | | |j qd S r   )r5  r  r  rS  r  r  r  )rN   entriesr  r   r   r   rS  	  s   

z_StatementCache.clearc                 C   s.   |  | | jr| j| j| j||_d S d S r   )r  r  r   
call_later_on_entry_expiredr  rN   r  r   r   r   r  
  s   


z"_StatementCache._set_entry_timeoutc                 C   s   t | ||}| | |S r   )r  r  )rN   r   r   r  r   r   r   r  

  s   
z_StatementCache._new_entryc                 C   s4   | j |j|u r| j |j | |j d S d S r   )r  r   r  r  r  r  r  r   r   r   r
  
  s   z!_StatementCache._on_entry_expiredc                 C   s   |j d ur|j   d S d S r   )r  ra  r  r   r   r   r  
  s   
z%_StatementCache._clear_entry_callbackc                 C   sP   t | j| jkr&| jjdd\}}| | | |j t | j| jksd S d S )NFr  )r   r  r  popitemr  r  r  )rN   	old_query	old_entryr   r   r   r  
  s
   
z_StatementCache._maybe_cleanupN)r   r   r   r  rS   r  r  r  r  r  r   rj  r   re  rS  r  r  r
  r  r  r   r   r   r   r<   	  s$    	r<   c                   @   s@   e Zd ZU ejd ed< eed< edejd dd fddZdS )r`   ).Nrf   r}  r   c                 C   s8   t |rd}nt|rd}ntd|| ||S )NTFz7expected a callable or an `async def` function,got {!r})inspectiscoroutinefunctionr"  r   ri   rU   )r   rf   r}  r   r   r   ra   *
  s   

z_Callback.from_callableN)	r   r   r   typingCallable__annotations__r  classmethodra   r   r   r   r   r`   %
  s
   
 r`   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	rK   	_acquiredc                 C   
   d| _ d S rh  r  rv   r   r   r   rS   <
  r  z_Atomic.__init__c                 C   s   | j rtdd| _ d S )Nz:cannot perform operation: another operation is in progressr   )r  r   ri   rv   r   r   r   	__enter__?
  s
   
z_Atomic.__enter__c                 C   r  rh  r  )rN   tr  tbr   r   r   __exit__E
  r  z_Atomic.__exit__N)r   r   r   r  rS   r  r  r   r   r   r   rK   9
  s
    rK   c                   @   s   e Zd ZdZdS )r   r   N)r   r   r   r  r   r   r   r   r   I
  s    r   r  r  z Log record of an executed query.ServerCapabilitiesr  r  r  r  r  r  r   zPostgreSQL server capabilities.c           	   	   C   s   t |drd}d}d}d}d}d}d}n;t |dr(d}d}d}d}d}d}d}n't |dr<d}d}d}d}d}d}d}nd}d}d}d}d}| dk}| jdk}t|||||||dS )	Npadb_revisionFTcrdb_versioncrate_version)   r      r  )r!  majorr  )	rF   connection_settingsr  r  r  r  r  r   r  r   r   r   rH   \
  sP   



rH   r9  c                 C   s   t  j}ztjjt|dd}W ~n~w tjd }d}|t	|k r?|| d 
|r?|d7 }|t	|k r?|| d 
|s,||||   }|  dt|S )zlReplacement for traceback.extract_stack() that only does the
    necessary work for asyncio debug mode.
    F)lookup_linesr   r   r   )sys	_getframef_back	tracebackStackSummaryextract
walk_stackasyncpg__path__r   
startswithreverser   format_list)r   framestackapg_pathir   r   r   rM   
  s   


rM   c                 C   sZ   | t ju rd S t| tr%t| t jr%| jtjus| jtjur#t	dd S t	d
| )Nz2record_class must not redefine __new__ or __init__zErecord_class is expected to be a subclass of asyncpg.Record, got {!r})r	   r  r   r   r  __new__objectrS   r   ri   rU   r   r   r   r   r   
  s    

r   c                 C   s    |  }|d ur| | d S d S r   )rk  )weak_refr   rN   r   r   r   r@   
  s   r@   r   )r9  ).rM  r-  r.  collections.abcr  r>   r  r  r  r&  r  r)  r  rV   rA   r   r   r   r   r   r   r   r	   r
   r   r   r   r   r   r  r  r  r<   
NamedTupler`   rK   r   
namedtupler  r  r  rH   rM   r   r@   rc  r   r   r   r   <module>   s                  ~  u 
1