From deeb2913d9efd3be552c69a4364099935b76b702 Mon Sep 17 00:00:00 2001 From: Jonathan Shi Date: Thu, 12 Mar 2026 12:10:12 -0700 Subject: [PATCH 1/6] unquote account/db/schema in default_artifact_repository path --- src/snowflake/snowpark/session.py | 6 +++--- tests/integ/test_session.py | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/snowflake/snowpark/session.py b/src/snowflake/snowpark/session.py index db2b90688c..532da23853 100644 --- a/src/snowflake/snowpark/session.py +++ b/src/snowflake/snowpark/session.py @@ -2424,9 +2424,9 @@ def _get_default_artifact_repository(self) -> str: if isinstance(self._conn, MockServerConnection): return _DEFAULT_ARTIFACT_REPOSITORY - account = self.get_current_account() - database = self.get_current_database() - schema = self.get_current_schema() + account = self._conn._get_current_parameter("account", quoted=False) + database = self._conn._get_current_parameter("database", quoted=False) + schema = self._conn._get_current_parameter("schema", quoted=False) cache_key = (database, schema) if ( diff --git a/tests/integ/test_session.py b/tests/integ/test_session.py index 7cd4017985..b411b46e04 100644 --- a/tests/integ/test_session.py +++ b/tests/integ/test_session.py @@ -8,6 +8,7 @@ import io from functools import partial from unittest.mock import patch +import logging import pytest @@ -41,6 +42,7 @@ _get_active_session, _get_active_sessions, ) +from snowflake.snowpark.context import _ANACONDA_SHARED_REPOSITORY from tests.utils import IS_IN_STORED_PROC, IS_IN_STORED_PROC_LOCALFS, TestFiles, Utils @@ -1091,3 +1093,27 @@ def test_get_active_sessions_empty(): with patch.object(session_module, "_active_sessions", return_value=set()): assert session_module._get_active_sessions(require_at_least_one=False) == set() + + +def test_default_artifact_repository_with_no_db_schema(session, caplog): + # The reported customer issue covered by this test (SNOW-3230493) occurs when no schema/database + # is set and an account locator is used, so we mock schema/db to be empty for this test. + # Oddly, getting schema and database appear to be fine (for example, schema comes back with + # double-quoted all-caps '"PUBLIC"') while account produces a double-quoted lowercase value + # ('"sfctest0') that causes an error when passed to SYSTEM$GET_DEFAULT_ARTIFACT_REPOSITORY. + # Apparently removing quoting makes these identifiers case-insensitive. + original_conn_implementation = session._conn._get_current_parameter + + def mock_session_parameters(param: str, quoted: bool = True): + if param == "schema" or param == "database": + return None + return original_conn_implementation(param, quoted) + + with patch.object( + session._conn, + "_get_current_parameter", + mock_session_parameters, + ), caplog.at_level(logging.WARNING): + result = session._get_default_artifact_repository() + assert result == _ANACONDA_SHARED_REPOSITORY + assert caplog.text.count("Error getting default artifact repository") == 0 From 6f4ef194ab430622c2b92e18f3618b5d5b8eeeaf Mon Sep 17 00:00:00 2001 From: Jonathan Shi Date: Thu, 12 Mar 2026 14:00:27 -0700 Subject: [PATCH 2/6] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c392df6ed..29769fba4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Fixed a bug when saving a fdn table into an iceberg table in overwrite mode, error is raised because `StringType` is saved in wrong length. - Fixed a bug in `ai_complete` where `model_parameters` and `response_format` values containing single quotes would generate malformed SQL. - Fixed a bug in `DataFrameReader.xml()` where reading XML with a custom schema whose field names contain colons (e.g., `px:name`) raised a `SnowparkColumnException`. +- Fixed a bug where the account-level default artifact repository setting was not reflected in creation of stored procedures/UDFs. #### Improvements From 802215675e81066076bfcc04a7eb1978a63273a9 Mon Sep 17 00:00:00 2001 From: Jonathan Shi Date: Thu, 12 Mar 2026 15:07:14 -0700 Subject: [PATCH 3/6] fix unit test mock --- tests/unit/test_session.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/tests/unit/test_session.py b/tests/unit/test_session.py index df979a0b7a..93a58fd007 100644 --- a/tests/unit/test_session.py +++ b/tests/unit/test_session.py @@ -745,14 +745,21 @@ def test_get_default_artifact_repository(): fake_server_connection._thread_safe_session_enabled = True session = Session(fake_server_connection) + original_conn_implementation = session._conn._get_current_parameter + + def mock_session_parameters_1(param: str, quoted: bool = True): + if param == "schema": + return "SCHEMA1" + elif param == "database": + return "DB1" + return original_conn_implementation(param, quoted) + with mock.patch.object( session, "_run_query", return_value=[["snowflake.snowpark.pypi_shared_repository"]], ) as mocked_run_query, mock.patch.object( - session, "get_current_database", return_value="DB1" - ), mock.patch.object( - session, "get_current_schema", return_value="SCHEMA1" + session._conn, "_get_current_parameter", mock_session_parameters_1 ): result = session._get_default_artifact_repository() assert result == "snowflake.snowpark.pypi_shared_repository" @@ -762,12 +769,19 @@ def test_get_default_artifact_repository(): assert mocked_run_query.call_count == 1 + def mock_session_parameters_2(param: str, quoted: bool = True): + if param == "schema": + return "SCHEMA2" + elif param == "database": + return "DB2" + return original_conn_implementation(param, quoted) + with mock.patch.object( session, "_run_query", return_value=[[None]] ) as mocked_run_query, mock.patch.object( - session, "get_current_database", return_value="DB2" - ), mock.patch.object( - session, "get_current_schema", return_value="SCHEMA2" + session._conn, + "_get_current_parameter", + mock_session_parameters_2, ): result = session._get_default_artifact_repository() assert result == _ANACONDA_SHARED_REPOSITORY From 74ff1fa8c5c955f293f5729e244800806434e89c Mon Sep 17 00:00:00 2001 From: Jonathan Shi Date: Tue, 17 Mar 2026 10:53:46 -0700 Subject: [PATCH 4/6] explicitly issue query for account ID --- src/snowflake/snowpark/session.py | 13 ++++++++++--- tests/integ/test_session.py | 6 +++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/snowflake/snowpark/session.py b/src/snowflake/snowpark/session.py index 532da23853..db329917c1 100644 --- a/src/snowflake/snowpark/session.py +++ b/src/snowflake/snowpark/session.py @@ -69,6 +69,9 @@ GeneratorTableFunction, TableFunctionRelation, ) +from snowflake.snowpark._internal.analyzer.analyzer_utils import ( + quote_name_without_upper_casing, +) from snowflake.snowpark._internal.analyzer.unary_expression import Cast from snowflake.snowpark._internal.ast.batch import AstBatch from snowflake.snowpark._internal.ast.utils import ( @@ -2424,9 +2427,13 @@ def _get_default_artifact_repository(self) -> str: if isinstance(self._conn, MockServerConnection): return _DEFAULT_ARTIFACT_REPOSITORY - account = self._conn._get_current_parameter("account", quoted=False) - database = self._conn._get_current_parameter("database", quoted=False) - schema = self._conn._get_current_parameter("schema", quoted=False) + # self.get_current_account uses a cached connector field that may not be properly cased, so we need to + # explicitly issue a query for it + account = quote_name_without_upper_casing( + self._conn._get_string_datum("SELECT CURRENT_ACCOUNT()") + ) + database = self.get_current_database() + schema = self.get_current_schema() cache_key = (database, schema) if ( diff --git a/tests/integ/test_session.py b/tests/integ/test_session.py index b411b46e04..128f8013f5 100644 --- a/tests/integ/test_session.py +++ b/tests/integ/test_session.py @@ -1099,9 +1099,9 @@ def test_default_artifact_repository_with_no_db_schema(session, caplog): # The reported customer issue covered by this test (SNOW-3230493) occurs when no schema/database # is set and an account locator is used, so we mock schema/db to be empty for this test. # Oddly, getting schema and database appear to be fine (for example, schema comes back with - # double-quoted all-caps '"PUBLIC"') while account produces a double-quoted lowercase value - # ('"sfctest0') that causes an error when passed to SYSTEM$GET_DEFAULT_ARTIFACT_REPOSITORY. - # Apparently removing quoting makes these identifiers case-insensitive. + # double-quoted all-caps '"PUBLIC"') while the connector's cached _account field produces a + # double-quoted lowercase value ('"sfctest0') that causes an error when passed to + # SYSTEM$GET_DEFAULT_ARTIFACT_REPOSITORY. original_conn_implementation = session._conn._get_current_parameter def mock_session_parameters(param: str, quoted: bool = True): From 433d8816fe2bab7cae8a1c9004830508782714dd Mon Sep 17 00:00:00 2001 From: Jonathan Shi Date: Tue, 17 Mar 2026 11:06:32 -0700 Subject: [PATCH 5/6] restore unit test --- tests/unit/test_session.py | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/tests/unit/test_session.py b/tests/unit/test_session.py index 93a58fd007..df979a0b7a 100644 --- a/tests/unit/test_session.py +++ b/tests/unit/test_session.py @@ -745,21 +745,14 @@ def test_get_default_artifact_repository(): fake_server_connection._thread_safe_session_enabled = True session = Session(fake_server_connection) - original_conn_implementation = session._conn._get_current_parameter - - def mock_session_parameters_1(param: str, quoted: bool = True): - if param == "schema": - return "SCHEMA1" - elif param == "database": - return "DB1" - return original_conn_implementation(param, quoted) - with mock.patch.object( session, "_run_query", return_value=[["snowflake.snowpark.pypi_shared_repository"]], ) as mocked_run_query, mock.patch.object( - session._conn, "_get_current_parameter", mock_session_parameters_1 + session, "get_current_database", return_value="DB1" + ), mock.patch.object( + session, "get_current_schema", return_value="SCHEMA1" ): result = session._get_default_artifact_repository() assert result == "snowflake.snowpark.pypi_shared_repository" @@ -769,19 +762,12 @@ def mock_session_parameters_1(param: str, quoted: bool = True): assert mocked_run_query.call_count == 1 - def mock_session_parameters_2(param: str, quoted: bool = True): - if param == "schema": - return "SCHEMA2" - elif param == "database": - return "DB2" - return original_conn_implementation(param, quoted) - with mock.patch.object( session, "_run_query", return_value=[[None]] ) as mocked_run_query, mock.patch.object( - session._conn, - "_get_current_parameter", - mock_session_parameters_2, + session, "get_current_database", return_value="DB2" + ), mock.patch.object( + session, "get_current_schema", return_value="SCHEMA2" ): result = session._get_default_artifact_repository() assert result == _ANACONDA_SHARED_REPOSITORY From 2b7a379f3ad7ac7454d9b2e0e99ca3b4b5ac397a Mon Sep 17 00:00:00 2001 From: Jonathan Shi Date: Tue, 17 Mar 2026 13:44:00 -0700 Subject: [PATCH 6/6] defer account query --- src/snowflake/snowpark/session.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/snowflake/snowpark/session.py b/src/snowflake/snowpark/session.py index db329917c1..f80255d00d 100644 --- a/src/snowflake/snowpark/session.py +++ b/src/snowflake/snowpark/session.py @@ -2427,11 +2427,6 @@ def _get_default_artifact_repository(self) -> str: if isinstance(self._conn, MockServerConnection): return _DEFAULT_ARTIFACT_REPOSITORY - # self.get_current_account uses a cached connector field that may not be properly cased, so we need to - # explicitly issue a query for it - account = quote_name_without_upper_casing( - self._conn._get_string_datum("SELECT CURRENT_ACCOUNT()") - ) database = self.get_current_database() schema = self.get_current_schema() cache_key = (database, schema) @@ -2449,7 +2444,10 @@ def _get_default_artifact_repository(self) -> str: if schema else f"'database', '{database}'" if database - else f"'account', '{account}'" + # self.get_current_account uses a cached connector field that may not be properly cased, so we need to + # explicitly issue a query for it. + # Since this issues a query, we should compute it only if database/schema are unset. + else f"""'account', '{quote_name_without_upper_casing(self._conn._get_string_datum("SELECT CURRENT_ACCOUNT()"))}'""" ) result = self._run_query( f"SELECT SYSTEM$GET_DEFAULT_PYTHON_ARTIFACT_REPOSITORY('{python_version}', {entity_selector_args})"