snowpark-connect 0.30.1__py3-none-any.whl → 0.31.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of snowpark-connect might be problematic. Click here for more details.
- snowflake/snowpark_connect/column_name_handler.py +150 -25
- snowflake/snowpark_connect/config.py +51 -16
- snowflake/snowpark_connect/date_time_format_mapping.py +71 -13
- snowflake/snowpark_connect/error/error_codes.py +50 -0
- snowflake/snowpark_connect/error/error_utils.py +142 -22
- snowflake/snowpark_connect/error/exceptions.py +13 -4
- snowflake/snowpark_connect/execute_plan/map_execution_command.py +5 -1
- snowflake/snowpark_connect/execute_plan/map_execution_root.py +5 -1
- snowflake/snowpark_connect/execute_plan/utils.py +5 -1
- snowflake/snowpark_connect/expression/function_defaults.py +9 -2
- snowflake/snowpark_connect/expression/literal.py +7 -1
- snowflake/snowpark_connect/expression/map_cast.py +17 -5
- snowflake/snowpark_connect/expression/map_expression.py +48 -4
- snowflake/snowpark_connect/expression/map_extension.py +25 -5
- snowflake/snowpark_connect/expression/map_sql_expression.py +65 -30
- snowflake/snowpark_connect/expression/map_udf.py +10 -2
- snowflake/snowpark_connect/expression/map_unresolved_attribute.py +33 -9
- snowflake/snowpark_connect/expression/map_unresolved_function.py +627 -205
- snowflake/snowpark_connect/expression/map_unresolved_star.py +5 -1
- snowflake/snowpark_connect/expression/map_update_fields.py +14 -4
- snowflake/snowpark_connect/expression/map_window_function.py +18 -3
- snowflake/snowpark_connect/relation/catalogs/abstract_spark_catalog.py +65 -17
- snowflake/snowpark_connect/relation/catalogs/snowflake_catalog.py +34 -12
- snowflake/snowpark_connect/relation/catalogs/utils.py +12 -4
- snowflake/snowpark_connect/relation/io_utils.py +6 -1
- snowflake/snowpark_connect/relation/map_catalog.py +5 -1
- snowflake/snowpark_connect/relation/map_column_ops.py +88 -56
- snowflake/snowpark_connect/relation/map_extension.py +28 -8
- snowflake/snowpark_connect/relation/map_join.py +21 -10
- snowflake/snowpark_connect/relation/map_local_relation.py +5 -1
- snowflake/snowpark_connect/relation/map_relation.py +33 -7
- snowflake/snowpark_connect/relation/map_row_ops.py +23 -7
- snowflake/snowpark_connect/relation/map_sql.py +91 -24
- snowflake/snowpark_connect/relation/map_stats.py +5 -1
- snowflake/snowpark_connect/relation/map_udtf.py +14 -4
- snowflake/snowpark_connect/relation/read/jdbc_read_dbapi.py +49 -13
- snowflake/snowpark_connect/relation/read/map_read.py +15 -3
- snowflake/snowpark_connect/relation/read/map_read_csv.py +11 -3
- snowflake/snowpark_connect/relation/read/map_read_jdbc.py +17 -5
- snowflake/snowpark_connect/relation/read/map_read_json.py +8 -2
- snowflake/snowpark_connect/relation/read/map_read_parquet.py +13 -3
- snowflake/snowpark_connect/relation/read/map_read_socket.py +11 -3
- snowflake/snowpark_connect/relation/read/map_read_table.py +15 -5
- snowflake/snowpark_connect/relation/read/map_read_text.py +5 -1
- snowflake/snowpark_connect/relation/read/metadata_utils.py +5 -1
- snowflake/snowpark_connect/relation/stage_locator.py +5 -1
- snowflake/snowpark_connect/relation/write/jdbc_write_dbapi.py +19 -3
- snowflake/snowpark_connect/relation/write/map_write.py +131 -34
- snowflake/snowpark_connect/relation/write/map_write_jdbc.py +8 -2
- snowflake/snowpark_connect/resources_initializer.py +5 -1
- snowflake/snowpark_connect/server.py +72 -19
- snowflake/snowpark_connect/type_mapping.py +54 -17
- snowflake/snowpark_connect/utils/context.py +42 -1
- snowflake/snowpark_connect/utils/describe_query_cache.py +3 -0
- snowflake/snowpark_connect/utils/env_utils.py +5 -1
- snowflake/snowpark_connect/utils/identifiers.py +11 -3
- snowflake/snowpark_connect/utils/pandas_udtf_utils.py +8 -4
- snowflake/snowpark_connect/utils/profiling.py +25 -8
- snowflake/snowpark_connect/utils/scala_udf_utils.py +11 -3
- snowflake/snowpark_connect/utils/session.py +5 -1
- snowflake/snowpark_connect/utils/telemetry.py +6 -0
- snowflake/snowpark_connect/utils/temporary_view_cache.py +5 -1
- snowflake/snowpark_connect/utils/udf_cache.py +5 -3
- snowflake/snowpark_connect/utils/udf_helper.py +20 -6
- snowflake/snowpark_connect/utils/udf_utils.py +4 -4
- snowflake/snowpark_connect/utils/udtf_helper.py +5 -1
- snowflake/snowpark_connect/utils/udtf_utils.py +34 -26
- snowflake/snowpark_connect/version.py +1 -1
- {snowpark_connect-0.30.1.dist-info → snowpark_connect-0.31.0.dist-info}/METADATA +3 -2
- {snowpark_connect-0.30.1.dist-info → snowpark_connect-0.31.0.dist-info}/RECORD +78 -77
- {snowpark_connect-0.30.1.data → snowpark_connect-0.31.0.data}/scripts/snowpark-connect +0 -0
- {snowpark_connect-0.30.1.data → snowpark_connect-0.31.0.data}/scripts/snowpark-session +0 -0
- {snowpark_connect-0.30.1.data → snowpark_connect-0.31.0.data}/scripts/snowpark-submit +0 -0
- {snowpark_connect-0.30.1.dist-info → snowpark_connect-0.31.0.dist-info}/WHEEL +0 -0
- {snowpark_connect-0.30.1.dist-info → snowpark_connect-0.31.0.dist-info}/licenses/LICENSE-binary +0 -0
- {snowpark_connect-0.30.1.dist-info → snowpark_connect-0.31.0.dist-info}/licenses/LICENSE.txt +0 -0
- {snowpark_connect-0.30.1.dist-info → snowpark_connect-0.31.0.dist-info}/licenses/NOTICE-binary +0 -0
- {snowpark_connect-0.30.1.dist-info → snowpark_connect-0.31.0.dist-info}/top_level.txt +0 -0
|
@@ -9,6 +9,8 @@ import pyspark.sql.connect.proto.relations_pb2 as relation_proto
|
|
|
9
9
|
from snowflake import snowpark
|
|
10
10
|
from snowflake.snowpark._internal.analyzer.analyzer_utils import unquote_if_quoted
|
|
11
11
|
from snowflake.snowpark_connect.dataframe_container import DataFrameContainer
|
|
12
|
+
from snowflake.snowpark_connect.error.error_codes import ErrorCodes
|
|
13
|
+
from snowflake.snowpark_connect.error.error_utils import attach_custom_error_code
|
|
12
14
|
from snowflake.snowpark_connect.relation.read.jdbc_read_dbapi import JdbcDataFrameReader
|
|
13
15
|
from snowflake.snowpark_connect.relation.read.utils import (
|
|
14
16
|
Connection,
|
|
@@ -28,7 +30,9 @@ def create_connection(jdbc_options: dict[str, str]) -> Connection:
|
|
|
28
30
|
return jaydebeapi.connect(driver, url, jdbc_options)
|
|
29
31
|
except Exception as e:
|
|
30
32
|
jpype.detachThreadFromJVM()
|
|
31
|
-
|
|
33
|
+
exception = Exception(f"Error connecting JDBC datasource: {e}")
|
|
34
|
+
attach_custom_error_code(exception, ErrorCodes.INTERNAL_ERROR)
|
|
35
|
+
raise exception
|
|
32
36
|
|
|
33
37
|
|
|
34
38
|
def close_connection(conn: Connection) -> None:
|
|
@@ -70,17 +74,23 @@ def map_read_jdbc(
|
|
|
70
74
|
dbtable = None
|
|
71
75
|
|
|
72
76
|
if not dbtable and not query:
|
|
73
|
-
|
|
77
|
+
exception = ValueError("Include dbtable or query is required option")
|
|
78
|
+
attach_custom_error_code(exception, ErrorCodes.INSUFFICIENT_INPUT)
|
|
79
|
+
raise exception
|
|
74
80
|
|
|
75
81
|
if query is not None and dbtable is not None:
|
|
76
|
-
|
|
82
|
+
exception = ValueError(
|
|
77
83
|
"Not allowed to specify dbtable and query options at the same time"
|
|
78
84
|
)
|
|
85
|
+
attach_custom_error_code(exception, ErrorCodes.INVALID_INPUT)
|
|
86
|
+
raise exception
|
|
79
87
|
|
|
80
88
|
if query is not None and partition_column is not None:
|
|
81
|
-
|
|
89
|
+
exception = ValueError(
|
|
82
90
|
"Not allowed to specify partitionColumn and query options at the same time"
|
|
83
91
|
)
|
|
92
|
+
attach_custom_error_code(exception, ErrorCodes.INVALID_INPUT)
|
|
93
|
+
raise exception
|
|
84
94
|
|
|
85
95
|
try:
|
|
86
96
|
df = JdbcDataFrameReader(session, jdbc_options).jdbc_read_dbapi(
|
|
@@ -105,4 +115,6 @@ def map_read_jdbc(
|
|
|
105
115
|
snowpark_column_types=[f.datatype for f in df.schema.fields],
|
|
106
116
|
)
|
|
107
117
|
except Exception as e:
|
|
108
|
-
|
|
118
|
+
exception = Exception(f"Error accessing JDBC datasource for read: {e}")
|
|
119
|
+
attach_custom_error_code(exception, ErrorCodes.INTERNAL_ERROR)
|
|
120
|
+
raise exception
|
|
@@ -28,6 +28,8 @@ from snowflake.snowpark.types import (
|
|
|
28
28
|
TimestampType,
|
|
29
29
|
)
|
|
30
30
|
from snowflake.snowpark_connect.dataframe_container import DataFrameContainer
|
|
31
|
+
from snowflake.snowpark_connect.error.error_codes import ErrorCodes
|
|
32
|
+
from snowflake.snowpark_connect.error.error_utils import attach_custom_error_code
|
|
31
33
|
from snowflake.snowpark_connect.relation.read.map_read import JsonReaderConfig
|
|
32
34
|
from snowflake.snowpark_connect.relation.read.metadata_utils import (
|
|
33
35
|
add_filename_metadata_to_reader,
|
|
@@ -64,9 +66,11 @@ def map_read_json(
|
|
|
64
66
|
|
|
65
67
|
if rel.read.is_streaming is True:
|
|
66
68
|
# TODO: Structured streaming implementation.
|
|
67
|
-
|
|
69
|
+
exception = SnowparkConnectNotImplementedError(
|
|
68
70
|
"Streaming is not supported for JSON files."
|
|
69
71
|
)
|
|
72
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
73
|
+
raise exception
|
|
70
74
|
else:
|
|
71
75
|
snowpark_options = options.convert_to_snowpark_args()
|
|
72
76
|
raw_options = rel.read.data_source.options
|
|
@@ -363,9 +367,11 @@ def construct_row_by_schema(
|
|
|
363
367
|
content.get(col_name, None), sf.datatype, snowpark_options
|
|
364
368
|
)
|
|
365
369
|
else:
|
|
366
|
-
|
|
370
|
+
exception = SnowparkConnectNotImplementedError(
|
|
367
371
|
f"JSON construct {str(content)} to StructType failed"
|
|
368
372
|
)
|
|
373
|
+
attach_custom_error_code(exception, ErrorCodes.TYPE_MISMATCH)
|
|
374
|
+
raise exception
|
|
369
375
|
return result
|
|
370
376
|
elif isinstance(schema, ArrayType):
|
|
371
377
|
result = []
|
|
@@ -22,6 +22,8 @@ from snowflake.snowpark._internal.analyzer.analyzer_utils import (
|
|
|
22
22
|
from snowflake.snowpark.column import METADATA_FILENAME
|
|
23
23
|
from snowflake.snowpark.types import DataType, DoubleType, IntegerType, StringType
|
|
24
24
|
from snowflake.snowpark_connect.dataframe_container import DataFrameContainer
|
|
25
|
+
from snowflake.snowpark_connect.error.error_codes import ErrorCodes
|
|
26
|
+
from snowflake.snowpark_connect.error.error_utils import attach_custom_error_code
|
|
25
27
|
from snowflake.snowpark_connect.relation.read.metadata_utils import (
|
|
26
28
|
add_filename_metadata_to_reader,
|
|
27
29
|
)
|
|
@@ -44,9 +46,11 @@ def map_read_parquet(
|
|
|
44
46
|
"""Read a Parquet file into a Snowpark DataFrame."""
|
|
45
47
|
|
|
46
48
|
if rel.read.is_streaming is True:
|
|
47
|
-
|
|
49
|
+
exception = SnowparkConnectNotImplementedError(
|
|
48
50
|
"Streaming is not supported for Parquet files."
|
|
49
51
|
)
|
|
52
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
53
|
+
raise exception
|
|
50
54
|
|
|
51
55
|
snowpark_options = options.convert_to_snowpark_args()
|
|
52
56
|
raw_options = rel.read.data_source.options
|
|
@@ -155,10 +159,14 @@ def _discover_partition_columns(
|
|
|
155
159
|
if i not in dir_level_to_column_name:
|
|
156
160
|
dir_level_to_column_name[i] = key
|
|
157
161
|
elif dir_level_to_column_name[i] != key:
|
|
158
|
-
|
|
162
|
+
exception = ValueError(
|
|
159
163
|
f"Conflicting partition column names detected: '{dir_level_to_column_name[i]}' and '{key}' "
|
|
160
164
|
f"at the same directory level"
|
|
161
165
|
)
|
|
166
|
+
attach_custom_error_code(
|
|
167
|
+
exception, ErrorCodes.INVALID_OPERATION
|
|
168
|
+
)
|
|
169
|
+
raise exception
|
|
162
170
|
|
|
163
171
|
partition_columns_values[key].add(value)
|
|
164
172
|
|
|
@@ -166,10 +174,12 @@ def _discover_partition_columns(
|
|
|
166
174
|
for level in sorted(dir_level_to_column_name.keys()):
|
|
167
175
|
col_name = dir_level_to_column_name[level]
|
|
168
176
|
if col_name in seen_columns:
|
|
169
|
-
|
|
177
|
+
exception = ValueError(
|
|
170
178
|
f"Found partition column '{col_name}' at multiple directory levels. "
|
|
171
179
|
f"A partition column can only appear at a single level."
|
|
172
180
|
)
|
|
181
|
+
attach_custom_error_code(exception, ErrorCodes.INVALID_OPERATION)
|
|
182
|
+
raise exception
|
|
173
183
|
seen_columns.add(col_name)
|
|
174
184
|
|
|
175
185
|
ordered_columns = [
|
|
@@ -9,6 +9,8 @@ import pyspark.sql.connect.proto.relations_pb2 as relation_proto
|
|
|
9
9
|
|
|
10
10
|
from snowflake import snowpark
|
|
11
11
|
from snowflake.snowpark_connect.dataframe_container import DataFrameContainer
|
|
12
|
+
from snowflake.snowpark_connect.error.error_codes import ErrorCodes
|
|
13
|
+
from snowflake.snowpark_connect.error.error_utils import attach_custom_error_code
|
|
12
14
|
from snowflake.snowpark_connect.utils.telemetry import (
|
|
13
15
|
SnowparkConnectNotImplementedError,
|
|
14
16
|
)
|
|
@@ -30,7 +32,9 @@ def map_read_socket(
|
|
|
30
32
|
host = options.get("host", None)
|
|
31
33
|
port = options.get("port", None)
|
|
32
34
|
if not host or not port:
|
|
33
|
-
|
|
35
|
+
exception = ValueError("Host and port must be provided in options.")
|
|
36
|
+
attach_custom_error_code(exception, ErrorCodes.INVALID_INPUT)
|
|
37
|
+
raise exception
|
|
34
38
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
35
39
|
try:
|
|
36
40
|
s.connect((host, int(port)))
|
|
@@ -56,8 +60,12 @@ def map_read_socket(
|
|
|
56
60
|
snowpark_column_names=[snowpark_cname],
|
|
57
61
|
)
|
|
58
62
|
except OSError as e:
|
|
59
|
-
|
|
63
|
+
exception = Exception(f"Error connecting to {host}:{port} - {e}")
|
|
64
|
+
attach_custom_error_code(exception, ErrorCodes.INTERNAL_ERROR)
|
|
65
|
+
raise exception
|
|
60
66
|
else:
|
|
61
|
-
|
|
67
|
+
exception = SnowparkConnectNotImplementedError(
|
|
62
68
|
"Socket reads are only supported in streaming mode."
|
|
63
69
|
)
|
|
70
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
71
|
+
raise exception
|
|
@@ -18,6 +18,8 @@ from snowflake.snowpark_connect.column_name_handler import (
|
|
|
18
18
|
)
|
|
19
19
|
from snowflake.snowpark_connect.config import auto_uppercase_non_column_identifiers
|
|
20
20
|
from snowflake.snowpark_connect.dataframe_container import DataFrameContainer
|
|
21
|
+
from snowflake.snowpark_connect.error.error_codes import ErrorCodes
|
|
22
|
+
from snowflake.snowpark_connect.error.error_utils import attach_custom_error_code
|
|
21
23
|
from snowflake.snowpark_connect.relation.read.utils import (
|
|
22
24
|
rename_columns_as_snowflake_standard,
|
|
23
25
|
)
|
|
@@ -64,9 +66,11 @@ def post_process_df(
|
|
|
64
66
|
# Check if this is a table/view not found error
|
|
65
67
|
# Snowflake error codes: 002003 (42S02) - Object does not exist or not authorized
|
|
66
68
|
if hasattr(e, "sql_error_code") and e.sql_error_code == 2003:
|
|
67
|
-
|
|
69
|
+
exception = AnalysisException(
|
|
68
70
|
f"[TABLE_OR_VIEW_NOT_FOUND] The table or view cannot be found. {source_table_name}"
|
|
69
|
-
)
|
|
71
|
+
)
|
|
72
|
+
attach_custom_error_code(exception, ErrorCodes.INTERNAL_ERROR)
|
|
73
|
+
raise exception from None # Suppress original exception to reduce message size
|
|
70
74
|
# Re-raise if it's not a table not found error
|
|
71
75
|
raise
|
|
72
76
|
|
|
@@ -118,9 +122,11 @@ def get_table_from_name(
|
|
|
118
122
|
|
|
119
123
|
# Verify if recursive view read is not attempted
|
|
120
124
|
if table_name in get_processed_views():
|
|
121
|
-
|
|
125
|
+
exception = AnalysisException(
|
|
122
126
|
f"[RECURSIVE_VIEW] Recursive view `{table_name}` detected (cycle: `{table_name}` -> `{table_name}`)"
|
|
123
127
|
)
|
|
128
|
+
attach_custom_error_code(exception, ErrorCodes.INVALID_OPERATION)
|
|
129
|
+
raise exception
|
|
124
130
|
|
|
125
131
|
snowpark_name = ".".join(
|
|
126
132
|
quote_name_without_upper_casing(part)
|
|
@@ -159,10 +165,14 @@ def map_read_table(
|
|
|
159
165
|
and rel.read.data_source.format.lower() == "iceberg"
|
|
160
166
|
):
|
|
161
167
|
if len(rel.read.data_source.paths) != 1:
|
|
162
|
-
|
|
168
|
+
exception = SnowparkConnectNotImplementedError(
|
|
163
169
|
f"Unexpected paths: {rel.read.data_source.paths}"
|
|
164
170
|
)
|
|
171
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
172
|
+
raise exception
|
|
165
173
|
table_identifier = rel.read.data_source.paths[0]
|
|
166
174
|
else:
|
|
167
|
-
|
|
175
|
+
exception = ValueError("The relation must have a table identifier.")
|
|
176
|
+
attach_custom_error_code(exception, ErrorCodes.INVALID_INPUT)
|
|
177
|
+
raise exception
|
|
168
178
|
return get_table_from_name(table_identifier, session, rel.common.plan_id)
|
|
@@ -8,6 +8,8 @@ import pyspark.sql.connect.proto.relations_pb2 as relation_proto
|
|
|
8
8
|
|
|
9
9
|
from snowflake import snowpark
|
|
10
10
|
from snowflake.snowpark_connect.dataframe_container import DataFrameContainer
|
|
11
|
+
from snowflake.snowpark_connect.error.error_codes import ErrorCodes
|
|
12
|
+
from snowflake.snowpark_connect.error.error_utils import attach_custom_error_code
|
|
11
13
|
from snowflake.snowpark_connect.relation.read.utils import (
|
|
12
14
|
get_spark_column_names_from_snowpark_columns,
|
|
13
15
|
rename_columns_as_snowflake_standard,
|
|
@@ -82,9 +84,11 @@ def map_read_text(
|
|
|
82
84
|
"""
|
|
83
85
|
if rel.read.is_streaming is True:
|
|
84
86
|
# TODO: Structured streaming implementation.
|
|
85
|
-
|
|
87
|
+
exception = SnowparkConnectNotImplementedError(
|
|
86
88
|
"Streaming is not supported for CSV files."
|
|
87
89
|
)
|
|
90
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
91
|
+
raise exception
|
|
88
92
|
|
|
89
93
|
df = read_text(paths[0], schema, session, rel.read.data_source.options)
|
|
90
94
|
if len(paths) > 1:
|
|
@@ -16,6 +16,8 @@ from snowflake.snowpark.column import METADATA_FILENAME
|
|
|
16
16
|
from snowflake.snowpark.functions import col
|
|
17
17
|
from snowflake.snowpark.types import StructField
|
|
18
18
|
from snowflake.snowpark_connect.dataframe_container import DataFrameContainer
|
|
19
|
+
from snowflake.snowpark_connect.error.error_codes import ErrorCodes
|
|
20
|
+
from snowflake.snowpark_connect.error.error_utils import attach_custom_error_code
|
|
19
21
|
|
|
20
22
|
# Constant for the metadata filename column name
|
|
21
23
|
METADATA_FILENAME_COLUMN = "METADATA$FILENAME"
|
|
@@ -129,9 +131,11 @@ def filter_metadata_columns(
|
|
|
129
131
|
if len(non_metadata_columns) == 0:
|
|
130
132
|
# DataFrame contains only metadata columns (METADATA$FILENAME), no actual data columns remaining.
|
|
131
133
|
# We don't have a way to return an empty dataframe.
|
|
132
|
-
|
|
134
|
+
exception = AnalysisException(
|
|
133
135
|
"[DATAFRAME_MISSING_DATA_COLUMNS] Cannot perform operation on DataFrame that contains no data columns."
|
|
134
136
|
)
|
|
137
|
+
attach_custom_error_code(exception, ErrorCodes.INVALID_OPERATION)
|
|
138
|
+
raise exception
|
|
135
139
|
|
|
136
140
|
filtered_df = result_df.select([col(name) for name in non_metadata_columns])
|
|
137
141
|
|
|
@@ -11,6 +11,8 @@ from s3fs.core import S3FileSystem
|
|
|
11
11
|
from snowflake import snowpark
|
|
12
12
|
from snowflake.snowpark.session import Session
|
|
13
13
|
from snowflake.snowpark_connect.config import sessions_config
|
|
14
|
+
from snowflake.snowpark_connect.error.error_codes import ErrorCodes
|
|
15
|
+
from snowflake.snowpark_connect.error.error_utils import attach_custom_error_code
|
|
14
16
|
from snowflake.snowpark_connect.relation.io_utils import (
|
|
15
17
|
get_cloud_from_url,
|
|
16
18
|
parse_azure_url,
|
|
@@ -42,9 +44,11 @@ def get_paths_from_stage(
|
|
|
42
44
|
rewrite_paths.append(f"{stage_name}/{path}")
|
|
43
45
|
paths = rewrite_paths
|
|
44
46
|
case "gcp":
|
|
45
|
-
|
|
47
|
+
exception = AnalysisException(
|
|
46
48
|
"You must configure an integration for Google Cloud Storage to perform I/O operations rather than accessing the URL directly. Reference: https://docs.snowflake.com/en/user-guide/data-load-gcs-config"
|
|
47
49
|
)
|
|
50
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
51
|
+
raise exception
|
|
48
52
|
case _:
|
|
49
53
|
filesystem, parsed_path = url_to_fs(paths[0])
|
|
50
54
|
if isinstance(filesystem, S3FileSystem): # aws
|
|
@@ -11,6 +11,8 @@ from snowflake import snowpark
|
|
|
11
11
|
from snowflake.snowpark import DataFrameWriter
|
|
12
12
|
from snowflake.snowpark.dataframe import DataFrame
|
|
13
13
|
from snowflake.snowpark_connect.dataframe_container import DataFrameContainer
|
|
14
|
+
from snowflake.snowpark_connect.error.error_codes import ErrorCodes
|
|
15
|
+
from snowflake.snowpark_connect.error.error_utils import attach_custom_error_code
|
|
14
16
|
from snowflake.snowpark_connect.relation.read import jdbc_read_dbapi
|
|
15
17
|
from snowflake.snowpark_connect.relation.read.jdbc_read_dbapi import JdbcDialect
|
|
16
18
|
from snowflake.snowpark_connect.relation.read.utils import Connection
|
|
@@ -65,9 +67,13 @@ class JdbcDataFrameWriter(DataFrameWriter):
|
|
|
65
67
|
self._create_table(conn, table, container, jdbc_dialect)
|
|
66
68
|
case "errorifexists":
|
|
67
69
|
if table_exist:
|
|
68
|
-
|
|
70
|
+
exception = ValueError(
|
|
69
71
|
"table is already exist and write mode is ERROR_IF_EXISTS"
|
|
70
72
|
)
|
|
73
|
+
attach_custom_error_code(
|
|
74
|
+
exception, ErrorCodes.INVALID_OPERATION
|
|
75
|
+
)
|
|
76
|
+
raise exception
|
|
71
77
|
else:
|
|
72
78
|
self._create_table(conn, table, container, jdbc_dialect)
|
|
73
79
|
case "overwrite":
|
|
@@ -82,7 +88,9 @@ class JdbcDataFrameWriter(DataFrameWriter):
|
|
|
82
88
|
else:
|
|
83
89
|
self._create_table(conn, table, container, jdbc_dialect)
|
|
84
90
|
case _:
|
|
85
|
-
|
|
91
|
+
exception = ValueError(f"Invalid write mode value{write_mode}")
|
|
92
|
+
attach_custom_error_code(exception, ErrorCodes.INVALID_INPUT)
|
|
93
|
+
raise exception
|
|
86
94
|
|
|
87
95
|
task_insert_into_data_source_with_retry(
|
|
88
96
|
input_df,
|
|
@@ -141,6 +149,7 @@ class JdbcDataFrameWriter(DataFrameWriter):
|
|
|
141
149
|
cursor.execute(sql)
|
|
142
150
|
except Exception as e:
|
|
143
151
|
logger.error(f"failed to drop table {table} from the data source {e}")
|
|
152
|
+
attach_custom_error_code(e, ErrorCodes.INTERNAL_ERROR)
|
|
144
153
|
raise e
|
|
145
154
|
|
|
146
155
|
def _create_table(
|
|
@@ -189,6 +198,7 @@ class JdbcDataFrameWriter(DataFrameWriter):
|
|
|
189
198
|
cursor.execute(sql)
|
|
190
199
|
except Exception as e:
|
|
191
200
|
logger.error(f"failed to create a table {table} from the data source {e}")
|
|
201
|
+
attach_custom_error_code(e, ErrorCodes.INTERNAL_ERROR)
|
|
192
202
|
raise e
|
|
193
203
|
|
|
194
204
|
|
|
@@ -218,6 +228,7 @@ def _task_insert_into_data_source(
|
|
|
218
228
|
except Exception as e:
|
|
219
229
|
logger.debug(f"failed to insert into data source {e}")
|
|
220
230
|
conn.rollback()
|
|
231
|
+
attach_custom_error_code(e, ErrorCodes.INTERNAL_ERROR)
|
|
221
232
|
raise e
|
|
222
233
|
finally:
|
|
223
234
|
cursor.close()
|
|
@@ -274,6 +285,7 @@ def task_insert_into_data_source_with_retry(
|
|
|
274
285
|
)
|
|
275
286
|
except Exception as e:
|
|
276
287
|
logger.debug(f"failed to insert into data source {e}")
|
|
288
|
+
attach_custom_error_code(e, ErrorCodes.INTERNAL_ERROR)
|
|
277
289
|
raise e
|
|
278
290
|
finally:
|
|
279
291
|
close_connection(conn)
|
|
@@ -339,4 +351,8 @@ def convert_sp_to_sql_type(
|
|
|
339
351
|
case _:
|
|
340
352
|
return "TIMESTAMP"
|
|
341
353
|
case _:
|
|
342
|
-
|
|
354
|
+
exception = TypeError(
|
|
355
|
+
f"Unsupported data type: {datatype.__class__.__name__}"
|
|
356
|
+
)
|
|
357
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_TYPE)
|
|
358
|
+
raise exception
|