Skip to content

Commit e914d59

Browse files
authored
fix(snowflake): Stop double-quoting connection identifiers (#6462)
fix(snowflake): stop double-quoting identifiers passed to connector.connect() Signed-off-by: Jia Le <5955220+jials@users.noreply.github.com>
1 parent 51c325e commit e914d59

3 files changed

Lines changed: 61 additions & 6 deletions

File tree

.secrets.baseline

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/python/feast/infra/utils/snowflake/snowflake_utils.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,6 @@ def __enter__(self):
7676

7777
kwargs.update((k, v) for k, v in config_dict.items() if v is not None)
7878

79-
for k, v in kwargs.items():
80-
if k in ["role", "warehouse", "database", "schema_"]:
81-
kwargs[k] = f'"{v}"'
82-
8379
kwargs["schema"] = kwargs.pop("schema_")
8480

8581
# https://docs.snowflake.com/en/user-guide/python-connector-example.html#using-key-pair-authentication-key-pair-rotation

sdk/python/tests/unit/infra/utils/snowflake/test_snowflake_utils.py

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import tempfile
22
from typing import Optional
3-
from unittest.mock import MagicMock
3+
from unittest.mock import MagicMock, patch
44

55
import pytest
66
from cryptography.hazmat.primitives import serialization
77
from cryptography.hazmat.primitives.asymmetric import rsa
88

99
from feast.infra.utils.snowflake.snowflake_utils import (
10+
GetSnowflakeConnection,
1011
execute_snowflake_statement,
1112
parse_private_key_path,
1213
)
@@ -75,6 +76,64 @@ def test_parse_private_key_path_key_path_encrypted(encrypted_private_key):
7576
)
7677

7778

79+
class _AttrDict(dict):
80+
__getattr__ = dict.__getitem__
81+
82+
83+
def _make_config(**overrides):
84+
defaults = {
85+
"type": "snowflake.offline",
86+
"account": "test_account",
87+
"user": "test_user",
88+
"password": "test_password", # pragma: allowlist secret
89+
"role": "test_role",
90+
"warehouse": "test_wh",
91+
"database": "test_db",
92+
"schema_": "test_schema",
93+
"config_path": "",
94+
}
95+
defaults.update(overrides)
96+
return _AttrDict(defaults)
97+
98+
99+
@patch("feast.infra.utils.snowflake.snowflake_utils.snowflake.connector")
100+
class TestGetSnowflakeConnectionIdentifierQuoting:
101+
@pytest.fixture(autouse=True)
102+
def _clear_cache(self):
103+
with patch("feast.infra.utils.snowflake.snowflake_utils._cache", {}):
104+
yield
105+
106+
@pytest.mark.parametrize(
107+
"config_key,connect_key,value",
108+
[
109+
("warehouse", "warehouse", "MY_WH"),
110+
("role", "role", "ANALYST"),
111+
("database", "database", "PROD_DB"),
112+
("schema_", "schema", "PUBLIC"),
113+
],
114+
)
115+
def test_identifier_passed_without_quoting(
116+
self, mock_connector, config_key, connect_key, value
117+
):
118+
mock_connector.connect.return_value = MagicMock()
119+
120+
with GetSnowflakeConnection(_make_config(**{config_key: value})):
121+
pass
122+
123+
kwargs = mock_connector.connect.call_args[1]
124+
assert kwargs[connect_key] == value
125+
126+
def test_schema_key_renamed_from_schema_underscore(self, mock_connector):
127+
mock_connector.connect.return_value = MagicMock()
128+
129+
with GetSnowflakeConnection(_make_config(schema_="analytics")):
130+
pass
131+
132+
kwargs = mock_connector.connect.call_args[1]
133+
assert "schema" in kwargs
134+
assert "schema_" not in kwargs
135+
136+
78137
class TestExecuteSnowflakeStatement:
79138
def test_empty_query_is_passed_through_to_execute(self):
80139
mock_conn = MagicMock()

0 commit comments

Comments
 (0)