summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2021-11-05 10:18:42 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2021-11-05 11:55:14 -0400
commit0c44a1e77cfde0f841a4a64140314c6b833efdab (patch)
tree1678a98a75b4b40882c638b9193e52d3b931fd34 /test
parent248d232459e38561999c4172acaaddd651c1a933 (diff)
downloadsqlalchemy-0c44a1e77cfde0f841a4a64140314c6b833efdab.tar.gz
use tuple expansion if type._is_tuple, test for Sequence if no type
Fixed regression where the row objects returned for ORM queries, which are now the normal :class:`_sql.Row` objects, would not be interpreted by the :meth:`_sql.ColumnOperators.in_` operator as tuple values to be broken out into individual bound parameters, and would instead pass them as single values to the driver leading to failures. The change to the "expanding IN" system now accommodates for the expression already being of type :class:`.TupleType` and treats values accordingly if so. In the uncommon case of using "tuple-in" with an untyped statement such as a textual statement with no typing information, a tuple value is detected for values that implement ``collections.abc.Sequence``, but that are not ``str`` or ``bytes``, as always when testing for ``Sequence``. Added :class:`.TupleType` to the top level ``sqlalchemy`` import namespace. Fixes: #7292 Change-Id: I8286387e3b3c3752b3bd4ae3560d4f31172acc22
Diffstat (limited to 'test')
-rw-r--r--test/sql/test_lambdas.py5
-rw-r--r--test/sql/test_resultset.py32
2 files changed, 35 insertions, 2 deletions
diff --git a/test/sql/test_lambdas.py b/test/sql/test_lambdas.py
index 2e794d7bc..a53401a4f 100644
--- a/test/sql/test_lambdas.py
+++ b/test/sql/test_lambdas.py
@@ -26,6 +26,7 @@ from sqlalchemy.testing import is_
from sqlalchemy.testing import ne_
from sqlalchemy.testing.assertions import expect_raises_message
from sqlalchemy.testing.assertsql import CompiledSQL
+from sqlalchemy.types import ARRAY
from sqlalchemy.types import Boolean
from sqlalchemy.types import Integer
from sqlalchemy.types import String
@@ -1180,9 +1181,9 @@ class LambdaElementTest(
def test_in_parameters_five(self):
def go(n1, n2):
stmt = lambdas.lambda_stmt(
- lambda: select(1).where(column("q").in_(n1))
+ lambda: select(1).where(column("q", ARRAY(String)).in_(n1))
)
- stmt += lambda s: s.where(column("y").in_(n2))
+ stmt += lambda s: s.where(column("y", ARRAY(String)).in_(n2))
return stmt
expr = go(["a", "b", "c"], ["d", "e", "f"])
diff --git a/test/sql/test_resultset.py b/test/sql/test_resultset.py
index 346cb3d58..3909fe60d 100644
--- a/test/sql/test_resultset.py
+++ b/test/sql/test_resultset.py
@@ -21,6 +21,7 @@ from sqlalchemy import table
from sqlalchemy import testing
from sqlalchemy import text
from sqlalchemy import true
+from sqlalchemy import tuple_
from sqlalchemy import type_coerce
from sqlalchemy import TypeDecorator
from sqlalchemy import util
@@ -869,6 +870,37 @@ class CursorResultTest(fixtures.TablesTest):
connection.execute(users.insert(), r._mapping)
eq_(connection.execute(users.select()).fetchall(), [(1, "john")])
+ @testing.requires.tuple_in
+ def test_row_tuple_interpretation(self, connection):
+ """test #7292"""
+ users = self.tables.users
+
+ connection.execute(
+ users.insert(),
+ [
+ dict(user_id=1, user_name="u1"),
+ dict(user_id=2, user_name="u2"),
+ dict(user_id=3, user_name="u3"),
+ ],
+ )
+ rows = connection.execute(
+ select(users.c.user_id, users.c.user_name)
+ ).all()
+
+ # was previously needed
+ # rows = [(x, y) for x, y in rows]
+
+ new_stmt = (
+ select(users)
+ .where(tuple_(users.c.user_id, users.c.user_name).in_(rows))
+ .order_by(users.c.user_id)
+ )
+
+ eq_(
+ connection.execute(new_stmt).all(),
+ [(1, "u1"), (2, "u2"), (3, "u3")],
+ )
+
def test_result_as_args(self, connection):
users = self.tables.users
users2 = self.tables.users2