Skip to content

Commit f696257

Browse files
Add connectables with default pool and add test for if_exists=append.
1 parent b138532 commit f696257

File tree

1 file changed

+119
-37
lines changed

1 file changed

+119
-37
lines changed

pandas/tests/io/test_sql.py

Lines changed: 119 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,6 @@ def create_and_load_types_postgresql(conn, types_data: list[dict]):
312312

313313
def create_and_load_types(conn, types_data: list[dict], dialect: str):
314314
from sqlalchemy import insert
315-
from sqlalchemy.engine import Engine
316315

317316
types = types_table_metadata(dialect)
318317

@@ -338,7 +337,6 @@ def create_and_load_postgres_datetz(conn):
338337
Table,
339338
insert,
340339
)
341-
from sqlalchemy.engine import Engine
342340

343341
metadata = MetaData()
344342
datetz = Table("datetz", metadata, Column("DateColWithTz", DateTime(timezone=True)))
@@ -620,6 +618,22 @@ def mysql_pymysql_engine():
620618
engine.dispose()
621619

622620

621+
@pytest.fixture
622+
def mysql_pymysql_engine_default_pool():
623+
sqlalchemy = pytest.importorskip("sqlalchemy")
624+
pymysql = pytest.importorskip("pymysql")
625+
engine = sqlalchemy.create_engine(
626+
"mysql+pymysql://root@localhost:3306/pandas",
627+
connect_args={"client_flag": pymysql.constants.CLIENT.MULTI_STATEMENTS},
628+
)
629+
yield engine
630+
for view in get_all_views(engine):
631+
drop_view(view, engine)
632+
for tbl in get_all_tables(engine):
633+
drop_table(tbl, engine)
634+
engine.dispose()
635+
636+
623637
@pytest.fixture
624638
def mysql_pymysql_engine_iris(mysql_pymysql_engine, iris_path):
625639
create_and_load_iris(mysql_pymysql_engine, iris_path)
@@ -639,6 +653,12 @@ def mysql_pymysql_conn(mysql_pymysql_engine):
639653
yield conn
640654

641655

656+
@pytest.fixture
657+
def mysql_pymysql_conn_default_pool(mysql_pymysql_engine_default_pool):
658+
with mysql_pymysql_engine_default_pool.connect() as conn:
659+
yield conn
660+
661+
642662
@pytest.fixture
643663
def mysql_pymysql_conn_iris(mysql_pymysql_engine_iris):
644664
with mysql_pymysql_engine_iris.connect() as conn:
@@ -667,6 +687,21 @@ def postgresql_psycopg2_engine():
667687
engine.dispose()
668688

669689

690+
@pytest.fixture
691+
def postgresql_psycopg2_engine_default_pool():
692+
sqlalchemy = pytest.importorskip("sqlalchemy")
693+
pytest.importorskip("psycopg2")
694+
engine = sqlalchemy.create_engine(
695+
"postgresql+psycopg2://postgres:postgres@localhost:5432/pandas",
696+
)
697+
yield engine
698+
for view in get_all_views(engine):
699+
drop_view(view, engine)
700+
for tbl in get_all_tables(engine):
701+
drop_table(tbl, engine)
702+
engine.dispose()
703+
704+
670705
@pytest.fixture
671706
def postgresql_psycopg2_engine_iris(postgresql_psycopg2_engine, iris_path):
672707
create_and_load_iris(postgresql_psycopg2_engine, iris_path)
@@ -686,6 +721,12 @@ def postgresql_psycopg2_conn(postgresql_psycopg2_engine):
686721
yield conn
687722

688723

724+
@pytest.fixture
725+
def postgresql_psycopg2_conn_default_pool(postgresql_psycopg2_engine_default_pool):
726+
with postgresql_psycopg2_engine_default_pool.connect() as conn:
727+
yield conn
728+
729+
689730
@pytest.fixture
690731
def postgresql_adbc_conn():
691732
pytest.importorskip("adbc_driver_postgresql")
@@ -768,12 +809,30 @@ def sqlite_engine(sqlite_str):
768809
engine.dispose()
769810

770811

812+
@pytest.fixture
813+
def sqlite_engine_default_pool(sqlite_str):
814+
sqlalchemy = pytest.importorskip("sqlalchemy")
815+
engine = sqlalchemy.create_engine(sqlite_str)
816+
yield engine
817+
for view in get_all_views(engine):
818+
drop_view(view, engine)
819+
for tbl in get_all_tables(engine):
820+
drop_table(tbl, engine)
821+
engine.dispose()
822+
823+
771824
@pytest.fixture
772825
def sqlite_conn(sqlite_engine):
773826
with sqlite_engine.connect() as conn:
774827
yield conn
775828

776829

830+
@pytest.fixture
831+
def sqlite_conn_default_pool(sqlite_engine_default_pool):
832+
with sqlite_engine_default_pool.connect() as conn:
833+
yield conn
834+
835+
777836
@pytest.fixture
778837
def sqlite_str_iris(sqlite_str, iris_path):
779838
sqlalchemy = pytest.importorskip("sqlalchemy")
@@ -900,6 +959,11 @@ def sqlite_buildin_types(sqlite_buildin, types_data):
900959
pytest.param("mysql_pymysql_conn", marks=pytest.mark.db),
901960
]
902961

962+
mysql_connectable_default_pool = [
963+
pytest.param("mysql_pymysql_engine_default_pool", marks=pytest.mark.db),
964+
pytest.param("mysql_pymysql_conn_default_pool", marks=pytest.mark.db),
965+
]
966+
903967
mysql_connectable_iris = [
904968
pytest.param("mysql_pymysql_engine_iris", marks=pytest.mark.db),
905969
pytest.param("mysql_pymysql_conn_iris", marks=pytest.mark.db),
@@ -915,6 +979,11 @@ def sqlite_buildin_types(sqlite_buildin, types_data):
915979
pytest.param("postgresql_psycopg2_conn", marks=pytest.mark.db),
916980
]
917981

982+
postgresql_connectable_default_pool = [
983+
pytest.param("postgresql_psycopg2_engine_default_pool", marks=pytest.mark.db),
984+
pytest.param("postgresql_psycopg2_conn_default_pool", marks=pytest.mark.db),
985+
]
986+
918987
postgresql_connectable_iris = [
919988
pytest.param("postgresql_psycopg2_engine_iris", marks=pytest.mark.db),
920989
pytest.param("postgresql_psycopg2_conn_iris", marks=pytest.mark.db),
@@ -931,6 +1000,11 @@ def sqlite_buildin_types(sqlite_buildin, types_data):
9311000
"sqlite_str",
9321001
]
9331002

1003+
sqlite_connectable_default_pool = [
1004+
"sqlite_engine_default_pool",
1005+
"sqlite_conn_default_pool",
1006+
]
1007+
9341008
sqlite_connectable_iris = [
9351009
"sqlite_engine_iris",
9361010
"sqlite_conn_iris",
@@ -945,6 +1019,12 @@ def sqlite_buildin_types(sqlite_buildin, types_data):
9451019

9461020
sqlalchemy_connectable = mysql_connectable + postgresql_connectable + sqlite_connectable
9471021

1022+
sqlalchemy_connectable_default_pool = (
1023+
mysql_connectable_default_pool
1024+
+ postgresql_connectable_default_pool
1025+
+ sqlite_connectable_default_pool
1026+
)
1027+
9481028
sqlalchemy_connectable_iris = (
9491029
mysql_connectable_iris + postgresql_connectable_iris + sqlite_connectable_iris
9501030
)
@@ -1135,7 +1215,6 @@ def test_read_iris_query_expression_with_parameter(conn, request):
11351215
from sqlalchemy import (
11361216
MetaData,
11371217
Table,
1138-
create_engine,
11391218
select,
11401219
)
11411220

@@ -1250,7 +1329,6 @@ def test_read_procedure(conn, request):
12501329
# GH 7324
12511330
# Although it is more an api test, it is added to the
12521331
# mysql tests as sqlite does not have stored procedures
1253-
from sqlalchemy.engine import Engine
12541332

12551333
df = DataFrame({"a": [1, 2, 3], "b": [0.1, 0.2, 0.3]})
12561334
df.to_sql(name="test_frame", con=conn, index=False)
@@ -1324,7 +1402,6 @@ def test_insertion_method_on_conflict_do_nothing(conn, request):
13241402
conn = request.getfixturevalue(conn)
13251403

13261404
from sqlalchemy.dialects.postgresql import insert
1327-
from sqlalchemy.engine import Engine
13281405
from sqlalchemy.sql import text
13291406

13301407
def insert_on_conflict(table, conn, keys, data_iter):
@@ -1406,7 +1483,6 @@ def test_insertion_method_on_conflict_update(conn, request):
14061483
conn = request.getfixturevalue(conn)
14071484

14081485
from sqlalchemy.dialects.mysql import insert
1409-
from sqlalchemy.engine import Engine
14101486
from sqlalchemy.sql import text
14111487

14121488
def insert_on_conflict(table, conn, keys, data_iter):
@@ -1458,7 +1534,6 @@ def test_read_view_postgres(conn, request):
14581534
# GH 52969
14591535
conn = request.getfixturevalue(conn)
14601536

1461-
from sqlalchemy.engine import Engine
14621537
from sqlalchemy.sql import text
14631538

14641539
table_name = f"group_{uuid.uuid4().hex}"
@@ -2389,7 +2464,6 @@ def test_read_sql_delegate(conn, request):
23892464

23902465
def test_not_reflect_all_tables(sqlite_conn):
23912466
conn = sqlite_conn
2392-
from sqlalchemy.engine import Engine
23932467

23942468
# create invalid table
23952469
query_list = [
@@ -3199,8 +3273,6 @@ def test_get_schema_create_table(conn, request, test_frame3):
31993273

32003274
conn = request.getfixturevalue(conn)
32013275

3202-
from sqlalchemy.engine import Engine
3203-
32043276
tbl = "test_get_schema_create_table"
32053277
create_sql = sql.get_schema(test_frame3, tbl, con=conn)
32063278
blank_test_df = test_frame3.iloc[:0]
@@ -3353,7 +3425,6 @@ def test_connectable_issue_example(conn, request):
33533425

33543426
# This tests the example raised in issue
33553427
# https://github.com/pandas-dev/pandas/issues/10104
3356-
from sqlalchemy.engine import Engine
33573428

33583429
def test_select(connection):
33593430
query = "SELECT test_foo_data FROM test_foo_data"
@@ -4356,7 +4427,7 @@ def test_xsqlite_if_exists(sqlite_buildin):
43564427
drop_table(table_name, sqlite_buildin)
43574428

43584429

4359-
@pytest.mark.parametrize("conn", sqlalchemy_connectable)
4430+
@pytest.mark.parametrize("conn", sqlalchemy_connectable_default_pool)
43604431
def test_exists_temporary_table(conn, test_frame1, request):
43614432
conn = request.getfixturevalue(conn)
43624433

@@ -4375,56 +4446,38 @@ def test_exists_temporary_table(conn, test_frame1, request):
43754446
assert True if table.exists() else False
43764447

43774448

4378-
@pytest.mark.parametrize("conn", sqlalchemy_connectable)
4449+
@pytest.mark.parametrize("conn", sqlalchemy_connectable_default_pool)
43794450
def test_to_sql_temporary_table_replace(conn, test_frame1, request):
43804451
conn = request.getfixturevalue(conn)
43814452

4382-
# some DBMS only allow temporary tables to exist within a connection, therefore
4383-
# we can only test for a connection and not all types of connectables.
4384-
if isinstance(conn, Engine):
4385-
con = conn.connect()
4386-
elif isinstance(conn, str):
4387-
con = create_engine(conn).connect()
4388-
else:
4389-
con = conn
4390-
43914453
test_frame1.to_sql(
43924454
name="test_frame1",
4393-
con=con,
4455+
con=conn,
43944456
if_exists="fail",
43954457
index=False,
43964458
prefixes=["TEMPORARY"],
43974459
)
43984460

43994461
test_frame1.to_sql(
44004462
name="test_frame1",
4401-
con=con,
4463+
con=conn,
44024464
if_exists="replace",
44034465
index=False,
44044466
prefixes=["TEMPORARY"],
44054467
)
44064468

4407-
df_test = pd.read_sql("SELECT * FROM test_frame1", con)
4469+
df_test = pd.read_sql("SELECT * FROM test_frame1", conn)
44084470

44094471
assert_frame_equal(test_frame1, df_test)
44104472

44114473

4412-
@pytest.mark.parametrize("conn", sqlalchemy_connectable)
4474+
@pytest.mark.parametrize("conn", sqlalchemy_connectable_default_pool)
44134475
def test_to_sql_temporary_table_fail(conn, test_frame1, request):
44144476
conn = request.getfixturevalue(conn)
44154477

4416-
# some DBMS only allow temporary tables to exist within a connection, therefore
4417-
# we can only test for a connection and not all types of connectables.
4418-
if isinstance(conn, Engine):
4419-
con = conn.connect()
4420-
elif isinstance(conn, str):
4421-
con = create_engine(conn).connect()
4422-
else:
4423-
con = conn
4424-
44254478
test_frame1.to_sql(
44264479
name="test_frame1",
4427-
con=con,
4480+
con=conn,
44284481
if_exists="fail",
44294482
index=False,
44304483
prefixes=["TEMPORARY"],
@@ -4433,8 +4486,37 @@ def test_to_sql_temporary_table_fail(conn, test_frame1, request):
44334486
with pytest.raises(ValueError, match=r"Table 'test_frame1' already exists."):
44344487
test_frame1.to_sql(
44354488
name="test_frame1",
4436-
con=con,
4489+
con=conn,
44374490
if_exists="fail",
44384491
index=False,
44394492
prefixes=["TEMPORARY"],
44404493
)
4494+
4495+
4496+
@pytest.mark.parametrize("conn", sqlalchemy_connectable_default_pool)
4497+
def test_to_sql_temporary_table_append(conn, test_frame1, request):
4498+
conn = request.getfixturevalue(conn)
4499+
4500+
test_frame1.to_sql(
4501+
name="test_frame1",
4502+
con=conn,
4503+
if_exists="fail",
4504+
index=False,
4505+
prefixes=["TEMPORARY"],
4506+
)
4507+
4508+
test_frame1.to_sql(
4509+
name="test_frame1",
4510+
con=conn,
4511+
if_exists="append",
4512+
index=False,
4513+
prefixes=["TEMPORARY"],
4514+
)
4515+
4516+
df_test = pd.read_sql("SELECT * FROM test_frame1", conn)
4517+
4518+
df_true = concat([test_frame1, test_frame1], axis=0, ignore_index=True).reset_index(
4519+
drop=True
4520+
)
4521+
4522+
assert_frame_equal(df_true, df_test)

0 commit comments

Comments
 (0)