U
    [¹Öh<B  ã                   @  sö  d dl mZ d dl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	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lmZ ddlmZ ddlmZ e	rvd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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 lm+Z+ dd!l,m-Z- e
d"ed#Z.ej/fd$d%d&d'd(œd)d*„Zej/fd$d%d&d'd(œd+d,„Z0G d-d.„ d.ej1e. ƒZ2G d/d0„ d0ej3e. ƒZ3d1d2d3œd4d5„Z4dS )6é    )ÚannotationsN)ÚAny)ÚIterable)ÚOptional)ÚSequence)ÚTYPE_CHECKING)ÚTypeVar)ÚUnioné   )ÚCONTAINED_BY)ÚCONTAINS)ÚOVERLAPé   )Útypes)Úutil)Ú
expression)Ú	operators)ÚInternalTraversal)ÚDialect)Ú_ColumnExpressionArgument)Ú_TypeEngineArgument)ÚColumnElement)ÚGrouping)ÚBindParameter)ÚOperatorType)Ú_SelectIterable)Ú_BindProcessorType)Ú_LiteralProcessorType)Ú_ResultProcessorType)Ú
TypeEngine)Ú_TraverseInternalsType)ÚSelfÚ_T)ZboundÚ
typing_Anyz_ColumnExpressionArgument[_T]r   úColumnElement[bool])ÚotherÚarrexprÚoperatorÚreturnc                 C  s   |  | |¡S )zjA synonym for the ARRAY-level :meth:`.ARRAY.Comparator.any` method.
    See that method for details.

    )Úany©r%   r&   r'   © r+   úJ./venv/lib/python3.8/site-packages/sqlalchemy/dialects/postgresql/array.pyr   1   s    
r   c                 C  s   |  | |¡S )zjA synonym for the ARRAY-level :meth:`.ARRAY.Comparator.all` method.
    See that method for details.

    )Úallr*   r+   r+   r,   ÚAll>   s    
r.   c                      s’   e Zd ZU dZd ZdZdejfdejfgZ	de
d< ddœd	d
ddœ‡ fdd„Zeddœdd„ƒZd ddddddœdd„Zd!dddœdd„Z‡  ZS )"ÚarrayaÝ  A PostgreSQL ARRAY literal.

    This is used to produce ARRAY literals in SQL expressions, e.g.::

        from sqlalchemy.dialects.postgresql import array
        from sqlalchemy.dialects import postgresql
        from sqlalchemy import select, func

        stmt = select(array([1, 2]) + array([3, 4, 5]))

        print(stmt.compile(dialect=postgresql.dialect()))

    Produces the SQL:

    .. sourcecode:: sql

        SELECT ARRAY[%(param_1)s, %(param_2)s] ||
            ARRAY[%(param_3)s, %(param_4)s, %(param_5)s]) AS anon_1

    An instance of :class:`.array` will always have the datatype
    :class:`_types.ARRAY`.  The "inner" type of the array is inferred from the
    values present, unless the :paramref:`_postgresql.array.type_` keyword
    argument is passed::

        array(["foo", "bar"], type_=CHAR)

    When constructing an empty array, the :paramref:`_postgresql.array.type_`
    argument is particularly important as PostgreSQL server typically requires
    a cast to be rendered for the inner type in order to render an empty array.
    SQLAlchemy's compilation for the empty array will produce this cast so
    that::

        stmt = array([], type_=Integer)
        print(stmt.compile(dialect=postgresql.dialect()))

    Produces:

    .. sourcecode:: sql

        ARRAY[]::INTEGER[]

    As required by PostgreSQL for empty arrays.

    .. versionadded:: 2.0.40 added support to render empty PostgreSQL array
       literals with a required cast.

    Multidimensional arrays are produced by nesting :class:`.array` constructs.
    The dimensionality of the final :class:`_types.ARRAY`
    type is calculated by
    recursively adding the dimensions of the inner :class:`_types.ARRAY`
    type::

        stmt = select(
            array(
                [array([1, 2]), array([3, 4]), array([column("q"), column("x")])]
            )
        )
        print(stmt.compile(dialect=postgresql.dialect()))

    Produces:

    .. sourcecode:: sql

        SELECT ARRAY[
            ARRAY[%(param_1)s, %(param_2)s],
            ARRAY[%(param_3)s, %(param_4)s],
            ARRAY[q, x]
        ] AS anon_1

    .. versionadded:: 1.3.6 added support for multidimensional array literals

    .. seealso::

        :class:`_postgresql.ARRAY`

    Z
postgresqlÚclausesÚtyper    Ú_traverse_internalsN)Útype_zIterable[_T]z!Optional[_TypeEngineArgument[_T]]r#   )r0   r3   Úkwc                  sx   t ƒ jtjf|ž|Ž |dk	r"|n| jr4| jd jntj}t|t	ƒrjt	|j
|jdk	r^|jd ndd| _n
t	|ƒ| _dS )a  Construct an ARRAY literal.

        :param clauses: iterable, such as a list, containing elements to be
         rendered in the array
        :param type\_: optional type.  If omitted, the type is inferred
         from the contents of the array.

        Nr   r
   é   )Ú
dimensions)ÚsuperÚ__init__r   Zcomma_opr0   r1   ÚsqltypesZNULLTYPEÚ
isinstanceÚARRAYÚ	item_typer6   )Úselfr0   r3   r4   Z	main_type©Ú	__class__r+   r,   r8   ¢   s    ÿý
ÿû
	zarray.__init__r   ©r(   c                 C  s   | fS ©Nr+   ©r=   r+   r+   r,   Ú_select_iterableÅ   s    zarray._select_iterableFr   zOptional[TypeEngine[_T]]ÚboolzBindParameter[_T])r'   Úobjr3   Ú_assume_scalarr(   c                   sD   |sˆ t jkr&tjd |ˆ ˆˆjddS t‡ ‡‡fdd„|D ƒƒS d S )NT)Z_compared_to_operatorr3   Z_compared_to_typeÚuniquec                   s   g | ]}ˆj ˆ |d ˆd‘qS )T)rF   r3   )Ú_bind_param)Ú.0Úo©r'   r=   r3   r+   r,   Ú
<listcomp>Ü   s   ý   ÿz%array._bind_param.<locals>.<listcomp>)r   Úgetitemr   r   r1   r/   )r=   r'   rE   r3   rF   r+   rK   r,   rH   É   s    ú
üÿzarray._bind_paramzOptional[OperatorType]zUnion[Self, Grouping[_T]])Úagainstr(   c                 C  s&   |t jt jt jfkrt | ¡S | S d S rA   )r   Zany_opZall_oprM   r   r   )r=   rN   r+   r+   r,   Ú
self_groupä   s    
zarray.self_group)NF)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Z__visit_name__Zstringify_dialectr   Zdp_clauseelement_tupleZdp_typer2   Ú__annotations__r8   ÚpropertyrC   rH   rO   Ú__classcell__r+   r+   r>   r,   r/   K   s   
Mþ	ü#  û ÿr/   c                   @  sˆ   e Zd ZdZddddddœdd	„ZG d
d„ dejje ƒZeZ	e
jddœdd„ƒZdddœdd„Zdddœdd„Zddddœdd„ZdS )r;   an
  PostgreSQL ARRAY type.

    The :class:`_postgresql.ARRAY` type is constructed in the same way
    as the core :class:`_types.ARRAY` type; a member type is required, and a
    number of dimensions is recommended if the type is to be used for more
    than one dimension::

        from sqlalchemy.dialects import postgresql

        mytable = Table(
            "mytable",
            metadata,
            Column("data", postgresql.ARRAY(Integer, dimensions=2)),
        )

    The :class:`_postgresql.ARRAY` type provides all operations defined on the
    core :class:`_types.ARRAY` type, including support for "dimensions",
    indexed access, and simple matching such as
    :meth:`.types.ARRAY.Comparator.any` and
    :meth:`.types.ARRAY.Comparator.all`.  :class:`_postgresql.ARRAY`
    class also
    provides PostgreSQL-specific methods for containment operations, including
    :meth:`.postgresql.ARRAY.Comparator.contains`
    :meth:`.postgresql.ARRAY.Comparator.contained_by`, and
    :meth:`.postgresql.ARRAY.Comparator.overlap`, e.g.::

        mytable.c.data.contains([1, 2])

    Indexed access is one-based by default, to match that of PostgreSQL;
    for zero-based indexed access, set
    :paramref:`_postgresql.ARRAY.zero_indexes`.

    Additionally, the :class:`_postgresql.ARRAY`
    type does not work directly in
    conjunction with the :class:`.ENUM` type.  For a workaround, see the
    special type at :ref:`postgresql_array_of_enum`.

    .. container:: topic

        **Detecting Changes in ARRAY columns when using the ORM**

        The :class:`_postgresql.ARRAY` type, when used with the SQLAlchemy ORM,
        does not detect in-place mutations to the array. In order to detect
        these, the :mod:`sqlalchemy.ext.mutable` extension must be used, using
        the :class:`.MutableList` class::

            from sqlalchemy.dialects.postgresql import ARRAY
            from sqlalchemy.ext.mutable import MutableList


            class SomeOrmClass(Base):
                # ...

                data = Column(MutableList.as_mutable(ARRAY(Integer)))

        This extension will allow "in-place" changes such to the array
        such as ``.append()`` to produce events which will be detected by the
        unit of work.  Note that changes to elements **inside** the array,
        including subarrays that are mutated in place, are **not** detected.

        Alternatively, assigning a new array value to an ORM element that
        replaces the old one will always trigger a change event.

    .. seealso::

        :class:`_types.ARRAY` - base array type

        :class:`_postgresql.array` - produces a literal array value.

    FNz_TypeEngineArgument[_T]rD   zOptional[int])r<   Úas_tupler6   Úzero_indexesc                 C  s>   t |tƒrtdƒ‚t |tƒr"|ƒ }|| _|| _|| _|| _dS )a-  Construct an ARRAY.

        E.g.::

          Column("myarray", ARRAY(Integer))

        Arguments are:

        :param item_type: The data type of items of this array. Note that
          dimensionality is irrelevant here, so multi-dimensional arrays like
          ``INTEGER[][]``, are constructed as ``ARRAY(Integer)``, not as
          ``ARRAY(ARRAY(Integer))`` or such.

        :param as_tuple=False: Specify whether return results
          should be converted to tuples from lists. DBAPIs such
          as psycopg2 return lists by default. When tuples are
          returned, the results are hashable.

        :param dimensions: if non-None, the ARRAY will assume a fixed
         number of dimensions.  This will cause the DDL emitted for this
         ARRAY to include the exact number of bracket clauses ``[]``,
         and will also optimize the performance of the type overall.
         Note that PG arrays are always implicitly "non-dimensioned",
         meaning they can store any number of dimensions no matter how
         they were declared.

        :param zero_indexes=False: when True, index values will be converted
         between Python zero-based and PostgreSQL one-based indexes, e.g.
         a value of one will be added to all index values before passing
         to the database.

        zUDo not nest ARRAY types; ARRAY(basetype) handles multi-dimensional arrays of basetypeN)r:   r;   Ú
ValueErrorr1   r<   rW   r6   rX   )r=   r<   rW   r6   rX   r+   r+   r,   r8   5  s    '
ÿ
zARRAY.__init__c                   @  sB   e Zd ZdZddddœdd„Zdddœdd	„Zdddœd
d„ZdS )zARRAY.Comparatora*  Define comparison operations for :class:`_types.ARRAY`.

        Note that these operations are in addition to those provided
        by the base :class:`.types.ARRAY.Comparator` class, including
        :meth:`.types.ARRAY.Comparator.any` and
        :meth:`.types.ARRAY.Comparator.all`.

        r#   r$   )r%   Úkwargsr(   c                 K  s   | j t|tjdS )zåBoolean expression.  Test if elements are a superset of the
            elements of the argument array expression.

            kwargs may be ignored by this operator but are required for API
            conformance.
            ©Zresult_type)Úoperater   r9   ÚBoolean)r=   r%   rZ   r+   r+   r,   Úcontainsr  s    	zARRAY.Comparator.contains)r%   r(   c                 C  s   | j t|tjdS )z„Boolean expression.  Test if elements are a proper subset of the
            elements of the argument array expression.
            r[   )r\   r   r9   r]   ©r=   r%   r+   r+   r,   Úcontained_by}  s
      ÿzARRAY.Comparator.contained_byc                 C  s   | j t|tjdS )zuBoolean expression.  Test if array has elements in common with
            an argument array expression.
            r[   )r\   r   r9   r]   r_   r+   r+   r,   Úoverlap…  s    zARRAY.Comparator.overlapN)rP   rQ   rR   rS   r^   r`   ra   r+   r+   r+   r,   Ú
Comparatorh  s   	rb   r@   c                 C  s   t | jtjƒo| jjS rA   )r:   r<   r9   ÚEnumZnative_enumrB   r+   r+   r,   Ú_against_native_enum  s    þzARRAY._against_native_enumr   z#Optional[_LiteralProcessorType[_T]])Údialectr(   c                   sJ   ˆj  |¡ |¡‰ ˆ d krd S dddœdd„‰dddœ‡ ‡‡fdd	„}|S )
NzIterable[typing_Any]Ústr)Úelementsr(   c                 S  s   dd  | ¡› dS )NzARRAY[z, ú])Újoin)rg   r+   r+   r,   Úto_str  s    z'ARRAY.literal_processor.<locals>.to_strúSequence[typing_Any]©Úvaluer(   c                   s   ˆ  | ˆ ˆjˆ¡}|S rA   )Ú_apply_item_processorr6   ©rm   Úinner©Ú	item_procr=   rj   r+   r,   Úprocess   s       ÿz(ARRAY.literal_processor.<locals>.process)r<   Údialect_implÚliteral_processor©r=   re   rs   r+   rq   r,   ru   ”  s    ÿzARRAY.literal_processorz2Optional[_BindProcessorType[Sequence[typing_Any]]]c                   s,   ˆj  |¡ |¡‰ dddœ‡ ‡fdd„}|S )NúOptional[Sequence[typing_Any]]zOptional[list[typing_Any]]rl   c                   s"   | d kr| S ˆ  | ˆ ˆjt¡S d S rA   )rn   r6   Úlist©rm   ©rr   r=   r+   r,   rs   ¯  s       ÿz%ARRAY.bind_processor.<locals>.process)r<   rt   Úbind_processorrv   r+   rz   r,   r{   ¨  s
    ÿ
zARRAY.bind_processorÚobjectz*_ResultProcessorType[Sequence[typing_Any]])re   Úcoltyper(   c                   sl   ˆj  |¡ ||¡‰dddœ‡‡fdd„}ˆjrh|‰t d¡‰dddœ‡fd	d
„‰ dddœ‡ ‡fdd„}|S )Nrk   rw   rl   c                   s,   | d kr| S ˆ  | ˆ ˆjˆjr"tnt¡S d S rA   )rn   r6   rW   Útuplerx   ry   rz   r+   r,   rs   Â  s    üz'ARRAY.result_processor.<locals>.processz^{(.*)}$rf   ú	list[str]c                   s   ˆ   | ¡ d¡}t|ƒS )Nr
   )ÚmatchÚgroupÚ_split_enum_valuesro   )Úpatternr+   r,   Úhandle_raw_stringÓ  s    z1ARRAY.result_processor.<locals>.handle_raw_stringc                   s&   | d kr| S ˆt | tƒr ˆ | ƒn| ƒS rA   )r:   rf   ry   )r„   Úsuper_rpr+   r,   rs   ×  s    ÿ
ý)r<   rt   Úresult_processorrd   ÚreÚcompile)r=   re   r}   rs   r+   )r„   rr   rƒ   r=   r…   r,   r†   »  s     ÿ
zARRAY.result_processor)FNF)rP   rQ   rR   rS   r8   r9   r;   rb   r"   Zcomparator_factoryr   Zmemoized_propertyrd   ru   r{   r†   r+   r+   r+   r,   r;   í   s   J   û3#r;   rf   r   )Úarray_stringr(   c                 C  sŽ   d| kr| r|   d¡S g S |  dd¡}| dd¡}g }t  d|¡}d}|D ]>}|dkr^| }qJ|rv| | dd¡¡ qJ| t d	|¡¡ qJ|S )
Nú"ú,z\"z_$ESC_QUOTE$_z\\ú\z(")Fz([^\s,]+),?)ÚsplitÚreplacer‡   ÚappendÚextendÚfindall)r‰   ÚtextÚresultZ	on_quotesZ	in_quotesÚtokr+   r+   r,   r‚   è  s    r‚   )5Z
__future__r   r‡   Útypingr   r#   r   r   r   r   r   r	   r   r   r   r   Ú r   r9   r   Zsqlr   Zsql.visitorsr   Zengine.interfacesr   Zsql._typingr   r   Zsql.elementsr   r   Zsql.expressionr   Zsql.operatorsr   Zsql.selectabler   Zsql.type_apir   r   r   r   r    Zutil.typingr!   r"   Úeqr.   ZExpressionClauseListr/   r;   r‚   r+   r+   r+   r,   Ú<module>	   sR   ýý # |