Skip to content

Commit 46a6e75

Browse files
author
Chuck Cadman
committed
Fix sqlalchemy 1.4.46 warning (#50558)
1 parent 83ef3e4 commit 46a6e75

File tree

2 files changed

+38
-23
lines changed

2 files changed

+38
-23
lines changed

pandas/io/sql.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ def read_sql_table(
319319
--------
320320
>>> pd.read_sql_table('table_name', 'postgres:///db_name') # doctest:+SKIP
321321
"""
322-
with pandasSQL_builder(con, schema=schema) as pandas_sql:
322+
with pandasSQL_builder(con, schema=schema, need_transaction=True) as pandas_sql:
323323
if not pandas_sql.has_table(table_name):
324324
raise ValueError(f"Table {table_name} not found")
325325

@@ -883,7 +883,8 @@ def sql_schema(self) -> str:
883883
def _execute_create(self) -> None:
884884
# Inserting table into database, add to MetaData object
885885
self.table = self.table.to_metadata(self.pd_sql.meta)
886-
self.table.create(bind=self.pd_sql.con)
886+
with self.pd_sql.run_transaction():
887+
self.table.create(bind=self.pd_sql.con)
887888

888889
def create(self) -> None:
889890
if self.exists():
@@ -1529,7 +1530,11 @@ def __exit__(self, *args) -> None:
15291530

15301531
@contextmanager
15311532
def run_transaction(self):
1532-
yield self.con
1533+
if not self.con.in_transaction():
1534+
with self.con.begin():
1535+
yield self.con
1536+
else:
1537+
yield self.con
15331538

15341539
def execute(self, sql: str | Select | TextClause, params=None):
15351540
"""Simple passthrough to SQLAlchemy connectable"""
@@ -1932,7 +1937,8 @@ def drop_table(self, table_name: str, schema: str | None = None) -> None:
19321937
schema = schema or self.meta.schema
19331938
if self.has_table(table_name, schema):
19341939
self.meta.reflect(bind=self.con, only=[table_name], schema=schema)
1935-
self.get_table(table_name, schema).drop(bind=self.con)
1940+
with self.run_transaction():
1941+
self.get_table(table_name, schema).drop(bind=self.con)
19361942
self.meta.clear()
19371943

19381944
def _create_sql_schema(

pandas/tests/io/test_sql.py

+28-19
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,6 @@ def create_and_load_iris(conn, iris_file: Path, dialect: str):
149149
from sqlalchemy.engine import Engine
150150

151151
iris = iris_table_metadata(dialect)
152-
iris.drop(conn, checkfirst=True)
153-
iris.create(bind=conn)
154152

155153
with iris_file.open(newline=None) as csvfile:
156154
reader = csv.reader(csvfile)
@@ -160,9 +158,14 @@ def create_and_load_iris(conn, iris_file: Path, dialect: str):
160158
if isinstance(conn, Engine):
161159
with conn.connect() as conn:
162160
with conn.begin():
161+
iris.drop(conn, checkfirst=True)
162+
iris.create(bind=conn)
163163
conn.execute(stmt)
164164
else:
165-
conn.execute(stmt)
165+
with conn.begin():
166+
iris.drop(conn, checkfirst=True)
167+
iris.create(bind=conn)
168+
conn.execute(stmt)
166169

167170

168171
def create_and_load_iris_view(conn):
@@ -180,7 +183,8 @@ def create_and_load_iris_view(conn):
180183
with conn.begin():
181184
conn.execute(stmt)
182185
else:
183-
conn.execute(stmt)
186+
with conn.begin():
187+
conn.execute(stmt)
184188

185189

186190
def types_table_metadata(dialect: str):
@@ -243,16 +247,19 @@ def create_and_load_types(conn, types_data: list[dict], dialect: str):
243247
from sqlalchemy.engine import Engine
244248

245249
types = types_table_metadata(dialect)
246-
types.drop(conn, checkfirst=True)
247-
types.create(bind=conn)
248250

249251
stmt = insert(types).values(types_data)
250252
if isinstance(conn, Engine):
251253
with conn.connect() as conn:
252254
with conn.begin():
255+
types.drop(conn, checkfirst=True)
256+
types.create(bind=conn)
253257
conn.execute(stmt)
254258
else:
255-
conn.execute(stmt)
259+
with conn.begin():
260+
types.drop(conn, checkfirst=True)
261+
types.create(bind=conn)
262+
conn.execute(stmt)
256263

257264

258265
def check_iris_frame(frame: DataFrame):
@@ -713,7 +720,8 @@ def test_read_procedure(conn, request):
713720
with engine_conn.begin():
714721
engine_conn.execute(proc)
715722
else:
716-
conn.execute(proc)
723+
with conn.begin():
724+
conn.execute(proc)
717725

718726
res1 = sql.read_sql_query("CALL get_testdb();", conn)
719727
tm.assert_frame_equal(df, res1)
@@ -995,8 +1003,6 @@ class _TestSQLApi(PandasSQLTest):
9951003
@pytest.fixture(autouse=True)
9961004
def setup_method(self, iris_path, types_data):
9971005
self.conn = self.connect()
998-
if not isinstance(self.conn, sqlite3.Connection):
999-
self.conn.begin()
10001006
self.load_iris_data(iris_path)
10011007
self.load_types_data(types_data)
10021008
self.load_test_data_and_sql()
@@ -1492,7 +1498,8 @@ def test_not_reflect_all_tables(self):
14921498
with conn.begin():
14931499
conn.execute(query)
14941500
else:
1495-
self.conn.execute(query)
1501+
with self.conn.begin():
1502+
self.conn.execute(query)
14961503

14971504
with tm.assert_produces_warning(None):
14981505
sql.read_sql_table("other_table", self.conn)
@@ -1742,7 +1749,6 @@ def setup_class(cls):
17421749
def setup_method(self, iris_path, types_data):
17431750
try:
17441751
self.conn = self.engine.connect()
1745-
self.conn.begin()
17461752
self.pandasSQL = sql.SQLDatabase(self.conn)
17471753
except sqlalchemy.exc.OperationalError:
17481754
pytest.skip(f"Can't connect to {self.flavor} server")
@@ -2146,7 +2152,6 @@ def _get_index_columns(self, tbl_name):
21462152
def test_to_sql_save_index(self):
21472153
self._to_sql_save_index()
21482154

2149-
@pytest.mark.xfail(reason="Nested transactions rollbacks don't work with Pandas")
21502155
def test_transactions(self):
21512156
self._transaction_test()
21522157

@@ -2168,7 +2173,8 @@ def test_get_schema_create_table(self, test_frame3):
21682173
with conn.begin():
21692174
conn.execute(create_sql)
21702175
else:
2171-
self.conn.execute(create_sql)
2176+
with self.conn.begin():
2177+
self.conn.execute(create_sql)
21722178
returned_df = sql.read_sql_table(tbl, self.conn)
21732179
tm.assert_frame_equal(returned_df, blank_test_df, check_index_type=False)
21742180
self.drop_table(tbl, self.conn)
@@ -2578,7 +2584,8 @@ class Test(BaseModel):
25782584
id = Column(Integer, primary_key=True)
25792585
string_column = Column(String(50))
25802586

2581-
BaseModel.metadata.create_all(self.conn)
2587+
with self.conn.begin():
2588+
BaseModel.metadata.create_all(self.conn)
25822589
Session = sessionmaker(bind=self.conn)
25832590
with Session() as session:
25842591
df = DataFrame({"id": [0, 1], "string_column": ["hello", "world"]})
@@ -2660,8 +2667,9 @@ def test_schema_support(self):
26602667
df = DataFrame({"col1": [1, 2], "col2": [0.1, 0.2], "col3": ["a", "n"]})
26612668

26622669
# create a schema
2663-
self.conn.exec_driver_sql("DROP SCHEMA IF EXISTS other CASCADE;")
2664-
self.conn.exec_driver_sql("CREATE SCHEMA other;")
2670+
with self.conn.begin():
2671+
self.conn.exec_driver_sql("DROP SCHEMA IF EXISTS other CASCADE;")
2672+
self.conn.exec_driver_sql("CREATE SCHEMA other;")
26652673

26662674
# write dataframe to different schema's
26672675
assert df.to_sql("test_schema_public", self.conn, index=False) == 2
@@ -2693,8 +2701,9 @@ def test_schema_support(self):
26932701
# different if_exists options
26942702

26952703
# create a schema
2696-
self.conn.exec_driver_sql("DROP SCHEMA IF EXISTS other CASCADE;")
2697-
self.conn.exec_driver_sql("CREATE SCHEMA other;")
2704+
with self.conn.begin():
2705+
self.conn.exec_driver_sql("DROP SCHEMA IF EXISTS other CASCADE;")
2706+
self.conn.exec_driver_sql("CREATE SCHEMA other;")
26982707

26992708
# write dataframe with different if_exists options
27002709
assert (

0 commit comments

Comments
 (0)