Skip to content

Commit 5637b34

Browse files
SNOW-1444663: fix SnowSQL PUT failed with a 400 error but the status shows as uploaded (#1956)
1 parent 5e61c94 commit 5637b34

File tree

3 files changed

+62
-1
lines changed

3 files changed

+62
-1
lines changed

DESCRIPTION.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
1313
- Added support for `token_file_path` connection parameter to read an OAuth token from a file when connecting to Snowflake.
1414
- Added support for `debug_arrow_chunk` connection parameter to allow debugging raw arrow data in case of arrow data parsing failure.
1515
- Fixed a bug that OCSP certificate signed using SHA384 algorithm cannot be verified.
16+
- Fixed a bug that status code shown as uploaded when PUT command failed with 400 error.
1617

1718
- v3.10.1(May 21, 2024)
1819

src/snowflake/connector/storage_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ def prepare_upload(self) -> None:
247247

248248
def finish_upload(self) -> None:
249249
meta = self.meta
250-
if self.successful_transfers == self.num_of_chunks:
250+
if self.successful_transfers == self.num_of_chunks and self.num_of_chunks != 0:
251251
if self.num_of_chunks > 1:
252252
self._complete_multipart_upload()
253253
meta.result_status = ResultStatus.UPLOADED

test/unit/test_storage_client.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,63 @@
11
#
22
# Copyright (c) 2012-2023 Snowflake Computing Inc. All rights reserved.
33
#
4+
from os import path
5+
from unittest.mock import MagicMock
6+
7+
try:
8+
from snowflake.connector import SnowflakeConnection
9+
from snowflake.connector.constants import ResultStatus
10+
from snowflake.connector.file_transfer_agent import (
11+
SnowflakeFileMeta,
12+
StorageCredential,
13+
)
14+
from snowflake.connector.s3_storage_client import SnowflakeS3RestClient
15+
except ImportError:
16+
# Compatibility for olddriver tests
17+
from snowflake.connector.s3_util import ERRORNO_WSAECONNABORTED # NOQA
18+
19+
SnowflakeFileMeta = dict
20+
SnowflakeS3RestClient = None
21+
RequestExceedMaxRetryError = None
22+
StorageCredential = None
23+
megabytes = 1024 * 1024
24+
DEFAULT_MAX_RETRY = 5
25+
26+
THIS_DIR = path.dirname(path.realpath(__file__))
27+
megabyte = 1024 * 1024
28+
29+
30+
def test_status_when_num_of_chunks_is_zero():
31+
meta_info = {
32+
"name": "data1.txt.gz",
33+
"stage_location_type": "S3",
34+
"no_sleeping_time": True,
35+
"put_callback": None,
36+
"put_callback_output_stream": None,
37+
"sha256_digest": "123456789abcdef",
38+
"dst_file_name": "data1.txt.gz",
39+
"src_file_name": path.join(THIS_DIR, "../data", "put_get_1.txt"),
40+
"overwrite": True,
41+
}
42+
meta = SnowflakeFileMeta(**meta_info)
43+
creds = {"AWS_SECRET_KEY": "", "AWS_KEY_ID": "", "AWS_TOKEN": ""}
44+
rest_client = SnowflakeS3RestClient(
45+
meta,
46+
StorageCredential(
47+
creds,
48+
MagicMock(autospec=SnowflakeConnection),
49+
"PUT file:/tmp/file.txt @~",
50+
),
51+
{
52+
"locationType": "AWS",
53+
"location": "bucket/path",
54+
"creds": creds,
55+
"region": "test",
56+
"endPoint": None,
57+
},
58+
8 * megabyte,
59+
)
60+
rest_client.successful_transfers = 0
61+
rest_client.num_of_chunks = 0
62+
rest_client.finish_upload()
63+
assert meta.result_status == ResultStatus.ERROR

0 commit comments

Comments
 (0)