3131import configparser
3232import logging
3333import os
34+ from enum import Enum
3435from pathlib import Path
35- from typing import Any , Dict , Final , Optional
36+ from typing import Any , Dict , Final , List , Optional
3637
3738from snowflake .cli .api .config_ng .core import ConfigValue , SourceType , ValueSource
3839
3940log = logging .getLogger (__name__ )
4041
42+
43+ class SnowSQLSection (Enum ):
44+ """
45+ SnowSQL configuration file section names.
46+
47+ These sections can be present in SnowSQL INI config files.
48+ """
49+
50+ CONNECTIONS = "connections"
51+ VARIABLES = "variables"
52+ OPTIONS = "options"
53+
54+
4155# Try to import tomllib (Python 3.11+) or fall back to tomli
4256try :
4357 import tomllib
@@ -142,9 +156,9 @@ def discover(self, key: Optional[str] = None) -> Dict[str, ConfigValue]:
142156
143157 # Process all connection sections
144158 for section in config .sections ():
145- if section .startswith ("connections" ):
159+ if section .startswith (SnowSQLSection . CONNECTIONS . value ):
146160 # Extract connection name
147- if section == "connections" :
161+ if section == SnowSQLSection . CONNECTIONS . value :
148162 # This is default connection
149163 connection_name = "default"
150164 else :
@@ -170,6 +184,19 @@ def discover(self, key: Optional[str] = None) -> Dict[str, ConfigValue]:
170184 raw_value = f"{ param_key } ={ param_value } " , # Show original key in raw_value
171185 )
172186
187+ elif section == SnowSQLSection .VARIABLES .value :
188+ # Process variables section (global, not connection-specific)
189+ section_data = dict (config [section ])
190+ for var_key , var_value in section_data .items ():
191+ full_key = f"variables.{ var_key } "
192+ if key is None or full_key == key :
193+ merged_values [full_key ] = ConfigValue (
194+ key = full_key ,
195+ value = var_value ,
196+ source_name = self .source_name ,
197+ raw_value = f"{ var_key } ={ var_value } " ,
198+ )
199+
173200 except Exception as e :
174201 log .debug ("Failed to read SnowSQL config %s: %s" , config_file , e )
175202
@@ -755,3 +782,36 @@ def discover(self, key: Optional[str] = None) -> Dict[str, ConfigValue]:
755782 def supports_key (self , key : str ) -> bool :
756783 """Check if key is present in CLI context with non-None value."""
757784 return key in self ._cli_context and self ._cli_context [key ] is not None
785+
786+
787+ def get_merged_variables (cli_variables : Optional [List [str ]] = None ) -> Dict [str , str ]:
788+ """
789+ Merge SnowSQL [variables] with CLI -D parameters.
790+
791+ Precedence: SnowSQL variables (lower) < -D parameters (higher)
792+
793+ Args:
794+ cli_variables: List of "key=value" strings from -D parameters
795+
796+ Returns:
797+ Dictionary of merged variables (key -> value)
798+ """
799+ from snowflake .cli .api .config_provider import get_config_provider_singleton
800+
801+ # Start with SnowSQL variables from config
802+ provider = get_config_provider_singleton ()
803+ try :
804+ snowsql_vars = provider .get_section (SnowSQLSection .VARIABLES .value )
805+ except Exception :
806+ # If variables section doesn't exist or provider not initialized, start with empty dict
807+ snowsql_vars = {}
808+
809+ # Parse and overlay -D parameters (higher precedence)
810+ if cli_variables :
811+ from snowflake .cli .api .commands .utils import parse_key_value_variables
812+
813+ cli_vars_parsed = parse_key_value_variables (cli_variables )
814+ for var in cli_vars_parsed :
815+ snowsql_vars [var .key ] = var .value
816+
817+ return snowsql_vars
0 commit comments