g 6LddlmZddlZddlmZddlmZddlmZddlmZddlm Z dd lm Z d d l m Z d d l mZd d lmZd dlmZd dlmZedeZej(fdZej(fdZGddej,eZGdde j0ZdZy)) annotationsN)Any)Optional)TypeVar) CONTAINED_BY)CONTAINS)OVERLAP)types)util) expression) operators)_TypeEngineArgument_T)boundc&|j||S)zjA synonym for the ARRAY-level :meth:`.ARRAY.Comparator.any` method. See that method for details. )anyotherarrexproperators U/opt/hc_python/lib64/python3.12/site-packages/sqlalchemy/dialects/postgresql/array.pyrr ;;uh ''c&|j||S)zjA synonym for the ARRAY-level :meth:`.ARRAY.Comparator.all` method. See that method for details. )allrs rAllr'rrcNeZdZdZdZdZdZfdZedZ ddZ d dZ xZ S) arraya0A 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 ``type_`` keyword argument is passed:: array(["foo", "bar"], type_=CHAR) 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` postgresqlTc |jdd}t|tjg|i||j Dcgc]}|j c}|_||n*|jr|jdntj}t|tr8t|j|j|jdznd|_yt||_ycc}w)Ntype_rr) dimensions)popsuper__init__rcomma_opclausestype _type_tuplesqltypesNULLTYPE isinstanceARRAY item_typer%)selfr*kwtype_argarg main_type __class__s rr(zarray.__init__ns66'4( ++O>O  i '##!++7((1, DIi(DI%>sC&c|fSNr2s r_select_iterablezarray._select_iterables wrc |s|tjur%tjd||||jdSt |Dcgc]}|j ||d|c}Scc}w)NT)_compared_to_operatorr#_compared_to_typeunique)_assume_scalarr#)rgetitemr BindParameterr+r _bind_param)r2robjrAr#os rrDzarray._bind_params X):)::++&."&))   ! !$$ !D%!  sA&c|tjtjtjfvrt j |S|Sr9)rany_opall_oprBrGrouping)r2againsts r self_groupzarray.self_groups9 y'')9)99;L;LM M&&t, ,Kr)FNr9) __name__ __module__ __qualname____doc____visit_name__stringify_dialect inherit_cacher(propertyr<rDrL __classcell__)r7s@rr r 0s>6pN$M)0*rr ceZdZdZ d ddZGddej jZeZe dZ e dZ dZ e jd Zd Zd Zd Zy)r0an 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. Nct|tr tdt|tr|}||_||_||_||_y)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/r0 ValueErrorr+r1as_tupler% zero_indexes)r2r1rYr%rZs rr(zARRAY.__init__sQN i '?  i &! I"  $(rc"eZdZdZdZdZdZy)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`. c N|jt|tjS)zBoolean 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.  result_type)operater r-Boolean)r2rkwargss rcontainszARRAY.Comparator.contains+s<<%X=M=M<N NrcN|jt|tjS)zBoolean expression. Test if elements are a proper subset of the elements of the argument array expression. r^)r`rr-rar2rs r contained_byzARRAY.Comparator.contained_by4s'<<e1A1A  rcN|jt|tjS)zuBoolean expression. Test if array has elements in common with an argument array expression. r^)r`r r-rares roverlapzARRAY.Comparator.overlap<s<<H.to_str]sDIIh/02 2rcDj|j}|Sr9)_apply_item_processorr%)valueinner item_procr2r|s rprocessz(ARRAY.literal_processor..process`s'..y$//6ELr)r1 dialect_implliteral_processor)r2dialectrrr|s` @@rrzARRAY.literal_processorVsANN//8JJ     3  rcjjj|j|fd}|S)NcP||Sj|jtSr9)r~r%rmrrr2s rrz%ARRAY.bind_processor..processms-} 119dootr)r1rbind_processor)r2rrrs` @rrzARRAY.bind_processorhs1NN//8GG   rcjj|j||fd}jr"|t j dfdfd}|S)Nc|||Sj|jjr tStSr9)r~r%rYtuplermrs rrz'ARRAY.result_processor..process|sE} 11OO!]]E 15 rz^{(.*)}$cZj|jd}t|S)Nr)matchgroup_split_enum_values)rrpatterns rhandle_raw_stringz1ARRAY.result_processor..handle_raw_strings' e,2215)%00rcT||St|tr |S|Sr9)r/str)rrsuper_rps rrz'ARRAY.result_processor..processs?= L !%-&e,r)r1rresult_processorrvrecompile)r2rcoltyperrrrrs` @@@@rrzARRAY.result_processorws[NN//8II W    $ $Hjj-G 1 r)FNF)r1z_TypeEngineArgument[Any]rYboolr%z Optional[int]rZr)rMrNrOrPr(r-r0ricomparator_factoryrTrkrnrrr memoized_propertyrvrrrr:rrr0r0sET$(" 1)+1)1)" 1)  1)fNX^^..NB$    $ $rr0cfd|vr|r|jdSgS|jdd}|jdd}g}tjd|}d}|D]T}|dk(r| } |r"|j|jdd0|j tj d |V|S) N",z\"z _$ESC_QUOTE$_z\\\z(")Fz ([^\s,]+),?)splitreplacerappendextendfindall) array_stringtextresult on_quotes in_quotestoks rrrs ,*6|!!#&>B>    7D <<t $D F&II #:% I  MM#++os; < MM"**^S9 :  Mr) __future__rrtypingrrrrrr r r r-r sqlr sql._typingrreqrExpressionClauseListr r0rr:rrrs# #!. T"+("+(sJ + +B /sluHNNupr