from .visitors import InternalTraversal
from .. import exc
from .. import util
-from ..inspection import inspect
class _OffsetLimitParam(BindParameter):
return self.effective_value
-@util.deprecated(
- "1.4",
- "The standalone :func:`.subquery` function is deprecated "
- "and will be removed in a future release. Use select().subquery().",
-)
-def subquery(alias, *args, **kwargs):
- r"""Return an :class:`.Subquery` object derived
- from a :class:`_expression.Select`.
-
- :param alias: the alias name for the subquery
-
- :param \*args, \**kwargs: all other arguments are passed through to the
- :func:`_expression.select` function.
-
- """
- return Select.create_legacy_select(*args, **kwargs).subquery(alias)
-
-
class ReturnsRows(roles.ReturnsRowsRole, ClauseElement):
"""The base-most class for Core constructs that have some concept of
columns that can represent rows.
_use_schema_map = False
- @util.deprecated_params(
- whereclause=(
- "2.0",
- "The :paramref:`_sql.FromClause.select().whereclause` parameter "
- "is deprecated and will be removed in version 2.0. "
- "Please make use of "
- "the :meth:`.Select.where` "
- "method to add WHERE criteria to the SELECT statement.",
- ),
- kwargs=(
- "2.0",
- "The :meth:`_sql.FromClause.select` method will no longer accept "
- "keyword arguments in version 2.0. Please use generative methods "
- "from the "
- ":class:`_sql.Select` construct in order to apply additional "
- "modifications.",
- ),
- )
- def select(self, whereclause=None, **kwargs):
+ def select(self) -> "Select":
r"""Return a SELECT of this :class:`_expression.FromClause`.
stmt = some_table.select().where(some_table.c.id == 5)
- :param whereclause: a WHERE clause, equivalent to calling the
- :meth:`_sql.Select.where` method.
-
- :param \**kwargs: additional keyword arguments are passed to the
- legacy constructor for :class:`_sql.Select` described at
- :meth:`_sql.Select.create_legacy_select`.
-
.. seealso::
:func:`_expression.select` - general purpose
method which allows for arbitrary column lists.
"""
- if whereclause is not None:
- kwargs["whereclause"] = whereclause
- return Select._create_select_from_fromclause(self, [self], **kwargs)
+ return Select._create(self)
def join(self, right, onclause=None, isouter=False, full=False):
"""Return a :class:`_expression.Join` from this
"join explicitly." % (a.description, b.description)
)
- @util.deprecated_params(
- whereclause=(
- "2.0",
- "The :paramref:`_sql.Join.select().whereclause` parameter "
- "is deprecated and will be removed in version 2.0. "
- "Please make use of "
- "the :meth:`.Select.where` "
- "method to add WHERE criteria to the SELECT statement.",
- ),
- kwargs=(
- "2.0",
- "The :meth:`_sql.Join.select` method will no longer accept "
- "keyword arguments in version 2.0. Please use generative "
- "methods from the "
- ":class:`_sql.Select` construct in order to apply additional "
- "modifications.",
- ),
- )
- def select(self, whereclause=None, **kwargs):
+ def select(self) -> "Select":
r"""Create a :class:`_expression.Select` from this
:class:`_expression.Join`.
SELECT table_a.id, table_a.col, table_b.id, table_b.a_id
FROM table_a JOIN table_b ON table_a.id = table_b.a_id
- :param whereclause: WHERE criteria, same as calling
- :meth:`_sql.Select.where` on the resulting statement
-
- :param \**kwargs: additional keyword arguments are passed to the
- legacy constructor for :class:`_sql.Select` described at
- :meth:`_sql.Select.create_legacy_select`.
-
"""
- collist = [self.left, self.right]
-
- if whereclause is not None:
- kwargs["whereclause"] = whereclause
- return Select._create_select_from_fromclause(
- self, collist, **kwargs
- ).select_from(self)
+ return Select._create(self.left, self.right).select_from(self)
@util.preload_module("sqlalchemy.sql.util")
def _anonymous_fromclause(self, name=None, flat=False):
]
@classmethod
- def _create_select_from_fromclause(cls, target, entities, *arg, **kw):
- if arg or kw:
- return Select.create_legacy_select(entities, *arg, **kw)
- else:
- return Select._create_select(*entities)
-
- @classmethod
- @util.deprecated(
- "2.0",
- "The legacy calling style of :func:`_sql.select` is deprecated and "
- "will be removed in SQLAlchemy 2.0. Please use the new calling "
- "style described at :func:`_sql.select`.",
- )
- def create_legacy_select(
- cls,
- columns=None,
- whereclause=None,
- from_obj=None,
- distinct=False,
- having=None,
- correlate=True,
- prefixes=None,
- suffixes=None,
- **kwargs
- ):
- """Construct a new :class:`_expression.Select` using the 1.x style API.
-
- This method is called implicitly when the :func:`_expression.select`
- construct is used and the first argument is a Python list or other
- plain sequence object, which is taken to refer to the columns
- collection.
-
- .. versionchanged:: 1.4 Added the :meth:`.Select.create_legacy_select`
- constructor which documents the calling style in use when the
- :func:`.select` construct is invoked using 1.x-style arguments.
-
- Similar functionality is also available via the
- :meth:`_expression.FromClause.select` method on any
- :class:`_expression.FromClause`.
-
- All arguments which accept :class:`_expression.ClauseElement` arguments
- also accept string arguments, which will be converted as appropriate
- into either :func:`_expression.text()` or
- :func:`_expression.literal_column()` constructs.
-
- .. seealso::
-
- :ref:`coretutorial_selecting` - Core Tutorial description of
- :func:`_expression.select`.
-
- :param columns:
- A list of :class:`_expression.ColumnElement` or
- :class:`_expression.FromClause`
- objects which will form the columns clause of the resulting
- statement. For those objects that are instances of
- :class:`_expression.FromClause` (typically :class:`_schema.Table`
- or :class:`_expression.Alias`
- objects), the :attr:`_expression.FromClause.c`
- collection is extracted
- to form a collection of :class:`_expression.ColumnElement` objects.
-
- This parameter will also accept :class:`_expression.TextClause`
- constructs as
- given, as well as ORM-mapped classes.
-
- .. note::
-
- The :paramref:`_expression.select.columns`
- parameter is not available
- in the method form of :func:`_expression.select`, e.g.
- :meth:`_expression.FromClause.select`.
-
- .. seealso::
-
- :meth:`_expression.Select.column`
-
- :meth:`_expression.Select.with_only_columns`
-
- :param whereclause:
- A :class:`_expression.ClauseElement`
- expression which will be used to form the
- ``WHERE`` clause. It is typically preferable to add WHERE
- criterion to an existing :class:`_expression.Select`
- using method chaining
- with :meth:`_expression.Select.where`.
-
- .. seealso::
-
- :meth:`_expression.Select.where`
-
- :param from_obj:
- A list of :class:`_expression.ClauseElement`
- objects which will be added to the
- ``FROM`` clause of the resulting statement. This is equivalent
- to calling :meth:`_expression.Select.select_from`
- using method chaining on
- an existing :class:`_expression.Select` object.
-
- .. seealso::
-
- :meth:`_expression.Select.select_from`
- - full description of explicit
- FROM clause specification.
-
- :param correlate=True:
- indicates that this :class:`_expression.Select`
- object should have its
- contained :class:`_expression.FromClause`
- elements "correlated" to an enclosing
- :class:`_expression.Select` object.
- It is typically preferable to specify
- correlations on an existing :class:`_expression.Select`
- construct using
- :meth:`_expression.Select.correlate`.
-
- .. seealso::
-
- :meth:`_expression.Select.correlate`
- - full description of correlation.
-
- :param distinct=False:
- when ``True``, applies a ``DISTINCT`` qualifier to the columns
- clause of the resulting statement.
-
- The boolean argument may also be a column expression or list
- of column expressions - this is a special calling form which
- is understood by the PostgreSQL dialect to render the
- ``DISTINCT ON (<columns>)`` syntax.
-
- ``distinct`` is also available on an existing
- :class:`_expression.Select`
- object via the :meth:`_expression.Select.distinct` method.
-
- .. seealso::
-
- :meth:`_expression.Select.distinct`
-
- :param group_by:
- a list of :class:`_expression.ClauseElement`
- objects which will comprise the
- ``GROUP BY`` clause of the resulting select. This parameter
- is typically specified more naturally using the
- :meth:`_expression.Select.group_by` method on an existing
- :class:`_expression.Select`.
-
- .. seealso::
-
- :meth:`_expression.Select.group_by`
-
- :param having:
- a :class:`_expression.ClauseElement`
- that will comprise the ``HAVING`` clause
- of the resulting select when ``GROUP BY`` is used. This parameter
- is typically specified more naturally using the
- :meth:`_expression.Select.having` method on an existing
- :class:`_expression.Select`.
-
- .. seealso::
-
- :meth:`_expression.Select.having`
+ def _create(cls, *entities) -> "Select":
+ r"""Construct a new :class:`_expression.Select`.
- :param limit=None:
- a numerical value which usually renders as a ``LIMIT``
- expression in the resulting select. Backends that don't
- support ``LIMIT`` will attempt to provide similar
- functionality. This parameter is typically specified more
- naturally using the :meth:`_expression.Select.limit`
- method on an existing
- :class:`_expression.Select`.
-
- .. seealso::
-
- :meth:`_expression.Select.limit`
-
- :param offset=None:
- a numeric value which usually renders as an ``OFFSET``
- expression in the resulting select. Backends that don't
- support ``OFFSET`` will attempt to provide similar
- functionality. This parameter is typically specified more naturally
- using the :meth:`_expression.Select.offset` method on an existing
- :class:`_expression.Select`.
-
- .. seealso::
-
- :meth:`_expression.Select.offset`
-
- :param order_by:
- a scalar or list of :class:`_expression.ClauseElement`
- objects which will
- comprise the ``ORDER BY`` clause of the resulting select.
- This parameter is typically specified more naturally using the
- :meth:`_expression.Select.order_by` method on an existing
- :class:`_expression.Select`.
-
- .. seealso::
-
- :meth:`_expression.Select.order_by`
-
- :param use_labels=False:
- when ``True``, the statement will be generated using labels
- for each column in the columns clause, which qualify each
- column with its parent table's (or aliases) name so that name
- conflicts between columns in different tables don't occur.
- The format of the label is ``<tablename>_<column>``. The "c"
- collection of a :class:`_expression.Subquery` created
- against this :class:`_expression.Select`
- object, as well as the :attr:`_expression.Select.selected_columns`
- collection of the :class:`_expression.Select` itself, will use these
- names for targeting column members.
-
- This parameter can also be specified on an existing
- :class:`_expression.Select` object using the
- :meth:`_expression.Select.set_label_style`
- method.
-
- .. seealso::
-
- :meth:`_expression.Select.set_label_style`
-
- """
- self = cls.__new__(cls)
-
- self._auto_correlate = correlate
-
- if distinct is not False:
- if distinct is True:
- self.distinct.non_generative(self)
- else:
- self.distinct.non_generative(self, *util.to_list(distinct))
-
- if from_obj is not None:
- self.select_from.non_generative(self, *util.to_list(from_obj))
-
- try:
- cols_present = bool(columns)
- except TypeError as err:
- raise exc.ArgumentError(
- "select() construct created in legacy mode, i.e. with "
- "keyword arguments, must provide the columns argument as "
- "a Python list or other iterable.",
- code="c9ae",
- ) from err
-
- if cols_present:
- self._raw_columns = [
- coercions.expect(
- roles.ColumnsClauseRole, c, apply_propagate_attrs=self
- )
- for c in columns
- ]
- else:
- self._raw_columns = []
-
- if whereclause is not None:
- self.where.non_generative(self, whereclause)
-
- if having is not None:
- self.having.non_generative(self, having)
-
- if prefixes:
- self._setup_prefixes(prefixes)
-
- if suffixes:
- self._setup_suffixes(suffixes)
-
- GenerativeSelect.__init__(self, **kwargs)
- return self
-
- @classmethod
- def _create_future_select(cls, *entities):
- r"""Construct a new :class:`_expression.Select` using the 2.
- x style API.
.. versionadded:: 1.4 - The :func:`_sql.select` function now accepts
column arguments positionally. The top-level :func:`_sql.select`
return self
- _create_select = _create_future_select
-
@classmethod
def _create_raw_select(cls, **kw):
"""Create a :class:`.Select` using raw ``__new__`` with no coercions.
stmt.__dict__.update(kw)
return stmt
- @classmethod
- def _create(cls, *args, **kw):
- r"""Create a :class:`.Select` using either the 1.x or 2.0 constructor
- style.
-
- For the legacy calling style, see :meth:`.Select.create_legacy_select`.
- If the first argument passed is a Python sequence or if keyword
- arguments are present, this style is used.
-
- .. versionadded:: 2.0 - the :func:`_future.select` construct is
- the same construct as the one returned by
- :func:`_expression.select`, except that the function only
- accepts the "columns clause" entities up front; the rest of the
- state of the SELECT should be built up using generative methods.
-
- Similar functionality is also available via the
- :meth:`_expression.FromClause.select` method on any
- :class:`_expression.FromClause`.
-
- .. seealso::
-
- :ref:`coretutorial_selecting` - Core Tutorial description of
- :func:`_expression.select`.
-
- :param \*entities:
- Entities to SELECT from. For Core usage, this is typically a series
- of :class:`_expression.ColumnElement` and / or
- :class:`_expression.FromClause`
- objects which will form the columns clause of the resulting
- statement. For those objects that are instances of
- :class:`_expression.FromClause` (typically :class:`_schema.Table`
- or :class:`_expression.Alias`
- objects), the :attr:`_expression.FromClause.c`
- collection is extracted
- to form a collection of :class:`_expression.ColumnElement` objects.
-
- This parameter will also accept :class:`_expression.TextClause`
- constructs as given, as well as ORM-mapped classes.
-
- """
- if (
- args
- and (
- isinstance(args[0], list)
- or (
- hasattr(args[0], "__iter__")
- and not isinstance(args[0], (str, ClauseElement))
- and inspect(args[0], raiseerr=False) is None
- and not hasattr(args[0], "__clause_element__")
- )
- )
- ) or kw:
- return cls.create_legacy_select(*args, **kw)
- else:
- return cls._create_future_select(*args)
-
def __init__(self):
raise NotImplementedError()
element = fn(element)
return element.self_group(against=operators.exists)
- @util.deprecated_params(
- whereclause=(
- "2.0",
- "The :paramref:`_sql.Exists.select().whereclause` parameter "
- "is deprecated and will be removed in version 2.0. "
- "Please make use "
- "of the :meth:`.Select.where` "
- "method to add WHERE criteria to the SELECT statement.",
- ),
- kwargs=(
- "2.0",
- "The :meth:`_sql.Exists.select` method will no longer accept "
- "keyword arguments in version 2.0. "
- "Please use generative methods from the "
- ":class:`_sql.Select` construct in order to apply additional "
- "modifications.",
- ),
- )
- def select(self, whereclause=None, **kwargs):
+ def select(self) -> "Select":
r"""Return a SELECT of this :class:`_expression.Exists`.
e.g.::
SELECT EXISTS (SELECT id FROM some_table WHERE some_table = :param) AS anon_1
- :param whereclause: a WHERE clause, equivalent to calling the
- :meth:`_sql.Select.where` method.
-
- :param **kwargs: additional keyword arguments are passed to the
- legacy constructor for :class:`_sql.Select` described at
- :meth:`_sql.Select.create_legacy_select`.
-
.. seealso::
:func:`_expression.select` - general purpose
""" # noqa
- if whereclause is not None:
- kwargs["whereclause"] = whereclause
- return Select._create_select_from_fromclause(self, [self], **kwargs)
+ return Select._create(self)
def correlate(self, *fromclause):
"""Apply correlation to the subquery noted by this :class:`_sql.Exists`.
from sqlalchemy import CHAR
from sqlalchemy import column
from sqlalchemy import exc
-from sqlalchemy import exists
from sqlalchemy import ForeignKey
from sqlalchemy import func
from sqlalchemy import Integer
from sqlalchemy.sql import roles
from sqlalchemy.sql import update
from sqlalchemy.sql import visitors
-from sqlalchemy.sql.selectable import LABEL_STYLE_NONE
from sqlalchemy.sql.selectable import SelectStatementGrouping
from sqlalchemy.testing import assert_raises_message
from sqlalchemy.testing import assertions
):
eq_(stmt.froms, [t1])
- def test_select_list_argument(self):
-
- with testing.expect_deprecated_20(
- r"The legacy calling style of select\(\) is deprecated "
- "and will be removed in SQLAlchemy 2.0"
- ):
- stmt = select([column("q")])
- self.assert_compile(stmt, "SELECT q")
-
- def test_select_column_collection_argument(self):
- t1 = table("t1", column("q"))
-
- with testing.expect_deprecated_20(
- r"The legacy calling style of select\(\) is deprecated "
- "and will be removed in SQLAlchemy 2.0"
- ):
- stmt = select(t1.c)
- self.assert_compile(stmt, "SELECT t1.q FROM t1")
-
- def test_select_kw_argument(self):
-
- with testing.expect_deprecated_20(
- r"The legacy calling style of select\(\) is deprecated "
- "and will be removed in SQLAlchemy 2.0"
- ):
- stmt = select(whereclause=column("q") == 5).add_columns(
- column("q")
- )
- self.assert_compile(stmt, "SELECT q WHERE q = :q_1")
-
- @testing.combinations(
- (
- lambda table1: table1.select(table1.c.col1 == 5),
- "FromClause",
- "whereclause",
- "SELECT table1.col1, table1.col2, table1.col3, table1.colx "
- "FROM table1 WHERE table1.col1 = :col1_1",
- ),
- (
- lambda table1: table1.select(whereclause=table1.c.col1 == 5),
- "FromClause",
- "whereclause",
- "SELECT table1.col1, table1.col2, table1.col3, table1.colx "
- "FROM table1 WHERE table1.col1 = :col1_1",
- ),
- (
- lambda table1: table1.select(order_by=table1.c.col1),
- "FromClause",
- "kwargs",
- "SELECT table1.col1, table1.col2, table1.col3, table1.colx "
- "FROM table1 ORDER BY table1.col1",
- ),
- (
- lambda table1: exists().select(table1.c.col1 == 5),
- "Exists",
- "whereclause",
- "SELECT EXISTS (SELECT *) AS anon_1 FROM table1 "
- "WHERE table1.col1 = :col1_1",
- ),
- (
- lambda table1: exists().select(whereclause=table1.c.col1 == 5),
- "Exists",
- "whereclause",
- "SELECT EXISTS (SELECT *) AS anon_1 FROM table1 "
- "WHERE table1.col1 = :col1_1",
- ),
- (
- lambda table1: exists().select(
- order_by=table1.c.col1, from_obj=table1
- ),
- "Exists",
- "kwargs",
- "SELECT EXISTS (SELECT *) AS anon_1 FROM table1 "
- "ORDER BY table1.col1",
- ),
- (
- lambda table1, table2: table1.join(table2)
- .select(table1.c.col1 == 5)
- .set_label_style(LABEL_STYLE_NONE),
- "Join",
- "whereclause",
- "SELECT table1.col1, table1.col2, table1.col3, table1.colx, "
- "table2.col1, table2.col2, table2.col3, table2.coly FROM table1 "
- "JOIN table2 ON table1.col1 = table2.col2 "
- "WHERE table1.col1 = :col1_1",
- ),
- (
- lambda table1, table2: table1.join(table2)
- .select(whereclause=table1.c.col1 == 5)
- .set_label_style(LABEL_STYLE_NONE),
- "Join",
- "whereclause",
- "SELECT table1.col1, table1.col2, table1.col3, table1.colx, "
- "table2.col1, table2.col2, table2.col3, table2.coly FROM table1 "
- "JOIN table2 ON table1.col1 = table2.col2 "
- "WHERE table1.col1 = :col1_1",
- ),
- (
- lambda table1, table2: table1.join(table2)
- .select(order_by=table1.c.col1)
- .set_label_style(LABEL_STYLE_NONE),
- "Join",
- "kwargs",
- "SELECT table1.col1, table1.col2, table1.col3, table1.colx, "
- "table2.col1, table2.col2, table2.col3, table2.coly FROM table1 "
- "JOIN table2 ON table1.col1 = table2.col2 "
- "ORDER BY table1.col1",
- ),
- )
- def test_select_method_parameters(
- self, stmt, clsname, paramname, expected_sql
- ):
- if paramname == "whereclause":
- warning_txt = (
- r"The %s.select\(\).whereclause parameter is deprecated "
- "and will be removed in version 2.0" % clsname
- )
- else:
- warning_txt = (
- r"The %s.select\(\) method will no longer accept "
- "keyword arguments in version 2.0. " % clsname
- )
- with testing.expect_deprecated_20(
- warning_txt,
- r"The legacy calling style of select\(\) is deprecated "
- "and will be removed in SQLAlchemy 2.0",
- ):
- stmt = testing.resolve_lambda(
- stmt, table1=self.table1, table2=self.table2
- )
-
- self.assert_compile(stmt, expected_sql)
-
- def test_deprecated_subquery_standalone(self):
- from sqlalchemy import subquery
-
- with testing.expect_deprecated(
- r"The standalone subquery\(\) function is deprecated"
- ):
- stmt = subquery(
- None,
- [literal_column("1").label("a")],
- order_by=literal_column("1"),
- )
-
- self.assert_compile(
- select(stmt),
- "SELECT anon_1.a FROM (SELECT 1 AS a ORDER BY 1) AS anon_1",
- )
-
def test_case_list_legacy(self):
t1 = table("t", column("q"))
column("othername", String),
)
return table1, table2
-
- def test_legacy_calling_style_kw_only(self, table_fixture):
- table1, table2 = table_fixture
- with testing.expect_deprecated_20(
- "The legacy calling style of select"
- ):
- stmt = select(
- whereclause=table1.c.myid == table2.c.otherid
- ).add_columns(table1.c.myid)
-
- self.assert_compile(
- stmt,
- "SELECT mytable.myid FROM mytable, myothertable "
- "WHERE mytable.myid = myothertable.otherid",
- )
-
- def test_legacy_calling_style_col_seq_only(self, table_fixture):
- table1, table2 = table_fixture
- with testing.expect_deprecated_20(
- "The legacy calling style of select"
- ):
- # keep [] here
- stmt = select([table1.c.myid]).where(
- table1.c.myid == table2.c.otherid
- )
-
- self.assert_compile(
- stmt,
- "SELECT mytable.myid FROM mytable, myothertable "
- "WHERE mytable.myid = myothertable.otherid",
- )
-
- def test_new_calling_style_thing_ok_actually_use_iter(self, table_fixture):
- table1, table2 = table_fixture
-
- class Thing:
- def __iter__(self):
- return iter([table1.c.name, table1.c.description])
-
- with testing.expect_deprecated_20(
- "The legacy calling style of select"
- ):
- stmt = select(Thing())
- self.assert_compile(
- stmt,
- "SELECT mytable.name, mytable.description FROM mytable",
- )
-
- def test_kw_triggers_old_style(self, table_fixture):
- table1, table2 = table_fixture
- with testing.expect_deprecated_20(
- "The legacy calling style of select"
- ):
- assert_raises_message(
- exc.ArgumentError,
- r"select\(\) construct created in legacy mode, "
- "i.e. with keyword arguments",
- select,
- table1.c.myid,
- whereclause=table1.c.myid == table2.c.otherid,
- )