Team Ai
Datasetpublic

codekingpro/portable-devtools

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

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

codekingpro/portable-devtools · Team Ai