@@ -38,7 +38,7 @@ class DatabaseError(IOError):
38
38
_SQLALCHEMY_INSTALLED = None
39
39
40
40
41
- def _is_sqlalchemy_engine (con ):
41
+ def _is_sqlalchemy_connectable (con ):
42
42
global _SQLALCHEMY_INSTALLED
43
43
if _SQLALCHEMY_INSTALLED is None :
44
44
try :
@@ -62,7 +62,7 @@ def compile_big_int_sqlite(type_, compiler, **kw):
62
62
63
63
if _SQLALCHEMY_INSTALLED :
64
64
import sqlalchemy
65
- return isinstance (con , sqlalchemy .engine .Engine )
65
+ return isinstance (con , sqlalchemy .engine .Connectable )
66
66
else :
67
67
return False
68
68
@@ -139,7 +139,7 @@ def execute(sql, con, cur=None, params=None):
139
139
----------
140
140
sql : string
141
141
Query to be executed
142
- con : SQLAlchemy engine or sqlite3 DBAPI2 connection
142
+ con : SQLAlchemy connectable( engine/connection) or sqlite3 DBAPI2 connection
143
143
Using SQLAlchemy makes it possible to use any DB supported by that
144
144
library.
145
145
If a DBAPI2 object, only sqlite3 is supported.
@@ -282,14 +282,14 @@ def read_sql_table(table_name, con, schema=None, index_col=None,
282
282
chunksize = None ):
283
283
"""Read SQL database table into a DataFrame.
284
284
285
- Given a table name and an SQLAlchemy engine , returns a DataFrame.
285
+ Given a table name and an SQLAlchemy connectable , returns a DataFrame.
286
286
This function does not support DBAPI connections.
287
287
288
288
Parameters
289
289
----------
290
290
table_name : string
291
291
Name of SQL table in database
292
- con : SQLAlchemy engine
292
+ con : SQLAlchemy connectable
293
293
Sqlite DBAPI connection mode not supported
294
294
schema : string, default None
295
295
Name of SQL schema in database to query (if database flavor
@@ -328,9 +328,9 @@ def read_sql_table(table_name, con, schema=None, index_col=None,
328
328
read_sql
329
329
330
330
"""
331
- if not _is_sqlalchemy_engine (con ):
331
+ if not _is_sqlalchemy_connectable (con ):
332
332
raise NotImplementedError ("read_sql_table only supported for "
333
- "SQLAlchemy engines ." )
333
+ "SQLAlchemy connectable ." )
334
334
import sqlalchemy
335
335
from sqlalchemy .schema import MetaData
336
336
meta = MetaData (con , schema = schema )
@@ -362,7 +362,7 @@ def read_sql_query(sql, con, index_col=None, coerce_float=True, params=None,
362
362
----------
363
363
sql : string
364
364
SQL query to be executed
365
- con : SQLAlchemy engine or sqlite3 DBAPI2 connection
365
+ con : SQLAlchemy connectable( engine/connection) or sqlite3 DBAPI2 connection
366
366
Using SQLAlchemy makes it possible to use any DB supported by that
367
367
library.
368
368
If a DBAPI2 object, only sqlite3 is supported.
@@ -420,7 +420,7 @@ def read_sql(sql, con, index_col=None, coerce_float=True, params=None,
420
420
----------
421
421
sql : string
422
422
SQL query to be executed or database table name.
423
- con : SQLAlchemy engine or DBAPI2 connection (fallback mode)
423
+ con : SQLAlchemy connectable( engine/connection) or DBAPI2 connection (fallback mode)
424
424
Using SQLAlchemy makes it possible to use any DB supported by that
425
425
library.
426
426
If a DBAPI2 object, only sqlite3 is supported.
@@ -504,14 +504,14 @@ def to_sql(frame, name, con, flavor='sqlite', schema=None, if_exists='fail',
504
504
frame : DataFrame
505
505
name : string
506
506
Name of SQL table
507
- con : SQLAlchemy engine or sqlite3 DBAPI2 connection
507
+ con : SQLAlchemy connectable( engine/connection) or sqlite3 DBAPI2 connection
508
508
Using SQLAlchemy makes it possible to use any DB supported by that
509
509
library.
510
510
If a DBAPI2 object, only sqlite3 is supported.
511
511
flavor : {'sqlite', 'mysql'}, default 'sqlite'
512
- The flavor of SQL to use. Ignored when using SQLAlchemy engine .
512
+ The flavor of SQL to use. Ignored when using SQLAlchemy connectable .
513
513
'mysql' is deprecated and will be removed in future versions, but it
514
- will be further supported through SQLAlchemy engines .
514
+ will be further supported through SQLAlchemy connectables .
515
515
schema : string, default None
516
516
Name of SQL schema in database to write to (if database flavor
517
517
supports this). If None, use default schema (default).
@@ -557,14 +557,14 @@ def has_table(table_name, con, flavor='sqlite', schema=None):
557
557
----------
558
558
table_name: string
559
559
Name of SQL table
560
- con: SQLAlchemy engine or sqlite3 DBAPI2 connection
560
+ con: SQLAlchemy connectable( engine/connection) or sqlite3 DBAPI2 connection
561
561
Using SQLAlchemy makes it possible to use any DB supported by that
562
562
library.
563
563
If a DBAPI2 object, only sqlite3 is supported.
564
564
flavor: {'sqlite', 'mysql'}, default 'sqlite'
565
- The flavor of SQL to use. Ignored when using SQLAlchemy engine .
565
+ The flavor of SQL to use. Ignored when using SQLAlchemy connectable .
566
566
'mysql' is deprecated and will be removed in future versions, but it
567
- will be further supported through SQLAlchemy engines .
567
+ will be further supported through SQLAlchemy connectables .
568
568
schema : string, default None
569
569
Name of SQL schema in database to write to (if database flavor supports
570
570
this). If None, use default schema (default).
@@ -581,7 +581,7 @@ def has_table(table_name, con, flavor='sqlite', schema=None):
581
581
582
582
_MYSQL_WARNING = ("The 'mysql' flavor with DBAPI connection is deprecated "
583
583
"and will be removed in future versions. "
584
- "MySQL will be further supported with SQLAlchemy engines ." )
584
+ "MySQL will be further supported with SQLAlchemy connectables ." )
585
585
586
586
587
587
def pandasSQL_builder (con , flavor = None , schema = None , meta = None ,
@@ -592,7 +592,7 @@ def pandasSQL_builder(con, flavor=None, schema=None, meta=None,
592
592
"""
593
593
# When support for DBAPI connections is removed,
594
594
# is_cursor should not be necessary.
595
- if _is_sqlalchemy_engine (con ):
595
+ if _is_sqlalchemy_connectable (con ):
596
596
return SQLDatabase (con , schema = schema , meta = meta )
597
597
else :
598
598
if flavor == 'mysql' :
@@ -637,7 +637,7 @@ def exists(self):
637
637
638
638
def sql_schema (self ):
639
639
from sqlalchemy .schema import CreateTable
640
- return str (CreateTable (self .table ).compile (self .pd_sql .engine ))
640
+ return str (CreateTable (self .table ).compile (self .pd_sql .connectable ))
641
641
642
642
def _execute_create (self ):
643
643
# Inserting table into database, add to MetaData object
@@ -982,11 +982,11 @@ class PandasSQL(PandasObject):
982
982
"""
983
983
984
984
def read_sql (self , * args , ** kwargs ):
985
- raise ValueError ("PandasSQL must be created with an SQLAlchemy engine "
985
+ raise ValueError ("PandasSQL must be created with an SQLAlchemy connectable "
986
986
" or connection+sql flavor" )
987
987
988
988
def to_sql (self , * args , ** kwargs ):
989
- raise ValueError ("PandasSQL must be created with an SQLAlchemy engine "
989
+ raise ValueError ("PandasSQL must be created with an SQLAlchemy connectable "
990
990
" or connection+sql flavor" )
991
991
992
992
@@ -997,8 +997,8 @@ class SQLDatabase(PandasSQL):
997
997
998
998
Parameters
999
999
----------
1000
- engine : SQLAlchemy engine
1001
- Engine to connect with the database. Using SQLAlchemy makes it
1000
+ engine : SQLAlchemy connectable
1001
+ Connectable to connect with the database. Using SQLAlchemy makes it
1002
1002
possible to use any DB supported by that library.
1003
1003
schema : string, default None
1004
1004
Name of SQL schema in database to write to (if database flavor
@@ -1011,19 +1011,24 @@ class SQLDatabase(PandasSQL):
1011
1011
"""
1012
1012
1013
1013
def __init__ (self , engine , schema = None , meta = None ):
1014
- self .engine = engine
1014
+ self .connectable = engine
1015
1015
if not meta :
1016
1016
from sqlalchemy .schema import MetaData
1017
- meta = MetaData (self .engine , schema = schema )
1017
+ meta = MetaData (self .connectable , schema = schema )
1018
1018
1019
1019
self .meta = meta
1020
1020
1021
+ @contextmanager
1021
1022
def run_transaction (self ):
1022
- return self .engine .begin ()
1023
+ with self .connectable .begin () as tx :
1024
+ if hasattr (tx , 'execute' ):
1025
+ yield tx
1026
+ else :
1027
+ yield self .connectable
1023
1028
1024
1029
def execute (self , * args , ** kwargs ):
1025
- """Simple passthrough to SQLAlchemy engine """
1026
- return self .engine .execute (* args , ** kwargs )
1030
+ """Simple passthrough to SQLAlchemy connectable """
1031
+ return self .connectable .execute (* args , ** kwargs )
1027
1032
1028
1033
def read_table (self , table_name , index_col = None , coerce_float = True ,
1029
1034
parse_dates = None , columns = None , schema = None ,
@@ -1191,7 +1196,13 @@ def to_sql(self, frame, name, if_exists='fail', index=True,
1191
1196
table .create ()
1192
1197
table .insert (chunksize )
1193
1198
# check for potentially case sensitivity issues (GH7815)
1194
- if name not in self .engine .table_names (schema = schema or self .meta .schema ):
1199
+ engine = self .connectable .engine
1200
+ with self .connectable .connect () as conn :
1201
+ table_names = engine .table_names (
1202
+ schema = schema or self .meta .schema ,
1203
+ connection = conn ,
1204
+ )
1205
+ if name not in table_names :
1195
1206
warnings .warn ("The provided table name '{0}' is not found exactly "
1196
1207
"as such in the database after writing the table, "
1197
1208
"possibly due to case sensitivity issues. Consider "
@@ -1202,7 +1213,11 @@ def tables(self):
1202
1213
return self .meta .tables
1203
1214
1204
1215
def has_table (self , name , schema = None ):
1205
- return self .engine .has_table (name , schema or self .meta .schema )
1216
+ return self .connectable .run_callable (
1217
+ self .connectable .dialect .has_table ,
1218
+ name ,
1219
+ schema or self .meta .schema ,
1220
+ )
1206
1221
1207
1222
def get_table (self , table_name , schema = None ):
1208
1223
schema = schema or self .meta .schema
@@ -1221,7 +1236,7 @@ def get_table(self, table_name, schema=None):
1221
1236
1222
1237
def drop_table (self , table_name , schema = None ):
1223
1238
schema = schema or self .meta .schema
1224
- if self .engine . has_table (table_name , schema ):
1239
+ if self .has_table (table_name , schema ):
1225
1240
self .meta .reflect (only = [table_name ], schema = schema )
1226
1241
self .get_table (table_name , schema ).drop ()
1227
1242
self .meta .clear ()
@@ -1610,12 +1625,12 @@ def get_schema(frame, name, flavor='sqlite', keys=None, con=None, dtype=None):
1610
1625
name : string
1611
1626
name of SQL table
1612
1627
flavor : {'sqlite', 'mysql'}, default 'sqlite'
1613
- The flavor of SQL to use. Ignored when using SQLAlchemy engine .
1628
+ The flavor of SQL to use. Ignored when using SQLAlchemy connectable .
1614
1629
'mysql' is deprecated and will be removed in future versions, but it
1615
1630
will be further supported through SQLAlchemy engines.
1616
1631
keys : string or sequence
1617
1632
columns to use a primary key
1618
- con: an open SQL database connection object or an SQLAlchemy engine
1633
+ con: an open SQL database connection object or a SQLAlchemy connectable
1619
1634
Using SQLAlchemy makes it possible to use any DB supported by that
1620
1635
library.
1621
1636
If a DBAPI2 object, only sqlite3 is supported.
@@ -1673,8 +1688,8 @@ def write_frame(frame, name, con, flavor='sqlite', if_exists='fail', **kwargs):
1673
1688
1674
1689
- With ``to_sql`` the index is written to the sql database by default. To
1675
1690
keep the behaviour this function you need to specify ``index=False``.
1676
- - The new ``to_sql`` function supports sqlalchemy engines to work with
1677
- different sql flavors.
1691
+ - The new ``to_sql`` function supports sqlalchemy connectables to work
1692
+ with different sql flavors.
1678
1693
1679
1694
See also
1680
1695
--------
0 commit comments