"""Materialized View Class and factory function.""" from snowflake_views.config import VIEW_CONFIG class MaterializedView(object): """Materialized View class. Encapsulates logic involved in constructing table views. """ def __init__( self, table_name, create_select, grant_params, cluster_dims, state_sql, cache_sql_where_predicate=''): """Create MaterializedView object. Args: table_name (str): Name of view table. create_select (str): SQL to select data for view. grant_params (dict): Dictionary of grant parameters with the following structure: privs (str): Comma-separated list of privileges. role (str): Role to apply privileges to. cluster_dims (str): Comma-separated list of dimensions to cluster by. state_sql (str): SQL to select latest timestamp of source data. cache_sql_where_predicate (str): WHERE predicate for SQL to cache view (default = ''). """ self.table_name = table_name self._create_select = create_select self._grant_params = grant_params self._cluster_dims = cluster_dims self._state_sql = state_sql self._cache_sql_where_predicate = cache_sql_where_predicate @property def create_sql(self): """Get create SQL.""" return ( 'CREATE OR REPLACE TABLE {table_name} AS {create_select}'.format( table_name=self._qualified_table_name(), create_select=self._create_select)) @property def grant_sql(self): """Get grant SQL.""" return ( 'GRANT {privs} ON {table_name} TO ROLE {role}'.format( table_name=self._qualified_table_name(), **self._grant_params)) @property def cluster_sql(self): """Get cluster SQL.""" return ( 'ALTER TABLE {table_name} CLUSTER BY ({dims})'.format( table_name=self._qualified_table_name(), dims=self._cluster_dims)) @property def cache_sql(self): """Get cache SQL.""" sql = 'SELECT * FROM {table_name}'.format( table_name=self._qualified_table_name()) if self._cache_sql_where_predicate: sql += ' WHERE {predicate}'.format( predicate=self._cache_sql_where_predicate) return sql @property def state_sql(self): """Get state SQL.""" return self._state_sql def _qualified_table_name(self): return '%(db)i.%(schema)i.{table_name}'.format( table_name=self.table_name) def load_view_from_config(view_name): """Factory function to create MaterializedView object from config. The table_name, create_select, grant_params, cluster_dims, and state_sql keys must be contained in a dictionary nested within snowflake_views.config.VIEW_CONFIG like this: VIEW_CONFIG = { 'view_name': { 'table_name': 'table_name', 'create_select': 'SELECT 1', 'grant_params': { 'privs': 'SELECT', 'role' 'role'}, 'cluster_dims': 'dim_one, dim_two', 'state_sql': 'SELECT 1'}} The key cache_sql_where_predicate is optional and defaults to ''. Args: view_name (str): Name of view. """ assert view_name in VIEW_CONFIG, 'Invalid view name "{view_name}"'.format( view_name=view_name) config = VIEW_CONFIG[view_name] for required_arg in [ 'table_name', 'create_select', 'grant_params', 'cluster_dims', 'state_sql']: assert required_arg in config, \ 'Cannot find key "{key}" in config'.format(key=required_arg) return MaterializedView(**config)