
    i@                    B   d Z ddlmZ ddlZddlZddlmZ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mZ dd
lmZ ddlmZ ddlmZ dddZ G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z ed      Z ed      Z y)z 
SQL composition utility module
    )annotationsN)ABCabstractmethod)AnyIterableIteratorSequence   )Escaping)AdaptContext)PyFormat)LiteralString)conn_encoding)Transformerc                6    t        |       j                  |      S )a  
    Adapt a Python object to a quoted SQL string.

    Use this function only if you absolutely want to convert a Python string to
    an SQL quoted literal to use e.g. to generate batch SQL and you won't have
    a connection available when you will need to use it.

    This function is relatively inefficient, because it doesn't cache the
    adaptation rules. If you pass a `!context` you can adapt the adaptation
    rules used, otherwise only global rules are used.

    )Literal	as_string)objcontexts     k/var/www/html/hwPaymentPortal-be-dev/hw-payment-portal-api/venv/lib/python3.12/site-packages/psycopg/sql.pyquoter      s     3<!!'**    c                  ^    e Zd ZdZddZddZeddd       ZdddZddZ	ddZ
dd	Zdd
Zy)
ComposableaP  
    Abstract base class for objects that can be used to compose an SQL string.

    `!Composable` objects can be joined using the ``+`` operator: the result
    will be a `Composed` instance containing the objects joined. The operator
    ``*`` is also supported with an integer argument: the result is a
    `!Composed` instance containing the left argument repeated as many times as
    requested.

    `!SQL` and `!Composed` objects can be passed directly to
    `~psycopg.Cursor.execute()`, `~psycopg.Cursor.executemany()`,
    `~psycopg.Cursor.copy()` in place of the query string.
    c                    || _         y N_obj)selfr   s     r   __init__zComposable.__init__5   s	    	r   c                N    | j                   j                   d| j                  dS )N())	__class____name__r   r   s    r   __repr__zComposable.__repr__8   s$    ..))*!DII=::r   Nc                    t         )a~  
        Return the value of the object as bytes.

        :param context: the context to evaluate the object into.
        :type context: `connection` or `cursor`

        The method is automatically invoked by `~psycopg.Cursor.execute()`,
        `~psycopg.Cursor.executemany()`, `~psycopg.Cursor.copy()` if a
        `!Composable` is passed instead of the query string.

        )NotImplementedErrorr   r   s     r   as_byteszComposable.as_bytes;   s
     "!r   c                    t        |r|j                  nd      }t        | j                  |      x}t              r|j                  |      S t        j                  |      j                  |      d   S )z
        Return the value of the object as string.

        :param context: the context to evaluate the string into.
        :type context: `connection` or `cursor`

        Nr   )r   
connection
isinstancer+   bytesdecodecodecslookup)r   r   encbs       r   r   zComposable.as_stringJ   s_     'G..tDDMM'22qU;88C=  ==%,,Q/22r   c                    t        |t              rt        | g      |z   S t        |t              rt        | g      t        |g      z   S t        S r   )r.   Composedr   NotImplementedr   others     r   __add__zComposable.__add__Y   sG    eX&TF#e++eZ(TF#hw&777!!r   c                     t        | g|z        S r   )r6   )r   ns     r   __mul__zComposable.__mul__a   s    
##r   c                d    t        |       t        |      u xr | j                  |j                  k(  S r   )typer   r8   s     r   __eq__zComposable.__eq__d   s'    DzT%[(DTYY%**-DDr   c                &    | j                  |       S r   )r@   r8   s     r   __ne__zComposable.__ne__g   s    ;;u%%%r   )r   r   returnstrr   r   AdaptContext | NonerD   r/   r   rG   rD   rE   r9   r   rD   r6   )r<   intrD   r6   )r9   r   rD   bool)r%   
__module____qualname____doc__r    r'   r   r+   r   r:   r=   r@   rB    r   r   r   r   &   s?    ; " "3"$E&r   r   c                  R     e Zd ZU dZded<   d	 fdZd
ddZddZddZddZ	 xZ
S )r6   a.  
    A `Composable` object made of a sequence of `!Composable`.

    The object is usually created using `!Composable` operators and methods
    (such as the `SQL.format()` method). `!Composed` objects can be passed
    directly to `~psycopg.Cursor.execute()`, `~psycopg.Cursor.executemany()`,
    `~psycopg.Cursor.copy()` in place of the query string.

    It is also possible to create a `!Composed` directly specifying a sequence
    of objects as arguments: if they are not `!Composable` they will be wrapped
    in a `Literal`.

    Example::

        >>> comp = sql.Composed(
        ...     [sql.SQL("INSERT INTO "), sql.Identifier("table")])
        >>> print(comp.as_string(conn))
        INSERT INTO "table"

    `!Composed` objects are iterable (so they can be used in `SQL.join` for
    instance).
    zlist[Composable]r   c                    |D cg c]  }t        |t              r|n
t        |      ! }}t        |   |       y c c}w r   )r.   r   r   superr    )r   seqr   r$   s      r   r    zComposed.__init__   s;    ORSjj1sws|CSS Ts   $<c                L    dj                  fd| j                  D              S )Nr   c              3  @   K   | ]  }|j                          y wr   )r+   ).0r   r   s     r   	<genexpr>z$Composed.as_bytes.<locals>.<genexpr>   s     C#W-Cs   )joinr   r*   s    `r   r+   zComposed.as_bytes   s    xxCCCCr   c                ,    t        | j                        S r   )iterr   r&   s    r   __iter__zComposed.__iter__   s    DIIr   c                    t        |t              r"t        | j                  |j                  z         S t        |t              rt        | j                  |gz         S t        S r   )r.   r6   r   r   r7   r8   s     r   r:   zComposed.__add__   sJ    eX&DII

233eZ(DII/00!!r   c                    t        |t              rt        |      }nt        |t              st        d|d      |j	                  | j
                        S )a~  
        Return a new `!Composed` interposing the `!joiner` with the `!Composed` items.

        The `!joiner` must be a `SQL` or a string which will be interpreted as
        an `SQL`.

        Example::

            >>> fields = sql.Identifier('foo') + sql.Identifier('bar')  # a Composed
            >>> print(fields.join(', ').as_string(conn))
            "foo", "bar"

        z5Composed.join() argument must be strings or SQL, got  instead)r.   rE   SQL	TypeErrorrX   r   )r   joiners     r   rX   zComposed.join   sT     fc"[FFC(z+ 
 {{499%%r   )rS   zSequence[Any]r   rF   )rD   zIterator[Composable]rI   )ra   zSQL | LiteralStringrD   r6   )r%   rL   rM   rN   __annotations__r    r+   r[   r:   rX   __classcell__r$   s   @r   r6   r6   k   s*    . D"&r   r6   c                  v     e Zd ZU dZded<    ej                         Zd	 fdZd
ddZ	d
ddZ
ddZddZ xZS )r_   a  
    A `Composable` representing a snippet of SQL statement.

    `!SQL` exposes `join()` and `format()` methods useful to create a template
    where to merge variable parts of a query (for instance field or table
    names).

    The `!obj` string doesn't undergo any form of escaping, so it is not
    suitable to represent variable identifiers or values: you should only use
    it to pass constant strings representing templates or snippets of SQL
    statements; use other objects such as `Identifier` or `Literal` to
    represent variable parts.

    `!SQL` objects can be passed directly to `~psycopg.Cursor.execute()`,
    `~psycopg.Cursor.executemany()`, `~psycopg.Cursor.copy()` in place of the
    query string.

    Example::

        >>> query = sql.SQL("SELECT {0} FROM {1}").format(
        ...    sql.SQL(', ').join([sql.Identifier('foo'), sql.Identifier('bar')]),
        ...    sql.Identifier('table'))
        >>> print(query.as_string(conn))
        SELECT "foo", "bar" FROM "table"
    r   r   c                b    t         |   |       t        |t              st	        d|d      y )Nz SQL values must be strings, got r^   )rR   r    r.   rE   r`   )r   r   r$   s     r   r    zSQL.__init__   s4    #s#>sgXNOO $r   c                    | j                   S r   r   r*   s     r   r   zSQL.as_string   s    yyr   c                n    |r|j                   nd }t        |      }| j                  j                  |      S r   )r-   r   r   encoder   r   connr3   s       r   r+   zSQL.as_bytes   s0    %,w!!$D!yy$$r   c                   g }d}| j                   j                  | j                        D ]  \  }}}}|rt        d      |rt        d      |r|j	                  t        |             |A|j                         r-|rt        d      |j	                  |t        |                d}~|s'|t        d      |j	                  ||          |dz  }|j	                  ||           t        |      S )a  
        Merge `Composable` objects into a template.

        :param args: parameters to replace to numbered (``{0}``, ``{1}``) or
            auto-numbered (``{}``) placeholders
        :param kwargs: parameters to replace to named (``{name}``) placeholders
        :return: the union of the `!SQL` string with placeholders replaced
        :rtype: `Composed`

        The method is similar to the Python `str.format()` method: the string
        template supports auto-numbered (``{}``), numbered (``{0}``,
        ``{1}``...), and named placeholders (``{name}``), with positional
        arguments replacing the numbered placeholders and keywords replacing
        the named ones. However placeholder modifiers (``{0!r}``, ``{0:<10}``)
        are not supported.

        If a `!Composable` objects is passed to the template it will be merged
        according to its `as_string()` method. If any other Python object is
        passed, it will be wrapped in a `Literal` object and so escaped
        according to SQL rules.

        Example::

            >>> print(sql.SQL("SELECT * FROM {} WHERE {} = %s")
            ...     .format(sql.Identifier('people'), sql.Identifier('id'))
            ...     .as_string(conn))
            SELECT * FROM "people" WHERE "id" = %s

            >>> print(sql.SQL("SELECT * FROM {tbl} WHERE name = {name}")
            ...     .format(tbl=sql.Identifier('people'), name="O'Rourke"))
            ...     .as_string(conn))
            SELECT * FROM "people" WHERE name = 'O''Rourke'

        r   z(no format specification supported by SQLz%no format conversion supported by SQLNz6cannot switch from automatic field numbering to manualz6cannot switch from manual field numbering to automaticr
   )	
_formatterparser   
ValueErrorappendr_   isdigitrJ   r6   )	r   argskwargsrvautonumprenamespecconvs	            r   formatz
SQL.format   s    F  " &*__%:%:499%E 	(!CtT !KLL !HII		#c(#|||~$P  		$s4y/*?$P  		$w-(1 		&,'9	(< |r   c                    g }t        |      }	 |j                  t        |             |D ]$  }|j                  |        |j                  |       & t	        |      S # t        $ r Y t	        |      S w xY w)a7  
        Join a sequence of `Composable`.

        :param seq: the elements to join. Elements that are not `Composable`
            will be considered `Literal`.

        Use the `!SQL` object's string to separate the elements in `!seq`.
        Note that `Composed` objects are iterable too, so they can be used as
        argument for this method.

        Example::

            >>> snip = sql.SQL(', ').join(
            ...     sql.Identifier(n) for n in ['foo', 'bar', 'baz'])
            >>> print(snip.as_string(conn))
            "foo", "bar", "baz"
        )rZ   rp   nextStopIterationr6   )r   rS   rt   itis        r   rX   zSQL.join#  sz    $ #Y	IId2h  		$		! |  	 |	s   A 	A32A3)r   r   r   rH   rF   )rr   r   rs   r   rD   r6   )rS   zIterable[Any]rD   r6   )r%   rL   rM   rN   rb   string	Formatterrm   r    r   r+   rz   rX   rc   rd   s   @r   r_   r_      s<    4 !!!#JP
%
FPr   r_   c                  J     e Zd ZU dZded<   d fdZd	dZd
ddZddZ xZ	S )
Identifiera#  
    A `Composable` representing an SQL identifier or a dot-separated sequence.

    Identifiers usually represent names of database objects, such as tables or
    fields. PostgreSQL identifiers follow `different rules`__ than SQL string
    literals for escaping (e.g. they use double quotes instead of single).

    .. __: https://www.postgresql.org/docs/current/sql-syntax-lexical.html#         SQL-SYNTAX-IDENTIFIERS

    Example::

        >>> t1 = sql.Identifier("foo")
        >>> t2 = sql.Identifier("ba'r")
        >>> t3 = sql.Identifier('ba"z')
        >>> print(sql.SQL(', ').join([t1, t2, t3]).as_string(conn))
        "foo", "ba'r", "ba""z"

    Multiple strings can be passed to the object to represent a qualified name,
    i.e. a dot-separated sequence of identifiers.

    Example::

        >>> query = sql.SQL("SELECT {} FROM {}").format(
        ...     sql.Identifier("table", "field"),
        ...     sql.Identifier("schema", "table"))
        >>> print(query.as_string(conn))
        SELECT "table"."field" FROM "schema"."table"

    zSequence[str]r   c                    t         |   |       |st        d      |D ]!  }t        |t              rt        d|d       y )NzIdentifier cannot be emptyz*SQL identifier parts must be strings, got r^   )rR   r    r`   r.   rE   )r   stringssr$   s      r   r    zIdentifier.__init__e  sQ    !899 	Aa%@XN 	r   c                    | j                   j                   ddj                  t        t        | j
                               dS )Nr"   , r#   )r$   r%   rX   mapreprr   r&   s    r   r'   zIdentifier.__repr__r  s5    ..))*!DIIc$		6J,K+LANNr   c                x   |r|j                   nd x}rXt        |j                        }t        |      }| j                  D cg c]"  }|j                  |j                  |            $ }}n6| j                  D cg c]!  }| j                  |j                               # }}dj                  |      S c c}w c c}w )N   .)	r-   r   pgconnr   r   escape_identifierri   _escape_identifierrX   )r   r   rk   escr3   r   escss          r   r+   zIdentifier.as_bytesu  s    *1G&&t<4<4;;'C%CBF))LQC))!((3-8LDLAEKAD++AHHJ7KDKyy MKs   'B29&B7c                2    d|j                  dd      z   dz   S )zK
        Approximation of PQescapeIdentifier taking no connection.
           "s   "")replace)r   r   s     r   r   zIdentifier._escape_identifier~  s     aiie,,t33r   )r   rE   rC   r   rF   )r   r/   rD   r/   )
r%   rL   rM   rN   rb   r    r'   r+   r   rc   rd   s   @r   r   r   C  s%    > O4r   r   c                      e Zd ZdZdddZy)r   a  
    A `Composable` representing an SQL value to include in a query.

    Usually you will want to include placeholders in the query and pass values
    as `~cursor.execute()` arguments. If however you really really need to
    include a literal value in the query you can use this object.

    The string returned by `!as_string()` follows the normal :ref:`adaptation
    rules <types-adaptation>` for Python objects.

    Example::

        >>> s1 = sql.Literal("fo'o")
        >>> s2 = sql.Literal(42)
        >>> s3 = sql.Literal(date(2000, 1, 1))
        >>> print(sql.SQL(', ').join([s1, s2, s3]).as_string(conn))
        'fo''o', 42, '2000-01-01'::date

    Nc                b    t        j                  |      }|j                  | j                        S r   )r   from_context
as_literalr   )r   r   txs      r   r+   zLiteral.as_bytes  s%    %%g.}}TYY''r   r   rF   )r%   rL   rM   rN   r+   rO   r   r   r   r     s    ((r   r   c                  Z     e Zd ZdZdej
                  fd fdZddZd	d
dZd	ddZ	 xZ
S )Placeholdera	  A `Composable` representing a placeholder for query parameters.

    If the name is specified, generate a named placeholder (e.g. ``%(name)s``,
    ``%(name)b``), otherwise generate a positional placeholder (e.g. ``%s``,
    ``%b``).

    The object is useful to generate SQL queries with a variable number of
    arguments.

    Examples::

        >>> names = ['foo', 'bar', 'baz']

        >>> q1 = sql.SQL("INSERT INTO my_table ({}) VALUES ({})").format(
        ...     sql.SQL(', ').join(map(sql.Identifier, names)),
        ...     sql.SQL(', ').join(sql.Placeholder() * len(names)))
        >>> print(q1.as_string(conn))
        INSERT INTO my_table ("foo", "bar", "baz") VALUES (%s, %s, %s)

        >>> q2 = sql.SQL("INSERT INTO my_table ({}) VALUES ({})").format(
        ...     sql.SQL(', ').join(map(sql.Identifier, names)),
        ...     sql.SQL(', ').join(map(sql.Placeholder, names)))
        >>> print(q2.as_string(conn))
        INSERT INTO my_table ("foo", "bar", "baz") VALUES (%(foo)s, %(bar)s, %(baz)s)

     c                ,   t         |   |       t        |t              st	        d|      d|v rt        d|      t        |      t        u rt        |      }t        |t              s!t	        dt        |      j                        || _	        y )Nzexpected string as name, got r#   zinvalid name: z!expected PyFormat as format, got )
rR   r    r.   rE   r`   ro   r?   r   r%   _format)r   rw   rz   r$   s      r   r    zPlaceholder.__init__  s    $$;D8DEE$;~dX677<3f%F&(+3DL4I4I3LM  "(r   c                D   g }| j                   r$|j                  t        | j                                | j                  t        j
                  ur(|j                  d| j                  j                          | j                  j                   ddj                  |       dS )Nzformat=r"   r   r#   )
r   rp   r   r   r   AUTOrw   r$   r%   rX   )r   partss     r   r'   zPlaceholder.__repr__  sx    99LLdii)<<x}},LL74<<#4#4"567..))*!DIIe,<+=Q??r   c                t    | j                   j                  }| j                  rd| j                   d| S d| S )Nz%(r#   %)r   valuer   )r   r   codes      r   r   zPlaceholder.as_string  s9    ||!!*.))DII;av&C1TFCr   c                x    |r|j                   nd }t        |      }| j                  |      j                  |      S r   )r-   r   r   ri   rj   s       r   r+   zPlaceholder.as_bytes  s5    %,w!!$D!~~g&--c22r   )rw   rE   rz   zstr | PyFormatrC   r   rH   rF   )r%   rL   rM   rN   r   r   r    r'   r   r+   rc   rd   s   @r   r   r     s.    6 $& ("@D3 3r   r   NULLDEFAULTr   )r   r   r   rG   rD   rE   )!rN   
__future__r   r1   r   abcr   r   typingr   r   r   r	   pqr   r   _enumsr   _compatr   
_encodingsr   _transformerr   r   r   r6   r_   r   r   r   r   r   rO   r   r   <module>r      s    #   # 4 4    " % %+ B& B&JB&z B&JP* Pf?4 ?4D(j (4=3* =3B 6{
i.r   