Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
functions.py2200 linesDownload Raw Back to sql
1# sql/functions.py
2# Copyright (C) 2005-2026 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7
8"""SQL function API, factories, and built-in functions."""
9
10from __future__ import annotations
11
12import datetime
13import decimal
14from typing import Any
15from typing import cast
16from typing import Dict
17from typing import List
18from typing import Mapping
19from typing import Optional
20from typing import overload
21from typing import Sequence
22from typing import Tuple
23from typing import Type
24from typing import TYPE_CHECKING
25from typing import TypeVar
26from typing import Union
27
28from . import annotation
29from . import coercions
30from . import operators
31from . import roles
32from . import schema
33from . import sqltypes
34from . import type_api
35from . import util as sqlutil
36from ._typing import is_table_value_type
37from .base import _entity_namespace
38from .base import ColumnCollection
39from .base import Executable
40from .base import Generative
41from .base import HasMemoized
42from .elements import _type_from_args
43from .elements import BinaryExpression
44from .elements import BindParameter
45from .elements import Cast
46from .elements import ClauseList
47from .elements import ColumnElement
48from .elements import Extract
49from .elements import FunctionFilter
50from .elements import Grouping
51from .elements import literal_column
52from .elements import NamedColumn
53from .elements import Over
54from .elements import WithinGroup
55from .selectable import FromClause
56from .selectable import Select
57from .selectable import TableValuedAlias
58from .sqltypes import TableValueType
59from .type_api import TypeEngine
60from .visitors import InternalTraversal
61from .. import util
62from ..util.typing import TypeAlias
63
64if TYPE_CHECKING:
65    from ._typing import _ByArgument
66    from ._typing import _ColumnExpressionArgument
67    from ._typing import _ColumnExpressionOrLiteralArgument
68    from ._typing import _ColumnExpressionOrStrLabelArgument
69    from ._typing import _StarOrOne
70    from ._typing import _TypeEngineArgument
71    from .base import _EntityNamespace
72    from .elements import ClauseElement
73    from .elements import KeyedColumnElement
74    from .elements import TableValuedColumn
75    from .operators import OperatorType
76    from ..engine.base import Connection
77    from ..engine.cursor import CursorResult
78    from ..engine.interfaces import _CoreMultiExecuteParams
79    from ..engine.interfaces import CoreExecuteOptionsParameter
80    from ..util.typing import Self
81
82_T = TypeVar("_T", bound=Any)
83_S = TypeVar("_S", bound=Any)
84
85_registry: util.defaultdict[str, Dict[str, Type[Function[Any]]]] = (
86    util.defaultdict(dict)
87)
88
89
90def register_function(
91    identifier: str, fn: Type[Function[Any]], package: str = "_default"
92) -> None:
93    """Associate a callable with a particular func. name.
94
95    This is normally called by GenericFunction, but is also
96    available by itself so that a non-Function construct
97    can be associated with the :data:`.func` accessor (i.e.
98    CAST, EXTRACT).
99
100    """
101    reg = _registry[package]
102
103    identifier = str(identifier).lower()
104
105    # Check if a function with the same identifier is registered.
106    if identifier in reg:
107        util.warn(
108            "The GenericFunction '{}' is already registered and "
109            "is going to be overridden.".format(identifier)
110        )
111    reg[identifier] = fn
112
113
114class FunctionElement(Executable, ColumnElement[_T], FromClause, Generative):
115    """Base for SQL function-oriented constructs.
116
117    This is a `generic type <https://peps.python.org/pep-0484/#generics>`_,
118    meaning that type checkers and IDEs can be instructed on the types to
119    expect in a :class:`_engine.Result` for this function. See
120    :class:`.GenericFunction` for an example of how this is done.
121
122    .. seealso::
123
124        :ref:`tutorial_functions` - in the :ref:`unified_tutorial`
125
126        :class:`.Function` - named SQL function.
127
128        :data:`.func` - namespace which produces registered or ad-hoc
129        :class:`.Function` instances.
130
131        :class:`.GenericFunction` - allows creation of registered function
132        types.
133
134    """
135
136    _traverse_internals = [
137        ("clause_expr", InternalTraversal.dp_clauseelement),
138        ("_with_ordinality", InternalTraversal.dp_boolean),
139        ("_table_value_type", InternalTraversal.dp_has_cache_key),
140    ] + Executable._executable_traverse_internals
141
142    packagenames: Tuple[str, ...] = ()
143
144    _has_args = False
145    _with_ordinality = False
146    _table_value_type: Optional[TableValueType] = None
147
148    # some attributes that are defined between both ColumnElement and
149    # FromClause are set to Any here to avoid typing errors
150    primary_key: Any
151    _is_clone_of: Any
152
153    clause_expr: Grouping[Any]
154
155    def __init__(
156        self, *clauses: _ColumnExpressionOrLiteralArgument[Any]
157    ) -> None:
158        r"""Construct a :class:`.FunctionElement`.
159
160        :param \*clauses: list of column expressions that form the arguments
161         of the SQL function call.
162
163        :param \**kwargs:  additional kwargs are typically consumed by
164         subclasses.
165
166        .. seealso::
167
168            :data:`.func`
169
170            :class:`.Function`
171
172        """
173        args: Sequence[_ColumnExpressionArgument[Any]] = [
174            coercions.expect(
175                roles.ExpressionElementRole,
176                c,
177                name=getattr(self, "name", None),
178                apply_propagate_attrs=self,
179            )
180            for c in clauses
181        ]
182        self._has_args = self._has_args or bool(args)
183        self.clause_expr = Grouping(
184            ClauseList(operator=operators.comma_op, group_contents=True, *args)
185        )
186
187    _non_anon_label = None
188
189    @property
190    def _proxy_key(self) -> Any:
191        return super()._proxy_key or getattr(self, "name", None)
192
193    def _execute_on_connection(
194        self,
195        connection: Connection,
196        distilled_params: _CoreMultiExecuteParams,
197        execution_options: CoreExecuteOptionsParameter,
198    ) -> CursorResult[Any]:
199        return connection._execute_function(
200            self, distilled_params, execution_options
201        )
202
203    def scalar_table_valued(
204        self, name: str, type_: Optional[_TypeEngineArgument[_T]] = None
205    ) -> ScalarFunctionColumn[_T]:
206        """Return a column expression that's against this
207        :class:`_functions.FunctionElement` as a scalar
208        table-valued expression.
209
210        The returned expression is similar to that returned by a single column
211        accessed off of a :meth:`_functions.FunctionElement.table_valued`
212        construct, except no FROM clause is generated; the function is rendered
213        in the similar way as a scalar subquery.
214
215        E.g.:
216
217        .. sourcecode:: pycon+sql
218
219            >>> from sqlalchemy import func, select
220            >>> fn = func.jsonb_each("{'k', 'v'}").scalar_table_valued("key")
221            >>> print(select(fn))
222            {printsql}SELECT (jsonb_each(:jsonb_each_1)).key
223
224        .. versionadded:: 1.4.0b2
225
226        .. seealso::
227
228            :meth:`_functions.FunctionElement.table_valued`
229
230            :meth:`_functions.FunctionElement.alias`
231
232            :meth:`_functions.FunctionElement.column_valued`
233
234        """  # noqa: E501
235
236        return ScalarFunctionColumn(self, name, type_)
237
238    def table_valued(
239        self, *expr: _ColumnExpressionOrStrLabelArgument[Any], **kw: Any
240    ) -> TableValuedAlias:
241        r"""Return a :class:`_sql.TableValuedAlias` representation of this
242        :class:`_functions.FunctionElement` with table-valued expressions added.
243
244        e.g. to use the SQLite form of ``generate_series()`` (including
245        hidden columns "start", "stop", "step"):
246
247        .. sourcecode:: pycon+sql
248
249            >>> fn = func.generate_series(1, 5).table_valued(
250            ...     "value", "start", "stop", "step"
251            ... )
252
253            >>> print(select(fn))
254            {printsql}SELECT anon_1.value, anon_1.start, anon_1.stop, anon_1.step
255            FROM generate_series(:generate_series_1, :generate_series_2) AS anon_1{stop}
256
257            >>> print(select(fn.c.value, fn.c.stop).where(fn.c.value > 2))
258            {printsql}SELECT anon_1.value, anon_1.stop
259            FROM generate_series(:generate_series_1, :generate_series_2) AS anon_1
260            WHERE anon_1.value > :value_1{stop}
261
262        Backends like PostgreSQL need the accessed columns to be explicitly
263        named in "AS" clause.  To achieve this, use
264        :meth:`_sql.TableValuedAlias.render_derived`; be sure to consult the
265        :ref:`PostgreSQL-specific documentation for table valued functions
266        <postgresql_table_valued>` for additional examples:
267
268        .. sourcecode:: pycon+sql
269
270            >>> fn = func.generate_series(1, 5).table_valued("value").render_derived()
271
272            >>> print(select(fn))
273            {printsql}SELECT anon_1.value FROM
274            generate_series(:generate_series_1, :generate_series_2) AS anon_1(value){stop}
275
276        A WITH ORDINALITY expression may be generated by passing the keyword
277        argument :paramref:`.FunctionElement.table_valued.with_ordinality`,
278        illustrated below using PostgreSQL's syntax:
279
280        .. sourcecode:: pycon+sql
281
282            >>> fn = func.generate_series(4, 1, -1).table_valued(
283            ...     "gen", with_ordinality="ordinality"
284            ... )
285            >>> print(select(fn.render_derived()))
286            {printsql}SELECT anon_1.gen, anon_1.ordinality
287            FROM generate_series(:generate_series_1, :generate_series_2, :generate_series_3)
288            WITH ORDINALITY AS anon_1(gen, ordinality)
289
290        :param \*expr: A series of string column names that will be added to the
291         ``.c`` collection of the resulting :class:`_sql.TableValuedAlias`
292         construct as columns.  :func:`_sql.column` objects with or without
293         datatypes may also be used.
294
295        :param name: optional name to assign to the alias name that's generated.
296         If omitted, a unique anonymizing name is used.
297
298        :param with_ordinality: string name that when present results in the
299         ``WITH ORDINALITY`` clause being added to the alias, and the given
300         string name will be added as a column to the .c collection
301         of the resulting :class:`_sql.TableValuedAlias`.
302
303        :param joins_implicitly: when True, the table valued function may be
304         used in the FROM clause without any explicit JOIN to other tables
305         in the SQL query, and no "cartesian product" warning will be generated.
306         May be useful for SQL functions such as ``func.json_each()``.
307
308         .. versionadded:: 1.4.33
309
310        .. versionadded:: 1.4.0b2
311
312
313        .. seealso::
314
315            :ref:`tutorial_functions_table_valued` - in the :ref:`unified_tutorial`
316
317            :ref:`Table-Valued Functions on PostgreSQL <postgresql_table_valued>` - in the :ref:`postgresql_toplevel` documentation
318
319            :meth:`_functions.FunctionElement.scalar_table_valued` - variant of
320            :meth:`_functions.FunctionElement.table_valued` which delivers the
321            complete table valued expression as a scalar column expression
322
323            :meth:`_functions.FunctionElement.column_valued`
324
325            :meth:`_sql.TableValuedAlias.render_derived` - renders the alias
326            using a derived column clause, e.g. ``AS name(col1, col2, ...)``
327
328        """  # noqa: 501
329
330        new_func = self._generate()
331
332        with_ordinality = kw.pop("with_ordinality", None)
333        joins_implicitly = kw.pop("joins_implicitly", None)
334        name = kw.pop("name", None)
335
336        if with_ordinality:
337            expr += (with_ordinality,)
338            new_func._with_ordinality = True
339
340        new_func.type = new_func._table_value_type = TableValueType(*expr)
341
342        return new_func.alias(name=name, joins_implicitly=joins_implicitly)
343
344    def column_valued(
345        self, name: Optional[str] = None, joins_implicitly: bool = False
346    ) -> TableValuedColumn[_T]:
347        """Return this :class:`_functions.FunctionElement` as a column expression that
348        selects from itself as a FROM clause.
349
350        E.g.:
351
352        .. sourcecode:: pycon+sql
353
354            >>> from sqlalchemy import select, func
355            >>> gs = func.generate_series(1, 5, -1).column_valued()
356            >>> print(select(gs))
357            {printsql}SELECT anon_1
358            FROM generate_series(:generate_series_1, :generate_series_2, :generate_series_3) AS anon_1
359
360        This is shorthand for::
361
362            gs = func.generate_series(1, 5, -1).alias().column
363
364        :param name: optional name to assign to the alias name that's generated.
365         If omitted, a unique anonymizing name is used.
366
367        :param joins_implicitly: when True, the "table" portion of the column
368         valued function may be a member of the FROM clause without any
369         explicit JOIN to other tables in the SQL query, and no "cartesian
370         product" warning will be generated. May be useful for SQL functions
371         such as ``func.json_array_elements()``.
372
373         .. versionadded:: 1.4.46
374
375        .. seealso::
376
377            :ref:`tutorial_functions_column_valued` - in the :ref:`unified_tutorial`
378
379            :ref:`postgresql_column_valued` - in the :ref:`postgresql_toplevel` documentation
380
381            :meth:`_functions.FunctionElement.table_valued`
382
383        """  # noqa: 501
384
385        return self.alias(name=name, joins_implicitly=joins_implicitly).column
386
387    @util.ro_non_memoized_property
388    def columns(self) -> ColumnCollection[str, KeyedColumnElement[Any]]:  # type: ignore[override]  # noqa: E501
389        r"""The set of columns exported by this :class:`.FunctionElement`.
390
391        This is a placeholder collection that allows the function to be
392        placed in the FROM clause of a statement:
393
394        .. sourcecode:: pycon+sql
395
396            >>> from sqlalchemy import column, select, func
397            >>> stmt = select(column("x"), column("y")).select_from(func.myfunction())
398            >>> print(stmt)
399            {printsql}SELECT x, y FROM myfunction()
400
401        The above form is a legacy feature that is now superseded by the
402        fully capable :meth:`_functions.FunctionElement.table_valued`
403        method; see that method for details.
404
405        .. seealso::
406
407            :meth:`_functions.FunctionElement.table_valued` - generates table-valued
408            SQL function expressions.
409
410        """  # noqa: E501
411        return self.c
412
413    @util.ro_memoized_property
414    def c(self) -> ColumnCollection[str, KeyedColumnElement[Any]]:  # type: ignore[override]  # noqa: E501
415        """synonym for :attr:`.FunctionElement.columns`."""
416
417        return ColumnCollection(
418            columns=[(col.key, col) for col in self._all_selected_columns]
419        )
420
421    @property
422    def _all_selected_columns(self) -> Sequence[KeyedColumnElement[Any]]:
423        if is_table_value_type(self.type):
424            # TODO: this might not be fully accurate
425            cols = cast(
426                "Sequence[KeyedColumnElement[Any]]", self.type._elements
427            )
428        else:
429            cols = [self.label(None)]
430
431        return cols
432
433    @property
434    def exported_columns(  # type: ignore[override]
435        self,
436    ) -> ColumnCollection[str, KeyedColumnElement[Any]]:
437        return self.columns
438
439    @HasMemoized.memoized_attribute
440    def clauses(self) -> ClauseList:
441        """Return the underlying :class:`.ClauseList` which contains
442        the arguments for this :class:`.FunctionElement`.
443
444        """
445        return cast(ClauseList, self.clause_expr.element)
446
447    def over(
448        self,
449        *,
450        partition_by: Optional[_ByArgument] = None,
451        order_by: Optional[_ByArgument] = None,
452        rows: Optional[Tuple[Optional[int], Optional[int]]] = None,
453        range_: Optional[Tuple[Optional[int], Optional[int]]] = None,
454        groups: Optional[Tuple[Optional[int], Optional[int]]] = None,
455    ) -> Over[_T]:
456        """Produce an OVER clause against this function.
457
458        Used against aggregate or so-called "window" functions,
459        for database backends that support window functions.
460
461        The expression::
462
463            func.row_number().over(order_by="x")
464
465        is shorthand for::
466
467            from sqlalchemy import over
468
469            over(func.row_number(), order_by="x")
470
471        See :func:`_expression.over` for a full description.
472
473        .. seealso::
474
475            :func:`_expression.over`
476
477            :ref:`tutorial_window_functions` - in the :ref:`unified_tutorial`
478
479        """
480        return Over(
481            self,
482            partition_by=partition_by,
483            order_by=order_by,
484            rows=rows,
485            range_=range_,
486            groups=groups,
487        )
488
489    def within_group(
490        self, *order_by: _ColumnExpressionArgument[Any]
491    ) -> WithinGroup[_T]:
492        """Produce a WITHIN GROUP (ORDER BY expr) clause against this function.
493
494        Used against so-called "ordered set aggregate" and "hypothetical
495        set aggregate" functions, including :class:`.percentile_cont`,
496        :class:`.rank`, :class:`.dense_rank`, etc.
497
498        See :func:`_expression.within_group` for a full description.
499
500        .. seealso::
501
502            :ref:`tutorial_functions_within_group` -
503            in the :ref:`unified_tutorial`
504
505
506        """
507        return WithinGroup(self, *order_by)
508
509    @overload
510    def filter(self) -> Self: ...
511
512    @overload
513    def filter(
514        self,
515        __criterion0: _ColumnExpressionArgument[bool],
516        *criterion: _ColumnExpressionArgument[bool],
517    ) -> FunctionFilter[_T]: ...
518
519    def filter(
520        self, *criterion: _ColumnExpressionArgument[bool]
521    ) -> Union[Self, FunctionFilter[_T]]:
522        """Produce a FILTER clause against this function.
523
524        Used against aggregate and window functions,
525        for database backends that support the "FILTER" clause.
526
527        The expression::
528
529            func.count(1).filter(True)
530
531        is shorthand for::
532
533            from sqlalchemy import funcfilter
534
535            funcfilter(func.count(1), True)
536
537        .. seealso::
538
539            :ref:`tutorial_functions_within_group` -
540            in the :ref:`unified_tutorial`
541
542            :class:`.FunctionFilter`
543
544            :func:`.funcfilter`
545
546
547        """
548        if not criterion:
549            return self
550        return FunctionFilter(self, *criterion)
551
552    def as_comparison(
553        self, left_index: int, right_index: int
554    ) -> FunctionAsBinary:
555        """Interpret this expression as a boolean comparison between two
556        values.
557
558        This method is used for an ORM use case described at
559        :ref:`relationship_custom_operator_sql_function`.
560
561        A hypothetical SQL function "is_equal()" which compares to values
562        for equality would be written in the Core expression language as::
563
564            expr = func.is_equal("a", "b")
565
566        If "is_equal()" above is comparing "a" and "b" for equality, the
567        :meth:`.FunctionElement.as_comparison` method would be invoked as::
568
569            expr = func.is_equal("a", "b").as_comparison(1, 2)
570
571        Where above, the integer value "1" refers to the first argument of the
572        "is_equal()" function and the integer value "2" refers to the second.
573
574        This would create a :class:`.BinaryExpression` that is equivalent to::
575
576            BinaryExpression("a", "b", operator=op.eq)
577
578        However, at the SQL level it would still render as
579        "is_equal('a', 'b')".
580
581        The ORM, when it loads a related object or collection, needs to be able
582        to manipulate the "left" and "right" sides of the ON clause of a JOIN
583        expression. The purpose of this method is to provide a SQL function
584        construct that can also supply this information to the ORM, when used
585        with the :paramref:`_orm.relationship.primaryjoin` parameter. The
586        return value is a containment object called :class:`.FunctionAsBinary`.
587
588        An ORM example is as follows::
589
590            class Venue(Base):
591                __tablename__ = "venue"
592                id = Column(Integer, primary_key=True)
593                name = Column(String)
594
595                descendants = relationship(
596                    "Venue",
597                    primaryjoin=func.instr(
598                        remote(foreign(name)), name + "/"
599                    ).as_comparison(1, 2)
600                    == 1,
601                    viewonly=True,
602                    order_by=name,
603                )
604
605        Above, the "Venue" class can load descendant "Venue" objects by
606        determining if the name of the parent Venue is contained within the
607        start of the hypothetical descendant value's name, e.g. "parent1" would
608        match up to "parent1/child1", but not to "parent2/child1".
609
610        Possible use cases include the "materialized path" example given above,
611        as well as making use of special SQL functions such as geometric
612        functions to create join conditions.
613
614        :param left_index: the integer 1-based index of the function argument
615         that serves as the "left" side of the expression.
616        :param right_index: the integer 1-based index of the function argument
617         that serves as the "right" side of the expression.
618
619        .. versionadded:: 1.3
620
621        .. seealso::
622
623            :ref:`relationship_custom_operator_sql_function` -
624            example use within the ORM
625
626        """
627        return FunctionAsBinary(self, left_index, right_index)
628
629    @property
630    def _from_objects(self) -> Any:
631        return self.clauses._from_objects
632
633    def within_group_type(
634        self, within_group: WithinGroup[_S]
635    ) -> Optional[TypeEngine[_S]]:
636        """For types that define their return type as based on the criteria
637        within a WITHIN GROUP (ORDER BY) expression, called by the
638        :class:`.WithinGroup` construct.
639
640        Returns None by default, in which case the function's normal ``.type``
641        is used.
642
643        """
644
645        return None
646
647    def alias(
648        self, name: Optional[str] = None, joins_implicitly: bool = False
649    ) -> TableValuedAlias:
650        r"""Produce a :class:`_expression.Alias` construct against this
651        :class:`.FunctionElement`.
652
653        .. tip::
654
655            The :meth:`_functions.FunctionElement.alias` method is part of the
656            mechanism by which "table valued" SQL functions are created.
657            However, most use cases are covered by higher level methods on
658            :class:`_functions.FunctionElement` including
659            :meth:`_functions.FunctionElement.table_valued`, and
660            :meth:`_functions.FunctionElement.column_valued`.
661
662        This construct wraps the function in a named alias which
663        is suitable for the FROM clause, in the style accepted for example
664        by PostgreSQL.  A column expression is also provided using the
665        special ``.column`` attribute, which may
666        be used to refer to the output of the function as a scalar value
667        in the columns or where clause, for a backend such as PostgreSQL.
668
669        For a full table-valued expression, use the
670        :meth:`_functions.FunctionElement.table_valued` method first to
671        establish named columns.
672
673        e.g.:
674
675        .. sourcecode:: pycon+sql
676
677            >>> from sqlalchemy import func, select, column
678            >>> data_view = func.unnest([1, 2, 3]).alias("data_view")
679            >>> print(select(data_view.column))
680            {printsql}SELECT data_view
681            FROM unnest(:unnest_1) AS data_view
682
683        The :meth:`_functions.FunctionElement.column_valued` method provides
684        a shortcut for the above pattern:
685
686        .. sourcecode:: pycon+sql
687
688            >>> data_view = func.unnest([1, 2, 3]).column_valued("data_view")
689            >>> print(select(data_view))
690            {printsql}SELECT data_view
691            FROM unnest(:unnest_1) AS data_view
692
693        .. versionadded:: 1.4.0b2  Added the ``.column`` accessor
694
695        :param name: alias name, will be rendered as ``AS <name>`` in the
696         FROM clause
697
698        :param joins_implicitly: when True, the table valued function may be
699         used in the FROM clause without any explicit JOIN to other tables
700         in the SQL query, and no "cartesian product" warning will be
701         generated.  May be useful for SQL functions such as
702         ``func.json_each()``.
703
704         .. versionadded:: 1.4.33
705
706        .. seealso::
707
708            :ref:`tutorial_functions_table_valued` -
709            in the :ref:`unified_tutorial`
710
711            :meth:`_functions.FunctionElement.table_valued`
712
713            :meth:`_functions.FunctionElement.scalar_table_valued`
714
715            :meth:`_functions.FunctionElement.column_valued`
716
717
718        """
719
720        return TableValuedAlias._construct(
721            self,
722            name=name,
723            table_value_type=self.type,
724            joins_implicitly=joins_implicitly,
725        )
726
727    def select(self) -> Select[Tuple[_T]]:
728        """Produce a :func:`_expression.select` construct
729        against this :class:`.FunctionElement`.
730
731        This is shorthand for::
732
733            s = select(function_element)
734
735        """
736        s: Select[Any] = Select(self)
737        if self._execution_options:
738            s = s.execution_options(**self._execution_options)
739        return s
740
741    def _bind_param(
742        self,
743        operator: OperatorType,
744        obj: Any,
745        type_: Optional[TypeEngine[_T]] = None,
746        expanding: bool = False,
747        **kw: Any,
748    ) -> BindParameter[_T]:
749        return BindParameter(
750            None,
751            obj,
752            _compared_to_operator=operator,
753            _compared_to_type=self.type,
754            unique=True,
755            type_=type_,
756            expanding=expanding,
757            **kw,
758        )
759
760    def self_group(self, against: Optional[OperatorType] = None) -> ClauseElement:  # type: ignore[override]  # noqa E501
761        # for the moment, we are parenthesizing all array-returning
762        # expressions against getitem.  This may need to be made
763        # more portable if in the future we support other DBs
764        # besides postgresql.
765        if against is operators.getitem and isinstance(
766            self.type, sqltypes.ARRAY
767        ):
768            return Grouping(self)
769        else:
770            return super().self_group(against=against)
771
772    @property
773    def entity_namespace(self) -> _EntityNamespace:
774        """overrides FromClause.entity_namespace as functions are generally
775        column expressions and not FromClauses.
776
777        """
778        # ideally functions would not be fromclauses but we failed to make
779        # this adjustment in 1.4
780        return _entity_namespace(self.clause_expr)
781
782
783class FunctionAsBinary(BinaryExpression[Any]):
784    _traverse_internals = [
785        ("sql_function", InternalTraversal.dp_clauseelement),
786        ("left_index", InternalTraversal.dp_plain_obj),
787        ("right_index", InternalTraversal.dp_plain_obj),
788        ("modifiers", InternalTraversal.dp_plain_dict),
789    ]
790
791    sql_function: FunctionElement[Any]
792    left_index: int
793    right_index: int
794
795    def _gen_cache_key(self, anon_map: Any, bindparams: Any) -> Any:
796        return ColumnElement._gen_cache_key(self, anon_map, bindparams)
797
798    def __init__(
799        self, fn: FunctionElement[Any], left_index: int, right_index: int
800    ) -> None:
801        self.sql_function = fn
802        self.left_index = left_index
803        self.right_index = right_index
804
805        self.operator = operators.function_as_comparison_op
806        self.type = sqltypes.BOOLEANTYPE
807        self.negate = None
808        self._is_implicitly_boolean = True
809        self.modifiers = util.immutabledict({})
810
811    @property
812    def left_expr(self) -> ColumnElement[Any]:
813        return self.sql_function.clauses.clauses[self.left_index - 1]
814
815    @left_expr.setter
816    def left_expr(self, value: ColumnElement[Any]) -> None:
817        self.sql_function.clauses.clauses[self.left_index - 1] = value
818
819    @property
820    def right_expr(self) -> ColumnElement[Any]:
821        return self.sql_function.clauses.clauses[self.right_index - 1]
822
823    @right_expr.setter
824    def right_expr(self, value: ColumnElement[Any]) -> None:
825        self.sql_function.clauses.clauses[self.right_index - 1] = value
826
827    if not TYPE_CHECKING:
828        # mypy can't accommodate @property to replace an instance
829        # variable
830
831        left = left_expr
832        right = right_expr
833
834
835class ScalarFunctionColumn(NamedColumn[_T]):
836    __visit_name__ = "scalar_function_column"
837
838    _traverse_internals = [
839        ("name", InternalTraversal.dp_anon_name),
840        ("type", InternalTraversal.dp_type),
841        ("fn", InternalTraversal.dp_clauseelement),
842    ]
843
844    is_literal = False
845    table = None
846
847    def __init__(
848        self,
849        fn: FunctionElement[_T],
850        name: str,
851        type_: Optional[_TypeEngineArgument[_T]] = None,
852    ) -> None:
853        self.fn = fn
854        self.name = name
855
856        # if type is None, we get NULLTYPE, which is our _T.  But I don't
857        # know how to get the overloads to express that correctly
858        self.type = type_api.to_instance(type_)  # type: ignore
859
860
861class _FunctionGenerator:
862    """Generate SQL function expressions.
863
864    :data:`.func` is a special object instance which generates SQL
865    functions based on name-based attributes, e.g.:
866
867    .. sourcecode:: pycon+sql
868
869        >>> print(func.count(1))
870        {printsql}count(:param_1)
871
872    The returned object is an instance of :class:`.Function`, and  is a
873    column-oriented SQL element like any other, and is used in that way:
874
875    .. sourcecode:: pycon+sql
876
877        >>> print(select(func.count(table.c.id)))
878        {printsql}SELECT count(sometable.id) FROM sometable
879
880    Any name can be given to :data:`.func`. If the function name is unknown to
881    SQLAlchemy, it will be rendered exactly as is. For common SQL functions
882    which SQLAlchemy is aware of, the name may be interpreted as a *generic
883    function* which will be compiled appropriately to the target database:
884
885    .. sourcecode:: pycon+sql
886
887        >>> print(func.current_timestamp())
888        {printsql}CURRENT_TIMESTAMP
889
890    To call functions which are present in dot-separated packages,
891    specify them in the same manner:
892
893    .. sourcecode:: pycon+sql
894
895        >>> print(func.stats.yield_curve(5, 10))
896        {printsql}stats.yield_curve(:yield_curve_1, :yield_curve_2)
897
898    SQLAlchemy can be made aware of the return type of functions to enable
899    type-specific lexical and result-based behavior. For example, to ensure
900    that a string-based function returns a Unicode value and is similarly
901    treated as a string in expressions, specify
902    :class:`~sqlalchemy.types.Unicode` as the type:
903
904    .. sourcecode:: pycon+sql
905
906        >>> print(
907        ...     func.my_string("hi", type_=Unicode)
908        ...     + " "
909        ...     + func.my_string("there", type_=Unicode)
910        ... )
911        {printsql}my_string(:my_string_1) || :my_string_2 || my_string(:my_string_3)
912
913    The object returned by a :data:`.func` call is usually an instance of
914    :class:`.Function`.
915    This object meets the "column" interface, including comparison and labeling
916    functions.  The object can also be passed the :meth:`~.Connectable.execute`
917    method of a :class:`_engine.Connection` or :class:`_engine.Engine`,
918    where it will be
919    wrapped inside of a SELECT statement first::
920
921        print(connection.execute(func.current_timestamp()).scalar())
922
923    In a few exception cases, the :data:`.func` accessor
924    will redirect a name to a built-in expression such as :func:`.cast`
925    or :func:`.extract`, as these names have well-known meaning
926    but are not exactly the same as "functions" from a SQLAlchemy
927    perspective.
928
929    Functions which are interpreted as "generic" functions know how to
930    calculate their return type automatically. For a listing of known generic
931    functions, see :ref:`generic_functions`.
932
933    .. note::
934
935        The :data:`.func` construct has only limited support for calling
936        standalone "stored procedures", especially those with special
937        parameterization concerns.
938
939        See the section :ref:`stored_procedures` for details on how to use
940        the DBAPI-level ``callproc()`` method for fully traditional stored
941        procedures.
942
943    .. seealso::
944
945        :ref:`tutorial_functions` - in the :ref:`unified_tutorial`
946
947        :class:`.Function`
948
949    """  # noqa
950
951    def __init__(self, **opts: Any) -> None:
952        self.__names: List[str] = []
953        self.opts = opts
954
955    def __getattr__(self, name: str) -> _FunctionGenerator:
956        # passthru __ attributes; fixes pydoc
957        if name.startswith("__"):
958            try:
959                return self.__dict__[name]  # type: ignore
960            except KeyError:
961                raise AttributeError(name)
962
963        elif name.endswith("_"):
964            name = name[0:-1]
965        f = _FunctionGenerator(**self.opts)
966        f.__names = list(self.__names) + [name]
967        return f
968
969    @overload
970    def __call__(
971        self, *c: Any, type_: _TypeEngineArgument[_T], **kwargs: Any
972    ) -> Function[_T]: ...
973
974    @overload
975    def __call__(self, *c: Any, **kwargs: Any) -> Function[Any]: ...
976
977    def __call__(self, *c: Any, **kwargs: Any) -> Function[Any]:
978        o = self.opts.copy()
979        o.update(kwargs)
980
981        tokens = len(self.__names)
982
983        if tokens == 2:
984            package, fname = self.__names
985        elif tokens == 1:
986            package, fname = "_default", self.__names[0]
987        else:
988            package = None
989
990        if package is not None:
991            func = _registry[package].get(fname.lower())
992            if func is not None:
993                return func(*c, **o)
994
995        return Function(
996            self.__names[-1], packagenames=tuple(self.__names[0:-1]), *c, **o
997        )
998
999    if TYPE_CHECKING:
1000        # START GENERATED FUNCTION ACCESSORS
1001
1002        # code within this block is **programmatically,
1003        # statically generated** by tools/generate_sql_functions.py
1004
1005        @property
1006        def aggregate_strings(self) -> Type[_aggregate_strings_func]: ...
1007
1008        @property
1009        def ansifunction(self) -> Type[_AnsiFunction_func[Any]]: ...
1010
1011        # set ColumnElement[_T] as a separate overload, to appease
1012        # mypy which seems to not want to accept _T from
1013        # _ColumnExpressionArgument. Seems somewhat related to the covariant
1014        # _HasClauseElement as of mypy 1.15
1015
1016        @overload
1017        def array_agg(
1018            self,
1019            col: ColumnElement[_T],
1020            *args: _ColumnExpressionOrLiteralArgument[Any],
1021            **kwargs: Any,
1022        ) -> _array_agg_func[_T]: ...
1023
1024        @overload
1025        def array_agg(
1026            self,
1027            col: _ColumnExpressionArgument[_T],
1028            *args: _ColumnExpressionOrLiteralArgument[Any],
1029            **kwargs: Any,
1030        ) -> _array_agg_func[_T]: ...
1031
1032        @overload
1033        def array_agg(
1034            self,
1035            col: _T,
1036            *args: _ColumnExpressionOrLiteralArgument[Any],
1037            **kwargs: Any,
1038        ) -> _array_agg_func[_T]: ...
1039
1040        def array_agg(
1041            self,
1042            col: _ColumnExpressionOrLiteralArgument[_T],
1043            *args: _ColumnExpressionOrLiteralArgument[Any],
1044            **kwargs: Any,
1045        ) -> _array_agg_func[_T]: ...
1046
1047        @property
1048        def cast(self) -> Type[_Cast_func[Any]]: ...
1049
1050        @property
1051        def char_length(self) -> Type[_char_length_func]: ...
1052
1053        # set ColumnElement[_T] as a separate overload, to appease
1054        # mypy which seems to not want to accept _T from
1055        # _ColumnExpressionArgument. Seems somewhat related to the covariant
1056        # _HasClauseElement as of mypy 1.15
1057
1058        @overload
1059        def coalesce(
1060            self,
1061            col: ColumnElement[_T],
1062            *args: _ColumnExpressionOrLiteralArgument[Any],
1063            **kwargs: Any,
1064        ) -> _coalesce_func[_T]: ...
1065
1066        @overload
1067        def coalesce(
1068            self,
1069            col: _ColumnExpressionArgument[Optional[_T]],
1070            *args: _ColumnExpressionOrLiteralArgument[Any],
1071            **kwargs: Any,
1072        ) -> _coalesce_func[_T]: ...
1073
1074        @overload
1075        def coalesce(
1076            self,
1077            col: Optional[_T],
1078            *args: _ColumnExpressionOrLiteralArgument[Any],
1079            **kwargs: Any,
1080        ) -> _coalesce_func[_T]: ...
1081
1082        def coalesce(
1083            self,
1084            col: _ColumnExpressionOrLiteralArgument[Optional[_T]],
1085            *args: _ColumnExpressionOrLiteralArgument[Any],
1086            **kwargs: Any,
1087        ) -> _coalesce_func[_T]: ...
1088
1089        @property
1090        def concat(self) -> Type[_concat_func]: ...
1091
1092        @property
1093        def count(self) -> Type[_count_func]: ...
1094
1095        @property
1096        def cube(self) -> Type[_cube_func[Any]]: ...
1097
1098        @property
1099        def cume_dist(self) -> Type[_cume_dist_func]: ...
1100
1101        @property
1102        def current_date(self) -> Type[_current_date_func]: ...
1103
1104        @property
1105        def current_time(self) -> Type[_current_time_func]: ...
1106
1107        @property
1108        def current_timestamp(self) -> Type[_current_timestamp_func]: ...
1109
1110        @property
1111        def current_user(self) -> Type[_current_user_func]: ...
1112
1113        @property
1114        def dense_rank(self) -> Type[_dense_rank_func]: ...
1115
1116        @property
1117        def extract(self) -> Type[_Extract_func]: ...
1118
1119        @property
1120        def grouping_sets(self) -> Type[_grouping_sets_func[Any]]: ...
1121
1122        @property
1123        def localtime(self) -> Type[_localtime_func]: ...
1124
1125        @property
1126        def localtimestamp(self) -> Type[_localtimestamp_func]: ...
1127
1128        # set ColumnElement[_T] as a separate overload, to appease
1129        # mypy which seems to not want to accept _T from
1130        # _ColumnExpressionArgument. Seems somewhat related to the covariant
1131        # _HasClauseElement as of mypy 1.15
1132
1133        @overload
1134        def max(  # noqa: A001
1135            self,
1136            col: ColumnElement[_T],
1137            *args: _ColumnExpressionOrLiteralArgument[Any],
1138            **kwargs: Any,
1139        ) -> _max_func[_T]: ...
1140
1141        @overload
1142        def max(  # noqa: A001
1143            self,
1144            col: _ColumnExpressionArgument[_T],
1145            *args: _ColumnExpressionOrLiteralArgument[Any],
1146            **kwargs: Any,
1147        ) -> _max_func[_T]: ...
1148
1149        @overload
1150        def max(  # noqa: A001
1151            self,
1152            col: _T,
1153            *args: _ColumnExpressionOrLiteralArgument[Any],
1154            **kwargs: Any,
1155        ) -> _max_func[_T]: ...
1156
1157        def max(  # noqa: A001
1158            self,
1159            col: _ColumnExpressionOrLiteralArgument[_T],
1160            *args: _ColumnExpressionOrLiteralArgument[Any],
1161            **kwargs: Any,
1162        ) -> _max_func[_T]: ...
1163
1164        # set ColumnElement[_T] as a separate overload, to appease
1165        # mypy which seems to not want to accept _T from
1166        # _ColumnExpressionArgument. Seems somewhat related to the covariant
1167        # _HasClauseElement as of mypy 1.15
1168
1169        @overload
1170        def min(  # noqa: A001
1171            self,
1172            col: ColumnElement[_T],
1173            *args: _ColumnExpressionOrLiteralArgument[Any],
1174            **kwargs: Any,
1175        ) -> _min_func[_T]: ...
1176
1177        @overload
1178        def min(  # noqa: A001
1179            self,
1180            col: _ColumnExpressionArgument[_T],
1181            *args: _ColumnExpressionOrLiteralArgument[Any],
1182            **kwargs: Any,
1183        ) -> _min_func[_T]: ...
1184
1185        @overload
1186        def min(  # noqa: A001
1187            self,
1188            col: _T,
1189            *args: _ColumnExpressionOrLiteralArgument[Any],
1190            **kwargs: Any,
1191        ) -> _min_func[_T]: ...
1192
1193        def min(  # noqa: A001
1194            self,
1195            col: _ColumnExpressionOrLiteralArgument[_T],
1196            *args: _ColumnExpressionOrLiteralArgument[Any],
1197            **kwargs: Any,
1198        ) -> _min_func[_T]: ...
1199
1200        @property

Showing the first 1,200 of 2200 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai