
    g9                         d Z ddlZddlmZ  ej
                         Z G 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 e	d      Z e	d      Zy)zSQL composition utility module
    N)
extensionsc                   :    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
y	)

Composablea6  
    Abstract base class for objects that can be used to compose an SQL string.

    `!Composable` objects can be passed directly to `~cursor.execute()`,
    `~cursor.executemany()`, `~cursor.copy_expert()` in place of the query
    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.
    c                     || _         y N_wrapped)selfwrappeds     L/var/www/api/v1/venv_getwork_v1/lib/python3.12/site-packages/psycopg2/sql.py__init__zComposable.__init__1   s	        c                 N    | j                   j                   d| j                  dS )N())	__class____name__r	   r
   s    r   __repr__zComposable.__repr__4   s%    ..))*!DMM+<A>>r   c                     t         )aj  
        Return the string value of the object.

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

        The method is automatically invoked by `~cursor.execute()`,
        `~cursor.executemany()`, `~cursor.copy_expert()` if a `!Composable` is
        passed instead of the query string.
        )NotImplementedErrorr
   contexts     r   	as_stringzComposable.as_string7   s
     "!r   c                     t        |t              rt        | g      |z   S t        |t              rt        | g      t        |g      z   S t        S r   )
isinstanceComposedr   NotImplementedr
   others     r   __add__zComposable.__add__D   sG    eX&TF#e++eZ(TF#hw&777!!r   c                      t        | g|z        S r   )r   )r
   ns     r   __mul__zComposable.__mul__L   s    
##r   c                 d    t        |       t        |      u xr | j                  |j                  k(  S r   )typer	   r   s     r   __eq__zComposable.__eq__O   s'    DzT%[(LT]]enn-LLr   c                 &    | j                  |       S r   )r'   r   s     r   __ne__zComposable.__ne__R   s    ;;u%%%r   N)r   
__module____qualname____doc__r   r   r   r!   r$   r'   r)    r   r   r   r   #   s+     ?""$M&r   r   c                   J     e Zd ZdZ fdZed        Zd Zd Zd Z	d Z
 xZS )r   a  
    A `Composable` object made of a sequence of `!Composable`.

    The object is usually created using `!Composable` operators and methods.
    However it is possible to create a `!Composed` directly specifying a
    sequence of `!Composable` as arguments.

    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).
    c                     g }|D ]2  }t        |t              st        d|d      |j                  |       4 t        |   |       y )Nz*Composed elements must be Composable, got z instead)r   r   	TypeErrorappendsuperr   )r
   seqr   ir   s       r   r   zComposed.__init__h   sR    Aa,@XNP PNN1	  	!r   c                 ,    t        | j                        S )z+The list of the content of the `!Composed`.)listr	   r   s    r   r3   zComposed.seqr   s     DMM""r   c                     g }| j                   D ]"  }|j                  |j                  |             $ dj                  |      S )N )r	   r1   r   join)r
   r   rvr4   s       r   r   zComposed.as_stringw   s8    AIIakk'*+ wwr{r   c                 ,    t        | j                        S r   )iterr	   r   s    r   __iter__zComposed.__iter__}   s    DMM""r   c                     t        |t              r"t        | j                  |j                  z         S t        |t              rt        | j                  |gz         S t        S r   )r   r   r	   r   r   r   s     r   r!   zComposed.__add__   sJ    eX&DMMENN:;;eZ(DMMUG344!!r   c                     t        |t              rt        |      }nt        |t              st        d      |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"

        z3Composed.join() argument must be a string or an SQL)r   strSQLr0   r9   )r
   joiners     r   r9   zComposed.join   sD     fc"[FFC(EG G {{4  r   )r   r*   r+   r,   r   propertyr3   r   r=   r!   r9   __classcell__r   s   @r   r   r   V   s5    "" # ##"!r   r   c                   D     e Zd ZdZ fdZed        Zd Zd Zd Z	 xZ
S )rA   aA  
    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 *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.

    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"
    c                 Z    t        |t              st        d      t        |   |       y )NzSQL values must be strings)r   r@   r0   r2   r   )r
   stringr   s     r   r   zSQL.__init__   s&    &#&899 r   c                     | j                   S )z(The string wrapped by the `!SQL` object.r   r   s    r   rH   z
SQL.string        }}r   c                     | j                   S r   r   r   s     r   r   zSQL.as_string   s    }}r   c                    g }d}t         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 `Composable` args: parameters to replace to numbered
            (``{0}``, ``{1}``) or auto-numbered (``{}``) placeholders
        :param `Composable` 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. Only `!Composable` objects can be passed to the
        template.

        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 {pkey} = %s")
            ...     .format(tbl=sql.Identifier('people'), pkey=sql.Identifier('id'))
            ...     .as_string(conn))
            select * from "people" where "id" = %s

        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 automatic   )	
_formatterparser	   
ValueErrorr1   rA   isdigitintr   )	r
   argskwargsr:   autonumprenamespecconvs	            r   formatz
SQL.format   s    @ %/%5%5dmm%D!CtT !KLL !HII		#c(#|||~$PR R		$s4y/*?$PR R		$w-(1 		&,'5 &E8 |r   c                     g }t        |      }	 |j                  t        |             |D ]$  }|j                  |        |j                  |       & t	        |      S # t        $ r Y t	        |      S w xY w)a  
        Join a sequence of `Composable`.

        :param seq: the elements to join.
        :type seq: iterable of `!Composable`

        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"
        )r<   r1   nextStopIterationr   )r
   r3   r:   itr4   s        r   r9   zSQL.join  su    $ #Y	IId2h 		$		!  |  	 |	s   A 	A32A3)r   r*   r+   r,   r   rC   rH   r   rZ   r9   rD   rE   s   @r   rA   rA      s1    *!
  >@r   rA   c                   N     e Zd ZdZ fdZed        Zed        Zd Z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/static/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"

    c                     |st        d      |D ]  }t        |t              rt        d       t        |   |       y )NzIdentifier cannot be emptyz$SQL identifier parts must be strings)r0   r   r@   r2   r   )r
   stringssr   s      r   r   zIdentifier.__init__A  sA    899Aa% FGG  	!r   c                     | j                   S )z5A tuple with the strings wrapped by the `Identifier`.r   r   s    r   rb   zIdentifier.stringsK  rJ   r   c                 f    t        | j                        dk(  r| j                  d   S t        d      )z0The string wrapped by the `Identifier`.
        rM   r   z2the Identifier wraps more than one than one string)lenr	   AttributeErrorr   s    r   rH   zIdentifier.stringP  s6     t}}"==## DF Fr   c                     | j                   j                   ddj                  t        t        | j
                               dS )Nr   z, r   )r   r   r9   mapreprr	   r   s    r   r   zIdentifier.__repr__Z  s6    ..))*!DIIc$6N,O+PPQRRr   c                 L    dj                  fd| j                  D              S )N.c              3   J   K   | ]  }t        j                  |        y wr   )extquote_ident).0rc   r   s     r   	<genexpr>z'Identifier.as_string.<locals>.<genexpr>^  s     K]73]s    #)r9   r	   r   s    `r   r   zIdentifier.as_string]  s    xxKT]]KKKr   )r   r*   r+   r,   r   rC   rb   rH   r   r   rD   rE   s   @r   r`   r`   "  sC    <"   F FSLr   r`   c                   &    e Zd ZdZed        Zd Zy)Literala  
    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 <python-types-adaptation>` for Python objects.

    Example::

        >>> s1 = sql.Literal("foo")
        >>> s2 = sql.Literal("ba'r")
        >>> s3 = sql.Literal(42)
        >>> print(sql.SQL(', ').join([s1, s2, s3]).as_string(conn))
        'foo', 'ba''r', 42

    c                     | j                   S )z%The object wrapped by the `!Literal`.r   r   s    r   r   zLiteral.wrappedu  rJ   r   c                    t        |t        j                        r|}n2t        |t        j                        r|j                  }nt	        d      t        j
                  | j                        }t        |d      r|j                  |       |j                         }t        |t              r,|j                  t        j                  |j                           }|S )Nz(context must be a connection or a cursorprepare)r   rn   
connectioncursorr0   adaptr	   hasattrrv   	getquotedbytesdecode	encodingsencoding)r
   r   connar:   s        r   r   zLiteral.as_stringz  s    gs~~.D,%%DFGGIIdmm$1i IIdO[[]b% 3==78B	r   N)r   r*   r+   r,   rC   r   r   r-   r   r   rs   rs   a  s     &  r   rs   c                   @     e Zd ZdZd fd	Zed        Zd Z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``),
    otherwise generate a positional placeholder (e.g. ``%s``).

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

    Examples::

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

        >>> q1 = sql.SQL("insert into table ({}) values ({})").format(
        ...     sql.SQL(', ').join(map(sql.Identifier, names)),
        ...     sql.SQL(', ').join(sql.Placeholder() * len(names)))
        >>> print(q1.as_string(conn))
        insert into table ("foo", "bar", "baz") values (%s, %s, %s)

        >>> q2 = sql.SQL("insert into table ({}) values ({})").format(
        ...     sql.SQL(', ').join(map(sql.Identifier, names)),
        ...     sql.SQL(', ').join(map(sql.Placeholder, names)))
        >>> print(q2.as_string(conn))
        insert into table ("foo", "bar", "baz") values (%(foo)s, %(bar)s, %(baz)s)

    c                     t        |t              rd|v rt        d|      |t        d|      t        |   |       y )Nr   zinvalid name: z%expected string or None as name, got )r   r@   rP   r0   r2   r   )r
   rW   r   s     r   r   zPlaceholder.__init__  sL    dC d{ >$!:;;CD8LMMr   c                     | j                   S )zThe name of the `!Placeholder`.r   r   s    r   rW   zPlaceholder.name  rJ   r   c                     | j                   | j                  j                   dS | j                  j                   d| j                   dS )Nz()r   r   )r	   r   r   r   s    r   r   zPlaceholder.__repr__  sG    == nn--.b11nn--.a/@BBr   c                 <    | j                   d| j                    dS y)Nz%(z)sz%sr   r   s     r   r   zPlaceholder.as_string  s"    ==$b))r   r   )
r   r*   r+   r,   r   rC   rW   r   r   rD   rE   s   @r   r   r     s,    4  Cr   r   NULLDEFAULT)r,   rH   psycopg2r   rn   	FormatterrN   r   r   rA   r`   rs   r   r   r   r-   r   r   <module>r      s   4  & V
0& 0&fF!z F!R@* @F<L <L~*j *Z4* 4p 6{
i.r   