summaryrefslogtreecommitdiff
path: root/test/sql
diff options
context:
space:
mode:
authorFederico Caselli <cfederico87@gmail.com>2023-03-04 23:33:02 +0100
committerFederico Caselli <cfederico87@gmail.com>2023-03-04 23:33:02 +0100
commit4dc2ce0fb15d72e508c72b0cb0e7fd622e6cc34f (patch)
tree3a6ab92c27cce72d1a7b3928a87df8a6491bf154 /test/sql
parent0465ea082c17b95fea2b6c6c9c1bcc7a34ea8f45 (diff)
downloadsqlalchemy-4dc2ce0fb15d72e508c72b0cb0e7fd622e6cc34f.tar.gz
Fixed bug where :meth:`_engine.Row`s could not be
unpickled by other processes. Fixes: #9423 Change-Id: Ie496e31158caff5f72e0a9069dddd55f3116e0b8
Diffstat (limited to 'test/sql')
-rw-r--r--test/sql/test_resultset.py142
1 files changed, 85 insertions, 57 deletions
diff --git a/test/sql/test_resultset.py b/test/sql/test_resultset.py
index 66584c96e..97f35164a 100644
--- a/test/sql/test_resultset.py
+++ b/test/sql/test_resultset.py
@@ -4,7 +4,11 @@ from contextlib import contextmanager
import csv
from io import StringIO
import operator
+import os
import pickle
+import subprocess
+import sys
+from tempfile import mkstemp
from unittest.mock import Mock
from unittest.mock import patch
@@ -420,9 +424,8 @@ class CursorResultTest(fixtures.TablesTest):
# in 1.x, would warn for string match, but return a result
not_in(sql.column("content_type"), row._mapping)
- def test_pickled_rows(self, connection):
+ def _pickle_row_data(self, connection, use_labels):
users = self.tables.users
- addresses = self.tables.addresses
connection.execute(
users.insert(),
@@ -433,70 +436,95 @@ class CursorResultTest(fixtures.TablesTest):
],
)
- for use_pickle in False, True:
- for use_labels in False, True:
- result = connection.execute(
- users.select()
- .order_by(users.c.user_id)
- .set_label_style(
- LABEL_STYLE_TABLENAME_PLUS_COL
- if use_labels
- else LABEL_STYLE_NONE
- )
- ).fetchall()
+ result = connection.execute(
+ users.select()
+ .order_by(users.c.user_id)
+ .set_label_style(
+ LABEL_STYLE_TABLENAME_PLUS_COL
+ if use_labels
+ else LABEL_STYLE_NONE
+ )
+ ).all()
+ return result
- if use_pickle:
- result = pickle.loads(pickle.dumps(result))
+ @testing.variation("use_pickle", [True, False])
+ @testing.variation("use_labels", [True, False])
+ def test_pickled_rows(self, connection, use_pickle, use_labels):
+ users = self.tables.users
+ addresses = self.tables.addresses
- eq_(result, [(7, "jack"), (8, "ed"), (9, "fred")])
- if use_labels:
- eq_(result[0]._mapping["users_user_id"], 7)
- eq_(
- list(result[0]._fields),
- ["users_user_id", "users_user_name"],
- )
- else:
- eq_(result[0]._mapping["user_id"], 7)
- eq_(list(result[0]._fields), ["user_id", "user_name"])
+ result = self._pickle_row_data(connection, use_labels)
- eq_(result[0][0], 7)
+ if use_pickle:
+ result = pickle.loads(pickle.dumps(result))
- assert_raises(
- exc.NoSuchColumnError,
- lambda: result[0]._mapping["fake key"],
- )
+ eq_(result, [(7, "jack"), (8, "ed"), (9, "fred")])
+ if use_labels:
+ eq_(result[0]._mapping["users_user_id"], 7)
+ eq_(
+ list(result[0]._fields),
+ ["users_user_id", "users_user_name"],
+ )
+ else:
+ eq_(result[0]._mapping["user_id"], 7)
+ eq_(list(result[0]._fields), ["user_id", "user_name"])
- # previously would warn
+ eq_(result[0][0], 7)
- if use_pickle:
- with expect_raises_message(
- exc.NoSuchColumnError,
- "Row was unpickled; lookup by ColumnElement is "
- "unsupported",
- ):
- result[0]._mapping[users.c.user_id]
- else:
- eq_(result[0]._mapping[users.c.user_id], 7)
+ assert_raises(
+ exc.NoSuchColumnError,
+ lambda: result[0]._mapping["fake key"],
+ )
- if use_pickle:
- with expect_raises_message(
- exc.NoSuchColumnError,
- "Row was unpickled; lookup by ColumnElement is "
- "unsupported",
- ):
- result[0]._mapping[users.c.user_name]
- else:
- eq_(result[0]._mapping[users.c.user_name], "jack")
+ # previously would warn
- assert_raises(
- exc.NoSuchColumnError,
- lambda: result[0]._mapping[addresses.c.user_id],
- )
+ if use_pickle:
+ with expect_raises_message(
+ exc.NoSuchColumnError,
+ "Row was unpickled; lookup by ColumnElement is " "unsupported",
+ ):
+ result[0]._mapping[users.c.user_id]
+ else:
+ eq_(result[0]._mapping[users.c.user_id], 7)
- assert_raises(
- exc.NoSuchColumnError,
- lambda: result[0]._mapping[addresses.c.address_id],
- )
+ if use_pickle:
+ with expect_raises_message(
+ exc.NoSuchColumnError,
+ "Row was unpickled; lookup by ColumnElement is " "unsupported",
+ ):
+ result[0]._mapping[users.c.user_name]
+ else:
+ eq_(result[0]._mapping[users.c.user_name], "jack")
+
+ assert_raises(
+ exc.NoSuchColumnError,
+ lambda: result[0]._mapping[addresses.c.user_id],
+ )
+
+ assert_raises(
+ exc.NoSuchColumnError,
+ lambda: result[0]._mapping[addresses.c.address_id],
+ )
+
+ @testing.variation("use_labels", [True, False])
+ def test_pickle_rows_other_process(self, connection, use_labels):
+ result = self._pickle_row_data(connection, use_labels)
+
+ f, name = mkstemp("pkl")
+ with os.fdopen(f, "wb") as f:
+ pickle.dump(result, f)
+ name = name.replace(os.sep, "/")
+ code = (
+ "import sqlalchemy; import pickle; print(["
+ f"r[0] for r in pickle.load(open('''{name}''', 'rb'))])"
+ )
+ proc = subprocess.run(
+ [sys.executable, "-c", code], stdout=subprocess.PIPE
+ )
+ exp = str([r[0] for r in result]).encode()
+ eq_(proc.returncode, 0)
+ eq_(proc.stdout.strip(), exp)
+ os.unlink(name)
def test_column_error_printing(self, connection):
result = connection.execute(select(1))