"""Common executors to share functionality.""" import logging import boto3 from snowflake_connector.etl_connector import SnowflakeSQLExecutor from feed_ingestion.util import sql_templating logger = logging.getLogger(__name__) class SnowflakeTemplatedSQLExecutor(SnowflakeSQLExecutor): """SnowflakeSQLExecutor with Jinja2-based SQL templating support. Adds execute_query() on top of the base executor. SQL templates use Jinja2 syntax: {{ value }} for bind params, {{ name | identifier }} for double-quote-quoted Snowflake identifiers. """ def execute_query(self, sql_loader, query_name, params): """Render a Jinja2 SQL template and execute it against Snowflake. Args: template (str): Jinja2 SQL template string. variables (dict): Template context variables. Returns: cursor: The executed cursor result. """ sql_template = sql_loader.load_query(query_name) if '%(' in sql_template: # support for old-style templates formatting with %(param)s if '{{' in sql_template or '{%' in sql_template: raise ValueError( 'SQL template cannot contain both Jinja2 ' 'and Python string formatting syntax' ) # execute super method return super(SnowflakeTemplatedSQLExecutor, self).execute_query( sql_loader, query_name, params) sql, params = sql_templating.render( template=sql_template, engine='snowflake', params=params, ) logger.debug(f'Executing query: {sql}') logger.debug(f'Params: {params}') return self.execute(sql_template=sql, params=params) class SnowflakeAWSExecutor(SnowflakeTemplatedSQLExecutor): """Helper class to abstract common Snowflake and AWS operations. Inherits from SnowflakeTemplatedSQLExecutor so all *SF executors can use Jinja2-templated SQL ({{ value }}, {{ ident | identifier }}) seamlessly. Legacy %()s-style queries fall through unchanged. """ def get_aws_params(self): """Get current AWS creds and return as query params.""" credentials = boto3.Session().get_credentials() aws_params = dict( aws_key_id=credentials.access_key, aws_secret_key=credentials.secret_key, aws_token=credentials.token if credentials.token else '', ) return aws_params