3
 (ƒh7:  ã               @   s¤   d Z ddlZddlmZ ddlmZmZ ejƒ Z	G dd„ de
ƒZG dd„ deƒZG d	d
„ d
eƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZedƒZedƒZdS )zSQL composition utility module
é    N)Ú
extensions)ÚPY3Ústring_typesc               @   sH   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„ 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             C   s
   || _ d S )N)Ú_wrapped)ÚselfÚwrapped© r	   ú9/tmp/pip-install-q3hcpn_q/psycopg2-binary/psycopg2/sql.pyÚ__init__2   s    zComposable.__init__c             C   s   d| j j| jf S )Nz%s(%r))Ú	__class__Ú__name__r   )r   r	   r	   r
   Ú__repr__5   s    zComposable.__repr__c             C   s   t ‚dS )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.
        N)ÚNotImplementedError)r   Úcontextr	   r	   r
   Ú	as_string8   s    zComposable.as_stringc             C   s>   t |tƒrt| gƒ| S t |tƒr6t| gƒt|gƒ S tS d S )N)Ú
isinstanceÚComposedr   ÚNotImplemented)r   Úotherr	   r	   r
   Ú__add__E   s
    

zComposable.__add__c             C   s   t | g| ƒS )N)r   )r   Únr	   r	   r
   Ú__mul__M   s    zComposable.__mul__c             C   s   t | ƒt |ƒko| j|jkS )N)Útyper   )r   r   r	   r	   r
   Ú__eq__P   s    zComposable.__eq__c             C   s   | j |ƒ S )N)r   )r   r   r	   r	   r
   Ú__ne__S   s    zComposable.__ne__N)r   Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r   r   r	   r	   r	   r
   r   $   s   r   c                   sL   e Zd ZdZ‡ fdd„Zedd„ ƒZdd„ Zdd	„ Zd
d„ Z	dd„ Z
‡  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                sF   g }x,|D ]$}t |tƒs$td| ƒ‚|j|ƒ q
W tt| ƒj|ƒ d S )Nz4Composed elements must be Composable, got %r instead)r   r   Ú	TypeErrorÚappendÚsuperr   r   )r   Úseqr   Úi)r   r	   r
   r   i   s    


zComposed.__init__c             C   s
   t | jƒS )z+The list of the content of the `!Composed`.)Úlistr   )r   r	   r	   r
   r"   s   s    zComposed.seqc             C   s.   g }x| j D ]}|j|j|ƒƒ qW dj|ƒS )NÚ )r   r    r   Újoin)r   r   Úrvr#   r	   r	   r
   r   x   s    zComposed.as_stringc             C   s
   t | jƒS )N)Úiterr   )r   r	   r	   r
   Ú__iter__~   s    zComposed.__iter__c             C   s<   t |tƒrt| j|j ƒS t |tƒr4t| j|g ƒS tS d S )N)r   r   r   r   r   )r   r   r	   r	   r
   r      s
    

zComposed.__add__c             C   s0   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   r   ÚSQLr   r&   )r   Zjoinerr	   r	   r
   r&   ‰   s    


zComposed.join)r   r   r   r   r   Úpropertyr"   r   r)   r   r&   Ú__classcell__r	   r	   )r   r
   r   W   s   
r   c                   sD   e Zd ZdZ‡ fdd„Zedd„ ƒZdd„ Zdd	„ Zd
d„ Z	‡  Z
S )r*   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                s&   t |tƒstdƒ‚tt| ƒj|ƒ d S )NzSQL values must be strings)r   r   r   r!   r*   r   )r   Ústring)r   r	   r
   r   ¶   s    
zSQL.__init__c             C   s   | j S )z(The string wrapped by the `!SQL` object.)r   )r   r	   r	   r
   r-   »   s    z
SQL.stringc             C   s   | j S )N)r   )r   r   r	   r	   r
   r   À   s    zSQL.as_stringc       	      O   sÈ   g }d}x¶t j| jƒD ]¦\}}}}|r.tdƒ‚|r:tdƒ‚|rL|jt|ƒƒ |dkrVq|jƒ r‚|rjtdƒ‚|j|t|ƒ ƒ d}q|s®|dkr–tdƒ‚|j|| ƒ |d7 }q|j|| ƒ qW 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   Ú
ValueErrorr    r*   ÚisdigitÚintr   )	r   ÚargsÚkwargsr'   ZautonumÚpreÚnameÚspecÚconvr	   r	   r
   ÚformatÃ   s2     
z
SQL.formatc             C   s^   g }t |ƒ}y|jt|ƒƒ W n tk
r2   Y n$X x |D ]}|j| ƒ |j|ƒ q: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(   r    ÚnextÚStopIterationr   )r   r"   r'   Úitr#   r	   r	   r
   r&     s    

zSQL.join)r   r   r   r   r   r+   r-   r   r:   r&   r,   r	   r	   )r   r
   r*       s   @r*   c                   sH   e Zd ZdZ‡ fdd„Zedd„ ƒZedd„ ƒZdd	„ Zd
d„ Z	‡  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@   |st dƒ‚x|D ]}t|tƒst dƒ‚qW tt| ƒj|ƒ d S )NzIdentifier cannot be emptyz$SQL identifier parts must be strings)r   r   r   r!   r>   r   )r   ÚstringsÚs)r   r	   r
   r   B  s    

zIdentifier.__init__c             C   s   | j S )z5A tuple with the strings wrapped by the `Identifier`.)r   )r   r	   r	   r
   r?   L  s    zIdentifier.stringsc             C   s$   t | jƒdkr| jd S tdƒ‚dS )z0The string wrapped by the `Identifier`.
        r.   r   z2the Identifier wraps more than one than one stringN)Úlenr   ÚAttributeError)r   r	   r	   r
   r-   Q  s    
zIdentifier.stringc             C   s   d| j jdjtt| jƒƒf S )Nz%s(%s)z, )r   r   r&   ÚmapÚreprr   )r   r	   r	   r
   r   [  s    zIdentifier.__repr__c                s   dj ‡ fdd„| jD ƒƒS )NÚ.c             3   s   | ]}t j|ˆ ƒV  qd S )N)ÚextZquote_ident)Ú.0r@   )r   r	   r
   ú	<genexpr>a  s    z'Identifier.as_string.<locals>.<genexpr>)r&   r   )r   r   r	   )r   r
   r   `  s    zIdentifier.as_string)r   r   r   r   r   r+   r?   r-   r   r   r,   r	   r	   )r   r
   r>   #  s   

r>   c               @   s$   e Zd ZdZedd„ ƒZd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             C   s   | j S )z%The object wrapped by the `!Literal`.)r   )r   r	   r	   r
   r   x  s    zLiteral.wrappedc             C   sz   t |tjƒr|}nt |tjƒr&|j}ntdƒ‚tj| jƒ}t|dƒrN|j|ƒ |j	ƒ }t
rvt |tƒrv|jtj|j ƒ}|S )Nz(context must be a connection or a cursorÚprepare)r   rF   Ú
connectionÚcursorr   Zadaptr   ÚhasattrrJ   Z	getquotedr   ÚbytesÚdecodeÚ	encodingsÚencoding)r   r   ÚconnÚar'   r	   r	   r
   r   }  s    

zLiteral.as_stringN)r   r   r   r   r+   r   r   r	   r	   r	   r
   rI   d  s   rI   c                   s>   e Zd ZdZd‡ fdd„	Zedd„ ƒZdd„ Zd	d
„ Z‡  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                sH   t |tƒr d|kr4td| ƒ‚n|d k	r4td| ƒ‚tt| ƒj|ƒ d S )Nú)zinvalid name: %rz'expected string or None as name, got %r)r   r   r1   r   r!   rT   r   )r   r7   )r   r	   r
   r   ¬  s    
zPlaceholder.__init__c             C   s   | j S )zThe name of the `!Placeholder`.)r   )r   r	   r	   r
   r7   ¶  s    zPlaceholder.namec             C   s   d| j d k	r| j ndf S )NzPlaceholder(%r)r%   )r   )r   r	   r	   r
   r   »  s    zPlaceholder.__repr__c             C   s   | j d k	rd| j  S dS d S )Nz%%(%s)sz%s)r   )r   r   r	   r	   r
   r   ¿  s    

zPlaceholder.as_string)N)
r   r   r   r   r   r+   r7   r   r   r,   r	   r	   )r   r
   rT   ‘  s
   
rT   ÚNULLÚDEFAULT)r   r-   Zpsycopg2r   rF   Zpsycopg2.compatr   r   Ú	Formatterr/   Úobjectr   r   r*   r>   rI   rT   rV   rW   r	   r	   r	   r
   Ú<module>   s   3I A-6