
    5Th9                        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dS )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
d	S )

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                     || _         d S N_wrapped)selfwrappeds     P/mounts/lovelace/software/anaconda3/lib/python3.11/site-packages/psycopg2/sql.py__init__zComposable.__init__1   s        c                 0    | j         j         d| j        dS )N())	__class____name__r	   r
   s    r   __repr__zComposable.__repr__4   s     .)>>DM>>>>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   s`    eX&& 	,TF##e++eZ(( 	"TF##hw&7&777!!r   c                 (    t          | g|z            S r   )r   )r
   ns     r   __mul__zComposable.__mul__L   s    
###r   c                 ^    t          |           t          |          u o| j        |j        k    S r   )typer	   r   s     r   __eq__zComposable.__eq__O   s'    DzzT%[[(LT]en-LLr   c                 .    |                      |           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 M M& & & & &r   r   c                   P     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 ]?}t          |t                    st          d|d          |                    |           @t	                                          |           d S )Nz*Composed elements must be Composable, got z instead)r   r   	TypeErrorappendsuperr   )r
   seqr   ir   s       r   r   zComposed.__init__h   s     	 	Aa,, PNNNNP 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     DM"""r   c                     g }| j         D ]*}|                    |                    |                     +d                    |          S )N )r	   r1   r   join)r
   r   rvr4   s       r   r   zComposed.as_stringw   sI     	, 	,AIIakk'**++++wwr{{r   c                 *    t          | j                  S r   )iterr	   r   s    r   __iter__zComposed.__iter__}   s    DM"""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__   sZ    eX&& 	<DMEN:;;;eZ(( 	"DMUG3444!!r   c                     t          |t                    rt          |          }n$t          |t                    st          d          |                    |           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   sc     fc"" 	G[[FFFC(( 	GEG G G {{4   r   )r   r*   r+   r,   r   propertyr3   r   r=   r!   r9   __classcell__r   s   @r   r   r   V   s         "" " " " " # # X#  # # #" " "! ! ! ! ! ! !r   r   c                   J     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                     t          |t                    st          d          t                                          |           d S )NzSQL values must be strings)r   r@   r0   r2   r   )r
   stringr   s     r   r   zSQL.__init__   sB    &#&& 	:89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                 F   g }d}t                               | j                  D ]\  }}}}|rt          d          |rt          d          |r"|                    t          |                     |P|                                r<|rt          d          |                    |t          |                              d}|s2|t          d          |                    ||                    |dz  }|                    ||                    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   sP   @ %/%5%5dm%D%D 	( 	(!CtT M !KLLL J !HIII $		#c((###|||~~ ( R$PR R R		$s4yy/*** (?$PR R R		$w-(((1 		&,''''||r   c                    g }t          |          }	 |                    t          |                     |D ],}|                    |            |                    |           -n# t          $ r Y nw xY wt	          |          S )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  s    $ #YY	IId2hh   		$		!  	 	 	D	 ||s   "A% %
A21A2)r   r*   r+   r,   r   rC   rH   r   rZ   r9   rD   rE   s   @r   rA   rA      s         *! ! ! ! !
   X  > > >@      r   rA   c                   Z     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                    st          d          't                                          |           d S )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  ss     	:8999 	H 	HAa%% H FGGGH 	!!!!!r   c                     | j         S )z5A tuple with the strings wrapped by the `Identifier`.r   r   s    r   rb   zIdentifier.stringsK  rJ   r   c                 j    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  s>     t}""=## DF F Fr   c                 |    | j         j         dd                    t          t          | j                             dS )Nr   z, r   )r   r   r9   mapreprr	   r   s    r   r   zIdentifier.__repr__Z  s6    .)RRDIIc$6N6N,O,ORRRRr   c                 P    d                     fd| j        D                       S )N.c              3   B   K   | ]}t          j        |          V  d S r   )extquote_ident).0rc   r   s     r   	<genexpr>z'Identifier.as_string.<locals>.<genexpr>^  s/      KK733KKKKKKr   )r9   r	   r   s    `r   r   zIdentifier.as_string]  s,    xxKKKKT]KKKKKKr   )r   r*   r+   r,   r   rC   rb   rH   r   r   rD   rE   s   @r   r`   r`   "  s         <" " " " "   X F F XFS S SL L L L L L Lr   r`   c                   .    e Zd ZdZed             Zd ZdS )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|}n1t          |t          j                  r|j        }nt	          d          t          j        | j                  }t          |d          r|                    |           |	                                }t          |t                    r*|                    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~.. 	HDD,, 	H%DDFGGGIdm$$1i   	IIdOOO[[]]b%   	93=788B	r   N)r   r*   r+   r,   rC   r   r   r-   r   r   rs   rs   a  sH         &   X    r   rs   c                   F     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)

    Nc                     t          |t                    rd|v rt          d|          n|t          d|          t	                                          |           d S )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__  sx    dC   	Nd{{ !:$!:!:;;;  LDLLM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__  s<    = n-1111n-BBBBBBr   c                 *    | j         d| j          dS dS )Nz%(z)sz%sr   r   s     r   r   zPlaceholder.as_string  s"    =$)))))4r   r   )
r   r*   r+   r,   r   rC   rW   r   r   rD   rE   s   @r   r   r     s         4        XC C C      r   r   NULLDEFAULT)r,   rH   psycopg2r   rn   	FormatterrN   r   r   rA   r`   rs   r   r   r   r-   r   r   <module>r      sv   4  & & & & & & V
0& 0& 0& 0& 0& 0& 0& 0&fF! F! F! F! F!z F! F! F!R@ @ @ @ @* @ @ @F<L <L <L <L <L <L <L <L~* * * * *j * * *Z4 4 4 4 4* 4 4 4p s6{{
#i..r   