Skip to content

Commit 7c4b6bd

Browse files
authored
SNOW-630797 Support table_type in pandas_tools (#1216)
* SNOW-630797 Support table_type in pandas_tools Description table_type could support transient table as well, which is more flexible comparing to create_temp_table Testing Added integ test * Add negative test * type hint + revert undesired test param change * import Literal from typing_extensions * refactor tests * assert success + various table name * use random_string
1 parent 0aec3ef commit 7c4b6bd

File tree

2 files changed

+97
-2
lines changed

2 files changed

+97
-2
lines changed

src/snowflake/connector/pandas_tools.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@
88
import os
99
import random
1010
import string
11+
import warnings
1112
from functools import partial
1213
from logging import getLogger
1314
from tempfile import TemporaryDirectory
1415
from typing import TYPE_CHECKING, Callable, Iterable, Iterator, Sequence, TypeVar
1516

17+
from typing_extensions import Literal
18+
1619
from snowflake.connector import ProgrammingError
1720
from snowflake.connector.options import pandas
1821

@@ -49,6 +52,7 @@ def write_pandas(
4952
auto_create_table: bool = False,
5053
create_temp_table: bool = False,
5154
overwrite: bool = False,
55+
table_type: Literal["", "temp", "temporary", "transient"] = "",
5256
) -> tuple[
5357
bool,
5458
int,
@@ -102,10 +106,12 @@ def write_pandas(
102106
I.e. identifiers will be coerced to uppercase by Snowflake. (Default value = True)
103107
auto_create_table: When true, will automatically create a table with corresponding columns for each column in
104108
the passed in DataFrame. The table will not be created if it already exists
105-
create_temp_table: Will make the auto-created table as a temporary table
109+
create_temp_table: (Deprecated) Will make the auto-created table as a temporary table
106110
overwrite: When true, and if auto_create_table is true, then it drops the table. Otherwise, it
107111
truncates the table. In both cases it will replace the existing contents of the table with that of the passed in
108112
Pandas DataFrame.
113+
table_type: The table type of to-be-created table. The supported table types include ``temp``/``temporary``
114+
and ``transient``. Empty means permanent table as per SQL convention.
109115
110116
Returns:
111117
Returns the COPY INTO command's results to verify ingestion in the form of a tuple of whether all chunks were
@@ -124,6 +130,22 @@ def write_pandas(
124130
compression, compression_map.keys()
125131
)
126132
)
133+
134+
if create_temp_table:
135+
warnings.warn(
136+
"create_temp_table is deprecated, we still respect this parameter when it is True but "
137+
'please consider using `table_type="temp"` instead',
138+
DeprecationWarning,
139+
# warnings.warn -> write_pandas
140+
stacklevel=2,
141+
)
142+
table_type = "temp"
143+
144+
if table_type and table_type.lower() not in ["temp", "temporary", "transient"]:
145+
raise ValueError(
146+
"Unsupported table type. Expected table types: temp/temporary, transient"
147+
)
148+
127149
if quote_identifiers:
128150
location = (
129151
(('"' + database + '".') if database else "")
@@ -224,7 +246,7 @@ def write_pandas(
224246
[f"{quote}{c}{quote} {column_type_mapping[c]}" for c in df.columns]
225247
)
226248
create_table_sql = (
227-
f"CREATE {'TEMP ' if create_temp_table else ''}TABLE IF NOT EXISTS {location} "
249+
f"CREATE {table_type.upper()} TABLE IF NOT EXISTS {location} "
228250
f"({create_table_columns})"
229251
f" /* Python:snowflake.connector.pandas_tools.write_pandas() */ "
230252
)

test/integ/pandas/test_pandas_tools.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,79 @@ def test_write_pandas(
219219
cnx.execute_string(drop_sql)
220220

221221

222+
@pytest.mark.parametrize("table_type", ["", "temp", "temporary", "transient"])
223+
def test_write_pandas_table_type(
224+
conn_cnx: Callable[..., Generator[SnowflakeConnection, None, None]],
225+
table_type: str,
226+
):
227+
with conn_cnx() as cnx:
228+
table_name = random_string(5, "write_pandas_table_type_")
229+
drop_sql = f"DROP TABLE IF EXISTS {table_name}"
230+
try:
231+
success, _, _, _ = write_pandas(
232+
cnx,
233+
sf_connector_version_df.get(),
234+
table_name,
235+
table_type=table_type,
236+
auto_create_table=True,
237+
)
238+
table_info = (
239+
cnx.cursor(DictCursor)
240+
.execute(f"show tables like '{table_name}'")
241+
.fetchall()
242+
)
243+
assert success
244+
if not table_type:
245+
expected_table_kind = "TABLE"
246+
elif table_type == "temp":
247+
expected_table_kind = "TEMPORARY"
248+
else:
249+
expected_table_kind = table_type.upper()
250+
assert table_info[0]["kind"] == expected_table_kind
251+
finally:
252+
cnx.execute_string(drop_sql)
253+
254+
255+
def test_write_pandas_create_temp_table_deprecation_warning(
256+
conn_cnx: Callable[..., Generator[SnowflakeConnection, None, None]],
257+
):
258+
with conn_cnx() as cnx:
259+
table_name = random_string(5, "driver_versions_")
260+
drop_sql = f"DROP TABLE IF EXISTS {table_name}"
261+
try:
262+
with pytest.deprecated_call(match="create_temp_table is deprecated"):
263+
success, _, _, _ = write_pandas(
264+
cnx,
265+
sf_connector_version_df.get(),
266+
table_name,
267+
create_temp_table=True,
268+
auto_create_table=True,
269+
)
270+
271+
assert success
272+
table_info = (
273+
cnx.cursor(DictCursor)
274+
.execute(f"show tables like '{table_name}'")
275+
.fetchall()
276+
)
277+
assert table_info[0]["kind"] == "TEMPORARY"
278+
finally:
279+
cnx.execute_string(drop_sql)
280+
281+
282+
def test_invalid_table_type_write_pandas(
283+
conn_cnx: Callable[..., Generator[SnowflakeConnection, None, None]],
284+
):
285+
with conn_cnx() as cnx:
286+
with pytest.raises(ValueError, match="Unsupported table type"):
287+
write_pandas(
288+
cnx,
289+
sf_connector_version_df.get(),
290+
"invalid_table_type",
291+
table_type="invalid",
292+
)
293+
294+
222295
@pytest.mark.parametrize("quote_identifiers", [True, False])
223296
def test_location_building_db_schema(conn_cnx, quote_identifiers: bool):
224297
"""This tests that write_pandas constructs location correctly with database, schema and table name."""

0 commit comments

Comments
 (0)