diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index ac930b3e77785..1cebb8bcf3b1c 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -260,6 +260,7 @@ Other enhancements - Added :meth:`~DataFrame.set_flags` for setting table-wide flags on a Series or DataFrame (:issue:`28394`) - :meth:`DataFrame.applymap` now supports ``na_action`` (:issue:`23803`) - :class:`Index` with object dtype supports division and multiplication (:issue:`34160`) +- :meth:`io.sql.get_schema` now supports a ``schema`` keyword argument that will add a schema into the create table statement (:issue:`28486`) - :meth:`DataFrame.explode` and :meth:`Series.explode` now support exploding of sets (:issue:`35614`) - :meth:`DataFrame.hist` now supports time series (datetime) data (:issue:`32590`) - :meth:`.Styler.set_table_styles` now allows the direct styling of rows and columns and can be chained (:issue:`35607`) diff --git a/pandas/io/sql.py b/pandas/io/sql.py index 1fea50ecade3c..5678133d5a706 100644 --- a/pandas/io/sql.py +++ b/pandas/io/sql.py @@ -7,7 +7,7 @@ from datetime import date, datetime, time from functools import partial import re -from typing import Iterator, Optional, Union, overload +from typing import Iterator, List, Optional, Union, overload import warnings import numpy as np @@ -1455,9 +1455,22 @@ def drop_table(self, table_name, schema=None): self.get_table(table_name, schema).drop() self.meta.clear() - def _create_sql_schema(self, frame, table_name, keys=None, dtype=None): + def _create_sql_schema( + self, + frame: DataFrame, + table_name: str, + keys: Optional[List[str]] = None, + dtype: Optional[dict] = None, + schema: Optional[str] = None, + ): table = SQLTable( - table_name, self, frame=frame, index=False, keys=keys, dtype=dtype + table_name, + self, + frame=frame, + index=False, + keys=keys, + dtype=dtype, + schema=schema, ) return str(table.sql_schema()) @@ -1588,9 +1601,13 @@ def _create_table_setup(self): create_tbl_stmts.append( f"CONSTRAINT {self.name}_pk PRIMARY KEY ({cnames_br})" ) - + if self.schema: + schema_name = self.schema + "." + else: + schema_name = "" create_stmts = [ "CREATE TABLE " + + schema_name + escape(self.name) + " (\n" + ",\n ".join(create_tbl_stmts) @@ -1845,14 +1862,20 @@ def drop_table(self, name, schema=None): drop_sql = f"DROP TABLE {_get_valid_sqlite_name(name)}" self.execute(drop_sql) - def _create_sql_schema(self, frame, table_name, keys=None, dtype=None): + def _create_sql_schema(self, frame, table_name, keys=None, dtype=None, schema=None): table = SQLiteTable( - table_name, self, frame=frame, index=False, keys=keys, dtype=dtype + table_name, + self, + frame=frame, + index=False, + keys=keys, + dtype=dtype, + schema=schema, ) return str(table.sql_schema()) -def get_schema(frame, name, keys=None, con=None, dtype=None): +def get_schema(frame, name, keys=None, con=None, dtype=None, schema=None): """ Get the SQL db table schema for the given frame. @@ -1870,7 +1893,12 @@ def get_schema(frame, name, keys=None, con=None, dtype=None): dtype : 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. + schema: str, default: None + Optional specifying the schema to be used in creating the table. + .. versionadded:: 1.2.0 """ pandas_sql = pandasSQL_builder(con=con) - return pandas_sql._create_sql_schema(frame, name, keys=keys, dtype=dtype) + return pandas_sql._create_sql_schema( + frame, name, keys=keys, dtype=dtype, schema=schema + ) diff --git a/pandas/tests/io/test_sql.py b/pandas/tests/io/test_sql.py index 1be6022bc0fcd..0195b61d13798 100644 --- a/pandas/tests/io/test_sql.py +++ b/pandas/tests/io/test_sql.py @@ -865,6 +865,13 @@ def test_get_schema(self): create_sql = sql.get_schema(self.test_frame1, "test", con=self.conn) assert "CREATE" in create_sql + def test_get_schema_with_schema(self): + # GH28486 + create_sql = sql.get_schema( + self.test_frame1, "test", con=self.conn, schema="pypi" + ) + assert "CREATE TABLE pypi." in create_sql + def test_get_schema_dtypes(self): float_frame = DataFrame({"a": [1.1, 1.2], "b": [2.1, 2.2]}) dtype = sqlalchemy.Integer if self.mode == "sqlalchemy" else "INTEGER"