Skip to content

Commit

Permalink
ENH: Allow to_sql to recognize single sql type pandas-dev#11886
Browse files Browse the repository at this point in the history
ENH: support decimal option in PythonParser pandas-dev#12933

closes pandas-dev#12933

Author: Camilo Cota <ccota@riplife.es>

Closes pandas-dev#13189 from camilocot/12933 and squashes the following commits:

465272e [Camilo Cota] Benchmark decimal option in read_csv for c engine
9f42d0c [Camilo Cota] double backticks around decimal and engine='python'
dc8ca62 [Camilo Cota] fix test_empty_decimal_marker comment
49613fe [Camilo Cota] Assert read_csv error message in test_empty_decimal_marker
d821052 [Camilo Cota] fix test_empty_decimal_marker comment
f71509d [Camilo Cota] Include descritive what's new line
803356e [Camilo Cota] set nonnum regex in init method
1472d80 [Camilo Cota] Include the issue number in what's new
b560fda [Camilo Cota] Fix what's new
dc7acd1 [Camilo Cota] ENH: support decimal option in PythonParser pandas-dev#12933

ENH: Allow to_sql to recognize single sql type pandas-dev#11886

PEP pandas-dev#3
  • Loading branch information
RahulHP committed May 28, 2016
1 parent ae2ca83 commit 9d7c7f6
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 17 deletions.
4 changes: 3 additions & 1 deletion doc/source/whatsnew/v0.18.2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ Other enhancements

pd.Timestamp(year=2012, month=1, day=1, hour=8, minute=30)

- ``DataFrame.to_sql `` now allows a single value as the SQL type for all columns (:issue:`11886`).

- The ``pd.read_csv()`` with ``engine='python'`` has gained support for the ``decimal`` option (:issue:`12933`)

- ``Index.astype()`` now accepts an optional boolean argument ``copy``, which allows optional copying if the requirements on dtype are satisfied (:issue:`13209`)
Expand All @@ -89,7 +91,7 @@ Other enhancements

- ``pd.read_html()`` has gained support for the ``decimal`` option (:issue:`12907`)


- ``DataFrame.to_sql `` now allows a single value as the SQL type for all columns (:issue:`11886`).

.. _whatsnew_0182.api:

Expand Down
21 changes: 16 additions & 5 deletions pandas/io/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
string_types, text_type)
from pandas.core.api import DataFrame, Series
from pandas.core.common import isnull
from pandas.core.generic import is_dictlike
from pandas.core.base import PandasObject
from pandas.types.api import DatetimeTZDtype
from pandas.tseries.tools import to_datetime
Expand Down Expand Up @@ -550,9 +551,10 @@ def to_sql(frame, name, con, flavor='sqlite', schema=None, if_exists='fail',
chunksize : int, default None
If not None, then rows will be written in batches of this size at a
time. If None, all rows will be written at once.
dtype : dict of column name to SQL type, default None
dtype : single SQLtype or dict of column name to SQL type, default None
Optional specifying the datatype for columns. The SQL type should
be a SQLAlchemy type, or a string for sqlite3 fallback connection.
If all columns are of the same type, one single value can be used.
"""
if if_exists not in ('fail', 'replace', 'append'):
Expand Down Expand Up @@ -1231,11 +1233,16 @@ def to_sql(self, frame, name, if_exists='fail', index=True,
chunksize : int, default None
If not None, then rows will be written in batches of this size at a
time. If None, all rows will be written at once.
dtype : dict of column name to SQL type, default None
dtype : single SQL type or dict of column name to SQL type, default
None
Optional specifying the datatype for columns. The SQL type should
be a SQLAlchemy type.
be a SQLAlchemy type. If all columns are of the same type, one
single value can be used.
"""
if dtype and not is_dictlike(dtype):
dtype = {col_name: dtype for col_name in frame}

if dtype is not None:
from sqlalchemy.types import to_instance, TypeEngine
for col, my_type in dtype.items():
Expand Down Expand Up @@ -1644,11 +1651,15 @@ def to_sql(self, frame, name, if_exists='fail', index=True,
chunksize : int, default None
If not None, then rows will be written in batches of this
size at a time. If None, all rows will be written at once.
dtype : dict of column name to SQL type, default None
dtype : single SQL type or dict of column name to SQL type, default
None
Optional specifying the datatype for columns. The SQL type should
be a string.
be a string. If all columns are of the same type, one single value
can be used.
"""
if dtype and not is_dictlike(dtype):
dtype = {col_name: dtype for col_name in frame}
if dtype is not None:
for col, my_type in dtype.items():
if not isinstance(my_type, str):
Expand Down
22 changes: 11 additions & 11 deletions pandas/io/tests/parser/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1302,17 +1302,17 @@ def test_read_duplicate_names(self):

def test_inf_parsing(self):
data = """\
,A
a,inf
b,-inf
c,+Inf
d,-Inf
e,INF
f,-INF
g,+INf
h,-INf
i,inF
j,-inF"""
,A
a,inf
b,-inf
c,+Inf
d,-Inf
e,INF
f,-INF
g,+INf
h,-INf
i,inF
j,-inF"""
inf = float('inf')
expected = Series([inf, -inf] * 5)

Expand Down
28 changes: 28 additions & 0 deletions pandas/io/tests/test_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -1552,6 +1552,19 @@ def test_dtype(self):
self.assertTrue(isinstance(sqltype, sqlalchemy.String))
self.assertEqual(sqltype.length, 10)

def test_to_sql_single_dtype(self):
cols = ['A', 'B']
data = [('a', 'b'),
('c', 'd')]
df = DataFrame(data, columns=cols)
df.to_sql('single_dtype_test', self.conn, dtype=sqlalchemy.TEXT)
meta = sqlalchemy.schema.MetaData(bind=self.conn)
meta.reflect()
sqltypea = meta.tables['single_dtype_test'].columns['A'].type
sqltypeb = meta.tables['single_dtype_test'].columns['B'].type
self.assertTrue(isinstance(sqltypea, sqlalchemy.TEXT))
self.assertTrue(isinstance(sqltypeb, sqlalchemy.TEXT))

def test_notnull_dtype(self):
cols = {'Bool': Series([True, None]),
'Date': Series([datetime(2012, 5, 1), None]),
Expand Down Expand Up @@ -2025,6 +2038,21 @@ def test_dtype(self):
self.assertRaises(ValueError, df.to_sql,
'error', self.conn, dtype={'B': bool})

def test_to_sql_single_dtype(self):
if self.flavor == 'mysql':
raise nose.SkipTest('Not applicable to MySQL legacy')
self.drop_table('single_dtype_test')
cols = ['A', 'B']
data = [('a', 'b'),
('c', 'd')]
df = DataFrame(data, columns=cols)
df.to_sql('single_dtype_test', self.conn, dtype='STRING')
self.assertEqual(
self._get_sqlite_column_type('single_dtype_test', 'A'), 'STRING')
self.assertEqual(
self._get_sqlite_column_type('single_dtype_test', 'B'), 'STRING')
self.drop_table('single_dtype_test')

def test_notnull_dtype(self):
if self.flavor == 'mysql':
raise nose.SkipTest('Not applicable to MySQL legacy')
Expand Down

0 comments on commit 9d7c7f6

Please sign in to comment.