Skip to content

SNOW-2900899: snowflake.connector.connect modifies the input session_parameters dictionary in-place #2716

@tekumara

Description

@tekumara

Python version

n/a

Operating system and processor architecture

n/a

Installed packages

snowflake-connector-python==4.1.1

What did you do?

def test_server_session_parameters_are_modified(server: dict) -> None:
    session_parameters = {"CLIENT_VALIDATE_DEFAULT_PARAMETERS": True}
    original_session_parameters = session_parameters.copy()

    with snowflake.connector.connect(**server | {"session_parameters": session_parameters}, autocommit=False):
        pass

    # session_parameters are modified by the connector based on connect kwargs and defaults
    assert session_parameters == original_session_parameters

Fails with

FAILED tests/test_server.py::test_server_session_parameters_are_modified - AssertionError: assert {'CLIENT_VALIDATE_DEFAULT_PARAMETERS': True, 'AUTOCOMMIT': False, 'CLIENT_PREFETCH_THREADS': 4, 'CLIENT_SESSION_KEEP_ALIVE_HEARTBEAT_FREQUENCY': 3600, 'TIMEZONE': 'Etc/UTC'} == {'CLIENT_VALIDATE_DEFAULT_PARAMETERS': True}
  
  Common items:
  {'CLIENT_VALIDATE_DEFAULT_PARAMETERS': True}
  Left contains 4 more items:
  {'AUTOCOMMIT': False,
   'CLIENT_PREFETCH_THREADS': 4,
   'CLIENT_SESSION_KEEP_ALIVE_HEARTBEAT_FREQUENCY': 3600,
   'TIMEZONE': 'Etc/UTC'}
  
  Full diff:
    {
  +     'AUTOCOMMIT': False,
  +     'CLIENT_PREFETCH_THREADS': 4,
  +     'CLIENT_SESSION_KEEP_ALIVE_HEARTBEAT_FREQUENCY': 3600,
        'CLIENT_VALIDATE_DEFAULT_PARAMETERS': True,
  +     'TIMEZONE': 'Etc/UTC',
    }

What did you expect to see?

The session_parameters dict should not be modified, because this can cause unintended side effects. If a user defines a session_parameters dictionary and reuses it for multiple connections, modifying it in-place means the second connection inherits settings (like autocommit=False) from the first one. This can lead to subtle bugs where subsequent connections behave differently than the first one, solely based on execution order.

Also session_parameters are inputs to the connection. By writing back response values (like TIMEZONE, or CLIENT_SESSION_KEEP_ALIVE_HEARTBEAT_FREQUENCY) into the input dictionary, the connector is mixing "configuration" (what I want) with "state" (what I got), which makes the dictionary an unreliable record of the initial configuration.

Can you set logging to DEBUG and collect the logs?

import logging
import os

for logger_name in ('snowflake.connector',):
    logger = logging.getLogger(logger_name)
    logger.setLevel(logging.DEBUG)
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    ch.setFormatter(logging.Formatter('%(asctime)s - %(threadName)s %(filename)s:%(lineno)d - %(funcName)s() - %(levelname)s - %(message)s'))
    logger.addHandler(ch)

Metadata

Metadata

Assignees

Labels

status-triage_doneInitial triage done, will be further handled by the driver team

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions