diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2023-03-01 11:07:25 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2023-03-02 10:47:03 -0500 |
commit | 45f7b3b8ac9a1b393b45f2f199a88c3bb0c86705 (patch) | |
tree | 5686c12e8030cfe423c181d9a9f9cf1caaed2489 /lib/sqlalchemy/sql/elements.py | |
parent | 466c3fde848e28cc85f2a78dd9a76f85455479f8 (diff) | |
download | sqlalchemy-45f7b3b8ac9a1b393b45f2f199a88c3bb0c86705.tar.gz |
TextualSelect is ReturnsRowsRole
Fixed typing bug where :meth:`_sql.Select.from_statement` would not accept
:func:`_sql.text` or :class:`.TextualSelect` objects as a valid type.
Additionally repaired the :class:`.TextClause.columns` method to have a
return type, which was missing.
Fixes: #9398
Change-Id: I627fc33bf83365e1c7f7c6ed29ea387dfd4a57d8
Diffstat (limited to 'lib/sqlalchemy/sql/elements.py')
-rw-r--r-- | lib/sqlalchemy/sql/elements.py | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index e51b755dd..a416b6ac0 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -99,6 +99,7 @@ if typing.TYPE_CHECKING: from .selectable import _SelectIterable from .selectable import FromClause from .selectable import NamedFromClause + from .selectable import TextualSelect from .sqltypes import TupleType from .type_api import TypeEngine from .visitors import _CloneCallableType @@ -2385,7 +2386,9 @@ class TextClause( return self @util.preload_module("sqlalchemy.sql.selectable") - def columns(self, *cols, **types): + def columns( + self, *cols: _ColumnExpressionArgument[Any], **types: TypeEngine[Any] + ) -> TextualSelect: r"""Turn this :class:`_expression.TextClause` object into a :class:`_expression.TextualSelect` object that serves the same role as a SELECT @@ -2503,29 +2506,38 @@ class TextClause( """ selectable = util.preloaded.sql_selectable + + input_cols: List[NamedColumn[Any]] = [ + coercions.expect(roles.LabeledColumnExprRole, col) for col in cols + ] + positional_input_cols = [ ColumnClause(col.key, types.pop(col.key)) if col.key in types else col - for col in cols + for col in input_cols ] - keyed_input_cols: List[ColumnClause[Any]] = [ + keyed_input_cols: List[NamedColumn[Any]] = [ ColumnClause(key, type_) for key, type_ in types.items() ] - return selectable.TextualSelect( + elem = selectable.TextualSelect.__new__(selectable.TextualSelect) + elem._init( self, positional_input_cols + keyed_input_cols, positional=bool(positional_input_cols) and not keyed_input_cols, ) + return elem @property - def type(self): + def type(self) -> TypeEngine[Any]: return type_api.NULLTYPE @property def comparator(self): - return self.type.comparator_factory(self) + # TODO: this seems wrong, it seems like we might not + # be using this method. + return self.type.comparator_factory(self) # type: ignore def self_group(self, against=None): if against is operators.in_op: |