summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2023-03-07 09:03:07 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2023-03-07 09:03:07 -0500
commitb97b313c6eb7f2fe4b98d011c292de4d258c508c (patch)
treee33b8abe85827a7d48df8e4f7e2f79ed97dd0b26 /lib/sqlalchemy/sql
parentdccc4577fec202947adac8da43d40f415433cf6b (diff)
downloadsqlalchemy-b97b313c6eb7f2fe4b98d011c292de4d258c508c.tar.gz
resolve select to NULLTYPE if no columns
Fixed regression where the :func:`_sql.select` construct would not be able to render if it were given no columns and then used in the context of an EXISTS, raising an internal exception instead. While an empty "SELECT" is not typically valid SQL, in the context of EXISTS databases such as PostgreSQL allow it, and in any case the condition now no longer raises an internal exception. For this case, also add an extra whitespace trim step for the unusual case that there are no columns to render. This is done in such a way as to not interfere with other test cases that are involving custom compilation schemes. Fixes: #9440 Change-Id: If65ba9ce15d371f09b4342ad0669143b7b082a78
Diffstat (limited to 'lib/sqlalchemy/sql')
-rw-r--r--lib/sqlalchemy/sql/compiler.py10
-rw-r--r--lib/sqlalchemy/sql/selectable.py3
2 files changed, 13 insertions, 0 deletions
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index bc463f9a1..ad0a3b686 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -4668,6 +4668,16 @@ class SQLCompiler(Compiled):
from_linter = None
warn_linting = False
+ # adjust the whitespace for no inner columns, part of #9440,
+ # so that a no-col SELECT comes out as "SELECT WHERE..." or
+ # "SELECT FROM ...".
+ # while it would be better to have built the SELECT starting string
+ # without trailing whitespace first, then add whitespace only if inner
+ # cols were present, this breaks compatibility with various custom
+ # compilation schemes that are currently being tested.
+ if not inner_columns:
+ text = text.rstrip()
+
if froms:
text += " \nFROM "
diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py
index 39ef420dd..56cca6f73 100644
--- a/lib/sqlalchemy/sql/selectable.py
+++ b/lib/sqlalchemy/sql/selectable.py
@@ -89,6 +89,7 @@ from .elements import literal_column
from .elements import TableValuedColumn
from .elements import UnaryExpression
from .operators import OperatorType
+from .sqltypes import NULLTYPE
from .visitors import _TraverseInternalsType
from .visitors import InternalTraversal
from .visitors import prefix_anon_map
@@ -5167,6 +5168,8 @@ class Select(
GenerativeSelect.__init__(self)
def _scalar_type(self) -> TypeEngine[Any]:
+ if not self._raw_columns:
+ return NULLTYPE
elem = self._raw_columns[0]
cols = list(elem._select_iterable)
return cols[0].type