snowpark-connect 0.27.0__py3-none-any.whl → 1.7.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.
- snowflake/snowpark_connect/__init__.py +1 -0
- snowflake/snowpark_connect/analyze_plan/map_tree_string.py +8 -4
- snowflake/snowpark_connect/client/__init__.py +15 -0
- snowflake/snowpark_connect/client/error_utils.py +30 -0
- snowflake/snowpark_connect/client/exceptions.py +36 -0
- snowflake/snowpark_connect/client/query_results.py +90 -0
- snowflake/snowpark_connect/client/server.py +717 -0
- snowflake/snowpark_connect/client/utils/__init__.py +10 -0
- snowflake/snowpark_connect/client/utils/session.py +85 -0
- snowflake/snowpark_connect/column_name_handler.py +404 -243
- snowflake/snowpark_connect/column_qualifier.py +43 -0
- snowflake/snowpark_connect/config.py +309 -26
- snowflake/snowpark_connect/constants.py +2 -0
- snowflake/snowpark_connect/dataframe_container.py +102 -8
- 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 +172 -23
- snowflake/snowpark_connect/error/exceptions.py +13 -4
- snowflake/snowpark_connect/execute_plan/map_execution_command.py +15 -160
- snowflake/snowpark_connect/execute_plan/map_execution_root.py +26 -20
- snowflake/snowpark_connect/execute_plan/utils.py +5 -1
- snowflake/snowpark_connect/expression/error_utils.py +28 -0
- snowflake/snowpark_connect/expression/function_defaults.py +9 -2
- snowflake/snowpark_connect/expression/hybrid_column_map.py +53 -5
- snowflake/snowpark_connect/expression/integral_types_support.py +219 -0
- snowflake/snowpark_connect/expression/literal.py +37 -13
- snowflake/snowpark_connect/expression/map_cast.py +224 -15
- snowflake/snowpark_connect/expression/map_expression.py +80 -27
- snowflake/snowpark_connect/expression/map_extension.py +322 -12
- snowflake/snowpark_connect/expression/map_sql_expression.py +316 -81
- snowflake/snowpark_connect/expression/map_udf.py +86 -20
- snowflake/snowpark_connect/expression/map_unresolved_attribute.py +451 -173
- snowflake/snowpark_connect/expression/map_unresolved_function.py +2964 -829
- snowflake/snowpark_connect/expression/map_unresolved_star.py +87 -23
- snowflake/snowpark_connect/expression/map_update_fields.py +70 -18
- snowflake/snowpark_connect/expression/map_window_function.py +18 -3
- snowflake/snowpark_connect/includes/jars/json4s-ast_2.13-3.7.0-M11.jar +0 -0
- snowflake/snowpark_connect/includes/jars/{scala-library-2.12.18.jar → sas-scala-udf_2.12-0.2.0.jar} +0 -0
- snowflake/snowpark_connect/includes/jars/sas-scala-udf_2.13-0.2.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/scala-reflect-2.13.16.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-common-utils_2.13-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/{spark-connect-client-jvm_2.12-3.5.6.jar → spark-connect-client-jvm_2.13-3.5.6.jar} +0 -0
- snowflake/snowpark_connect/includes/jars/{spark-sql_2.12-3.5.6.jar → spark-sql_2.13-3.5.6.jar} +0 -0
- snowflake/snowpark_connect/includes/python/pyspark/sql/connect/streaming/worker/foreach_batch_worker.py +1 -1
- snowflake/snowpark_connect/includes/python/pyspark/sql/connect/streaming/worker/listener_worker.py +1 -1
- snowflake/snowpark_connect/proto/snowflake_expression_ext_pb2.py +12 -10
- snowflake/snowpark_connect/proto/snowflake_expression_ext_pb2.pyi +14 -2
- snowflake/snowpark_connect/proto/snowflake_relation_ext_pb2.py +10 -8
- snowflake/snowpark_connect/proto/snowflake_relation_ext_pb2.pyi +13 -6
- snowflake/snowpark_connect/relation/catalogs/abstract_spark_catalog.py +65 -17
- snowflake/snowpark_connect/relation/catalogs/snowflake_catalog.py +297 -49
- snowflake/snowpark_connect/relation/catalogs/utils.py +12 -4
- snowflake/snowpark_connect/relation/io_utils.py +110 -10
- snowflake/snowpark_connect/relation/map_aggregate.py +239 -256
- snowflake/snowpark_connect/relation/map_catalog.py +5 -1
- snowflake/snowpark_connect/relation/map_column_ops.py +264 -96
- snowflake/snowpark_connect/relation/map_extension.py +263 -29
- snowflake/snowpark_connect/relation/map_join.py +683 -442
- snowflake/snowpark_connect/relation/map_local_relation.py +28 -1
- snowflake/snowpark_connect/relation/map_map_partitions.py +83 -8
- snowflake/snowpark_connect/relation/map_relation.py +48 -19
- snowflake/snowpark_connect/relation/map_row_ops.py +310 -91
- snowflake/snowpark_connect/relation/map_show_string.py +13 -6
- snowflake/snowpark_connect/relation/map_sql.py +1233 -222
- snowflake/snowpark_connect/relation/map_stats.py +48 -9
- snowflake/snowpark_connect/relation/map_subquery_alias.py +11 -2
- snowflake/snowpark_connect/relation/map_udtf.py +14 -4
- snowflake/snowpark_connect/relation/read/jdbc_read_dbapi.py +53 -14
- snowflake/snowpark_connect/relation/read/map_read.py +134 -43
- snowflake/snowpark_connect/relation/read/map_read_csv.py +326 -47
- snowflake/snowpark_connect/relation/read/map_read_jdbc.py +21 -6
- snowflake/snowpark_connect/relation/read/map_read_json.py +324 -86
- snowflake/snowpark_connect/relation/read/map_read_parquet.py +146 -28
- snowflake/snowpark_connect/relation/read/map_read_partitioned_parquet.py +142 -0
- snowflake/snowpark_connect/relation/read/map_read_socket.py +15 -3
- snowflake/snowpark_connect/relation/read/map_read_table.py +86 -6
- snowflake/snowpark_connect/relation/read/map_read_text.py +22 -4
- snowflake/snowpark_connect/relation/read/metadata_utils.py +170 -0
- snowflake/snowpark_connect/relation/read/reader_config.py +42 -3
- snowflake/snowpark_connect/relation/read/utils.py +50 -5
- snowflake/snowpark_connect/relation/stage_locator.py +91 -55
- snowflake/snowpark_connect/relation/utils.py +128 -5
- snowflake/snowpark_connect/relation/write/jdbc_write_dbapi.py +19 -3
- snowflake/snowpark_connect/relation/write/map_write.py +929 -319
- snowflake/snowpark_connect/relation/write/map_write_jdbc.py +8 -2
- snowflake/snowpark_connect/resources/java_udfs-1.0-SNAPSHOT.jar +0 -0
- snowflake/snowpark_connect/resources_initializer.py +171 -48
- snowflake/snowpark_connect/server.py +528 -473
- snowflake/snowpark_connect/server_common/__init__.py +503 -0
- snowflake/snowpark_connect/snowflake_session.py +65 -0
- snowflake/snowpark_connect/start_server.py +53 -5
- snowflake/snowpark_connect/type_mapping.py +349 -27
- snowflake/snowpark_connect/type_support.py +130 -0
- snowflake/snowpark_connect/typed_column.py +9 -7
- snowflake/snowpark_connect/utils/artifacts.py +9 -8
- snowflake/snowpark_connect/utils/cache.py +49 -27
- snowflake/snowpark_connect/utils/concurrent.py +36 -1
- snowflake/snowpark_connect/utils/context.py +195 -37
- snowflake/snowpark_connect/utils/describe_query_cache.py +68 -53
- snowflake/snowpark_connect/utils/env_utils.py +5 -1
- snowflake/snowpark_connect/utils/expression_transformer.py +172 -0
- snowflake/snowpark_connect/utils/identifiers.py +137 -3
- snowflake/snowpark_connect/utils/io_utils.py +57 -1
- snowflake/snowpark_connect/utils/java_stored_procedure.py +151 -0
- snowflake/snowpark_connect/utils/java_udaf_utils.py +321 -0
- snowflake/snowpark_connect/utils/java_udtf_utils.py +239 -0
- snowflake/snowpark_connect/utils/jvm_udf_utils.py +281 -0
- snowflake/snowpark_connect/utils/open_telemetry.py +516 -0
- snowflake/snowpark_connect/utils/pandas_udtf_utils.py +8 -4
- snowflake/snowpark_connect/utils/patch_spark_line_number.py +181 -0
- snowflake/snowpark_connect/utils/profiling.py +25 -8
- snowflake/snowpark_connect/utils/scala_udf_utils.py +185 -340
- snowflake/snowpark_connect/utils/sequence.py +21 -0
- snowflake/snowpark_connect/utils/session.py +64 -28
- snowflake/snowpark_connect/utils/snowpark_connect_logging.py +51 -9
- snowflake/snowpark_connect/utils/spcs_logger.py +290 -0
- snowflake/snowpark_connect/utils/telemetry.py +192 -40
- snowflake/snowpark_connect/utils/temporary_view_cache.py +67 -0
- snowflake/snowpark_connect/utils/temporary_view_helper.py +334 -0
- snowflake/snowpark_connect/utils/udf_cache.py +117 -41
- snowflake/snowpark_connect/utils/udf_helper.py +39 -37
- snowflake/snowpark_connect/utils/udf_utils.py +133 -14
- snowflake/snowpark_connect/utils/udtf_helper.py +8 -1
- snowflake/snowpark_connect/utils/udtf_utils.py +46 -31
- snowflake/snowpark_connect/utils/udxf_import_utils.py +9 -2
- snowflake/snowpark_connect/utils/upload_java_jar.py +57 -0
- snowflake/snowpark_connect/version.py +1 -1
- snowflake/snowpark_decoder/dp_session.py +6 -2
- snowflake/snowpark_decoder/spark_decoder.py +12 -0
- {snowpark_connect-0.27.0.data → snowpark_connect-1.7.0.data}/scripts/snowpark-submit +14 -4
- {snowpark_connect-0.27.0.dist-info → snowpark_connect-1.7.0.dist-info}/METADATA +16 -7
- {snowpark_connect-0.27.0.dist-info → snowpark_connect-1.7.0.dist-info}/RECORD +139 -168
- snowflake/snowpark_connect/hidden_column.py +0 -39
- snowflake/snowpark_connect/includes/jars/antlr4-runtime-4.9.3.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-cli-1.5.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-codec-1.16.1.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-collections-3.2.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-collections4-4.4.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-compiler-3.1.9.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-compress-1.26.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-crypto-1.1.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-dbcp-1.4.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-io-2.16.1.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-lang-2.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-lang3-3.12.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-logging-1.1.3.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-math3-3.6.1.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-pool-1.5.4.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-text-1.10.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/hadoop-client-api-trimmed-3.3.4.jar +0 -0
- snowflake/snowpark_connect/includes/jars/jackson-annotations-2.15.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/jackson-core-2.15.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/jackson-core-asl-1.9.13.jar +0 -0
- snowflake/snowpark_connect/includes/jars/jackson-databind-2.15.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/jackson-dataformat-yaml-2.15.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/jackson-datatype-jsr310-2.15.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/jackson-module-scala_2.12-2.15.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/json4s-ast_2.12-3.7.0-M11.jar +0 -0
- snowflake/snowpark_connect/includes/jars/json4s-core_2.12-3.7.0-M11.jar +0 -0
- snowflake/snowpark_connect/includes/jars/json4s-jackson_2.12-3.7.0-M11.jar +0 -0
- snowflake/snowpark_connect/includes/jars/json4s-native_2.12-3.7.0-M11.jar +0 -0
- snowflake/snowpark_connect/includes/jars/json4s-scalap_2.12-3.7.0-M11.jar +0 -0
- snowflake/snowpark_connect/includes/jars/kryo-shaded-4.0.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/log4j-1.2-api-2.20.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/log4j-api-2.20.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/log4j-core-2.20.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/log4j-slf4j2-impl-2.20.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/paranamer-2.8.3.jar +0 -0
- snowflake/snowpark_connect/includes/jars/paranamer-2.8.jar +0 -0
- snowflake/snowpark_connect/includes/jars/sas-scala-udf_2.12-0.1.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/scala-collection-compat_2.12-2.7.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/scala-parser-combinators_2.12-2.3.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/scala-reflect-2.12.18.jar +0 -0
- snowflake/snowpark_connect/includes/jars/scala-xml_2.12-2.1.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/slf4j-api-2.0.7.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-catalyst_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-common-utils_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-core_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-graphx_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-hive-thriftserver_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-hive_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-kvstore_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-launcher_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-mesos_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-mllib-local_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-network-common_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-network-shuffle_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-repl_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-sketch_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-sql-api_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-tags_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-unsafe_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-yarn_2.12-3.5.6.jar +0 -0
- {snowpark_connect-0.27.0.data → snowpark_connect-1.7.0.data}/scripts/snowpark-connect +0 -0
- {snowpark_connect-0.27.0.data → snowpark_connect-1.7.0.data}/scripts/snowpark-session +0 -0
- {snowpark_connect-0.27.0.dist-info → snowpark_connect-1.7.0.dist-info}/WHEEL +0 -0
- {snowpark_connect-0.27.0.dist-info → snowpark_connect-1.7.0.dist-info}/licenses/LICENSE-binary +0 -0
- {snowpark_connect-0.27.0.dist-info → snowpark_connect-1.7.0.dist-info}/licenses/LICENSE.txt +0 -0
- {snowpark_connect-0.27.0.dist-info → snowpark_connect-1.7.0.dist-info}/licenses/NOTICE-binary +0 -0
- {snowpark_connect-0.27.0.dist-info → snowpark_connect-1.7.0.dist-info}/top_level.txt +0 -0
|
@@ -8,23 +8,29 @@ import typing
|
|
|
8
8
|
import pandas
|
|
9
9
|
import pyspark.sql.connect.proto.common_pb2 as common_proto
|
|
10
10
|
import pyspark.sql.connect.proto.types_pb2 as types_proto
|
|
11
|
+
from pyspark.errors.exceptions.base import AnalysisException
|
|
11
12
|
from pyspark.sql.connect.client.core import Retrying
|
|
12
13
|
from snowflake.core.exceptions import APIError, NotFoundError
|
|
13
14
|
from snowflake.core.schema import Schema
|
|
14
15
|
from snowflake.core.table import Table, TableColumn
|
|
15
16
|
|
|
16
|
-
from snowflake.snowpark import functions
|
|
17
17
|
from snowflake.snowpark._internal.analyzer.analyzer_utils import (
|
|
18
18
|
quote_name_without_upper_casing,
|
|
19
19
|
unquote_if_quoted,
|
|
20
20
|
)
|
|
21
21
|
from snowflake.snowpark.functions import lit
|
|
22
22
|
from snowflake.snowpark.types import BooleanType, StringType
|
|
23
|
+
from snowflake.snowpark_connect.column_qualifier import ColumnQualifier
|
|
23
24
|
from snowflake.snowpark_connect.config import (
|
|
24
25
|
auto_uppercase_non_column_identifiers,
|
|
25
26
|
global_config,
|
|
26
27
|
)
|
|
27
28
|
from snowflake.snowpark_connect.dataframe_container import DataFrameContainer
|
|
29
|
+
from snowflake.snowpark_connect.error.error_codes import ErrorCodes
|
|
30
|
+
from snowflake.snowpark_connect.error.error_utils import (
|
|
31
|
+
TABLE_OR_VIEW_NOT_FOUND_ERROR_CLASS,
|
|
32
|
+
attach_custom_error_code,
|
|
33
|
+
)
|
|
28
34
|
from snowflake.snowpark_connect.error.exceptions import MaxRetryExceeded
|
|
29
35
|
from snowflake.snowpark_connect.relation.catalogs.abstract_spark_catalog import (
|
|
30
36
|
AbstractSparkCatalog,
|
|
@@ -34,12 +40,19 @@ from snowflake.snowpark_connect.relation.catalogs.abstract_spark_catalog import
|
|
|
34
40
|
)
|
|
35
41
|
from snowflake.snowpark_connect.type_mapping import proto_to_snowpark_type
|
|
36
42
|
from snowflake.snowpark_connect.utils.identifiers import (
|
|
43
|
+
FQN,
|
|
44
|
+
spark_to_sf_single_id_with_unquoting,
|
|
37
45
|
split_fully_qualified_spark_name,
|
|
38
46
|
)
|
|
39
47
|
from snowflake.snowpark_connect.utils.session import get_or_create_snowpark_session
|
|
40
48
|
from snowflake.snowpark_connect.utils.telemetry import (
|
|
41
49
|
SnowparkConnectNotImplementedError,
|
|
42
50
|
)
|
|
51
|
+
from snowflake.snowpark_connect.utils.temporary_view_helper import (
|
|
52
|
+
get_temp_view,
|
|
53
|
+
get_temp_view_normalized_names,
|
|
54
|
+
unregister_temp_view,
|
|
55
|
+
)
|
|
43
56
|
from snowflake.snowpark_connect.utils.udf_cache import cached_udf
|
|
44
57
|
|
|
45
58
|
|
|
@@ -103,9 +116,11 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
103
116
|
catalog, sf_database, sf_schema = _process_multi_layer_database(pattern)
|
|
104
117
|
sf_schema = sf_schema.replace("*", ".*")
|
|
105
118
|
if catalog is not None and self != catalog:
|
|
106
|
-
|
|
119
|
+
exception = SnowparkConnectNotImplementedError(
|
|
107
120
|
"Calling into another catalog is not currently supported"
|
|
108
121
|
)
|
|
122
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
123
|
+
raise exception
|
|
109
124
|
sp_catalog = get_or_create_snowpark_session().catalog
|
|
110
125
|
|
|
111
126
|
dbs: list[Schema] | None = None
|
|
@@ -125,7 +140,8 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
125
140
|
)
|
|
126
141
|
if dbs is None:
|
|
127
142
|
raise MaxRetryExceeded(
|
|
128
|
-
f"Failed to fetch databases {f'with pattern {pattern} ' if pattern is not None else ''}after all retry attempts"
|
|
143
|
+
f"Failed to fetch databases {f'with pattern {pattern} ' if pattern is not None else ''}after all retry attempts",
|
|
144
|
+
custom_error_code=ErrorCodes.INTERNAL_ERROR,
|
|
129
145
|
)
|
|
130
146
|
names: list[str] = list()
|
|
131
147
|
catalogs: list[str] = list()
|
|
@@ -157,9 +173,11 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
157
173
|
"""Listing a single database that's accessible in Snowflake."""
|
|
158
174
|
catalog, sf_database, sf_schema = _process_multi_layer_database(spark_dbName)
|
|
159
175
|
if catalog is not None and self != catalog:
|
|
160
|
-
|
|
176
|
+
exception = SnowparkConnectNotImplementedError(
|
|
161
177
|
"Calling into another catalog is not currently supported"
|
|
162
178
|
)
|
|
179
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
180
|
+
raise exception
|
|
163
181
|
sp_catalog = get_or_create_snowpark_session().catalog
|
|
164
182
|
|
|
165
183
|
db: Schema | None = None
|
|
@@ -178,7 +196,8 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
178
196
|
)
|
|
179
197
|
if db is None:
|
|
180
198
|
raise MaxRetryExceeded(
|
|
181
|
-
f"Failed to fetch database {spark_dbName} after all retry attempts"
|
|
199
|
+
f"Failed to fetch database {spark_dbName} after all retry attempts",
|
|
200
|
+
custom_error_code=ErrorCodes.INTERNAL_ERROR,
|
|
182
201
|
)
|
|
183
202
|
|
|
184
203
|
name = unquote_if_quoted(db.name)
|
|
@@ -203,6 +222,93 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
203
222
|
exists = False
|
|
204
223
|
return pandas.DataFrame({"exists": [exists]})
|
|
205
224
|
|
|
225
|
+
def _get_temp_view_prefixes(self, spark_dbName: str | None) -> list[str]:
|
|
226
|
+
if spark_dbName is None:
|
|
227
|
+
return []
|
|
228
|
+
return [
|
|
229
|
+
quote_name_without_upper_casing(part)
|
|
230
|
+
for part in split_fully_qualified_spark_name(spark_dbName)
|
|
231
|
+
]
|
|
232
|
+
|
|
233
|
+
def _list_temp_views(
|
|
234
|
+
self,
|
|
235
|
+
spark_dbName: str | None = None,
|
|
236
|
+
pattern: str | None = None,
|
|
237
|
+
) -> typing.Tuple[
|
|
238
|
+
list[str | None],
|
|
239
|
+
list[list[str | None]],
|
|
240
|
+
list[str],
|
|
241
|
+
list[str | None],
|
|
242
|
+
list[str | None],
|
|
243
|
+
list[bool],
|
|
244
|
+
]:
|
|
245
|
+
catalogs: list[str | None] = list()
|
|
246
|
+
namespaces: list[list[str | None]] = list()
|
|
247
|
+
names: list[str] = list()
|
|
248
|
+
descriptions: list[str | None] = list()
|
|
249
|
+
table_types: list[str | None] = list()
|
|
250
|
+
is_temporaries: list[bool] = list()
|
|
251
|
+
|
|
252
|
+
temp_views_prefix = ".".join(self._get_temp_view_prefixes(spark_dbName))
|
|
253
|
+
normalized_spark_dbName = (
|
|
254
|
+
temp_views_prefix.lower()
|
|
255
|
+
if global_config.spark_sql_caseSensitive
|
|
256
|
+
else temp_views_prefix
|
|
257
|
+
)
|
|
258
|
+
normalized_global_temp_database_name = (
|
|
259
|
+
quote_name_without_upper_casing(
|
|
260
|
+
global_config.spark_sql_globalTempDatabase.lower()
|
|
261
|
+
)
|
|
262
|
+
if global_config.spark_sql_caseSensitive
|
|
263
|
+
else quote_name_without_upper_casing(
|
|
264
|
+
global_config.spark_sql_globalTempDatabase
|
|
265
|
+
)
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
temp_views = get_temp_view_normalized_names()
|
|
269
|
+
null_safe_pattern = pattern if pattern is not None else ""
|
|
270
|
+
|
|
271
|
+
for temp_view in temp_views:
|
|
272
|
+
normalized_temp_view = (
|
|
273
|
+
temp_view.lower()
|
|
274
|
+
if global_config.spark_sql_caseSensitive
|
|
275
|
+
else temp_view
|
|
276
|
+
)
|
|
277
|
+
fqn = FQN.from_string(temp_view)
|
|
278
|
+
normalized_schema = (
|
|
279
|
+
fqn.schema.lower()
|
|
280
|
+
if fqn.schema is not None and global_config.spark_sql_caseSensitive
|
|
281
|
+
else fqn.schema
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
is_global_view = normalized_global_temp_database_name == normalized_schema
|
|
285
|
+
is_local_temp_view = fqn.schema is None
|
|
286
|
+
# Temporary views are always shown if they match the pattern
|
|
287
|
+
matches_prefix = (
|
|
288
|
+
normalized_spark_dbName == normalized_schema or is_local_temp_view
|
|
289
|
+
)
|
|
290
|
+
if matches_prefix and bool(
|
|
291
|
+
re.match(null_safe_pattern, normalized_temp_view)
|
|
292
|
+
):
|
|
293
|
+
names.append(unquote_if_quoted(fqn.name))
|
|
294
|
+
catalogs.append(None)
|
|
295
|
+
namespaces.append(
|
|
296
|
+
[global_config.spark_sql_globalTempDatabase]
|
|
297
|
+
if is_global_view
|
|
298
|
+
else []
|
|
299
|
+
)
|
|
300
|
+
descriptions.append(None)
|
|
301
|
+
table_types.append("TEMPORARY")
|
|
302
|
+
is_temporaries.append(True)
|
|
303
|
+
return (
|
|
304
|
+
catalogs,
|
|
305
|
+
namespaces,
|
|
306
|
+
names,
|
|
307
|
+
descriptions,
|
|
308
|
+
table_types,
|
|
309
|
+
is_temporaries,
|
|
310
|
+
)
|
|
311
|
+
|
|
206
312
|
def listTables(
|
|
207
313
|
self,
|
|
208
314
|
spark_dbName: str | None = None,
|
|
@@ -214,9 +320,11 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
214
320
|
spark_dbName
|
|
215
321
|
)
|
|
216
322
|
if catalog is not None and self != catalog:
|
|
217
|
-
|
|
323
|
+
exception = SnowparkConnectNotImplementedError(
|
|
218
324
|
"Calling into another catalog is not currently supported"
|
|
219
325
|
)
|
|
326
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
327
|
+
raise exception
|
|
220
328
|
else:
|
|
221
329
|
catalog = sf_database = sf_schema = None
|
|
222
330
|
|
|
@@ -232,8 +340,7 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
232
340
|
schema=sf_quote(sf_schema),
|
|
233
341
|
pattern=_normalize_identifier(pattern),
|
|
234
342
|
)
|
|
235
|
-
|
|
236
|
-
catalogs: list[str] = list()
|
|
343
|
+
catalogs: list[str | None] = list()
|
|
237
344
|
namespaces: list[list[str | None]] = list()
|
|
238
345
|
names: list[str] = list()
|
|
239
346
|
descriptions: list[str | None] = list()
|
|
@@ -253,6 +360,22 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
253
360
|
descriptions.append(o[6] if o[6] else None)
|
|
254
361
|
table_types.append("PERMANENT")
|
|
255
362
|
is_temporaries.append(False)
|
|
363
|
+
|
|
364
|
+
(
|
|
365
|
+
non_materialized_catalogs,
|
|
366
|
+
non_materialized_namespaces,
|
|
367
|
+
non_materialized_names,
|
|
368
|
+
non_materialized_descriptions,
|
|
369
|
+
non_materialized_table_types,
|
|
370
|
+
non_materialized_is_temporaries,
|
|
371
|
+
) = self._list_temp_views(spark_dbName, pattern)
|
|
372
|
+
catalogs.extend(non_materialized_catalogs)
|
|
373
|
+
namespaces.extend(non_materialized_namespaces)
|
|
374
|
+
names.extend(non_materialized_names)
|
|
375
|
+
descriptions.extend(non_materialized_descriptions)
|
|
376
|
+
table_types.extend(non_materialized_table_types)
|
|
377
|
+
is_temporaries.extend(non_materialized_is_temporaries)
|
|
378
|
+
|
|
256
379
|
return pandas.DataFrame(
|
|
257
380
|
{
|
|
258
381
|
"name": names,
|
|
@@ -297,35 +420,76 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
297
420
|
spark_tableName: str,
|
|
298
421
|
) -> pandas.DataFrame:
|
|
299
422
|
"""Listing a single table/view with provided name that's accessible in Snowflake."""
|
|
423
|
+
|
|
424
|
+
def _get_temp_view():
|
|
425
|
+
spark_table_name_parts = [
|
|
426
|
+
quote_name_without_upper_casing(part)
|
|
427
|
+
for part in split_fully_qualified_spark_name(spark_tableName)
|
|
428
|
+
]
|
|
429
|
+
spark_view_name = ".".join(spark_table_name_parts)
|
|
430
|
+
temp_view = get_temp_view(spark_view_name)
|
|
431
|
+
if temp_view:
|
|
432
|
+
return pandas.DataFrame(
|
|
433
|
+
{
|
|
434
|
+
"name": [unquote_if_quoted(spark_table_name_parts[-1])],
|
|
435
|
+
"catalog": [None],
|
|
436
|
+
"namespace": [
|
|
437
|
+
[unquote_if_quoted(spark_table_name_parts[-2])]
|
|
438
|
+
if len(spark_table_name_parts) > 1
|
|
439
|
+
else []
|
|
440
|
+
],
|
|
441
|
+
"description": [None],
|
|
442
|
+
"tableType": ["TEMPORARY"],
|
|
443
|
+
"isTemporary": [True],
|
|
444
|
+
}
|
|
445
|
+
)
|
|
446
|
+
return None
|
|
447
|
+
|
|
448
|
+
# Attempt to get the view from the non materialized views first
|
|
449
|
+
temp_view = _get_temp_view()
|
|
450
|
+
if temp_view is not None:
|
|
451
|
+
return temp_view
|
|
452
|
+
|
|
300
453
|
sp_catalog = get_or_create_snowpark_session().catalog
|
|
301
454
|
catalog, sf_database, sf_schema, table_name = _process_multi_layer_identifier(
|
|
302
455
|
spark_tableName
|
|
303
456
|
)
|
|
304
457
|
if catalog is not None and self != catalog:
|
|
305
|
-
|
|
458
|
+
exception = SnowparkConnectNotImplementedError(
|
|
306
459
|
"Calling into another catalog is not currently supported"
|
|
307
460
|
)
|
|
461
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
462
|
+
raise exception
|
|
308
463
|
|
|
309
464
|
table: Table | None = None
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
465
|
+
try:
|
|
466
|
+
for attempt in Retrying(
|
|
467
|
+
max_retries=5,
|
|
468
|
+
initial_backoff=100, # 100ms
|
|
469
|
+
max_backoff=5000, # 5 s
|
|
470
|
+
backoff_multiplier=2.0,
|
|
471
|
+
jitter=100,
|
|
472
|
+
min_jitter_threshold=200,
|
|
473
|
+
can_retry=_is_retryable_api_error,
|
|
474
|
+
):
|
|
475
|
+
with attempt:
|
|
476
|
+
table = sp_catalog.get_table(
|
|
477
|
+
database=sf_quote(sf_database),
|
|
478
|
+
schema=sf_quote(sf_schema),
|
|
479
|
+
table_name=sf_quote(table_name),
|
|
480
|
+
)
|
|
481
|
+
except NotFoundError:
|
|
482
|
+
exception = AnalysisException(
|
|
483
|
+
error_class=TABLE_OR_VIEW_NOT_FOUND_ERROR_CLASS,
|
|
484
|
+
message_parameters={"relationName": spark_tableName},
|
|
485
|
+
)
|
|
486
|
+
attach_custom_error_code(exception, ErrorCodes.TABLE_NOT_FOUND)
|
|
487
|
+
raise exception
|
|
325
488
|
|
|
326
489
|
if table is None:
|
|
327
490
|
raise MaxRetryExceeded(
|
|
328
|
-
f"Failed to fetch table {spark_tableName} after all retry attempts"
|
|
491
|
+
f"Failed to fetch table {spark_tableName} after all retry attempts",
|
|
492
|
+
custom_error_code=ErrorCodes.INTERNAL_ERROR,
|
|
329
493
|
)
|
|
330
494
|
|
|
331
495
|
return pandas.DataFrame(
|
|
@@ -356,16 +520,74 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
356
520
|
try:
|
|
357
521
|
self.getTable(table_mli)
|
|
358
522
|
exists = True
|
|
359
|
-
except
|
|
360
|
-
|
|
523
|
+
except AnalysisException as ex:
|
|
524
|
+
if ex.error_class == TABLE_OR_VIEW_NOT_FOUND_ERROR_CLASS:
|
|
525
|
+
exists = False
|
|
361
526
|
return pandas.DataFrame({"exists": [exists]})
|
|
362
527
|
|
|
528
|
+
def _list_temp_view_columns(
|
|
529
|
+
self,
|
|
530
|
+
spark_tableName: str,
|
|
531
|
+
spark_dbName: typing.Optional[str] = None,
|
|
532
|
+
):
|
|
533
|
+
spark_view_name_parts = [
|
|
534
|
+
quote_name_without_upper_casing(part)
|
|
535
|
+
for part in split_fully_qualified_spark_name(spark_tableName)
|
|
536
|
+
]
|
|
537
|
+
spark_view_name_parts = (
|
|
538
|
+
self._get_temp_view_prefixes(spark_dbName) + spark_view_name_parts
|
|
539
|
+
)
|
|
540
|
+
spark_view_name = ".".join(spark_view_name_parts)
|
|
541
|
+
temp_view = get_temp_view(spark_view_name)
|
|
542
|
+
|
|
543
|
+
if not temp_view:
|
|
544
|
+
return None
|
|
545
|
+
|
|
546
|
+
return self._list_columns_from_dataframe_container(temp_view)
|
|
547
|
+
|
|
548
|
+
def _list_columns_from_dataframe_container(
|
|
549
|
+
self, container: DataFrameContainer
|
|
550
|
+
) -> pandas.DataFrame:
|
|
551
|
+
names: list[str] = list()
|
|
552
|
+
descriptions: list[str | None] = list()
|
|
553
|
+
data_types: list[str] = list()
|
|
554
|
+
nullables: list[bool] = list()
|
|
555
|
+
is_partitions: list[bool] = list()
|
|
556
|
+
is_buckets: list[bool] = list()
|
|
557
|
+
|
|
558
|
+
for field, spark_column in zip(
|
|
559
|
+
container.dataframe.schema.fields,
|
|
560
|
+
container.column_map.get_spark_columns(),
|
|
561
|
+
):
|
|
562
|
+
names.append(spark_column)
|
|
563
|
+
descriptions.append(None)
|
|
564
|
+
data_types.append(field.datatype.simpleString())
|
|
565
|
+
nullables.append(field.nullable)
|
|
566
|
+
is_partitions.append(False)
|
|
567
|
+
is_buckets.append(False)
|
|
568
|
+
|
|
569
|
+
return pandas.DataFrame(
|
|
570
|
+
{
|
|
571
|
+
"name": names,
|
|
572
|
+
"description": descriptions,
|
|
573
|
+
"dataType": data_types,
|
|
574
|
+
"nullable": nullables,
|
|
575
|
+
"isPartition": is_partitions,
|
|
576
|
+
"isBucket": is_buckets,
|
|
577
|
+
}
|
|
578
|
+
)
|
|
579
|
+
|
|
363
580
|
def listColumns(
|
|
364
581
|
self,
|
|
365
582
|
spark_tableName: str,
|
|
366
583
|
spark_dbName: typing.Optional[str] = None,
|
|
367
584
|
) -> pandas.DataFrame:
|
|
368
585
|
"""List all columns in a table/view, optionally database name filter can be provided."""
|
|
586
|
+
|
|
587
|
+
temp_view_columns = self._list_temp_view_columns(spark_tableName, spark_dbName)
|
|
588
|
+
if temp_view_columns is not None:
|
|
589
|
+
return temp_view_columns
|
|
590
|
+
|
|
369
591
|
sp_catalog = get_or_create_snowpark_session().catalog
|
|
370
592
|
columns: list[TableColumn] | None = None
|
|
371
593
|
if spark_dbName is None:
|
|
@@ -373,9 +595,11 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
373
595
|
spark_tableName
|
|
374
596
|
)
|
|
375
597
|
if catalog is not None and self != catalog:
|
|
376
|
-
|
|
598
|
+
exception = SnowparkConnectNotImplementedError(
|
|
377
599
|
"Calling into another catalog is not currently supported"
|
|
378
600
|
)
|
|
601
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
602
|
+
raise exception
|
|
379
603
|
for attempt in Retrying(
|
|
380
604
|
max_retries=5,
|
|
381
605
|
initial_backoff=100, # 100ms
|
|
@@ -408,7 +632,8 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
408
632
|
)
|
|
409
633
|
if columns is None:
|
|
410
634
|
raise MaxRetryExceeded(
|
|
411
|
-
f"Failed to fetch columns of {spark_tableName} after all retry attempts"
|
|
635
|
+
f"Failed to fetch columns of {spark_tableName} after all retry attempts",
|
|
636
|
+
custom_error_code=ErrorCodes.INTERNAL_ERROR,
|
|
412
637
|
)
|
|
413
638
|
names: list[str] = list()
|
|
414
639
|
descriptions: list[str | None] = list()
|
|
@@ -456,16 +681,23 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
456
681
|
) -> DataFrameContainer:
|
|
457
682
|
session = get_or_create_snowpark_session()
|
|
458
683
|
schema = global_config.spark_sql_globalTempDatabase
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
684
|
+
result = False
|
|
685
|
+
if spark_view_name:
|
|
686
|
+
result = unregister_temp_view(
|
|
687
|
+
f"{spark_to_sf_single_id_with_unquoting(schema)}.{spark_to_sf_single_id_with_unquoting(spark_view_name)}"
|
|
688
|
+
)
|
|
689
|
+
|
|
690
|
+
if not result:
|
|
691
|
+
drop_result = session.sql(
|
|
692
|
+
"drop view if exists identifier(?)",
|
|
693
|
+
params=[f"{sf_quote(schema)}.{sf_quote(spark_view_name)}"],
|
|
694
|
+
).collect()
|
|
695
|
+
result = (
|
|
696
|
+
len(drop_result) == 1
|
|
697
|
+
and "successfully dropped" in drop_result[0]["status"]
|
|
466
698
|
)
|
|
467
|
-
)
|
|
468
699
|
columns = ["value"]
|
|
700
|
+
result_df = session.createDataFrame([result], schema=columns)
|
|
469
701
|
return DataFrameContainer.create_with_column_mapping(
|
|
470
702
|
dataframe=result_df,
|
|
471
703
|
spark_column_names=columns,
|
|
@@ -479,15 +711,23 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
479
711
|
) -> DataFrameContainer:
|
|
480
712
|
"""Drop the current temporary view."""
|
|
481
713
|
session = get_or_create_snowpark_session()
|
|
482
|
-
result = session.sql(
|
|
483
|
-
"drop view if exists identifier(?)",
|
|
484
|
-
params=[sf_quote(spark_view_name)],
|
|
485
|
-
).collect()
|
|
486
|
-
view_was_dropped = (
|
|
487
|
-
len(result) == 1 and "successfully dropped" in result[0]["status"]
|
|
488
|
-
)
|
|
489
|
-
result_df = session.createDataFrame([(view_was_dropped,)], schema=["value"])
|
|
490
714
|
columns = ["value"]
|
|
715
|
+
result = False
|
|
716
|
+
if spark_view_name:
|
|
717
|
+
result = unregister_temp_view(
|
|
718
|
+
spark_to_sf_single_id_with_unquoting(spark_view_name)
|
|
719
|
+
)
|
|
720
|
+
if not result:
|
|
721
|
+
drop_result = session.sql(
|
|
722
|
+
"drop view if exists identifier(?)",
|
|
723
|
+
params=[sf_quote(spark_view_name)],
|
|
724
|
+
).collect()
|
|
725
|
+
result = (
|
|
726
|
+
len(drop_result) == 1
|
|
727
|
+
and "successfully dropped" in drop_result[0]["status"]
|
|
728
|
+
)
|
|
729
|
+
|
|
730
|
+
result_df = session.createDataFrame([result], schema=columns)
|
|
491
731
|
return DataFrameContainer.create_with_column_mapping(
|
|
492
732
|
dataframe=result_df,
|
|
493
733
|
spark_column_names=columns,
|
|
@@ -515,26 +755,34 @@ class SnowflakeCatalog(AbstractSparkCatalog):
|
|
|
515
755
|
if source == "":
|
|
516
756
|
source = global_config.get("spark.sql.sources.default")
|
|
517
757
|
if source not in ("csv", "json", "avro", "parquet", "orc", "xml"):
|
|
518
|
-
|
|
758
|
+
exception = SnowparkConnectNotImplementedError(
|
|
519
759
|
f"Source '{source}' is not currently supported by Catalog.createTable. "
|
|
520
760
|
"Maybe default value through 'spark.sql.sources.default' should be set."
|
|
521
761
|
)
|
|
762
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
763
|
+
raise exception
|
|
522
764
|
if path != "":
|
|
523
765
|
# External table creation is not supported currently.
|
|
524
|
-
|
|
766
|
+
exception = SnowparkConnectNotImplementedError(
|
|
525
767
|
"External table creation is not supported currently."
|
|
526
768
|
)
|
|
769
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
770
|
+
raise exception
|
|
527
771
|
|
|
528
772
|
session = get_or_create_snowpark_session()
|
|
529
773
|
# Managed table
|
|
530
774
|
if schema.ByteSize() == 0:
|
|
531
|
-
|
|
775
|
+
exception = SnowparkConnectNotImplementedError(
|
|
532
776
|
f"Unable to infer schema for {source.upper()}. It must be specified manually.",
|
|
533
777
|
)
|
|
778
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
779
|
+
raise exception
|
|
534
780
|
sp_schema = proto_to_snowpark_type(schema)
|
|
535
781
|
columns = [c.name for c in schema.struct.fields]
|
|
536
782
|
table_name_parts = split_fully_qualified_spark_name(tableName)
|
|
537
|
-
qualifiers = [
|
|
783
|
+
qualifiers: list[set[ColumnQualifier]] = [
|
|
784
|
+
{ColumnQualifier(tuple(table_name_parts))} for _ in columns
|
|
785
|
+
]
|
|
538
786
|
column_types = [f.datatype for f in sp_schema.fields]
|
|
539
787
|
return DataFrameContainer.create_with_column_mapping(
|
|
540
788
|
dataframe=session.createDataFrame([], sp_schema),
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
from collections import defaultdict
|
|
6
6
|
|
|
7
7
|
from snowflake.connector.errors import ProgrammingError
|
|
8
|
+
from snowflake.snowpark_connect.error.error_codes import ErrorCodes
|
|
9
|
+
from snowflake.snowpark_connect.error.error_utils import attach_custom_error_code
|
|
8
10
|
from snowflake.snowpark_connect.relation.catalogs import CATALOGS, SNOWFLAKE_CATALOG
|
|
9
11
|
from snowflake.snowpark_connect.relation.catalogs.abstract_spark_catalog import (
|
|
10
12
|
AbstractSparkCatalog,
|
|
@@ -27,11 +29,15 @@ def set_current_catalog(catalog_name: str | None) -> AbstractSparkCatalog:
|
|
|
27
29
|
|
|
28
30
|
# Validate input parameters to match PySpark behavior
|
|
29
31
|
if catalog_name is None:
|
|
30
|
-
|
|
32
|
+
exception = ValueError("Catalog name cannot be None")
|
|
33
|
+
attach_custom_error_code(exception, ErrorCodes.INVALID_INPUT)
|
|
34
|
+
raise exception
|
|
31
35
|
if catalog_name == "":
|
|
32
|
-
|
|
36
|
+
exception = ValueError(
|
|
33
37
|
"Catalog '' plugin class not found: spark.sql.catalog. is not defined"
|
|
34
38
|
)
|
|
39
|
+
attach_custom_error_code(exception, ErrorCodes.INTERNAL_ERROR)
|
|
40
|
+
raise exception
|
|
35
41
|
|
|
36
42
|
CURRENT_CATALOG_NAME = catalog_name
|
|
37
43
|
if catalog_name in CATALOGS:
|
|
@@ -42,9 +48,11 @@ def set_current_catalog(catalog_name: str | None) -> AbstractSparkCatalog:
|
|
|
42
48
|
sf_catalog.setCurrentDatabase(catalog_name if catalog_name is not None else "")
|
|
43
49
|
return get_current_catalog()
|
|
44
50
|
except ProgrammingError as e:
|
|
45
|
-
|
|
51
|
+
exception = Exception(
|
|
46
52
|
f"Catalog '{catalog_name}' plugin class not found: spark.sql.catalog.{catalog_name} is not defined"
|
|
47
|
-
)
|
|
53
|
+
)
|
|
54
|
+
attach_custom_error_code(exception, ErrorCodes.INSUFFICIENT_INPUT)
|
|
55
|
+
raise exception from e
|
|
48
56
|
|
|
49
57
|
|
|
50
58
|
def _get_current_temp_objects() -> set[tuple[str | None, str | None, str]]:
|