summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/selectable.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2021-01-17 13:35:02 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2021-01-20 23:30:21 -0500
commit05a31f2708590161d4b3b4c7ff65196c99b4a22b (patch)
treef61183159f3210d72a76bfe6d9afc57fecf5d8ef /lib/sqlalchemy/sql/selectable.py
parent1a94d0c0cabbce3d6bd957ab2d4350ff48ad716d (diff)
downloadsqlalchemy-05a31f2708590161d4b3b4c7ff65196c99b4a22b.tar.gz
Implement support for functions as FROM with columns clause support
WIP Fixes: #3566 Change-Id: I5b093b72533ef695293e737eb75850b9713e5e03
Diffstat (limited to 'lib/sqlalchemy/sql/selectable.py')
-rw-r--r--lib/sqlalchemy/sql/selectable.py67
1 files changed, 67 insertions, 0 deletions
diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py
index 8e478583f..c299065ae 100644
--- a/lib/sqlalchemy/sql/selectable.py
+++ b/lib/sqlalchemy/sql/selectable.py
@@ -51,6 +51,8 @@ from .elements import ColumnClause
from .elements import GroupedElement
from .elements import Grouping
from .elements import literal_column
+from .elements import Record
+from .elements import TableValuedColumn
from .elements import UnaryExpression
from .visitors import InternalTraversal
from .. import exc
@@ -623,6 +625,33 @@ class FromClause(roles.AnonymizedFromClauseRole, Selectable):
return Alias._construct(self, name)
+ def record(self):
+ """Return a :class:`_sql.Record` object for this
+ :class:`_expression.FromClause`.
+
+ A "record" is a :class:`_sql.ColumnElement` that represents a complete
+ row in a table. Support for this construct is backend dependent,
+ however databases such as PostgreSQL and Oracle have support
+ for "record" datatypes.
+
+ E.g.::
+
+ >>> from sqlalchemy import select, column, func, table
+ >>> a = table("a", column("id"), column("x"), column("y"))
+ >>> stmt = select(func.row_to_json(a.record()))
+ >>> print(stmt)
+ SELECT row_to_json(a) AS row_to_json_1
+ FROM a
+
+ .. versionadded:: 1.4.0b2
+
+ .. seealso::
+
+ :ref:`tutorial_functions` - in the :ref:`unified_tutorial`
+
+ """
+ return Record(self)
+
def tablesample(self, sampling, name=None, seed=None):
"""Return a TABLESAMPLE alias of this :class:`_expression.FromClause`.
@@ -1583,6 +1612,44 @@ class Alias(roles.DMLTableRole, AliasedReturnsRows):
).alias(name=name, flat=flat)
+class TableValuedAlias(Alias):
+ """An alias that includes the ability to be used in a columns context.
+
+ Provides the :attr:`_sql.ScalarAlias.column` accessor that returns
+ a :class:`_sql.ColumnElement` representing this object.
+
+ The main use case for this construct is that of PostgreSQL functions
+ that may be used in the FROM clause of a SELECT.
+
+ .. versionadded:: 1.4.0b2
+
+ """
+
+ __visit_name__ = "table_valued_alias"
+
+ named = False
+
+ _traverse_internals = [
+ ("element", InternalTraversal.dp_clauseelement),
+ ("name", InternalTraversal.dp_anon_name),
+ ("named", InternalTraversal.dp_boolean),
+ ]
+
+ def _init(self, selectable, name=None, named=False):
+ self.named = named
+ super(TableValuedAlias, self)._init(selectable, name=name)
+
+ @HasMemoized.memoized_attribute
+ def column(self):
+ """Return a column expression representing this
+ :class:`_sql.ScalarAlias`."""
+
+ return TableValuedColumn(self)
+
+ def alias(self, name=None):
+ return self.element.alias(name=name)
+
+
class Lateral(AliasedReturnsRows):
"""Represent a LATERAL subquery.