
    (ph:?                    F   S r SSKJr  SSKrSSKrSSKJrJr  SSKJ	r	J
r
JrJr  SSKJr  SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJr  SSS jjr " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r\" S5      r\" S5      r g)z 
SQL composition utility module
    )annotationsN)ABCabstractmethod)AnyIteratorIterableSequence   )Escaping)AdaptContext)PyFormat)LiteralString)conn_encoding)Transformerc                6    [        U 5      R                  U5      $ )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     >/var/www/html/venv/lib/python3.13/site-packages/psycopg/sql.pyquoter      s     3<!!'**    c                  z    \ rS rSrSrSS jrSS jr\SSS jj5       rSSS jjr	SS jr
SS	 jrSS
 jrSS jrSrg)
Composable&   a  
Abstract base class for objects that can be used to compose an SQL string.

`!Composable` objects can be passed directly to
`~psycopg.Cursor.execute()`, `~psycopg.Cursor.executemany()`,
`~psycopg.Cursor.copy()` 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                    Xl         g N_obj)selfr   s     r   __init__Composable.__init__5   s    	r   c                P    U R                   R                   SU R                  < S3$ )N())	__class____name__r   r    s    r   __repr__Composable.__repr__8   s$    ..))*!DII=::r   Nc                    [         e)aF  
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_bytesComposable.as_bytes;   s
     "!r   c                    U(       a  UR                   OSn[        U5      nU R                  U5      n[        U[        5      (       a  UR                  U5      $ [        R                  " U5      R                  U5      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   )
connectionr   r.   
isinstancebytesdecodecodecslookup)r    r   connencbs        r   r   Composable.as_stringJ   sg     &-w!!$D!MM'"a88C=  ==%,,Q/22r   c                    [        U[        5      (       a  [        U /5      U-   $ [        U[        5      (       a  [        U /5      [        U/5      -   $ [        $ r   )r2   Composedr   NotImplementedr    others     r   __add__Composable.__add__[   sM    eX&&TF#e++eZ((TF#hw&777!!r   c                     [        U /U-  5      $ r   )r<   )r    ns     r   __mul__Composable.__mul__c   s    
##r   c                n    [        U 5      [        U5      L =(       a    U R                  UR                  :H  $ r   )typer   r>   s     r   __eq__Composable.__eq__f   s'    DzT%[(DTYY%**-DDr   c                .    U R                  U5      (       + $ r   )rH   r>   s     r   __ne__Composable.__ne__i   s    ;;u%%%r   r   )r   r   returnstrr   r   AdaptContext | NonerN   r3   r   rQ   rN   rO   r?   r   rN   r<   )rC   intrN   r<   )r?   r   rN   bool)r'   
__module____qualname____firstlineno____doc__r!   r)   r   r.   r   r@   rD   rH   rK   __static_attributes__ r   r   r   r   &   s?    ; " "3""$E&r   r   c                  h   ^  \ rS rSr% SrS\S'   SU 4S jjrSSS jjrSS jrSS jr	SS	 jr
S
rU =r$ )r<   m   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 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                   > U Vs/ s H%  n[        U[        5      (       a  UO
[        U5      PM'     nn[        TU ]  U5        g s  snf r   )r2   r   r   superr!   )r    seqr   r&   s      r   r!   Composed.__init__   s?    ORSsjj11sws|CsS Ts   ,Ac                N   ^ SR                  U4S jU R                   5       5      $ )Nr   c              3  D   >#    U  H  oR                  T5      v   M     g 7fr   )r.   ).0r   r   s     r   	<genexpr>$Composed.as_bytes.<locals>.<genexpr>   s     C#W--s    )joinr   r-   s    `r   r.   Composed.as_bytes   s    xxCCCCr   c                ,    [        U R                  5      $ r   )iterr   r(   s    r   __iter__Composed.__iter__   s    DIIr   c                    [        U[        5      (       a"  [        U R                  UR                  -   5      $ [        U[        5      (       a  [        U R                  U/-   5      $ [        $ r   )r2   r<   r   r   r=   r>   s     r   r@   Composed.__add__   sP    eX&&DII

233eZ((DII/00!!r   c                    [        U[        5      (       a  [        U5      nO%[        U[        5      (       d  [        SU< S35      eUR	                  U R
                  5      $ )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)r2   rO   SQL	TypeErrorrg   r   )r    joiners     r   rg   Composed.join   sZ     fc""[FFC((z+ 
 {{499%%r   r[   )r`   zSequence[Any]r   rP   )rN   zIterator[Composable]rS   )rs   zSQL | LiteralStringrN   r<   )r'   rV   rW   rX   rY   __annotations__r!   r.   rk   r@   rg   rZ   __classcell__r&   s   @r   r<   r<   m   s/    & D"& &r   r<   c                     ^  \ rS rSr% SrS\S'   \R                  " 5       rSU 4S jjr	SSS jjr
SSS jjrSS jrSS	 jrS
rU =r$ )rq      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.

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                n   > [         TU ]  U5        [        U[        5      (       d  [	        SU< S35      eg )Nz SQL values must be strings, got rp   )r_   r!   r2   rO   rr   )r    r   r&   s     r   r!   SQL.__init__   s7    #s##>sgXNOO $r   c                    U R                   $ r   r   r-   s     r   r   SQL.as_string   s    yyr   c                x    U(       a  UR                   OS n[        U5      nU R                  R                  U5      $ r   )r1   r   r   encoder    r   r7   r8   s       r   r.   SQL.as_bytes   s0    %,w!!$D!yy$$r   c                &   / nSnU R                   R                  U R                  5       H  u  pVpxU(       a  [        S5      eU(       a  [        S5      eU(       a  UR	                  [        U5      5        Uc  MP  UR                  5       (       a3  U(       a  [        S5      eUR	                  U[        U5         5        SnM  U(       d(  Uc  [        S5      eUR	                  X   5        US-  nM  UR	                  X&   5        M     [        U5      $ )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appendrq   isdigitrT   r<   )	r    argskwargsrvautonumprenamespecconvs	            r   format
SQL.format   s    F  " &*__%:%:499%E!Ct !KLL !HII		#c(#|||~~$P  		$s4y/*?$P  		$-(1 		&,'9 &F< |r   c                    / n[        U5      n UR                  [        U5      5        U H%  nUR                  U 5        UR                  U5        M'     [	        U5      $ ! [         a     Nf = f)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"
)rj   r   nextStopIterationr<   )r    r`   r   itis        r   rg   SQL.join  si    $ #Y	IId2h 		$		!  |  		s   A 
A,+A,r[   )r   r   r   rR   rP   )r   r   r   r   rN   r<   )r`   zIterable[Composable]rN   r<   )r'   rV   rW   rX   rY   ru   string	Formatterr   r!   r   r.   r   rg   rZ   rv   rw   s   @r   rq   rq      s?    , !!#JP
%
FP r   rq   c                  ^   ^  \ rS rSr% SrS\S'   S
U 4S jjrSS jrSSS jjrSS jr	S	r
U =r$ )
Identifieri=  a  
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U ]  U5        U(       d  [        S5      eU H(  n[        U[        5      (       a  M  [        SU< S35      e   g )NzIdentifier cannot be emptyz*SQL identifier parts must be strings, got rp   )r_   r!   rr   r2   rO   )r    stringssr&   s      r   r!   Identifier.__init___  sO    !899Aa%%@XN  r   c                    U R                   R                   SSR                  [        [        U R
                  5      5       S3$ )Nr$   , r%   )r&   r'   rg   mapreprr   r(   s    r   r)   Identifier.__repr__l  s5    ..))*!DIIc$		6J,K+LANNr   c                   U(       a  UR                   OS nU(       aZ  [        UR                  5      n[        U5      nU R                   Vs/ s H"  oSR                  UR                  U5      5      PM$     nnO8U R                   Vs/ s H!  oPR                  UR                  5       5      PM#     nnSR                  U5      $ s  snf s  snf )N   .)	r1   r   pgconnr   r   escape_identifierr   _escape_identifierrg   )r    r   r7   escr8   r   escss          r   r.   Identifier.as_byteso  s    %,w!!$4;;'C%CBF))L)Q))!((3-8)DLDAEKA++AHHJ7DKyy MKs   )C (Cc                2    SUR                  SS5      -   S-   $ )z;
Approximation of PQescapeIdentifier taking no connection.
   "s   "")replace)r    r   s     r   r   Identifier._escape_identifiery  s     aiie,,t33r   r[   )r   rO   rM   r   rP   )r   r3   rN   r3   )r'   rV   rW   rX   rY   ru   r!   r)   r.   r   rZ   rv   rw   s   @r   r   r   =  s*    > O4 4r   r   c                  &    \ rS rSrSrSSS jjrSrg)r   i  ae  
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                d    [         R                  " U5      nUR                  U R                  5      $ r   )r   from_context
as_literalr   )r    r   txs      r   r.   Literal.as_bytes  s%    %%g.}}TYY''r   r[   r   rP   )r'   rV   rW   rX   rY   r.   rZ   r[   r   r   r   r     s    (( (r   r   c                  r   ^  \ rS rSrSrS\R                  4S	U 4S jjjrS
S jrSSS jjr	SSS jjr
SrU =r$ )Placeholderi  a  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                J  > [         TU ]  U5        [        U[        5      (       d  [	        SU< 35      eSU;   a  [        SU< 35      e[        U5      [        L a  [        U5      n[        U[        5      (       d"  [	        S[        U5      R                  < 35      eX l	        g )Nzexpected string as name, got r%   zinvalid name: z!expected PyFormat as format, got )
r_   r!   r2   rO   rr   r   rG   r   r'   _format)r    r   r   r&   s      r   r!   Placeholder.__init__  s    $$$;D8DEE$;~dX677<3f%F&(++3DL4I4I3LM  "(r   c                P   / nU R                   (       a$  UR                  [        U R                   5      5        U R                  [        R
                  La(  UR                  SU R                  R                   35        U R                  R                   SSR                  U5       S3$ )Nzformat=r$   r   r%   )
r   r   r   r   r   AUTOr   r&   r'   rg   )r    partss     r   r)   Placeholder.__repr__  sx    99LLdii)<<x}},LL74<<#4#4"567..))*!DIIe,<+=Q??r   c                ~    U R                   R                  nU R                  (       a  SU R                   SU 3$ SU 3$ )Nz%(r%   %)r   valuer   )r    r   codes      r   r   Placeholder.as_string  s9    ||!!*.))DII;av&C1TFCr   c                    U(       a  UR                   OS n[        U5      nU R                  U5      R                  U5      $ r   )r1   r   r   r   r   s       r   r.   Placeholder.as_bytes  s5    %,w!!$D!~~g&--c22r   )r   )r   rO   r   zstr | PyFormatrM   r   rR   rP   )r'   rV   rW   rX   rY   r   r   r!   r)   r   r.   rZ   rv   rw   s   @r   r   r     s3    6 $& ( ("@D3 3r   r   NULLDEFAULTr   )r   r   r   rQ   rN   rO   )!rY   
__future__r   r5   r   abcr   r   typingr   r   r   r	   pqr   r   _enumsr   _compatr   
_encodingsr   _transformerr   r   r   r<   rq   r   r   r   r   r   r[   r   r   <module>r      s    #   # 4 4    " % %+ D& D&N>&z >&BL* L^@4 @4F(j (4=3* =3B 6{
i.r   