Skip to content

Commit 3823216

Browse files
Fix write_pandas() truncate-only flow to prevent CREATE TABLE IF NOT EXISTS (#1899)
* Fix write_pandas() truncate-only flow to prevent CREATE TABLE IF NOT EXISTS * Updated DESCRIPTION.md
1 parent 6d325aa commit 3823216

File tree

3 files changed

+40
-8
lines changed

3 files changed

+40
-8
lines changed

DESCRIPTION.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
2020
- Add `SNOWFLAKE_AUTH_SOCKET_MSG_DONTWAIT` flag (usage: `SNOWFLAKE_AUTH_SOCKET_MSG_DONTWAIT=true`) to make a non-blocking socket.recv call and retry on Error
2121
- Consider using this if running in a containerized environment and externalbrowser auth frequently hangs while waiting for callback
2222
- NOTE: this has not been tested extensively, but has been shown to improve the experience when using WSL
23-
- Updated diagnostics to use system$allowlist instead of system$whitelist.
23+
- Updated diagnostics to use system$allowlist instead of system$whitelist.
24+
- Update `write_pandas` to skip TABLE IF NOT EXISTS in truncate mode
2425

2526
- v3.7.1(February 21, 2024)
2627

src/snowflake/connector/pandas_tools.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -393,13 +393,14 @@ def drop_object(name: str, object_type: str) -> None:
393393
quote_identifiers,
394394
)
395395

396-
create_table_sql = (
397-
f"CREATE {table_type.upper()} TABLE IF NOT EXISTS {target_table_location} "
398-
f"({create_table_columns})"
399-
f" /* Python:snowflake.connector.pandas_tools.write_pandas() */ "
400-
)
401-
logger.debug(f"auto creating table with '{create_table_sql}'")
402-
cursor.execute(create_table_sql, _is_internal=True)
396+
if auto_create_table:
397+
create_table_sql = (
398+
f"CREATE {table_type.upper()} TABLE IF NOT EXISTS {target_table_location} "
399+
f"({create_table_columns})"
400+
f" /* Python:snowflake.connector.pandas_tools.write_pandas() */ "
401+
)
402+
logger.debug(f"auto creating table with '{create_table_sql}'")
403+
cursor.execute(create_table_sql, _is_internal=True)
403404
# need explicit casting when the underlying table schema is inferred
404405
parquet_columns = "$1:" + ",$1:".join(
405406
f"{quote}{snowflake_col}{quote}::{column_type_mapping[col]}"

test/integ/pandas/test_pandas_tools.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ def test_write_pandas_with_overwrite(
115115
f"({col_name} STRING, {col_points} INT, {col_id} INT AUTOINCREMENT)"
116116
)
117117

118+
show_sql = f"SHOW TABLES LIKE '{random_table_name}'" # SHOW command like is case-insensitive
118119
select_sql = f"SELECT * FROM {table_name}"
119120
select_count_sql = f"SELECT count(*) FROM {table_name}"
120121
drop_sql = f"DROP TABLE IF EXISTS {table_name}"
@@ -148,6 +149,35 @@ def test_write_pandas_with_overwrite(
148149
# Check number of rows
149150
assert result["COUNT(*)"] == 1
150151

152+
# Truncate-only mode
153+
if not auto_create_table:
154+
# Capture the created_on timestamp of the target table before truncation
155+
result = cnx.cursor(DictCursor).execute(show_sql).fetchone()
156+
create_ts_before_trunc = result["created_on"]
157+
158+
# This operation should only truncate the table
159+
success, nchunks, nrows, _ = write_pandas(
160+
cnx,
161+
df2,
162+
random_table_name,
163+
quote_identifiers=quote_identifiers,
164+
auto_create_table=auto_create_table,
165+
overwrite=True,
166+
index=index,
167+
)
168+
169+
# Capture the created_on timestamp of the target table after truncation
170+
result = cnx.cursor(DictCursor).execute(show_sql).fetchone()
171+
create_ts_after_trunc = result["created_on"]
172+
assert create_ts_before_trunc == create_ts_after_trunc
173+
174+
# Check write_pandas output
175+
assert success
176+
assert nchunks == 1
177+
result = cnx.cursor(DictCursor).execute(select_count_sql).fetchone()
178+
# Check number of rows
179+
assert result["COUNT(*)"] == 1
180+
151181
# Write dataframe with a different schema
152182
if auto_create_table:
153183
# Should drop table and SUCCEED because the new table will be created with new schema of df3

0 commit comments

Comments
 (0)